@nocobase/cli 2.1.0-beta.9 → 2.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/assets/env-proxy/nginx/app.conf.tpl +23 -0
- package/assets/env-proxy/nginx/nocobase.conf.tpl +5 -0
- package/assets/env-proxy/nginx/snippets/dist-location.conf +5 -0
- package/assets/env-proxy/nginx/snippets/gzip.conf +17 -0
- package/assets/env-proxy/nginx/snippets/log-format-http.conf +13 -0
- package/assets/env-proxy/nginx/snippets/maps-http.conf +14 -0
- package/assets/env-proxy/nginx/snippets/mime-types.conf +98 -0
- package/assets/env-proxy/nginx/snippets/proxy-location.conf +17 -0
- package/assets/env-proxy/nginx/snippets/spa-location.conf +6 -0
- package/assets/env-proxy/nginx/snippets/uploads-location.conf +21 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +145 -0
- package/bin/session-env.js +39 -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/app/autostart/disable.js +55 -0
- package/dist/commands/app/autostart/enable.js +55 -0
- package/dist/commands/app/autostart/list.js +37 -0
- package/dist/commands/app/autostart/run.js +84 -0
- package/dist/commands/app/autostart/shared.js +49 -0
- package/dist/commands/app/destroy.js +234 -0
- package/dist/commands/app/down.js +71 -0
- package/dist/commands/app/logs.js +115 -0
- package/dist/commands/app/restart.js +229 -0
- package/dist/commands/app/shared.js +123 -0
- package/dist/commands/app/start.js +416 -0
- package/dist/commands/app/stop.js +183 -0
- package/dist/commands/app/upgrade.js +523 -0
- package/dist/commands/backup/create.js +147 -0
- package/dist/commands/backup/index.js +20 -0
- package/dist/commands/backup/restore.js +105 -0
- package/{src/cli.js → dist/commands/build.js} +4 -11
- package/dist/commands/config/delete.js +42 -0
- package/dist/commands/config/get.js +39 -0
- package/dist/commands/config/index.js +20 -0
- package/dist/commands/config/list.js +29 -0
- package/dist/commands/config/set.js +49 -0
- package/dist/commands/db/check.js +240 -0
- package/dist/commands/db/logs.js +85 -0
- package/dist/commands/db/ps.js +47 -0
- package/dist/commands/db/shared.js +96 -0
- package/dist/commands/db/start.js +86 -0
- package/dist/commands/db/stop.js +71 -0
- package/{templates/plugin/src/client/models/index.ts → dist/commands/dev.js} +4 -4
- package/{src/commands/locale/react-js-cron/index.js → dist/commands/down.js} +3 -8
- package/dist/commands/download.js +13 -0
- package/dist/commands/env/add.js +406 -0
- package/dist/commands/env/auth.js +189 -0
- package/dist/commands/env/current.js +21 -0
- package/dist/commands/env/info.js +202 -0
- package/dist/commands/env/list.js +43 -0
- package/dist/commands/env/remove.js +174 -0
- package/dist/commands/env/shared.js +204 -0
- package/dist/commands/env/status.js +93 -0
- package/dist/commands/env/update.js +448 -0
- package/dist/commands/env/use.js +38 -0
- package/dist/commands/examples/prompts-stages.js +150 -0
- package/dist/commands/examples/prompts-test.js +181 -0
- package/dist/commands/init.js +1390 -0
- package/dist/commands/install.js +2609 -0
- package/dist/commands/license/activate.js +179 -0
- package/dist/commands/license/env.js +94 -0
- package/dist/commands/license/generate-id.js +108 -0
- package/dist/commands/license/id.js +70 -0
- package/dist/commands/license/index.js +20 -0
- package/dist/commands/license/plugins/clean.js +115 -0
- package/dist/commands/license/plugins/index.js +20 -0
- package/dist/commands/license/plugins/list.js +64 -0
- package/dist/commands/license/plugins/shared.js +382 -0
- package/dist/commands/license/plugins/sync.js +314 -0
- package/dist/commands/license/shared.js +423 -0
- package/dist/commands/license/status.js +64 -0
- package/dist/commands/logs.js +12 -0
- package/dist/commands/plugin/disable.js +86 -0
- package/dist/commands/plugin/enable.js +86 -0
- package/dist/commands/plugin/import.js +108 -0
- package/dist/commands/plugin/list.js +82 -0
- package/dist/commands/pm/disable.js +12 -0
- package/dist/commands/pm/enable.js +12 -0
- package/dist/commands/pm/list.js +12 -0
- package/dist/commands/proxy/caddy/current.js +17 -0
- package/dist/commands/proxy/caddy/generate.js +69 -0
- package/dist/commands/proxy/caddy/index.js +28 -0
- package/dist/commands/proxy/caddy/info.js +31 -0
- package/dist/commands/proxy/caddy/reload.js +30 -0
- package/dist/commands/proxy/caddy/restart.js +28 -0
- package/dist/commands/proxy/caddy/start.js +30 -0
- package/dist/commands/proxy/caddy/status.js +19 -0
- package/dist/commands/proxy/caddy/stop.js +30 -0
- package/dist/commands/proxy/caddy/use.js +26 -0
- package/dist/commands/proxy/index.js +28 -0
- package/dist/commands/proxy/nginx/current.js +18 -0
- package/dist/commands/proxy/nginx/generate.js +68 -0
- package/dist/commands/proxy/nginx/index.js +28 -0
- package/dist/commands/proxy/nginx/info.js +34 -0
- package/dist/commands/proxy/nginx/reload.js +30 -0
- package/dist/commands/proxy/nginx/restart.js +28 -0
- package/dist/commands/proxy/nginx/start.js +30 -0
- package/dist/commands/proxy/nginx/status.js +19 -0
- package/dist/commands/proxy/nginx/stop.js +30 -0
- package/dist/commands/proxy/nginx/use.js +31 -0
- package/dist/commands/restart.js +12 -0
- package/dist/commands/revision/create.js +118 -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 +152 -0
- package/dist/commands/session/id.js +24 -0
- package/dist/commands/session/remove.js +57 -0
- package/dist/commands/session/setup.js +62 -0
- package/dist/commands/skills/check.js +69 -0
- package/dist/commands/skills/index.js +20 -0
- package/dist/commands/skills/install.js +80 -0
- package/dist/commands/skills/remove.js +80 -0
- package/dist/commands/skills/update.js +87 -0
- package/dist/commands/source/build.js +58 -0
- package/dist/commands/source/dev.js +182 -0
- package/dist/commands/source/download.js +884 -0
- package/dist/commands/source/publish.js +109 -0
- package/dist/commands/source/registry/logs.js +70 -0
- package/dist/commands/source/registry/start.js +57 -0
- package/dist/commands/source/registry/status.js +33 -0
- package/dist/commands/source/registry/stop.js +48 -0
- package/dist/commands/source/test.js +476 -0
- package/dist/commands/start.js +12 -0
- package/dist/commands/stop.js +12 -0
- package/dist/commands/test.js +12 -0
- package/dist/commands/upgrade.js +12 -0
- package/dist/commands/v1.js +210 -0
- package/dist/generated/command-registry.js +134 -0
- package/dist/help/runtime-help.js +23 -0
- package/dist/lib/api-client.js +335 -0
- package/dist/lib/api-command-compat.js +641 -0
- package/dist/lib/app-health.js +139 -0
- package/dist/lib/app-managed-resources.js +337 -0
- package/dist/lib/app-public-path.js +80 -0
- package/dist/lib/app-runtime.js +189 -0
- package/dist/lib/auth-store.js +528 -0
- package/dist/lib/backup.js +171 -0
- package/dist/lib/bootstrap.js +409 -0
- package/dist/lib/build-config.js +18 -0
- package/dist/lib/builtin-db.js +86 -0
- package/dist/lib/cli-config.js +569 -0
- package/dist/lib/cli-entry-error.js +52 -0
- package/dist/lib/cli-home.js +47 -0
- package/dist/lib/cli-locale.js +141 -0
- package/dist/lib/command-discovery.js +39 -0
- package/dist/lib/command-log.js +284 -0
- package/dist/lib/db-connection-check.js +219 -0
- package/dist/lib/docker-env-file.js +60 -0
- package/dist/lib/docker-image.js +37 -0
- package/dist/lib/docker-log-stream.js +45 -0
- package/dist/lib/env-auth.js +963 -0
- package/dist/lib/env-command-config.js +45 -0
- package/dist/lib/env-config.js +108 -0
- package/dist/lib/env-guard.js +61 -0
- package/dist/lib/env-paths.js +101 -0
- package/dist/lib/env-proxy.js +1325 -0
- package/dist/lib/generated-command.js +203 -0
- package/dist/lib/http-request.js +49 -0
- package/dist/lib/inquirer-theme.js +17 -0
- package/dist/lib/inquirer.js +243 -0
- package/dist/lib/managed-env-file.js +101 -0
- package/dist/lib/managed-init-env.js +32 -0
- package/dist/lib/naming.js +70 -0
- package/dist/lib/object-utils.js +76 -0
- package/dist/lib/openapi.js +62 -0
- package/dist/lib/plugin-import.js +279 -0
- package/dist/lib/plugin-storage.js +64 -0
- package/dist/lib/post-processors.js +23 -0
- package/dist/lib/prompt-catalog-core.js +186 -0
- package/dist/lib/prompt-catalog-terminal.js +374 -0
- package/{src/index.js → dist/lib/prompt-catalog.js} +2 -6
- package/dist/lib/prompt-validators.js +278 -0
- package/dist/lib/prompt-web-ui.js +2234 -0
- package/dist/lib/proxy-caddy.js +274 -0
- package/dist/lib/proxy-nginx.js +330 -0
- package/dist/lib/resource-command.js +357 -0
- package/dist/lib/resource-request.js +104 -0
- package/dist/lib/run-npm.js +429 -0
- package/dist/lib/runtime-env-vars.js +32 -0
- package/dist/lib/runtime-generator.js +498 -0
- package/dist/lib/runtime-store.js +56 -0
- package/dist/lib/self-manager.js +301 -0
- package/dist/lib/session-id.js +17 -0
- package/dist/lib/session-integration.js +703 -0
- package/dist/lib/session-store.js +118 -0
- package/dist/lib/skills-manager.js +438 -0
- package/dist/lib/source-publish.js +326 -0
- package/dist/lib/source-registry.js +188 -0
- package/dist/lib/startup-update.js +309 -0
- package/dist/lib/ui.js +159 -0
- package/dist/locale/en-US.json +526 -0
- package/dist/locale/zh-CN.json +526 -0
- package/dist/post-processors/data-modeling.js +84 -0
- package/dist/post-processors/data-source-manager.js +138 -0
- package/dist/post-processors/index.js +19 -0
- package/nocobase-ctl.config.json +388 -0
- package/package.json +128 -24
- package/scripts/build.mjs +34 -0
- package/scripts/clean.mjs +9 -0
- package/tsconfig.json +19 -0
- package/bin/index.js +0 -39
- package/nocobase.conf.tpl +0 -95
- 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/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/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/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
|
@@ -0,0 +1,93 @@
|
|
|
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 { formatMissingManagedAppEnvMessage, resolveManagedAppRuntime } from '../../lib/app-runtime.js';
|
|
11
|
+
import { getCurrentEnvName, listEnvs } from '../../lib/auth-store.js';
|
|
12
|
+
import { resolveDefaultConfigScope } from '../../lib/cli-home.js';
|
|
13
|
+
import { translateCli } from '../../lib/cli-locale.js';
|
|
14
|
+
import { renderTable } from '../../lib/ui.js';
|
|
15
|
+
import { apiStatus, runtimeStatus } from './shared.js';
|
|
16
|
+
export default class EnvStatus extends Command {
|
|
17
|
+
static summary = 'Show application runtime status for the current env, one env, or all envs';
|
|
18
|
+
static examples = [
|
|
19
|
+
'<%= config.bin %> <%= command.id %>',
|
|
20
|
+
'<%= config.bin %> <%= command.id %> app1',
|
|
21
|
+
'<%= config.bin %> <%= command.id %> --all',
|
|
22
|
+
'<%= config.bin %> <%= command.id %> --all --json-output',
|
|
23
|
+
];
|
|
24
|
+
static args = {
|
|
25
|
+
name: Args.string({
|
|
26
|
+
description: 'Configured environment name to inspect. Defaults to the current env when omitted; cannot be used with --all',
|
|
27
|
+
required: false,
|
|
28
|
+
}),
|
|
29
|
+
};
|
|
30
|
+
static flags = {
|
|
31
|
+
all: Flags.boolean({
|
|
32
|
+
description: 'Show status for all configured envs',
|
|
33
|
+
default: false,
|
|
34
|
+
}),
|
|
35
|
+
'json-output': Flags.boolean({
|
|
36
|
+
description: 'Output the result as JSON',
|
|
37
|
+
default: false,
|
|
38
|
+
}),
|
|
39
|
+
};
|
|
40
|
+
async run() {
|
|
41
|
+
const { args, flags } = await this.parse(EnvStatus);
|
|
42
|
+
const scope = resolveDefaultConfigScope();
|
|
43
|
+
const requestedEnv = args.name?.trim() || undefined;
|
|
44
|
+
if (requestedEnv && flags.all) {
|
|
45
|
+
this.error('`nb env status <name>` and `nb env status --all` cannot be used together.');
|
|
46
|
+
}
|
|
47
|
+
const { envs } = await listEnvs({ scope });
|
|
48
|
+
const configuredEnvNames = Object.keys(envs).sort();
|
|
49
|
+
if (!configuredEnvNames.length) {
|
|
50
|
+
this.log(translateCli('commands.env.messages.noEnvsConfigured'));
|
|
51
|
+
this.log(translateCli('commands.env.messages.noEnvsConfiguredHelp'));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const envNames = flags.all ? configuredEnvNames : [requestedEnv || (await getCurrentEnvName({ scope }))];
|
|
55
|
+
const rows = [];
|
|
56
|
+
for (const envName of envNames) {
|
|
57
|
+
const runtime = await resolveManagedAppRuntime(envName);
|
|
58
|
+
if (!runtime) {
|
|
59
|
+
if (!flags.all) {
|
|
60
|
+
this.error(formatMissingManagedAppEnvMessage(envName));
|
|
61
|
+
}
|
|
62
|
+
rows.push({
|
|
63
|
+
env: envName,
|
|
64
|
+
status: 'missing',
|
|
65
|
+
apiBaseUrl: '',
|
|
66
|
+
});
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const status = runtime.kind === 'http' || runtime.kind === 'ssh'
|
|
70
|
+
? await apiStatus(envName, {
|
|
71
|
+
...envs[envName],
|
|
72
|
+
...(runtime.env.config ?? {}),
|
|
73
|
+
}, { scope })
|
|
74
|
+
: await runtimeStatus(runtime);
|
|
75
|
+
rows.push({
|
|
76
|
+
env: runtime.envName,
|
|
77
|
+
status,
|
|
78
|
+
apiBaseUrl: runtime.env.apiBaseUrl ||
|
|
79
|
+
String(runtime.env.config.apiBaseUrl ??
|
|
80
|
+
runtime.env.config.baseUrl ??
|
|
81
|
+
envs[envName]?.apiBaseUrl ??
|
|
82
|
+
envs[envName]?.baseUrl ??
|
|
83
|
+
'').trim(),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (flags['json-output']) {
|
|
87
|
+
this.log(JSON.stringify(flags.all ? rows : rows[0], null, 2));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const tableRows = rows.map((row) => [row.env, row.status, row.apiBaseUrl]);
|
|
91
|
+
this.log(renderTable(['Env', 'Status', 'API Base URL'], tableRows));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,448 @@
|
|
|
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 path from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
12
|
+
import { getCurrentEnvName, getEnv, replaceEnvConfig } from '../../lib/auth-store.js';
|
|
13
|
+
import { updateEnvRuntime } from '../../lib/bootstrap.js';
|
|
14
|
+
import { resolveDefaultConfigScope } from '../../lib/cli-home.js';
|
|
15
|
+
import { appendDiagnosticLogPath } from '../../lib/cli-entry-error.js';
|
|
16
|
+
import { getActiveCommandLogFile } from '../../lib/command-log.js';
|
|
17
|
+
import { ENV_BOOLEAN_CONFIG_FLAG_MAP, ENV_STRING_CONFIG_FLAG_MAP } from '../../lib/env-command-config.js';
|
|
18
|
+
import { buildStoredEnvConfig } from '../../lib/env-config.js';
|
|
19
|
+
import { validateApiBaseUrl } from '../../lib/prompt-validators.js';
|
|
20
|
+
import { failTask, printInfo, printVerbose, printWarningBlock, setVerboseMode, startTask, stopTask, succeedTask, } from '../../lib/ui.js';
|
|
21
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
22
|
+
function throwValidationError(message) {
|
|
23
|
+
throw new Error(appendDiagnosticLogPath(message, getActiveCommandLogFile()));
|
|
24
|
+
}
|
|
25
|
+
const UPDATE_STRING_FLAGS = [
|
|
26
|
+
'source',
|
|
27
|
+
'download-version',
|
|
28
|
+
'docker-registry',
|
|
29
|
+
'docker-platform',
|
|
30
|
+
'git-url',
|
|
31
|
+
'npm-registry',
|
|
32
|
+
'app-path',
|
|
33
|
+
'app-root-path',
|
|
34
|
+
'storage-path',
|
|
35
|
+
'app-public-path',
|
|
36
|
+
'cdn-base-url',
|
|
37
|
+
'env-file',
|
|
38
|
+
'app-port',
|
|
39
|
+
'app-key',
|
|
40
|
+
'timezone',
|
|
41
|
+
'db-dialect',
|
|
42
|
+
'builtin-db-image',
|
|
43
|
+
'db-host',
|
|
44
|
+
'db-port',
|
|
45
|
+
'db-database',
|
|
46
|
+
'db-user',
|
|
47
|
+
'db-password',
|
|
48
|
+
'db-schema',
|
|
49
|
+
'db-table-prefix',
|
|
50
|
+
];
|
|
51
|
+
const UPDATE_BOOLEAN_FLAGS = ['builtin-db', 'dev-dependencies', 'build', 'build-dts', 'db-underscored'];
|
|
52
|
+
const UPDATE_SPECIAL_FIELDS = ['api-base-url', 'auth-type', 'access-token', 'username'];
|
|
53
|
+
const UNSETTABLE_FIELDS = new Set([...UPDATE_SPECIAL_FIELDS, ...UPDATE_STRING_FLAGS, ...UPDATE_BOOLEAN_FLAGS]);
|
|
54
|
+
const SOURCE_SETTING_FIELDS = new Set([
|
|
55
|
+
'source',
|
|
56
|
+
'download-version',
|
|
57
|
+
'docker-registry',
|
|
58
|
+
'docker-platform',
|
|
59
|
+
'git-url',
|
|
60
|
+
'npm-registry',
|
|
61
|
+
'dev-dependencies',
|
|
62
|
+
'build',
|
|
63
|
+
'build-dts',
|
|
64
|
+
]);
|
|
65
|
+
const APP_RESTART_FIELDS = new Set([
|
|
66
|
+
'app-path',
|
|
67
|
+
'app-root-path',
|
|
68
|
+
'storage-path',
|
|
69
|
+
'app-public-path',
|
|
70
|
+
'env-file',
|
|
71
|
+
'app-port',
|
|
72
|
+
'app-key',
|
|
73
|
+
'timezone',
|
|
74
|
+
'db-host',
|
|
75
|
+
'db-port',
|
|
76
|
+
'db-database',
|
|
77
|
+
'db-user',
|
|
78
|
+
'db-password',
|
|
79
|
+
'db-schema',
|
|
80
|
+
'db-table-prefix',
|
|
81
|
+
'db-underscored',
|
|
82
|
+
]);
|
|
83
|
+
const APP_RESTART_WITH_DB_FIELDS = new Set([
|
|
84
|
+
'builtin-db',
|
|
85
|
+
'db-dialect',
|
|
86
|
+
'builtin-db-image',
|
|
87
|
+
'db-port',
|
|
88
|
+
'db-database',
|
|
89
|
+
'db-user',
|
|
90
|
+
'db-password',
|
|
91
|
+
'storage-path',
|
|
92
|
+
]);
|
|
93
|
+
const __dirnameConfigFile = path.join(path.dirname(path.dirname(path.dirname(__dirname))), 'nocobase-ctl.config.json');
|
|
94
|
+
function hasTokenOverride(flags) {
|
|
95
|
+
return flags['access-token'] !== undefined || flags.token !== undefined;
|
|
96
|
+
}
|
|
97
|
+
function collectProvidedConfigFields(flags) {
|
|
98
|
+
const fields = new Set();
|
|
99
|
+
for (const field of UPDATE_SPECIAL_FIELDS) {
|
|
100
|
+
if (field === 'access-token') {
|
|
101
|
+
if (hasTokenOverride(flags)) {
|
|
102
|
+
fields.add(field);
|
|
103
|
+
}
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (flags[field] !== undefined) {
|
|
107
|
+
fields.add(field);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
for (const field of UPDATE_STRING_FLAGS) {
|
|
111
|
+
if (flags[field] !== undefined) {
|
|
112
|
+
fields.add(field);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
for (const field of UPDATE_BOOLEAN_FLAGS) {
|
|
116
|
+
if (flags[field] !== undefined) {
|
|
117
|
+
fields.add(field);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return fields;
|
|
121
|
+
}
|
|
122
|
+
function normalizeUnsetFields(unset) {
|
|
123
|
+
const normalized = (unset ?? [])
|
|
124
|
+
.flatMap((value) => value.split(','))
|
|
125
|
+
.map((value) => value.trim())
|
|
126
|
+
.filter(Boolean);
|
|
127
|
+
for (const field of normalized) {
|
|
128
|
+
if (!UNSETTABLE_FIELDS.has(field)) {
|
|
129
|
+
throw new Error(`Unsupported --unset field "${field}". Supported fields: ${Array.from(UNSETTABLE_FIELDS).sort().join(', ')}.`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return Array.from(new Set(normalized));
|
|
133
|
+
}
|
|
134
|
+
function buildCurrentConfigInput(env) {
|
|
135
|
+
return {
|
|
136
|
+
...env.config,
|
|
137
|
+
apiBaseUrl: env.apiBaseUrl,
|
|
138
|
+
authType: env.authType,
|
|
139
|
+
authUsername: env.config.authUsername,
|
|
140
|
+
accessToken: env.auth?.type === 'token' ? env.auth.accessToken : undefined,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function applyUnsetField(nextInput, field) {
|
|
144
|
+
switch (field) {
|
|
145
|
+
case 'api-base-url':
|
|
146
|
+
delete nextInput.apiBaseUrl;
|
|
147
|
+
return;
|
|
148
|
+
case 'auth-type':
|
|
149
|
+
delete nextInput.authType;
|
|
150
|
+
return;
|
|
151
|
+
case 'access-token':
|
|
152
|
+
delete nextInput.accessToken;
|
|
153
|
+
return;
|
|
154
|
+
case 'username':
|
|
155
|
+
delete nextInput.authUsername;
|
|
156
|
+
return;
|
|
157
|
+
default:
|
|
158
|
+
if (field in ENV_STRING_CONFIG_FLAG_MAP) {
|
|
159
|
+
delete nextInput[ENV_STRING_CONFIG_FLAG_MAP[field]];
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (field in ENV_BOOLEAN_CONFIG_FLAG_MAP) {
|
|
163
|
+
delete nextInput[ENV_BOOLEAN_CONFIG_FLAG_MAP[field]];
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
export default class EnvUpdate extends Command {
|
|
168
|
+
static summary = 'Refresh an environment runtime from swagger:get, or update the saved env config for one environment';
|
|
169
|
+
static examples = [
|
|
170
|
+
'<%= config.bin %> <%= command.id %>',
|
|
171
|
+
'<%= config.bin %> <%= command.id %> prod',
|
|
172
|
+
'<%= config.bin %> <%= command.id %> prod --api-base-url http://localhost:13000/api --access-token <token>',
|
|
173
|
+
'<%= config.bin %> <%= command.id %> local --app-port 13080 --timezone Asia/Shanghai',
|
|
174
|
+
'<%= config.bin %> <%= command.id %> local --cdn-base-url https://cdn.example.com/nocobase/',
|
|
175
|
+
'<%= config.bin %> <%= command.id %> local --unset git-url --unset npm-registry',
|
|
176
|
+
];
|
|
177
|
+
static args = {
|
|
178
|
+
name: Args.string({
|
|
179
|
+
description: 'Configured environment name to update. Defaults to the current env when omitted',
|
|
180
|
+
required: false,
|
|
181
|
+
}),
|
|
182
|
+
};
|
|
183
|
+
static flags = {
|
|
184
|
+
verbose: Flags.boolean({
|
|
185
|
+
description: 'Show detailed progress output',
|
|
186
|
+
default: false,
|
|
187
|
+
}),
|
|
188
|
+
'api-base-url': Flags.string({
|
|
189
|
+
char: 'u',
|
|
190
|
+
description: 'Root URL for HTTP API calls, including the /api prefix (e.g. http://localhost:13000/api)',
|
|
191
|
+
}),
|
|
192
|
+
'auth-type': Flags.string({
|
|
193
|
+
description: 'Authentication: basic, token, or oauth',
|
|
194
|
+
options: ['basic', 'token', 'oauth'],
|
|
195
|
+
}),
|
|
196
|
+
'access-token': Flags.string({
|
|
197
|
+
char: 't',
|
|
198
|
+
aliases: ['token'],
|
|
199
|
+
description: 'API key or access token for token-based authentication',
|
|
200
|
+
}),
|
|
201
|
+
username: Flags.string({
|
|
202
|
+
description: 'Username to save for basic authentication',
|
|
203
|
+
}),
|
|
204
|
+
source: Flags.string({
|
|
205
|
+
description: 'Saved application source type for this env',
|
|
206
|
+
options: ['docker', 'git', 'local', 'npm'],
|
|
207
|
+
}),
|
|
208
|
+
'download-version': Flags.string({
|
|
209
|
+
aliases: ['version'],
|
|
210
|
+
description: 'Saved downloaded app version for this env',
|
|
211
|
+
}),
|
|
212
|
+
'docker-registry': Flags.string({
|
|
213
|
+
description: 'Saved Docker registry for this env',
|
|
214
|
+
}),
|
|
215
|
+
'docker-platform': Flags.string({
|
|
216
|
+
description: 'Saved Docker image platform for this env',
|
|
217
|
+
options: ['auto', 'linux/amd64', 'linux/arm64'],
|
|
218
|
+
}),
|
|
219
|
+
'git-url': Flags.string({
|
|
220
|
+
description: 'Saved Git repository URL for this env',
|
|
221
|
+
}),
|
|
222
|
+
'npm-registry': Flags.string({
|
|
223
|
+
description: 'Saved npm registry for this env',
|
|
224
|
+
}),
|
|
225
|
+
'dev-dependencies': Flags.boolean({
|
|
226
|
+
allowNo: true,
|
|
227
|
+
description: 'Whether development dependencies are installed for this env',
|
|
228
|
+
}),
|
|
229
|
+
build: Flags.boolean({
|
|
230
|
+
allowNo: true,
|
|
231
|
+
description: 'Whether the app should be built after source download',
|
|
232
|
+
}),
|
|
233
|
+
'build-dts': Flags.boolean({
|
|
234
|
+
allowNo: true,
|
|
235
|
+
description: 'Whether declaration files should be emitted during build',
|
|
236
|
+
}),
|
|
237
|
+
'app-path': Flags.string({
|
|
238
|
+
description: 'Saved app path for this env',
|
|
239
|
+
}),
|
|
240
|
+
'app-root-path': Flags.string({
|
|
241
|
+
hidden: true,
|
|
242
|
+
description: 'Saved application root path for this env',
|
|
243
|
+
}),
|
|
244
|
+
'storage-path': Flags.string({
|
|
245
|
+
hidden: true,
|
|
246
|
+
description: 'Saved storage path for this env',
|
|
247
|
+
}),
|
|
248
|
+
'app-public-path': Flags.string({
|
|
249
|
+
description: 'Saved application public path for this env',
|
|
250
|
+
}),
|
|
251
|
+
'cdn-base-url': Flags.string({
|
|
252
|
+
description: 'Saved client asset CDN base URL (CDN_BASE_URL) for this env',
|
|
253
|
+
}),
|
|
254
|
+
'env-file': Flags.string({
|
|
255
|
+
hidden: true,
|
|
256
|
+
description: 'Saved Docker --env-file path for this env',
|
|
257
|
+
}),
|
|
258
|
+
'app-port': Flags.string({
|
|
259
|
+
description: 'Saved application HTTP port for this env',
|
|
260
|
+
}),
|
|
261
|
+
'app-key': Flags.string({
|
|
262
|
+
description: 'Saved application secret key for this env',
|
|
263
|
+
}),
|
|
264
|
+
timezone: Flags.string({
|
|
265
|
+
description: 'Saved application timezone for this env',
|
|
266
|
+
}),
|
|
267
|
+
'builtin-db': Flags.boolean({
|
|
268
|
+
allowNo: true,
|
|
269
|
+
description: 'Whether this env uses a CLI-managed built-in database',
|
|
270
|
+
}),
|
|
271
|
+
'db-dialect': Flags.string({
|
|
272
|
+
description: 'Saved database dialect for this env',
|
|
273
|
+
options: ['kingbase', 'mariadb', 'mysql', 'postgres'],
|
|
274
|
+
}),
|
|
275
|
+
'builtin-db-image': Flags.string({
|
|
276
|
+
description: 'Saved built-in database image for this env',
|
|
277
|
+
}),
|
|
278
|
+
'db-host': Flags.string({
|
|
279
|
+
description: 'Saved database host for this env',
|
|
280
|
+
}),
|
|
281
|
+
'db-port': Flags.string({
|
|
282
|
+
description: 'Saved database port for this env',
|
|
283
|
+
}),
|
|
284
|
+
'db-database': Flags.string({
|
|
285
|
+
description: 'Saved database name for this env',
|
|
286
|
+
}),
|
|
287
|
+
'db-user': Flags.string({
|
|
288
|
+
description: 'Saved database user for this env',
|
|
289
|
+
}),
|
|
290
|
+
'db-password': Flags.string({
|
|
291
|
+
description: 'Saved database password for this env',
|
|
292
|
+
}),
|
|
293
|
+
'db-schema': Flags.string({
|
|
294
|
+
description: 'Saved database schema for this env',
|
|
295
|
+
}),
|
|
296
|
+
'db-table-prefix': Flags.string({
|
|
297
|
+
description: 'Saved database table prefix for this env',
|
|
298
|
+
}),
|
|
299
|
+
'db-underscored': Flags.boolean({
|
|
300
|
+
allowNo: true,
|
|
301
|
+
description: 'Whether this env uses underscored database naming',
|
|
302
|
+
}),
|
|
303
|
+
unset: Flags.string({
|
|
304
|
+
multiple: true,
|
|
305
|
+
description: 'Unset one or more saved env config fields by canonical flag name',
|
|
306
|
+
}),
|
|
307
|
+
};
|
|
308
|
+
buildRuntimeUpdateTaskMessage(envLabel) {
|
|
309
|
+
return `Updating env runtime: ${envLabel}`;
|
|
310
|
+
}
|
|
311
|
+
async refreshRuntime(envName, envLabel, verbose) {
|
|
312
|
+
startTask(this.buildRuntimeUpdateTaskMessage(envLabel));
|
|
313
|
+
try {
|
|
314
|
+
const runtime = await updateEnvRuntime({
|
|
315
|
+
envName,
|
|
316
|
+
scope: resolveDefaultConfigScope(),
|
|
317
|
+
configFile: __dirnameConfigFile,
|
|
318
|
+
verbose,
|
|
319
|
+
});
|
|
320
|
+
if (verbose) {
|
|
321
|
+
succeedTask(`Updated env "${envLabel}" to runtime "${runtime.version}".`);
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
stopTask();
|
|
325
|
+
printVerbose(`Updated env "${envLabel}" to runtime "${runtime.version}".`);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
catch (error) {
|
|
329
|
+
failTask(`Failed to update env "${envLabel}".`);
|
|
330
|
+
throw error;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
printConfigUpdateHints(envName, changedFields, nextConfig) {
|
|
334
|
+
if (changedFields.size === 0) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
printInfo('Saved env config was updated. Runtime commands were not refreshed automatically.');
|
|
338
|
+
const shouldRestartWithDb = Array.from(changedFields).some((field) => APP_RESTART_WITH_DB_FIELDS.has(field)) &&
|
|
339
|
+
(nextConfig.builtinDb === true || changedFields.has('builtin-db'));
|
|
340
|
+
if (shouldRestartWithDb) {
|
|
341
|
+
printInfo(`Run \`nb app restart --env ${envName} --with-db\` when you're ready to apply these changes.`);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
if (Array.from(changedFields).some((field) => APP_RESTART_FIELDS.has(field))) {
|
|
345
|
+
printInfo(`Run \`nb app restart --env ${envName}\` when you're ready to apply these changes.`);
|
|
346
|
+
}
|
|
347
|
+
if (Array.from(changedFields).some((field) => SOURCE_SETTING_FIELDS.has(field))) {
|
|
348
|
+
printInfo('Saved source settings were updated. Existing local source files are not replaced automatically.');
|
|
349
|
+
}
|
|
350
|
+
if (Array.from(changedFields).some((field) => field === 'auth-type' || field === 'access-token' || field === 'username') &&
|
|
351
|
+
(nextConfig.authType === 'basic' || nextConfig.authType === 'oauth' || !nextConfig.accessToken)) {
|
|
352
|
+
printInfo(`Run \`nb env auth ${envName}\` if you need to authenticate this env again before using runtime commands.`);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
async run() {
|
|
356
|
+
const { args, flags } = await this.parse(EnvUpdate);
|
|
357
|
+
const parsedFlags = flags;
|
|
358
|
+
setVerboseMode(Boolean(parsedFlags.verbose));
|
|
359
|
+
const unsetFields = normalizeUnsetFields(parsedFlags.unset);
|
|
360
|
+
const providedFields = collectProvidedConfigFields(parsedFlags);
|
|
361
|
+
const hasConfigChanges = providedFields.size > 0 || unsetFields.length > 0;
|
|
362
|
+
const tokenOverride = hasTokenOverride(parsedFlags);
|
|
363
|
+
for (const field of unsetFields) {
|
|
364
|
+
if (providedFields.has(field)) {
|
|
365
|
+
this.error(`Cannot combine --unset ${field} with an explicit update for the same field.`);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
if (tokenOverride && parsedFlags['auth-type'] && parsedFlags['auth-type'] !== 'token') {
|
|
369
|
+
this.error('--access-token or --token can only be used with --auth-type token.');
|
|
370
|
+
}
|
|
371
|
+
if (!hasConfigChanges) {
|
|
372
|
+
const envName = args.name;
|
|
373
|
+
const envLabel = envName ?? (await getCurrentEnvName({ scope: resolveDefaultConfigScope() }));
|
|
374
|
+
await this.refreshRuntime(envName, envLabel, Boolean(parsedFlags.verbose));
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
const currentEnv = await getEnv(args.name, { scope: resolveDefaultConfigScope() });
|
|
378
|
+
if (!currentEnv) {
|
|
379
|
+
this.error(args.name?.trim()
|
|
380
|
+
? `Env "${args.name.trim()}" is not configured`
|
|
381
|
+
: 'No env is configured. Run `nb init --ui` or `nb env add <name> --api-base-url <url>` first.');
|
|
382
|
+
}
|
|
383
|
+
const envName = String(currentEnv.name ?? '').trim();
|
|
384
|
+
const effectiveAuthType = parsedFlags['auth-type'] ?? (tokenOverride ? 'token' : currentEnv.authType);
|
|
385
|
+
if (parsedFlags.username !== undefined && effectiveAuthType !== 'basic') {
|
|
386
|
+
this.error('--username can only be used when the env uses basic authentication.');
|
|
387
|
+
}
|
|
388
|
+
const nextInput = buildCurrentConfigInput(currentEnv);
|
|
389
|
+
nextInput.apiBaseUrl = currentEnv.apiBaseUrl;
|
|
390
|
+
nextInput.authType = currentEnv.authType;
|
|
391
|
+
nextInput.authUsername = currentEnv.config.authUsername;
|
|
392
|
+
if (parsedFlags['api-base-url'] !== undefined) {
|
|
393
|
+
const apiBaseUrlValidationError = await validateApiBaseUrl(parsedFlags['api-base-url']);
|
|
394
|
+
if (apiBaseUrlValidationError) {
|
|
395
|
+
throwValidationError(apiBaseUrlValidationError);
|
|
396
|
+
}
|
|
397
|
+
nextInput.apiBaseUrl = parsedFlags['api-base-url'];
|
|
398
|
+
}
|
|
399
|
+
if (parsedFlags['auth-type'] !== undefined) {
|
|
400
|
+
nextInput.authType = parsedFlags['auth-type'];
|
|
401
|
+
}
|
|
402
|
+
if (parsedFlags.username !== undefined) {
|
|
403
|
+
nextInput.authUsername = String(parsedFlags.username ?? '').trim();
|
|
404
|
+
}
|
|
405
|
+
if (tokenOverride) {
|
|
406
|
+
nextInput.authType = 'token';
|
|
407
|
+
nextInput.accessToken = parsedFlags['access-token'] ?? parsedFlags.token;
|
|
408
|
+
}
|
|
409
|
+
for (const field of UPDATE_STRING_FLAGS) {
|
|
410
|
+
if (parsedFlags[field] !== undefined) {
|
|
411
|
+
nextInput[ENV_STRING_CONFIG_FLAG_MAP[field]] = parsedFlags[field];
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
for (const field of UPDATE_BOOLEAN_FLAGS) {
|
|
415
|
+
if (parsedFlags[field] !== undefined) {
|
|
416
|
+
nextInput[ENV_BOOLEAN_CONFIG_FLAG_MAP[field]] = parsedFlags[field];
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
for (const field of unsetFields) {
|
|
420
|
+
applyUnsetField(nextInput, field);
|
|
421
|
+
}
|
|
422
|
+
const nextConfig = buildStoredEnvConfig(nextInput);
|
|
423
|
+
startTask(`Saving env config: ${envName}`);
|
|
424
|
+
try {
|
|
425
|
+
await replaceEnvConfig(envName, nextConfig, { scope: resolveDefaultConfigScope() });
|
|
426
|
+
succeedTask(`Saved env config for "${envName}".`);
|
|
427
|
+
}
|
|
428
|
+
catch (error) {
|
|
429
|
+
failTask(`Failed to save env config for "${envName}".`);
|
|
430
|
+
throw error;
|
|
431
|
+
}
|
|
432
|
+
const shouldRefreshRuntime = providedFields.has('api-base-url') || providedFields.has('access-token');
|
|
433
|
+
if (!shouldRefreshRuntime) {
|
|
434
|
+
this.printConfigUpdateHints(envName, new Set([...providedFields, ...unsetFields]), nextConfig);
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
try {
|
|
438
|
+
await this.refreshRuntime(envName, envName, Boolean(parsedFlags.verbose));
|
|
439
|
+
}
|
|
440
|
+
catch (error) {
|
|
441
|
+
this.printConfigUpdateHints(envName, new Set([...providedFields, ...unsetFields]), nextConfig);
|
|
442
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
443
|
+
printWarningBlock(`Saved env config for "${envName}", but failed to refresh the runtime.\n${message}`);
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
printVerbose(`Updated env "${envName}" config and refreshed the runtime.`);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
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 } from '@oclif/core';
|
|
10
|
+
import { setCurrentEnv } from '../../lib/auth-store.js';
|
|
11
|
+
import { resolveDefaultConfigScope } from '../../lib/cli-home.js';
|
|
12
|
+
import { resolveSessionIdentity } from '../../lib/session-id.js';
|
|
13
|
+
import { isInteractiveTerminal, printInfo } from '../../lib/ui.js';
|
|
14
|
+
export default class EnvUse extends Command {
|
|
15
|
+
static summary = 'Switch the current environment';
|
|
16
|
+
static examples = [
|
|
17
|
+
'<%= config.bin %> <%= command.id %> local',
|
|
18
|
+
];
|
|
19
|
+
static args = {
|
|
20
|
+
name: Args.string({
|
|
21
|
+
description: 'Configured environment name to switch to',
|
|
22
|
+
required: true,
|
|
23
|
+
}),
|
|
24
|
+
};
|
|
25
|
+
async run() {
|
|
26
|
+
const { args } = await this.parse(EnvUse);
|
|
27
|
+
await setCurrentEnv(args.name, { scope: resolveDefaultConfigScope() });
|
|
28
|
+
this.log(`Current env: ${args.name}`);
|
|
29
|
+
const identity = resolveSessionIdentity();
|
|
30
|
+
if (identity || !isInteractiveTerminal()) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
this.log('Session mode is not enabled for the current shell or runtime.');
|
|
34
|
+
this.log('Without session mode, switching the current env here can affect other sessions running in parallel.');
|
|
35
|
+
this.log('');
|
|
36
|
+
printInfo('Run `nb session setup` to enable session mode for this shell or runtime.');
|
|
37
|
+
}
|
|
38
|
+
}
|