@nocobase/cli 2.1.0-beta.22 → 2.1.0-beta.23
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 +11 -5
- package/README.zh-CN.md +10 -4
- package/dist/commands/{app → env}/info.js +19 -7
- package/dist/commands/env/list.js +23 -9
- package/dist/commands/{app → env}/shared.js +70 -7
- package/dist/commands/init.js +8 -1
- package/dist/lib/api-client.js +20 -6
- package/dist/lib/prompt-web-ui.js +13 -6
- package/package.json +4 -4
- package/dist/commands/app/ps.js +0 -60
- package/dist/commands/ps.js +0 -12
package/README.md
CHANGED
|
@@ -115,7 +115,7 @@ nb init --env app1 --resume
|
|
|
115
115
|
|
|
116
116
|
`--resume` reuses the saved workspace env config for app, source, database, and env connection settings. In interactive mode, it only asks for any missing setup-only values.
|
|
117
117
|
|
|
118
|
-
In non-interactive mode,
|
|
118
|
+
In non-interactive resume mode, `nb init --resume --yes` uses default initialization values unless these flags are passed explicitly:
|
|
119
119
|
|
|
120
120
|
- `--lang`
|
|
121
121
|
- `--root-username`
|
|
@@ -128,7 +128,7 @@ In non-interactive mode, pass these setup-only flags again because they are not
|
|
|
128
128
|
| Command | Description |
|
|
129
129
|
| --- | --- |
|
|
130
130
|
| `nb init` | Set up NocoBase and connect it as a CLI env for coding agents. |
|
|
131
|
-
| `nb app` | Manage app runtimes: start, stop, restart, logs,
|
|
131
|
+
| `nb app` | Manage app runtimes: start, stop, restart, logs, cleanup, and upgrades. |
|
|
132
132
|
| `nb source` | Manage the local source project: download, develop, build, and test. |
|
|
133
133
|
| `nb db` | Inspect or manage built-in database runtime status for local envs. |
|
|
134
134
|
| `nb env` | Manage saved CLI env connections. |
|
|
@@ -137,13 +137,13 @@ In non-interactive mode, pass these setup-only flags again because they are not
|
|
|
137
137
|
| `nb self` | Check or update the installed NocoBase CLI. |
|
|
138
138
|
| `nb skills` | Check, install, or update global NocoBase AI coding skills. |
|
|
139
139
|
|
|
140
|
-
Recommended style:
|
|
140
|
+
Recommended style: pass the env name explicitly when operating on a specific env. Runtime commands accept `--env`, and `nb env info` also accepts a positional env name:
|
|
141
141
|
|
|
142
142
|
```bash
|
|
143
143
|
nb app start --env app1
|
|
144
144
|
nb app restart --env app1
|
|
145
145
|
nb app logs --env app1
|
|
146
|
-
nb
|
|
146
|
+
nb env info app1
|
|
147
147
|
nb db ps --env app1
|
|
148
148
|
```
|
|
149
149
|
|
|
@@ -291,12 +291,18 @@ Show the current env:
|
|
|
291
291
|
nb env
|
|
292
292
|
```
|
|
293
293
|
|
|
294
|
-
List configured envs:
|
|
294
|
+
List configured envs with token-verified API status:
|
|
295
295
|
|
|
296
296
|
```bash
|
|
297
297
|
nb env list
|
|
298
298
|
```
|
|
299
299
|
|
|
300
|
+
Show details for one env:
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
nb env info app1
|
|
304
|
+
```
|
|
305
|
+
|
|
300
306
|
Switch the current env:
|
|
301
307
|
|
|
302
308
|
```bash
|
package/README.zh-CN.md
CHANGED
|
@@ -110,7 +110,7 @@ nb init --env app1 --resume
|
|
|
110
110
|
|
|
111
111
|
`--resume` 会复用工作区里已保存的 env config,包括应用、source、数据库和 env 连接相关配置。在交互模式下,只会继续补齐缺失的初始化参数。
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
在非交互恢复模式下,如果没有显式传入这些参数,`nb init --resume --yes` 会使用默认初始化值:
|
|
114
114
|
|
|
115
115
|
- `--lang`
|
|
116
116
|
- `--root-username`
|
|
@@ -130,13 +130,13 @@ nb init --env app1 --resume
|
|
|
130
130
|
| `nb api` | 通过 CLI 调用 NocoBase API 资源。 |
|
|
131
131
|
| `nb plugin` | 管理选中 NocoBase env 的插件。 |
|
|
132
132
|
|
|
133
|
-
|
|
133
|
+
推荐在操作指定 env 时显式传入 env 名称。运行时命令支持 `--env`,`nb env info` 也支持位置参数:
|
|
134
134
|
|
|
135
135
|
```bash
|
|
136
136
|
nb app start --env app1
|
|
137
137
|
nb app restart --env app1
|
|
138
138
|
nb app logs --env app1
|
|
139
|
-
nb
|
|
139
|
+
nb env info app1
|
|
140
140
|
nb db ps --env app1
|
|
141
141
|
```
|
|
142
142
|
|
|
@@ -252,12 +252,18 @@ nb app down --env app1 --all --yes
|
|
|
252
252
|
nb env
|
|
253
253
|
```
|
|
254
254
|
|
|
255
|
-
查看已配置的 env
|
|
255
|
+
查看已配置的 env 及 Token 验证后的 API 状态:
|
|
256
256
|
|
|
257
257
|
```bash
|
|
258
258
|
nb env list
|
|
259
259
|
```
|
|
260
260
|
|
|
261
|
+
查看某个 env 的详情:
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
nb env info app1
|
|
265
|
+
```
|
|
266
|
+
|
|
261
267
|
切换当前 env:
|
|
262
268
|
|
|
263
269
|
```bash
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
|
-
import { Command, Flags } from '@oclif/core';
|
|
9
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
10
10
|
import { formatMissingManagedAppEnvMessage, resolveManagedAppRuntime } from '../../lib/app-runtime.js';
|
|
11
11
|
import { renderTable } from '../../lib/ui.js';
|
|
12
12
|
import { appRootPath, dbStatus, runtimeStatus, storagePath } from './shared.js';
|
|
@@ -42,14 +42,21 @@ function createGroupTable(title, values) {
|
|
|
42
42
|
function serializeGroup(values) {
|
|
43
43
|
return Object.fromEntries(Object.entries(values).map(([field, value]) => [field, normalizeJsonValue(value)]));
|
|
44
44
|
}
|
|
45
|
-
export default class
|
|
45
|
+
export default class EnvInfo extends Command {
|
|
46
46
|
static hidden = false;
|
|
47
|
-
static description = 'Show grouped details for the selected NocoBase
|
|
47
|
+
static description = 'Show grouped details for the selected NocoBase env, including app, database, API, and auth settings.';
|
|
48
48
|
static examples = [
|
|
49
|
+
'<%= config.bin %> <%= command.id %> app1',
|
|
50
|
+
'<%= config.bin %> <%= command.id %> app1 --json',
|
|
51
|
+
'<%= config.bin %> <%= command.id %> app1 --show-secrets',
|
|
49
52
|
'<%= config.bin %> <%= command.id %> --env app1',
|
|
50
|
-
'<%= config.bin %> <%= command.id %> --env app1 --json',
|
|
51
|
-
'<%= config.bin %> <%= command.id %> --env app1 --show-secrets',
|
|
52
53
|
];
|
|
54
|
+
static args = {
|
|
55
|
+
name: Args.string({
|
|
56
|
+
description: 'CLI env name to inspect. Defaults to the current env when omitted',
|
|
57
|
+
required: false,
|
|
58
|
+
}),
|
|
59
|
+
};
|
|
53
60
|
static flags = {
|
|
54
61
|
env: Flags.string({
|
|
55
62
|
char: 'e',
|
|
@@ -65,8 +72,13 @@ export default class AppInfo extends Command {
|
|
|
65
72
|
}),
|
|
66
73
|
};
|
|
67
74
|
async run() {
|
|
68
|
-
const { flags } = await this.parse(
|
|
69
|
-
const
|
|
75
|
+
const { args, flags } = await this.parse(EnvInfo);
|
|
76
|
+
const envNameArg = args.name?.trim() || undefined;
|
|
77
|
+
const envNameFlag = flags.env?.trim() || undefined;
|
|
78
|
+
if (envNameArg && envNameFlag && envNameArg !== envNameFlag) {
|
|
79
|
+
this.error(`Environment name was provided both as the argument ("${envNameArg}") and as --env ("${envNameFlag}"). Please use only one.`);
|
|
80
|
+
}
|
|
81
|
+
const requestedEnv = envNameArg || envNameFlag;
|
|
70
82
|
const showSecrets = flags['show-secrets'];
|
|
71
83
|
const runtime = await resolveManagedAppRuntime(requestedEnv);
|
|
72
84
|
if (!runtime) {
|
|
@@ -7,30 +7,44 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
import { Command } from '@oclif/core';
|
|
10
|
+
import { resolveManagedAppRuntime } from '../../lib/app-runtime.js';
|
|
10
11
|
import { listEnvs } from '../../lib/auth-store.js';
|
|
11
12
|
import { resolveDefaultConfigScope } from '../../lib/cli-home.js';
|
|
12
13
|
import { renderTable } from '../../lib/ui.js';
|
|
13
|
-
|
|
14
|
-
return String(config.apiBaseUrl ?? config.baseUrl ?? config.apibaseUrl ?? '').trim();
|
|
15
|
-
}
|
|
14
|
+
import { apiStatus, appUrl, resolveApiBaseUrl } from './shared.js';
|
|
16
15
|
export default class EnvList extends Command {
|
|
17
|
-
static summary = 'List configured environments';
|
|
16
|
+
static summary = 'List configured environments and API auth status';
|
|
18
17
|
static examples = [
|
|
19
18
|
'<%= config.bin %> <%= command.id %>',
|
|
20
19
|
];
|
|
21
20
|
async run() {
|
|
22
21
|
await this.parse(EnvList);
|
|
23
|
-
const
|
|
22
|
+
const scope = resolveDefaultConfigScope();
|
|
23
|
+
const { currentEnv, envs } = await listEnvs({ scope });
|
|
24
24
|
const names = Object.keys(envs).sort();
|
|
25
25
|
if (!names.length) {
|
|
26
26
|
this.log('No envs configured.');
|
|
27
27
|
this.log('Run `nb env add <name> --api-base-url <url>` to add one.');
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
|
-
const rows =
|
|
30
|
+
const rows = [];
|
|
31
|
+
for (const name of names) {
|
|
31
32
|
const env = envs[name];
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
const runtime = await resolveManagedAppRuntime(name);
|
|
34
|
+
const statusConfig = {
|
|
35
|
+
...env,
|
|
36
|
+
...(runtime?.env.config ?? {}),
|
|
37
|
+
};
|
|
38
|
+
rows.push([
|
|
39
|
+
name === currentEnv ? '*' : '',
|
|
40
|
+
name,
|
|
41
|
+
runtime?.kind ?? env.kind ?? '-',
|
|
42
|
+
await apiStatus(name, statusConfig, { scope }),
|
|
43
|
+
runtime ? appUrl(runtime) : resolveApiBaseUrl(env),
|
|
44
|
+
env.auth?.type ?? '',
|
|
45
|
+
env.runtime?.version ?? '',
|
|
46
|
+
]);
|
|
47
|
+
}
|
|
48
|
+
this.log(renderTable(['Current', 'Name', 'Kind', 'App Status', 'URL', 'Auth', 'Runtime'], rows));
|
|
35
49
|
}
|
|
36
50
|
}
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
|
-
import { buildDockerDbContainerName, dockerContainerExists, dockerContainerIsRunning,
|
|
9
|
+
import { buildDockerDbContainerName, dockerContainerExists, dockerContainerIsRunning, } from '../../lib/app-runtime.js';
|
|
10
|
+
import { executeRawApiRequest } from '../../lib/api-client.js';
|
|
10
11
|
export function resolveApiBaseUrl(config) {
|
|
11
12
|
return String(config.apiBaseUrl ?? config.baseUrl ?? config.apibaseUrl ?? '').trim();
|
|
12
13
|
}
|
|
@@ -18,12 +19,6 @@ export function appUrl(runtime) {
|
|
|
18
19
|
const baseUrl = resolveApiBaseUrl(runtime.env.config);
|
|
19
20
|
return baseUrl.replace(/\/api\/?$/, '');
|
|
20
21
|
}
|
|
21
|
-
export function appNetwork(runtime) {
|
|
22
|
-
if (runtime.kind === 'docker') {
|
|
23
|
-
return runtime.workspaceName?.trim() || defaultWorkspaceName();
|
|
24
|
-
}
|
|
25
|
-
return '-';
|
|
26
|
-
}
|
|
27
22
|
export function appRootPath(runtime) {
|
|
28
23
|
if (runtime.kind === 'http' || runtime.kind === 'docker') {
|
|
29
24
|
return '-';
|
|
@@ -40,6 +35,74 @@ export function storagePath(runtime) {
|
|
|
40
35
|
const value = String(runtime.env.storagePath ?? runtime.env.config.storagePath ?? '').trim();
|
|
41
36
|
return value || '-';
|
|
42
37
|
}
|
|
38
|
+
function collectErrorCodes(value) {
|
|
39
|
+
if (!value || typeof value !== 'object') {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
if (Array.isArray(value)) {
|
|
43
|
+
return value.flatMap((item) => collectErrorCodes(item));
|
|
44
|
+
}
|
|
45
|
+
const out = [];
|
|
46
|
+
const record = value;
|
|
47
|
+
if (typeof record.code === 'string') {
|
|
48
|
+
out.push(record.code);
|
|
49
|
+
}
|
|
50
|
+
for (const key of ['data', 'error', 'errors']) {
|
|
51
|
+
out.push(...collectErrorCodes(record[key]));
|
|
52
|
+
}
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
function isAuthFailureData(value) {
|
|
56
|
+
const codes = collectErrorCodes(value);
|
|
57
|
+
return codes.some((code) => ['EMPTY_TOKEN', 'INVALID_TOKEN', 'EXPIRED_TOKEN', 'BLOCKED_TOKEN', 'EXPIRED_SESSION', 'NOT_EXIST_USER'].includes(code));
|
|
58
|
+
}
|
|
59
|
+
function isNetworkFailure(error) {
|
|
60
|
+
if (!(error instanceof Error)) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
return (error.name === 'AbortError'
|
|
64
|
+
|| /fetch failed|network|timeout|timed out|abort|ECONNREFUSED|ECONNRESET|ENOTFOUND|ETIMEDOUT|EAI_AGAIN|ENETUNREACH/i.test(error.message));
|
|
65
|
+
}
|
|
66
|
+
function isUnconfiguredFailure(error) {
|
|
67
|
+
return error instanceof Error && /missing (a )?base url|missing base URL/i.test(error.message);
|
|
68
|
+
}
|
|
69
|
+
function isAuthFailure(error) {
|
|
70
|
+
return (error instanceof Error
|
|
71
|
+
&& /EMPTY_TOKEN|INVALID_TOKEN|EXPIRED_TOKEN|BLOCKED_TOKEN|EXPIRED_SESSION|NOT_EXIST_USER|invalid_grant|sign in|signin|authentication failed/i.test(error.message));
|
|
72
|
+
}
|
|
73
|
+
export async function apiStatus(envName, config, options = {}) {
|
|
74
|
+
if (!resolveApiBaseUrl(config)) {
|
|
75
|
+
return 'unconfigured';
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const response = await executeRawApiRequest({
|
|
79
|
+
envName,
|
|
80
|
+
scope: options.scope,
|
|
81
|
+
method: 'GET',
|
|
82
|
+
path: '/auth:check',
|
|
83
|
+
timeoutMs: options.timeoutMs ?? 2000,
|
|
84
|
+
});
|
|
85
|
+
if (response.ok) {
|
|
86
|
+
return 'ok';
|
|
87
|
+
}
|
|
88
|
+
if (response.status === 401 || response.status === 403 || isAuthFailureData(response.data)) {
|
|
89
|
+
return 'auth failed';
|
|
90
|
+
}
|
|
91
|
+
return 'error';
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
if (isUnconfiguredFailure(error)) {
|
|
95
|
+
return 'unconfigured';
|
|
96
|
+
}
|
|
97
|
+
if (isAuthFailure(error)) {
|
|
98
|
+
return 'auth failed';
|
|
99
|
+
}
|
|
100
|
+
if (isNetworkFailure(error)) {
|
|
101
|
+
return 'unreachable';
|
|
102
|
+
}
|
|
103
|
+
return 'error';
|
|
104
|
+
}
|
|
105
|
+
}
|
|
43
106
|
async function isLocalAppHealthy(runtime) {
|
|
44
107
|
const port = String(runtime.env.config.appPort ?? '').trim();
|
|
45
108
|
if (!port) {
|
package/dist/commands/init.js
CHANGED
|
@@ -139,6 +139,12 @@ function logInitUiReady(command, url) {
|
|
|
139
139
|
function logInitUiBrowserOpenFallback() {
|
|
140
140
|
p.log.warn(translateCli('commands.init.messages.uiOpenBrowserFallback'));
|
|
141
141
|
}
|
|
142
|
+
function formatBrowserOpenError(error) {
|
|
143
|
+
if (error instanceof Error) {
|
|
144
|
+
return error.message;
|
|
145
|
+
}
|
|
146
|
+
return String(error);
|
|
147
|
+
}
|
|
142
148
|
export default class Init extends Command {
|
|
143
149
|
static summary = 'Set up NocoBase so coding agents can connect and work with it';
|
|
144
150
|
static description = `Set up NocoBase for coding agents in the current workspace.
|
|
@@ -405,8 +411,9 @@ Prompt modes:
|
|
|
405
411
|
onServerStart: ({ url }) => {
|
|
406
412
|
logInitUiReady(this, url);
|
|
407
413
|
},
|
|
408
|
-
onOpenBrowserError: (_url,
|
|
414
|
+
onOpenBrowserError: (_url, err) => {
|
|
409
415
|
logInitUiBrowserOpenFallback();
|
|
416
|
+
p.log.info(`Browser open error: ${formatBrowserOpenError(err)}`);
|
|
410
417
|
},
|
|
411
418
|
});
|
|
412
419
|
}
|
package/dist/lib/api-client.js
CHANGED
|
@@ -235,10 +235,24 @@ export async function executeRawApiRequest(options) {
|
|
|
235
235
|
}
|
|
236
236
|
url.searchParams.set(key, typeof value === 'object' ? JSON.stringify(value) : String(value));
|
|
237
237
|
}
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
238
|
+
const controller = options.timeoutMs && options.timeoutMs > 0 ? new AbortController() : undefined;
|
|
239
|
+
const timeout = controller
|
|
240
|
+
? setTimeout(() => {
|
|
241
|
+
controller.abort();
|
|
242
|
+
}, options.timeoutMs)
|
|
243
|
+
: undefined;
|
|
244
|
+
try {
|
|
245
|
+
const response = await fetchWithPreservedAuthRedirect(url.toString(), {
|
|
246
|
+
method: options.method.toUpperCase(),
|
|
247
|
+
headers,
|
|
248
|
+
body: options.body === undefined ? undefined : JSON.stringify(options.body),
|
|
249
|
+
signal: controller?.signal,
|
|
250
|
+
});
|
|
251
|
+
return parseResponse(response);
|
|
252
|
+
}
|
|
253
|
+
finally {
|
|
254
|
+
if (timeout) {
|
|
255
|
+
clearTimeout(timeout);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
244
258
|
}
|
|
@@ -559,17 +559,23 @@ function readFormFromClientStrippingPwcMeta(o) {
|
|
|
559
559
|
const { [PWC_FORM_META_STEP]: _meta, ...rest } = o;
|
|
560
560
|
return rest;
|
|
561
561
|
}
|
|
562
|
-
function openUrlInDefaultBrowser(url) {
|
|
562
|
+
function openUrlInDefaultBrowser(url, onError) {
|
|
563
|
+
const reportError = (error) => {
|
|
564
|
+
onError?.(url, error);
|
|
565
|
+
};
|
|
563
566
|
const platform = process.platform;
|
|
567
|
+
let child;
|
|
564
568
|
if (platform === 'darwin') {
|
|
565
|
-
spawn('open', [url], { stdio: 'ignore', detached: true })
|
|
569
|
+
child = spawn('open', [url], { stdio: 'ignore', detached: true });
|
|
566
570
|
}
|
|
567
571
|
else if (platform === 'win32') {
|
|
568
|
-
spawn('cmd', ['/c', 'start', '', url], { stdio: 'ignore', detached: true, windowsHide: true })
|
|
572
|
+
child = spawn('cmd', ['/c', 'start', '', url], { stdio: 'ignore', detached: true, windowsHide: true });
|
|
569
573
|
}
|
|
570
574
|
else {
|
|
571
|
-
spawn('xdg-open', [url], { stdio: 'ignore', detached: true })
|
|
575
|
+
child = spawn('xdg-open', [url], { stdio: 'ignore', detached: true });
|
|
572
576
|
}
|
|
577
|
+
child.once('error', reportError);
|
|
578
|
+
child.unref();
|
|
573
579
|
}
|
|
574
580
|
function closePromptWebUiServer(server, done) {
|
|
575
581
|
server.close(done);
|
|
@@ -2084,11 +2090,12 @@ function runPromptCatalogWebUIImpl(options) {
|
|
|
2084
2090
|
const port = addr.port;
|
|
2085
2091
|
const startUrl = `http://${host}:${port}/`;
|
|
2086
2092
|
options.onServerStart?.({ host, port, url: startUrl });
|
|
2093
|
+
const onOpenBrowserError = options.onOpenBrowserError ?? ((u, err) => console.warn(String(err), u));
|
|
2087
2094
|
try {
|
|
2088
|
-
openUrlInDefaultBrowser(startUrl);
|
|
2095
|
+
openUrlInDefaultBrowser(startUrl, onOpenBrowserError);
|
|
2089
2096
|
}
|
|
2090
2097
|
catch (e) {
|
|
2091
|
-
|
|
2098
|
+
onOpenBrowserError(startUrl, e);
|
|
2092
2099
|
}
|
|
2093
2100
|
timeoutId = setTimeout(() => rejectAndClose(new Error('Local UI timeout — close the tab and try again, or resubmit within the time limit.')), timeoutMs);
|
|
2094
2101
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/cli",
|
|
3
|
-
"version": "2.1.0-beta.
|
|
3
|
+
"version": "2.1.0-beta.23",
|
|
4
4
|
"description": "NocoBase Command Line Tool",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/generated/command-registry.js",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"topicSeparator": " ",
|
|
38
38
|
"topics": {
|
|
39
39
|
"app": {
|
|
40
|
-
"description": "Manage NocoBase app runtimes: start, stop, restart, logs,
|
|
40
|
+
"description": "Manage NocoBase app runtimes: start, stop, restart, logs, and upgrades."
|
|
41
41
|
},
|
|
42
42
|
"source": {
|
|
43
43
|
"description": "Work with the local NocoBase source project: download, develop, build, and test."
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"description": "Manage the built-in database for the selected env."
|
|
57
57
|
},
|
|
58
58
|
"env": {
|
|
59
|
-
"description": "Manage NocoBase project environments and
|
|
59
|
+
"description": "Manage NocoBase project environments, status, details, and command runtimes."
|
|
60
60
|
},
|
|
61
61
|
"self": {
|
|
62
62
|
"description": "Inspect or update the NocoBase CLI itself."
|
|
@@ -91,5 +91,5 @@
|
|
|
91
91
|
"type": "git",
|
|
92
92
|
"url": "git+https://github.com/nocobase/nocobase.git"
|
|
93
93
|
},
|
|
94
|
-
"gitHead": "
|
|
94
|
+
"gitHead": "bb4c0d3551bf9eff505b63756dd24a0813231f16"
|
|
95
95
|
}
|
package/dist/commands/app/ps.js
DELETED
|
@@ -1,60 +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 { formatMissingManagedAppEnvMessage, resolveManagedAppRuntime, } from '../../lib/app-runtime.js';
|
|
11
|
-
import { listEnvs } from '../../lib/auth-store.js';
|
|
12
|
-
import { renderTable } from '../../lib/ui.js';
|
|
13
|
-
import { appNetwork, appRootPath, appUrl, dbStatus, runtimeStatus, storagePath } from './shared.js';
|
|
14
|
-
export default class AppPs extends Command {
|
|
15
|
-
static hidden = false;
|
|
16
|
-
static description = 'Show NocoBase runtime status for configured envs without starting or stopping anything.';
|
|
17
|
-
static examples = [
|
|
18
|
-
'<%= config.bin %> <%= command.id %>',
|
|
19
|
-
'<%= config.bin %> <%= command.id %> --env app1',
|
|
20
|
-
];
|
|
21
|
-
static flags = {
|
|
22
|
-
env: Flags.string({
|
|
23
|
-
char: 'e',
|
|
24
|
-
description: 'CLI env name to inspect. Omit to show all configured envs',
|
|
25
|
-
}),
|
|
26
|
-
};
|
|
27
|
-
async run() {
|
|
28
|
-
const { flags } = await this.parse(AppPs);
|
|
29
|
-
const requestedEnv = flags.env?.trim() || undefined;
|
|
30
|
-
const envNames = requestedEnv
|
|
31
|
-
? [requestedEnv]
|
|
32
|
-
: Object.keys((await listEnvs()).envs).sort();
|
|
33
|
-
if (!envNames.length) {
|
|
34
|
-
this.log('No NocoBase env is configured yet. Run `nb init` to create one first.');
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
const rows = [];
|
|
38
|
-
for (const envName of envNames) {
|
|
39
|
-
const runtime = await resolveManagedAppRuntime(envName);
|
|
40
|
-
if (!runtime) {
|
|
41
|
-
if (requestedEnv) {
|
|
42
|
-
this.error(formatMissingManagedAppEnvMessage(envName));
|
|
43
|
-
}
|
|
44
|
-
rows.push([envName, '-', 'missing', '-', '-', '-', '-', '']);
|
|
45
|
-
continue;
|
|
46
|
-
}
|
|
47
|
-
rows.push([
|
|
48
|
-
runtime.envName,
|
|
49
|
-
runtime.kind,
|
|
50
|
-
await runtimeStatus(runtime),
|
|
51
|
-
await dbStatus(runtime),
|
|
52
|
-
appNetwork(runtime),
|
|
53
|
-
appRootPath(runtime),
|
|
54
|
-
storagePath(runtime),
|
|
55
|
-
appUrl(runtime),
|
|
56
|
-
]);
|
|
57
|
-
}
|
|
58
|
-
this.log(renderTable(['Env', 'Kind', 'App Status', 'Database Status', 'Network', 'App Root', 'Storage', 'URL'], rows));
|
|
59
|
-
}
|
|
60
|
-
}
|
package/dist/commands/ps.js
DELETED
|
@@ -1,12 +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 AppPs from './app/ps.js';
|
|
10
|
-
export default class Ps extends AppPs {
|
|
11
|
-
static hidden = true;
|
|
12
|
-
}
|