@nocobase/cli 2.1.0-alpha.25 → 2.1.0-alpha.27
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 +61 -49
- package/README.zh-CN.md +40 -47
- package/dist/commands/app/down.js +259 -0
- package/dist/commands/app/logs.js +98 -0
- package/dist/commands/app/restart.js +75 -0
- package/dist/commands/app/start.js +252 -0
- package/dist/commands/app/stop.js +98 -0
- package/dist/commands/app/upgrade.js +579 -0
- package/dist/commands/build.js +3 -48
- package/dist/commands/config/delete.js +30 -0
- package/dist/commands/config/get.js +29 -0
- package/dist/commands/config/index.js +20 -0
- package/dist/commands/config/list.js +29 -0
- package/dist/commands/config/set.js +35 -0
- package/dist/commands/db/check.js +230 -0
- package/dist/commands/db/shared.js +1 -1
- package/dist/commands/dev.js +3 -147
- package/dist/commands/down.js +3 -188
- package/dist/commands/download.js +4 -856
- package/dist/commands/env/add.js +28 -23
- package/dist/commands/env/info.js +152 -0
- package/dist/commands/env/list.js +23 -9
- package/dist/commands/env/shared.js +158 -0
- package/dist/commands/{prompts-stages.js → examples/prompts-stages.js} +3 -3
- package/dist/commands/{prompts-test.js → examples/prompts-test.js} +3 -3
- package/dist/commands/init.js +83 -6
- package/dist/commands/install.js +361 -82
- package/dist/commands/license/activate.js +357 -0
- package/dist/commands/license/env.js +94 -0
- package/dist/commands/license/generate-id.js +107 -0
- package/dist/commands/license/id.js +52 -0
- package/dist/commands/license/index.js +20 -0
- package/dist/commands/license/plugins/clean.js +98 -0
- package/dist/commands/license/plugins/index.js +20 -0
- package/dist/commands/license/plugins/list.js +50 -0
- package/dist/commands/license/plugins/shared.js +325 -0
- package/dist/commands/license/plugins/sync.js +267 -0
- package/dist/commands/license/shared.js +411 -0
- package/dist/commands/license/status.js +50 -0
- package/dist/commands/logs.js +3 -88
- package/dist/commands/plugin/disable.js +64 -0
- package/dist/commands/plugin/enable.js +64 -0
- package/dist/commands/plugin/list.js +62 -0
- package/dist/commands/pm/disable.js +3 -54
- package/dist/commands/pm/enable.js +3 -54
- package/dist/commands/pm/list.js +3 -52
- package/dist/commands/restart.js +3 -65
- package/dist/commands/scaffold/migration.js +1 -1
- package/dist/commands/scaffold/plugin.js +1 -1
- package/dist/commands/skills/remove.js +71 -0
- package/dist/commands/skills/update.js +7 -0
- package/dist/commands/source/build.js +58 -0
- package/dist/commands/source/dev.js +157 -0
- package/dist/commands/source/download.js +866 -0
- package/dist/commands/source/test.js +467 -0
- package/dist/commands/start.js +3 -209
- package/dist/commands/stop.js +3 -88
- package/dist/commands/test.js +3 -457
- package/dist/commands/upgrade.js +3 -585
- package/dist/help/runtime-help.js +3 -0
- package/dist/lib/api-client.js +94 -9
- package/dist/lib/app-health.js +126 -0
- package/dist/lib/app-managed-resources.js +264 -0
- package/dist/lib/app-runtime.js +26 -10
- package/dist/lib/auth-store.js +29 -63
- package/dist/lib/build-config.js +8 -0
- package/dist/lib/cli-config.js +176 -0
- package/dist/lib/cli-home.js +12 -26
- package/dist/lib/cli-locale.js +15 -1
- package/dist/lib/db-connection-check.js +178 -0
- package/dist/lib/env-config.js +80 -0
- package/dist/lib/generated-command.js +23 -3
- package/dist/lib/plugin-storage.js +127 -0
- package/dist/lib/prompt-validators.js +4 -4
- package/dist/lib/prompt-web-ui.js +13 -6
- package/dist/lib/runtime-generator.js +89 -10
- package/dist/lib/self-manager.js +57 -2
- package/dist/lib/skills-manager.js +34 -7
- package/dist/lib/startup-update.js +85 -7
- package/dist/locale/en-US.json +16 -13
- package/dist/locale/zh-CN.json +16 -13
- package/nocobase-ctl.config.json +82 -0
- package/package.json +41 -6
- package/dist/commands/ps.js +0 -119
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import fs from 'node:fs/promises';
|
|
10
10
|
import path from 'node:path';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
11
12
|
import * as p from '@clack/prompts';
|
|
12
|
-
import { inspectSelfStatus, } from './self-manager.js';
|
|
13
|
+
import { inspectSelfInstall, inspectSelfStatus, } from './self-manager.js';
|
|
13
14
|
import { inspectSkillsStatus } from './skills-manager.js';
|
|
14
15
|
import { resolveCliHomeDir } from './cli-home.js';
|
|
15
16
|
import { isInteractiveTerminal, printWarning } from './ui.js';
|
|
@@ -19,8 +20,37 @@ const NB_SKIP_STARTUP_UPDATE_ENV = 'NB_SKIP_STARTUP_UPDATE';
|
|
|
19
20
|
function getStateFile() {
|
|
20
21
|
return path.join(resolveCliHomeDir('global'), STARTUP_UPDATE_STATE_FILE);
|
|
21
22
|
}
|
|
23
|
+
function getCurrentInstallBinPath() {
|
|
24
|
+
return path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..', 'bin', 'run.js');
|
|
25
|
+
}
|
|
26
|
+
function getCurrentInstallEntry(state) {
|
|
27
|
+
return state.entries?.[getCurrentInstallBinPath()];
|
|
28
|
+
}
|
|
22
29
|
function todayStamp(now = new Date()) {
|
|
23
|
-
|
|
30
|
+
const timeZone = String(process.env.TZ ?? '').trim();
|
|
31
|
+
if (timeZone) {
|
|
32
|
+
try {
|
|
33
|
+
const parts = new Intl.DateTimeFormat('en-CA', {
|
|
34
|
+
timeZone,
|
|
35
|
+
year: 'numeric',
|
|
36
|
+
month: '2-digit',
|
|
37
|
+
day: '2-digit',
|
|
38
|
+
}).formatToParts(now);
|
|
39
|
+
const year = parts.find((part) => part.type === 'year')?.value;
|
|
40
|
+
const month = parts.find((part) => part.type === 'month')?.value;
|
|
41
|
+
const day = parts.find((part) => part.type === 'day')?.value;
|
|
42
|
+
if (year && month && day) {
|
|
43
|
+
return `${year}-${month}-${day}`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Fall back to the host local timezone.
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const year = now.getFullYear();
|
|
51
|
+
const month = String(now.getMonth() + 1).padStart(2, '0');
|
|
52
|
+
const day = String(now.getDate()).padStart(2, '0');
|
|
53
|
+
return `${year}-${month}-${day}`;
|
|
24
54
|
}
|
|
25
55
|
function shouldSkipByArgv(argv) {
|
|
26
56
|
const tokens = argv.filter((token) => token && !token.startsWith('-'));
|
|
@@ -46,8 +76,46 @@ async function writeState(state) {
|
|
|
46
76
|
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
47
77
|
await fs.writeFile(filePath, JSON.stringify(state, null, 2));
|
|
48
78
|
}
|
|
79
|
+
function readCurrentInstallLastCheckedDate(state) {
|
|
80
|
+
return getCurrentInstallEntry(state)?.lastCheckedDate ?? state.lastCheckedDate;
|
|
81
|
+
}
|
|
82
|
+
async function writeCurrentInstallEntry(updater) {
|
|
83
|
+
const state = await readState();
|
|
84
|
+
const installBinPath = getCurrentInstallBinPath();
|
|
85
|
+
const nextEntry = updater(getCurrentInstallEntry(state), state);
|
|
86
|
+
await writeState({
|
|
87
|
+
...state,
|
|
88
|
+
entries: {
|
|
89
|
+
...(state.entries ?? {}),
|
|
90
|
+
[installBinPath]: nextEntry,
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
}
|
|
49
94
|
async function markChecked(now = new Date()) {
|
|
50
|
-
await
|
|
95
|
+
await writeCurrentInstallEntry((current, state) => {
|
|
96
|
+
return {
|
|
97
|
+
policy: current?.policy ?? 'daily',
|
|
98
|
+
lastCheckedDate: todayStamp(now),
|
|
99
|
+
};
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
async function disableStartupUpdateForCurrentInstall() {
|
|
103
|
+
await writeCurrentInstallEntry((current, state) => {
|
|
104
|
+
return {
|
|
105
|
+
policy: 'disabled',
|
|
106
|
+
lastCheckedDate: current?.lastCheckedDate
|
|
107
|
+
?? state.lastCheckedDate,
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
async function enableDailyStartupUpdateForCurrentInstall() {
|
|
112
|
+
await writeCurrentInstallEntry((current, state) => {
|
|
113
|
+
return {
|
|
114
|
+
policy: 'daily',
|
|
115
|
+
lastCheckedDate: current?.lastCheckedDate
|
|
116
|
+
?? state.lastCheckedDate,
|
|
117
|
+
};
|
|
118
|
+
});
|
|
51
119
|
}
|
|
52
120
|
export async function shouldRunStartupUpdateCheck(argv, now = new Date()) {
|
|
53
121
|
if (process.env[NB_SKIP_STARTUP_UPDATE_ENV] === '1') {
|
|
@@ -57,7 +125,20 @@ export async function shouldRunStartupUpdateCheck(argv, now = new Date()) {
|
|
|
57
125
|
return false;
|
|
58
126
|
}
|
|
59
127
|
const state = await readState();
|
|
60
|
-
|
|
128
|
+
const currentEntry = getCurrentInstallEntry(state);
|
|
129
|
+
if (currentEntry?.policy === 'disabled') {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
if (currentEntry?.policy === 'daily') {
|
|
133
|
+
return readCurrentInstallLastCheckedDate(state) !== todayStamp(now);
|
|
134
|
+
}
|
|
135
|
+
const selfInstall = await inspectSelfInstall();
|
|
136
|
+
if (!shouldEnableStartupUpdateForInstallMethod(selfInstall.installMethod)) {
|
|
137
|
+
await disableStartupUpdateForCurrentInstall();
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
await enableDailyStartupUpdateForCurrentInstall();
|
|
141
|
+
return readCurrentInstallLastCheckedDate(state) !== todayStamp(now);
|
|
61
142
|
}
|
|
62
143
|
export function shouldEnableStartupUpdateForInstallMethod(installMethod) {
|
|
63
144
|
return installMethod === 'npm-global';
|
|
@@ -173,9 +254,6 @@ export async function maybeRunStartupUpdatePrompt(argv) {
|
|
|
173
254
|
return { kind: 'skipped' };
|
|
174
255
|
}
|
|
175
256
|
const selfStatus = await inspectSelfStatus();
|
|
176
|
-
if (!shouldEnableStartupUpdateForInstallMethod(selfStatus.installMethod)) {
|
|
177
|
-
return { kind: 'skipped' };
|
|
178
|
-
}
|
|
179
257
|
const skillsStatus = await inspectSkillsStatus();
|
|
180
258
|
if (!hasPendingUpdates(selfStatus, skillsStatus)) {
|
|
181
259
|
await markChecked();
|
package/dist/locale/en-US.json
CHANGED
|
@@ -62,6 +62,13 @@
|
|
|
62
62
|
"allocateNotDockerPublished": "Failed to allocate an available TCP port that is not already published by Docker.",
|
|
63
63
|
"alreadyInUse": "Port {{port}} is already in use. Choose another port.",
|
|
64
64
|
"alreadyInUseByDocker": "Port {{port}} is already in use by a Docker container. Choose another port."
|
|
65
|
+
},
|
|
66
|
+
"dbConnection": {
|
|
67
|
+
"unreachable": "Can't reach the database at {{host}}:{{port}}. Check the host, port, and network connectivity. Details: {{details}}",
|
|
68
|
+
"timeout": "Timed out connecting to the database at {{host}}:{{port}} after about {{seconds}} seconds.",
|
|
69
|
+
"authenticationFailed": "Failed to sign in to database \"{{database}}\" with user \"{{user}}\". Check the username and password.",
|
|
70
|
+
"databaseNotFound": "Database \"{{database}}\" does not exist or is not accessible with the current connection settings.",
|
|
71
|
+
"connectionFailed": "Database connection check failed. Details: {{details}}"
|
|
65
72
|
}
|
|
66
73
|
},
|
|
67
74
|
"commands": {
|
|
@@ -73,10 +80,6 @@
|
|
|
73
80
|
},
|
|
74
81
|
"scope": {
|
|
75
82
|
"message": "Where should this connection be saved?",
|
|
76
|
-
"autoLabel": "Auto",
|
|
77
|
-
"autoHint": "project if this repo already has .nocobase, otherwise global",
|
|
78
|
-
"projectLabel": "Project",
|
|
79
|
-
"projectHint": ".nocobase in this repo",
|
|
80
83
|
"globalLabel": "Global",
|
|
81
84
|
"globalHint": "user-level config"
|
|
82
85
|
},
|
|
@@ -273,7 +276,7 @@
|
|
|
273
276
|
"envExists": "Env \"{{envName}}\" already exists. Choose another env name."
|
|
274
277
|
},
|
|
275
278
|
"messages": {
|
|
276
|
-
"title": "Set Up
|
|
279
|
+
"title": "Set Up NocoBase for Coding Agents",
|
|
277
280
|
"appNameRequiredWhenSkipped": "Env name is required when prompts are skipped.",
|
|
278
281
|
"appNameEnvHelp": "Use `nb init --yes --env <envName>` to continue.",
|
|
279
282
|
"resumeEnvRequired": "Env name is required when resuming setup.",
|
|
@@ -303,24 +306,24 @@
|
|
|
303
306
|
}
|
|
304
307
|
},
|
|
305
308
|
"webUi": {
|
|
306
|
-
"pageTitle": "Set Up
|
|
307
|
-
"documentHeading": "Set Up
|
|
308
|
-
"documentHint": "Connect an existing NocoBase app, or install a new one
|
|
309
|
+
"pageTitle": "Set Up NocoBase for Coding Agents",
|
|
310
|
+
"documentHeading": "Set Up NocoBase for Coding Agents",
|
|
311
|
+
"documentHint": "Connect an existing NocoBase app, or install a new one, so coding agents can access and work with NocoBase.",
|
|
309
312
|
"gettingStarted": {
|
|
310
313
|
"title": "Getting started",
|
|
311
|
-
"description": "
|
|
314
|
+
"description": "Choose whether to connect an existing app or install a new one."
|
|
312
315
|
},
|
|
313
316
|
"connectExistingApp": {
|
|
314
317
|
"title": "Connect an existing app",
|
|
315
|
-
"description": "
|
|
318
|
+
"description": "Save your app connection."
|
|
316
319
|
},
|
|
317
320
|
"createNewApp": {
|
|
318
|
-
"title": "
|
|
319
|
-
"description": "Set
|
|
321
|
+
"title": "Install a new app",
|
|
322
|
+
"description": "Set app basics and install options."
|
|
320
323
|
},
|
|
321
324
|
"downloadAppFiles": {
|
|
322
325
|
"title": "Download app files",
|
|
323
|
-
"description": "Choose
|
|
326
|
+
"description": "Choose how to get the app files."
|
|
324
327
|
},
|
|
325
328
|
"configureDatabase": {
|
|
326
329
|
"title": "Configure the database",
|
package/dist/locale/zh-CN.json
CHANGED
|
@@ -62,6 +62,13 @@
|
|
|
62
62
|
"allocateNotDockerPublished": "分配未被 Docker 占用的可用 TCP 端口失败。",
|
|
63
63
|
"alreadyInUse": "端口 {{port}} 已被占用,请更换其他端口。",
|
|
64
64
|
"alreadyInUseByDocker": "端口 {{port}} 已被 Docker 容器占用,请更换其他端口。"
|
|
65
|
+
},
|
|
66
|
+
"dbConnection": {
|
|
67
|
+
"unreachable": "无法连接到数据库 {{host}}:{{port}}。请检查主机、端口和网络连通性。详情:{{details}}",
|
|
68
|
+
"timeout": "连接数据库 {{host}}:{{port}} 超时,约 {{seconds}} 秒内未成功建立连接。",
|
|
69
|
+
"authenticationFailed": "无法使用用户 \"{{user}}\" 登录数据库 \"{{database}}\"。请检查用户名和密码。",
|
|
70
|
+
"databaseNotFound": "数据库 \"{{database}}\" 不存在,或当前连接配置无权访问该数据库。",
|
|
71
|
+
"connectionFailed": "数据库连接检查失败。详情:{{details}}"
|
|
65
72
|
}
|
|
66
73
|
},
|
|
67
74
|
"commands": {
|
|
@@ -73,10 +80,6 @@
|
|
|
73
80
|
},
|
|
74
81
|
"scope": {
|
|
75
82
|
"message": "这个连接要保存到哪里?",
|
|
76
|
-
"autoLabel": "自动",
|
|
77
|
-
"autoHint": "当前仓库已有 .nocobase 时保存到项目内,否则保存到全局",
|
|
78
|
-
"projectLabel": "项目内",
|
|
79
|
-
"projectHint": "保存在当前仓库的 .nocobase 中",
|
|
80
83
|
"globalLabel": "全局",
|
|
81
84
|
"globalHint": "保存在用户级配置中"
|
|
82
85
|
},
|
|
@@ -273,7 +276,7 @@
|
|
|
273
276
|
"envExists": "Env \"{{envName}}\" 已存在,请换一个 env name。"
|
|
274
277
|
},
|
|
275
278
|
"messages": {
|
|
276
|
-
"title": "
|
|
279
|
+
"title": "配置供 Coding Agents 使用的 NocoBase",
|
|
277
280
|
"appNameRequiredWhenSkipped": "跳过 prompts 时必须提供 Env name。",
|
|
278
281
|
"appNameEnvHelp": "请使用 `nb init --yes --env <envName>` 继续。",
|
|
279
282
|
"resumeEnvRequired": "恢复安装时必须提供 Env name。",
|
|
@@ -303,24 +306,24 @@
|
|
|
303
306
|
}
|
|
304
307
|
},
|
|
305
308
|
"webUi": {
|
|
306
|
-
"pageTitle": "
|
|
307
|
-
"documentHeading": "
|
|
308
|
-
"documentHint": "连接已有的 NocoBase
|
|
309
|
+
"pageTitle": "配置供 Coding Agents 使用的 NocoBase",
|
|
310
|
+
"documentHeading": "配置供 Coding Agents 使用的 NocoBase",
|
|
311
|
+
"documentHint": "连接已有的 NocoBase 应用,或安装一个新的应用,让 Coding Agents 可以在当前工作区中访问和操作 NocoBase。",
|
|
309
312
|
"gettingStarted": {
|
|
310
313
|
"title": "开始设置",
|
|
311
|
-
"description": "
|
|
314
|
+
"description": "选择连接已有应用,或安装一个新应用。"
|
|
312
315
|
},
|
|
313
316
|
"connectExistingApp": {
|
|
314
317
|
"title": "连接已有应用",
|
|
315
|
-
"description": "
|
|
318
|
+
"description": "保存现有应用连接。"
|
|
316
319
|
},
|
|
317
320
|
"createNewApp": {
|
|
318
|
-
"title": "
|
|
319
|
-
"description": "
|
|
321
|
+
"title": "安装新应用",
|
|
322
|
+
"description": "设置应用基础信息和安装选项。"
|
|
320
323
|
},
|
|
321
324
|
"downloadAppFiles": {
|
|
322
325
|
"title": "下载应用文件",
|
|
323
|
-
"description": "
|
|
326
|
+
"description": "选择获取应用文件的方式。"
|
|
324
327
|
},
|
|
325
328
|
"configureDatabase": {
|
|
326
329
|
"title": "配置数据库",
|
package/nocobase-ctl.config.json
CHANGED
|
@@ -215,6 +215,88 @@
|
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
},
|
|
218
|
+
"backup": {
|
|
219
|
+
"name": "backup",
|
|
220
|
+
"description": "Create, inspect, download, remove, and restore NocoBase backups.",
|
|
221
|
+
"include": true,
|
|
222
|
+
"resources": {
|
|
223
|
+
"includes": ["backup"],
|
|
224
|
+
"excludes": [],
|
|
225
|
+
"overrides": {
|
|
226
|
+
"backup": {
|
|
227
|
+
"name": "backup",
|
|
228
|
+
"description": "Manage backup and restore files.",
|
|
229
|
+
"topLevel": true,
|
|
230
|
+
"operations": {
|
|
231
|
+
"includes": [
|
|
232
|
+
"backup:list",
|
|
233
|
+
"backup:create",
|
|
234
|
+
"backup:status",
|
|
235
|
+
"backup:download",
|
|
236
|
+
"backup:remove",
|
|
237
|
+
"backup:restore",
|
|
238
|
+
"backup:restoreUpload",
|
|
239
|
+
"backup:restoreStatus"
|
|
240
|
+
]
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
"migration": {
|
|
247
|
+
"name": "migration",
|
|
248
|
+
"description": "Create, check, execute, and inspect migration packages.",
|
|
249
|
+
"include": true,
|
|
250
|
+
"resources": {
|
|
251
|
+
"includes": ["migration", "migrationLog", "migrationRule", "migrationRules"],
|
|
252
|
+
"excludes": [],
|
|
253
|
+
"overrides": {
|
|
254
|
+
"migration": {
|
|
255
|
+
"name": "migration",
|
|
256
|
+
"description": "Manage migration files and executions.",
|
|
257
|
+
"topLevel": true,
|
|
258
|
+
"operations": {
|
|
259
|
+
"includes": [
|
|
260
|
+
"migration:list",
|
|
261
|
+
"migration:get",
|
|
262
|
+
"migration:create",
|
|
263
|
+
"migration:download",
|
|
264
|
+
"migration:remove",
|
|
265
|
+
"migration:check",
|
|
266
|
+
"migration:execute"
|
|
267
|
+
]
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
"migrationRule": {
|
|
271
|
+
"name": "migration rules",
|
|
272
|
+
"segments": ["migration", "rules"],
|
|
273
|
+
"description": "Create migration rules with global user/system policies.",
|
|
274
|
+
"topLevel": true,
|
|
275
|
+
"operations": {
|
|
276
|
+
"includes": ["migrationRule:create"]
|
|
277
|
+
}
|
|
278
|
+
},
|
|
279
|
+
"migrationRules": {
|
|
280
|
+
"name": "migration rules",
|
|
281
|
+
"segments": ["migration", "rules"],
|
|
282
|
+
"description": "List and inspect migration rules.",
|
|
283
|
+
"topLevel": true,
|
|
284
|
+
"operations": {
|
|
285
|
+
"includes": ["migrationRules:list", "migrationRules:get"]
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
"migrationLog": {
|
|
289
|
+
"name": "migration logs",
|
|
290
|
+
"segments": ["migration", "logs"],
|
|
291
|
+
"description": "List, inspect, and download migration logs.",
|
|
292
|
+
"topLevel": true,
|
|
293
|
+
"operations": {
|
|
294
|
+
"includes": ["migrationLog:list", "migrationLog:get", "migrationLog:download"]
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
},
|
|
218
300
|
"system-settings": {
|
|
219
301
|
"name": "system-settings",
|
|
220
302
|
"description": "Adjust system title, logo, language, and other global settings.",
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/cli",
|
|
3
|
-
"version": "2.1.0-alpha.
|
|
3
|
+
"version": "2.1.0-alpha.27",
|
|
4
4
|
"description": "NocoBase Command Line Tool",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/generated/command-registry.js",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"clean": "node ./scripts/clean.mjs",
|
|
9
9
|
"build": "node ./scripts/build.mjs",
|
|
10
|
-
"test": "TEST_ENV=server-side yarn --cwd ../../.. vitest run packages/core/cli"
|
|
10
|
+
"test": "NB_CLI_ROOT=. TEST_ENV=server-side yarn --cwd ../../.. vitest run packages/core/cli"
|
|
11
11
|
},
|
|
12
12
|
"keywords": [],
|
|
13
13
|
"author": "",
|
|
@@ -36,8 +36,33 @@
|
|
|
36
36
|
"dirname": "nb",
|
|
37
37
|
"topicSeparator": " ",
|
|
38
38
|
"topics": {
|
|
39
|
+
"app": {
|
|
40
|
+
"description": "Manage NocoBase app runtimes: start, stop, restart, logs, and upgrades."
|
|
41
|
+
},
|
|
42
|
+
"source": {
|
|
43
|
+
"description": "Work with the local NocoBase source project: download, develop, build, and test."
|
|
44
|
+
},
|
|
45
|
+
"scaffold": {
|
|
46
|
+
"description": "Generate NocoBase plugin development scaffolds."
|
|
47
|
+
},
|
|
48
|
+
"plugin": {
|
|
49
|
+
"description": "Manage plugins in the selected NocoBase env."
|
|
50
|
+
},
|
|
51
|
+
"pm": {
|
|
52
|
+
"description": "Manage plugins in the selected NocoBase env.",
|
|
53
|
+
"hidden": true
|
|
54
|
+
},
|
|
55
|
+
"db": {
|
|
56
|
+
"description": "Manage the built-in database for the selected env."
|
|
57
|
+
},
|
|
39
58
|
"env": {
|
|
40
|
-
"description": "Manage NocoBase project environments and
|
|
59
|
+
"description": "Manage NocoBase project environments, status, details, and command runtimes."
|
|
60
|
+
},
|
|
61
|
+
"license": {
|
|
62
|
+
"description": "Manage NocoBase commercial licensing and licensed plugins."
|
|
63
|
+
},
|
|
64
|
+
"config": {
|
|
65
|
+
"description": "Manage CLI configuration defaults."
|
|
41
66
|
},
|
|
42
67
|
"self": {
|
|
43
68
|
"description": "Inspect or update the NocoBase CLI itself."
|
|
@@ -45,6 +70,10 @@
|
|
|
45
70
|
"skills": {
|
|
46
71
|
"description": "Inspect or synchronize NocoBase AI coding skills for the current workspace."
|
|
47
72
|
},
|
|
73
|
+
"examples": {
|
|
74
|
+
"description": "Internal example commands for prompt and UI experiments.",
|
|
75
|
+
"hidden": true
|
|
76
|
+
},
|
|
48
77
|
"api": {
|
|
49
78
|
"description": "Work with NocoBase API."
|
|
50
79
|
}
|
|
@@ -52,21 +81,27 @@
|
|
|
52
81
|
},
|
|
53
82
|
"dependencies": {
|
|
54
83
|
"@clack/prompts": "^0.9.1",
|
|
84
|
+
"@nocobase/license-kit": "^0.3.8",
|
|
55
85
|
"@oclif/core": "^4.10.4",
|
|
56
86
|
"cross-spawn": "^7.0.6",
|
|
57
87
|
"lodash": "^4.17.21",
|
|
88
|
+
"mariadb": "^2.5.6",
|
|
89
|
+
"mysql2": "^3.14.0",
|
|
58
90
|
"openapi-types": "^12.1.3",
|
|
59
91
|
"ora": "^8.2.0",
|
|
60
|
-
"
|
|
92
|
+
"pg": "^8.14.1",
|
|
93
|
+
"picocolors": "^1.1.1",
|
|
94
|
+
"tar": "^7.4.3"
|
|
61
95
|
},
|
|
62
96
|
"devDependencies": {
|
|
63
97
|
"@types/node": "^18.19.130",
|
|
64
98
|
"tsx": "^4.20.6",
|
|
65
|
-
"typescript": "^6.0.2"
|
|
99
|
+
"typescript": "^6.0.2",
|
|
100
|
+
"vitest": "^1.5.0"
|
|
66
101
|
},
|
|
67
102
|
"repository": {
|
|
68
103
|
"type": "git",
|
|
69
104
|
"url": "git+https://github.com/nocobase/nocobase.git"
|
|
70
105
|
},
|
|
71
|
-
"gitHead": "
|
|
106
|
+
"gitHead": "a340a88d86d3ff7e06d723215b02aa3c122f4870"
|
|
72
107
|
}
|
package/dist/commands/ps.js
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
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, Flags } from '@oclif/core';
|
|
10
|
-
import { buildDockerDbContainerName, dockerContainerExists, dockerContainerIsRunning, formatMissingManagedAppEnvMessage, resolveManagedAppRuntime, } from '../lib/app-runtime.js';
|
|
11
|
-
import { listEnvs } from '../lib/auth-store.js';
|
|
12
|
-
import { renderTable } from '../lib/ui.js';
|
|
13
|
-
function resolveApiBaseUrl(config) {
|
|
14
|
-
return String(config.apiBaseUrl ?? config.baseUrl ?? config.apibaseUrl ?? '').trim();
|
|
15
|
-
}
|
|
16
|
-
function appUrl(runtime) {
|
|
17
|
-
const port = String(runtime.env.config.appPort ?? '').trim();
|
|
18
|
-
if (port) {
|
|
19
|
-
return `http://127.0.0.1:${port}`;
|
|
20
|
-
}
|
|
21
|
-
const baseUrl = resolveApiBaseUrl(runtime.env.config);
|
|
22
|
-
return baseUrl.replace(/\/api\/?$/, '');
|
|
23
|
-
}
|
|
24
|
-
async function isLocalAppHealthy(runtime) {
|
|
25
|
-
const port = String(runtime.env.config.appPort ?? '').trim();
|
|
26
|
-
if (!port) {
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
const controller = new AbortController();
|
|
30
|
-
const timeout = setTimeout(() => controller.abort(), 1500);
|
|
31
|
-
try {
|
|
32
|
-
const response = await fetch(`http://127.0.0.1:${port}/api/__health_check`, {
|
|
33
|
-
signal: controller.signal,
|
|
34
|
-
});
|
|
35
|
-
const text = await response.text();
|
|
36
|
-
return response.ok && text.trim().toLowerCase() === 'ok';
|
|
37
|
-
}
|
|
38
|
-
catch (_error) {
|
|
39
|
-
return false;
|
|
40
|
-
}
|
|
41
|
-
finally {
|
|
42
|
-
clearTimeout(timeout);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
async function dockerStatus(containerName) {
|
|
46
|
-
if (!(await dockerContainerExists(containerName))) {
|
|
47
|
-
return 'missing';
|
|
48
|
-
}
|
|
49
|
-
return await dockerContainerIsRunning(containerName) ? 'running' : 'stopped';
|
|
50
|
-
}
|
|
51
|
-
async function dbStatus(runtime) {
|
|
52
|
-
if (!runtime.env.config.builtinDb) {
|
|
53
|
-
return runtime.kind === 'http' ? 'external' : '-';
|
|
54
|
-
}
|
|
55
|
-
if (runtime.kind === 'http') {
|
|
56
|
-
return 'external';
|
|
57
|
-
}
|
|
58
|
-
if (runtime.kind === 'ssh') {
|
|
59
|
-
return '-';
|
|
60
|
-
}
|
|
61
|
-
const dbDialect = String(runtime.env.config.dbDialect ?? 'postgres').trim() || 'postgres';
|
|
62
|
-
const containerName = buildDockerDbContainerName(runtime.envName, dbDialect, runtime.workspaceName);
|
|
63
|
-
return await dockerStatus(containerName);
|
|
64
|
-
}
|
|
65
|
-
async function runtimeStatus(runtime) {
|
|
66
|
-
if (runtime.kind === 'http') {
|
|
67
|
-
return 'http';
|
|
68
|
-
}
|
|
69
|
-
if (runtime.kind === 'ssh') {
|
|
70
|
-
return 'ssh';
|
|
71
|
-
}
|
|
72
|
-
if (runtime.kind === 'docker') {
|
|
73
|
-
return await dockerStatus(runtime.containerName);
|
|
74
|
-
}
|
|
75
|
-
return await isLocalAppHealthy(runtime) ? 'running' : 'stopped';
|
|
76
|
-
}
|
|
77
|
-
export default class Ps extends Command {
|
|
78
|
-
static description = 'Show NocoBase runtime status for configured envs without starting or stopping anything.';
|
|
79
|
-
static examples = [
|
|
80
|
-
'<%= config.bin %> <%= command.id %>',
|
|
81
|
-
'<%= config.bin %> <%= command.id %> --env app1',
|
|
82
|
-
];
|
|
83
|
-
static flags = {
|
|
84
|
-
env: Flags.string({
|
|
85
|
-
char: 'e',
|
|
86
|
-
description: 'CLI env name to inspect. Omit to show all configured envs',
|
|
87
|
-
}),
|
|
88
|
-
};
|
|
89
|
-
async run() {
|
|
90
|
-
const { flags } = await this.parse(Ps);
|
|
91
|
-
const requestedEnv = flags.env?.trim() || undefined;
|
|
92
|
-
const envNames = requestedEnv
|
|
93
|
-
? [requestedEnv]
|
|
94
|
-
: Object.keys((await listEnvs()).envs).sort();
|
|
95
|
-
if (!envNames.length) {
|
|
96
|
-
this.log('No NocoBase env is configured yet. Run `nb init` to create one first.');
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
const rows = [];
|
|
100
|
-
for (const envName of envNames) {
|
|
101
|
-
const runtime = await resolveManagedAppRuntime(envName);
|
|
102
|
-
if (!runtime) {
|
|
103
|
-
if (requestedEnv) {
|
|
104
|
-
this.error(formatMissingManagedAppEnvMessage(envName));
|
|
105
|
-
}
|
|
106
|
-
rows.push([envName, '-', 'missing', '-', '']);
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
109
|
-
rows.push([
|
|
110
|
-
runtime.envName,
|
|
111
|
-
runtime.kind,
|
|
112
|
-
await runtimeStatus(runtime),
|
|
113
|
-
await dbStatus(runtime),
|
|
114
|
-
appUrl(runtime),
|
|
115
|
-
]);
|
|
116
|
-
}
|
|
117
|
-
this.log(renderTable(['Env', 'Kind', 'Status', 'Database', 'URL'], rows));
|
|
118
|
-
}
|
|
119
|
-
}
|