@nocobase/cli 2.1.0-beta.24 → 2.1.0-beta.26
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 +19 -0
- package/dist/commands/app/down.js +12 -6
- package/dist/commands/app/logs.js +2 -2
- package/dist/commands/app/start.js +2 -1
- package/dist/commands/app/stop.js +2 -1
- package/dist/commands/app/upgrade.js +116 -129
- 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 +171 -65
- package/dist/commands/db/logs.js +2 -2
- package/dist/commands/db/shared.js +6 -5
- package/dist/commands/db/start.js +2 -1
- package/dist/commands/db/stop.js +2 -1
- package/dist/commands/env/info.js +6 -2
- package/dist/commands/env/shared.js +1 -1
- package/dist/commands/install.js +50 -35
- package/dist/commands/license/activate.js +360 -0
- package/dist/commands/license/env.js +94 -0
- package/dist/commands/license/generate-id.js +108 -0
- package/dist/commands/license/id.js +56 -0
- package/dist/commands/license/index.js +20 -0
- package/dist/commands/license/plugins/clean.js +101 -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 +269 -0
- package/dist/commands/license/shared.js +414 -0
- package/dist/commands/license/status.js +50 -0
- package/dist/commands/plugin/disable.js +2 -0
- package/dist/commands/plugin/enable.js +2 -0
- package/dist/commands/source/dev.js +2 -1
- package/dist/commands/source/test.js +11 -1
- package/dist/lib/api-client.js +74 -3
- package/dist/lib/app-managed-resources.js +10 -6
- package/dist/lib/app-runtime.js +29 -11
- package/dist/lib/auth-store.js +36 -68
- package/dist/lib/bootstrap.js +0 -4
- package/dist/lib/build-config.js +8 -0
- package/dist/lib/builtin-db.js +86 -0
- package/dist/lib/cli-config.js +176 -0
- package/dist/lib/cli-home.js +6 -21
- package/dist/lib/env-config.js +7 -0
- package/dist/lib/generated-command.js +24 -3
- package/dist/lib/plugin-storage.js +127 -0
- package/dist/lib/prompt-validators.js +4 -4
- package/dist/lib/run-npm.js +53 -0
- package/dist/lib/runtime-env-vars.js +32 -0
- package/dist/lib/runtime-generator.js +89 -10
- package/dist/lib/self-manager.js +57 -2
- package/dist/lib/skills-manager.js +2 -2
- package/dist/lib/startup-update.js +81 -6
- package/dist/lib/ui.js +3 -0
- package/dist/locale/en-US.json +0 -4
- package/dist/locale/zh-CN.json +0 -4
- package/nocobase-ctl.config.json +82 -0
- package/package.json +13 -4
|
@@ -0,0 +1,35 @@
|
|
|
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 { assertSupportedCliConfigKey, setCliConfigValue } from '../../lib/cli-config.js';
|
|
11
|
+
export default class ConfigSet extends Command {
|
|
12
|
+
static summary = 'Set a CLI configuration value';
|
|
13
|
+
static description = 'Set a supported CLI configuration key. Supported keys: license.pkg-url, docker.network, docker.container-prefix.';
|
|
14
|
+
static examples = [
|
|
15
|
+
'<%= config.bin %> <%= command.id %> license.pkg-url https://pkg.nocobase.com/',
|
|
16
|
+
'<%= config.bin %> <%= command.id %> docker.network nocobase',
|
|
17
|
+
'<%= config.bin %> <%= command.id %> docker.container-prefix nb',
|
|
18
|
+
];
|
|
19
|
+
static args = {
|
|
20
|
+
key: Args.string({
|
|
21
|
+
description: 'Configuration key',
|
|
22
|
+
required: true,
|
|
23
|
+
}),
|
|
24
|
+
value: Args.string({
|
|
25
|
+
description: 'Configuration value',
|
|
26
|
+
required: true,
|
|
27
|
+
}),
|
|
28
|
+
};
|
|
29
|
+
async run() {
|
|
30
|
+
const { args } = await this.parse(ConfigSet);
|
|
31
|
+
const key = assertSupportedCliConfigKey(args.key);
|
|
32
|
+
const value = await setCliConfigValue(key, args.value);
|
|
33
|
+
this.log(`${key}=${value}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -7,10 +7,13 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
import { Command, Flags } from '@oclif/core';
|
|
10
|
-
import { formatMissingManagedAppEnvMessage } from '../../lib/app-runtime.js';
|
|
11
|
-
import {
|
|
10
|
+
import { formatMissingManagedAppEnvMessage, resolveManagedAppRuntime } from '../../lib/app-runtime.js';
|
|
11
|
+
import { resolveBuiltinDbConnection } from '../../lib/builtin-db.js';
|
|
12
12
|
import { checkExternalDbConnection, formatDbCheckAddress, readExternalDbConnectionConfig, } from "../../lib/db-connection-check.js";
|
|
13
|
+
import { commandOutput } from '../../lib/run-npm.js';
|
|
13
14
|
import { validateTcpPort } from "../../lib/prompt-validators.js";
|
|
15
|
+
const DEFAULT_DOCKER_REGISTRY = 'nocobase/nocobase';
|
|
16
|
+
const DEFAULT_DOCKER_VERSION = 'alpha';
|
|
14
17
|
function trimValue(value) {
|
|
15
18
|
const text = String(value ?? '').trim();
|
|
16
19
|
return text || undefined;
|
|
@@ -18,19 +21,166 @@ function trimValue(value) {
|
|
|
18
21
|
function resolveRequiredDbField(flagValue, envValue) {
|
|
19
22
|
return trimValue(flagValue) ?? trimValue(envValue);
|
|
20
23
|
}
|
|
21
|
-
function
|
|
24
|
+
function normalizeDockerPlatform(value) {
|
|
25
|
+
const text = trimValue(value);
|
|
26
|
+
if (!text || text === 'auto') {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
if (text === 'linux/amd64' || text === 'linux/arm64') {
|
|
30
|
+
return text;
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
function formatMissingFieldsMessage(missing, hasEnv) {
|
|
22
35
|
return [
|
|
23
36
|
'Missing database settings for connectivity check.',
|
|
24
37
|
`Required: ${missing.join(', ')}.`,
|
|
25
|
-
|
|
38
|
+
hasEnv
|
|
39
|
+
? 'Pass `--env <name>` to reuse a saved env, or provide the missing `--db-*` flags explicitly.'
|
|
40
|
+
: 'Provide all required `--db-*` flags explicitly, or pass `--env <name>` to reuse a saved env.',
|
|
26
41
|
].join('\n');
|
|
27
42
|
}
|
|
43
|
+
function resolveDbConfigFromFlags(flags, envConfig) {
|
|
44
|
+
return {
|
|
45
|
+
builtinDb: false,
|
|
46
|
+
dbDialect: resolveRequiredDbField(flags['db-dialect'], envConfig?.dbDialect),
|
|
47
|
+
dbHost: resolveRequiredDbField(flags['db-host'], envConfig?.dbHost),
|
|
48
|
+
dbPort: resolveRequiredDbField(flags['db-port'], envConfig?.dbPort),
|
|
49
|
+
dbDatabase: resolveRequiredDbField(flags['db-database'], envConfig?.dbDatabase),
|
|
50
|
+
dbUser: resolveRequiredDbField(flags['db-user'], envConfig?.dbUser),
|
|
51
|
+
dbPassword: flags['db-password'] !== undefined
|
|
52
|
+
? String(flags['db-password'] ?? '')
|
|
53
|
+
: envConfig?.dbPassword !== undefined
|
|
54
|
+
? String(envConfig.dbPassword ?? '')
|
|
55
|
+
: undefined,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function validateDbConfigOrThrow(command, dbConfig, hasEnv) {
|
|
59
|
+
const missing = [];
|
|
60
|
+
if (!dbConfig.dbDialect) {
|
|
61
|
+
missing.push('--db-dialect');
|
|
62
|
+
}
|
|
63
|
+
if (!dbConfig.dbHost) {
|
|
64
|
+
missing.push('--db-host');
|
|
65
|
+
}
|
|
66
|
+
if (!dbConfig.dbPort) {
|
|
67
|
+
missing.push('--db-port');
|
|
68
|
+
}
|
|
69
|
+
if (!dbConfig.dbDatabase) {
|
|
70
|
+
missing.push('--db-database');
|
|
71
|
+
}
|
|
72
|
+
if (!dbConfig.dbUser) {
|
|
73
|
+
missing.push('--db-user');
|
|
74
|
+
}
|
|
75
|
+
if (!dbConfig.dbPassword) {
|
|
76
|
+
missing.push('--db-password');
|
|
77
|
+
}
|
|
78
|
+
if (missing.length > 0) {
|
|
79
|
+
command.error(formatMissingFieldsMessage(missing, hasEnv));
|
|
80
|
+
}
|
|
81
|
+
const portError = validateTcpPort(dbConfig.dbPort);
|
|
82
|
+
if (portError) {
|
|
83
|
+
command.error(portError);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async function resolveDbCheckInput(command, flags) {
|
|
87
|
+
const envName = flags.env?.trim() || undefined;
|
|
88
|
+
if (!envName) {
|
|
89
|
+
const dbConfig = resolveDbConfigFromFlags(flags);
|
|
90
|
+
validateDbConfigOrThrow(command, dbConfig, false);
|
|
91
|
+
return {
|
|
92
|
+
dbConfig,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const runtime = await resolveManagedAppRuntime(envName);
|
|
96
|
+
if (!runtime) {
|
|
97
|
+
command.error(formatMissingManagedAppEnvMessage(envName));
|
|
98
|
+
}
|
|
99
|
+
const envConfig = { ...runtime.env.config };
|
|
100
|
+
if ((runtime.kind === 'local' || runtime.kind === 'docker') && runtime.env.config.builtinDb) {
|
|
101
|
+
const builtinDbConnection = await resolveBuiltinDbConnection(runtime);
|
|
102
|
+
envConfig.dbHost = builtinDbConnection.dbHost;
|
|
103
|
+
envConfig.dbPort = builtinDbConnection.dbPort;
|
|
104
|
+
envConfig.dbDialect = builtinDbConnection.dbDialect;
|
|
105
|
+
}
|
|
106
|
+
const dbConfig = resolveDbConfigFromFlags(flags, envConfig);
|
|
107
|
+
validateDbConfigOrThrow(command, dbConfig, true);
|
|
108
|
+
return {
|
|
109
|
+
envName: runtime.envName,
|
|
110
|
+
kind: runtime.kind,
|
|
111
|
+
runtime: runtime,
|
|
112
|
+
dbConfig,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function buildConnectionConfigOrThrow(command, dbConfig) {
|
|
116
|
+
const connectionConfig = readExternalDbConnectionConfig(dbConfig);
|
|
117
|
+
if (!connectionConfig) {
|
|
118
|
+
command.error('Unsupported or incomplete database settings for connectivity check.');
|
|
119
|
+
}
|
|
120
|
+
return connectionConfig;
|
|
121
|
+
}
|
|
122
|
+
async function runExplicitDbCheck(command, dbConfig) {
|
|
123
|
+
const connectionConfig = buildConnectionConfigOrThrow(command, dbConfig);
|
|
124
|
+
const address = formatDbCheckAddress(connectionConfig);
|
|
125
|
+
const validationError = await checkExternalDbConnection(connectionConfig);
|
|
126
|
+
return {
|
|
127
|
+
ok: !validationError,
|
|
128
|
+
dialect: connectionConfig.dialect,
|
|
129
|
+
address,
|
|
130
|
+
error: validationError ?? null,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
async function runDockerDbCheck(command, runtime, dbConfig) {
|
|
134
|
+
const connectionConfig = buildConnectionConfigOrThrow(command, dbConfig);
|
|
135
|
+
const config = runtime.env.config ?? {};
|
|
136
|
+
const imageRef = `${trimValue(config.dockerRegistry) || DEFAULT_DOCKER_REGISTRY}:${trimValue(config.downloadVersion) || DEFAULT_DOCKER_VERSION}`;
|
|
137
|
+
const args = [
|
|
138
|
+
'run',
|
|
139
|
+
'--rm',
|
|
140
|
+
'--network',
|
|
141
|
+
runtime.dockerNetworkName || runtime.workspaceName,
|
|
142
|
+
];
|
|
143
|
+
const dockerPlatform = normalizeDockerPlatform(config.dockerPlatform);
|
|
144
|
+
if (dockerPlatform) {
|
|
145
|
+
args.push('--platform', dockerPlatform);
|
|
146
|
+
}
|
|
147
|
+
args.push('--entrypoint', 'nb', imageRef, 'db', 'check', '--db-dialect', connectionConfig.dialect, '--db-host', connectionConfig.host, '--db-port', String(connectionConfig.port), '--db-database', connectionConfig.database, '--db-user', connectionConfig.user, '--db-password', connectionConfig.password, '--json');
|
|
148
|
+
const output = await commandOutput('docker', args, {
|
|
149
|
+
errorName: 'docker run',
|
|
150
|
+
});
|
|
151
|
+
let payload;
|
|
152
|
+
try {
|
|
153
|
+
payload = JSON.parse(output);
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
command.error(`Failed to parse database check response from Docker: ${output}`);
|
|
157
|
+
}
|
|
158
|
+
const ok = Boolean(payload.ok);
|
|
159
|
+
const dialect = trimValue(payload.dialect) || connectionConfig.dialect;
|
|
160
|
+
const address = trimValue(payload.address) || formatDbCheckAddress(connectionConfig);
|
|
161
|
+
const error = trimValue(payload.error) || null;
|
|
162
|
+
return {
|
|
163
|
+
ok,
|
|
164
|
+
dialect,
|
|
165
|
+
address,
|
|
166
|
+
error,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
async function runDbCheckForRuntime(command, runtime, dbConfig) {
|
|
170
|
+
if (runtime.kind === 'docker') {
|
|
171
|
+
return await runDockerDbCheck(command, runtime, dbConfig);
|
|
172
|
+
}
|
|
173
|
+
if (runtime.kind === 'local') {
|
|
174
|
+
return await runExplicitDbCheck(command, dbConfig);
|
|
175
|
+
}
|
|
176
|
+
command.error(`Env "${runtime.envName}" does not support automatic database connectivity checks.`);
|
|
177
|
+
}
|
|
28
178
|
export default class DbCheck extends Command {
|
|
29
|
-
static description = 'Check whether
|
|
179
|
+
static description = 'Check whether a database is reachable using the selected env settings or explicit `--db-*` flags.';
|
|
30
180
|
static examples = [
|
|
31
181
|
'<%= config.bin %> <%= command.id %> --env app1',
|
|
32
|
-
'<%= config.bin %> <%= command.id %> --db-dialect postgres --db-host 127.0.0.1 --db-port 5432 --db-database nocobase --db-user nocobase --db-password secret',
|
|
33
182
|
'<%= config.bin %> <%= command.id %> --env app1 --db-password new-secret --json',
|
|
183
|
+
'<%= config.bin %> <%= command.id %> --db-dialect postgres --db-host 127.0.0.1 --db-port 5432 --db-database nocobase --db-user nocobase --db-password secret',
|
|
34
184
|
];
|
|
35
185
|
static flags = {
|
|
36
186
|
env: Flags.string({
|
|
@@ -63,70 +213,26 @@ export default class DbCheck extends Command {
|
|
|
63
213
|
};
|
|
64
214
|
async run() {
|
|
65
215
|
const { flags } = await this.parse(DbCheck);
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
this.
|
|
70
|
-
}
|
|
71
|
-
const config = env?.config ?? {};
|
|
72
|
-
const dbConfig = {
|
|
73
|
-
builtinDb: false,
|
|
74
|
-
dbDialect: resolveRequiredDbField(flags['db-dialect'], config.dbDialect),
|
|
75
|
-
dbHost: resolveRequiredDbField(flags['db-host'], config.dbHost),
|
|
76
|
-
dbPort: resolveRequiredDbField(flags['db-port'], config.dbPort),
|
|
77
|
-
dbDatabase: resolveRequiredDbField(flags['db-database'], config.dbDatabase),
|
|
78
|
-
dbUser: resolveRequiredDbField(flags['db-user'], config.dbUser),
|
|
79
|
-
dbPassword: flags['db-password'] !== undefined
|
|
80
|
-
? String(flags['db-password'] ?? '')
|
|
81
|
-
: String(config.dbPassword ?? ''),
|
|
82
|
-
};
|
|
83
|
-
const missing = [];
|
|
84
|
-
if (!dbConfig.dbDialect) {
|
|
85
|
-
missing.push('--db-dialect');
|
|
86
|
-
}
|
|
87
|
-
if (!dbConfig.dbHost) {
|
|
88
|
-
missing.push('--db-host');
|
|
89
|
-
}
|
|
90
|
-
if (!dbConfig.dbPort) {
|
|
91
|
-
missing.push('--db-port');
|
|
92
|
-
}
|
|
93
|
-
if (!dbConfig.dbDatabase) {
|
|
94
|
-
missing.push('--db-database');
|
|
95
|
-
}
|
|
96
|
-
if (!dbConfig.dbUser) {
|
|
97
|
-
missing.push('--db-user');
|
|
98
|
-
}
|
|
99
|
-
if (!dbConfig.dbPassword) {
|
|
100
|
-
missing.push('--db-password');
|
|
101
|
-
}
|
|
102
|
-
if (missing.length > 0) {
|
|
103
|
-
this.error(formatMissingFieldsMessage(missing));
|
|
104
|
-
}
|
|
105
|
-
const portError = validateTcpPort(dbConfig.dbPort);
|
|
106
|
-
if (portError) {
|
|
107
|
-
this.error(portError);
|
|
108
|
-
}
|
|
109
|
-
const connectionConfig = readExternalDbConnectionConfig(dbConfig);
|
|
110
|
-
if (!connectionConfig) {
|
|
111
|
-
this.error('Unsupported or incomplete database settings for connectivity check.');
|
|
112
|
-
}
|
|
113
|
-
const address = formatDbCheckAddress(connectionConfig);
|
|
114
|
-
const validationError = await checkExternalDbConnection(connectionConfig);
|
|
216
|
+
const input = await resolveDbCheckInput(this, flags);
|
|
217
|
+
const result = input.runtime
|
|
218
|
+
? await runDbCheckForRuntime(this, input.runtime, input.dbConfig)
|
|
219
|
+
: await runExplicitDbCheck(this, input.dbConfig);
|
|
115
220
|
if (flags.json) {
|
|
116
221
|
this.log(JSON.stringify({
|
|
117
|
-
ok:
|
|
118
|
-
env:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
222
|
+
ok: result.ok,
|
|
223
|
+
env: input.envName,
|
|
224
|
+
kind: input.kind,
|
|
225
|
+
dialect: result.dialect,
|
|
226
|
+
address: result.address,
|
|
227
|
+
error: result.error,
|
|
122
228
|
}, null, 2));
|
|
123
229
|
return;
|
|
124
230
|
}
|
|
125
|
-
if (
|
|
126
|
-
this.error(
|
|
231
|
+
if (!result.ok) {
|
|
232
|
+
this.error(result.error ?? 'Database check failed.');
|
|
127
233
|
}
|
|
128
|
-
this.log(
|
|
129
|
-
? `Database check passed for env "${
|
|
130
|
-
: `Database check passed (${
|
|
234
|
+
this.log(input.envName
|
|
235
|
+
? `Database check passed for env "${input.envName}" (${result.dialect} ${result.address}).`
|
|
236
|
+
: `Database check passed (${result.dialect} ${result.address}).`);
|
|
131
237
|
}
|
|
132
238
|
}
|
package/dist/commands/db/logs.js
CHANGED
|
@@ -47,7 +47,7 @@ export default class DbLogs extends Command {
|
|
|
47
47
|
follow: Flags.boolean({
|
|
48
48
|
char: 'f',
|
|
49
49
|
description: 'Keep streaming new log lines',
|
|
50
|
-
default:
|
|
50
|
+
default: false,
|
|
51
51
|
allowNo: true,
|
|
52
52
|
}),
|
|
53
53
|
};
|
|
@@ -62,7 +62,7 @@ export default class DbLogs extends Command {
|
|
|
62
62
|
this.error(formatUnmanagedDbLogsMessage(runtime));
|
|
63
63
|
}
|
|
64
64
|
const tail = String(flags.tail ?? 100);
|
|
65
|
-
const follow = flags.follow
|
|
65
|
+
const follow = flags.follow === true;
|
|
66
66
|
printInfo(follow
|
|
67
67
|
? `Showing built-in database logs for "${runtime.envName}" (press Ctrl+C to stop).`
|
|
68
68
|
: `Showing recent built-in database logs for "${runtime.envName}".`);
|
|
@@ -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 {
|
|
9
|
+
import { dockerContainerExists, dockerContainerIsRunning, resolveManagedAppRuntime, } from '../../lib/app-runtime.js';
|
|
10
|
+
import { resolveBuiltinDbConnection } from '../../lib/builtin-db.js';
|
|
10
11
|
function formatAddress(host, port, fallbackHost) {
|
|
11
12
|
const normalizedHost = String(host ?? '').trim() || String(fallbackHost ?? '').trim();
|
|
12
13
|
const normalizedPort = String(port ?? '').trim();
|
|
@@ -23,14 +24,14 @@ export async function resolveDbRuntime(envName) {
|
|
|
23
24
|
const source = runtime.kind === 'http' || runtime.kind === 'ssh' ? runtime.kind : runtime.source;
|
|
24
25
|
const dbDialect = String(runtime.env.config.dbDialect ?? 'postgres').trim() || 'postgres';
|
|
25
26
|
if ((runtime.kind === 'local' || runtime.kind === 'docker') && runtime.env.config.builtinDb) {
|
|
26
|
-
const
|
|
27
|
+
const connection = await resolveBuiltinDbConnection(runtime);
|
|
27
28
|
return {
|
|
28
29
|
kind: 'builtin',
|
|
29
30
|
envName: runtime.envName,
|
|
30
31
|
source,
|
|
31
|
-
dbDialect,
|
|
32
|
-
containerName,
|
|
33
|
-
address: formatAddress(
|
|
32
|
+
dbDialect: connection.dbDialect,
|
|
33
|
+
containerName: connection.containerName,
|
|
34
|
+
address: formatAddress(connection.dbHost, connection.dbPort, connection.containerName),
|
|
34
35
|
appRuntime: runtime,
|
|
35
36
|
};
|
|
36
37
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { Command, Flags } from '@oclif/core';
|
|
10
10
|
import { formatMissingManagedAppEnvMessage, startDockerContainer, } from '../../lib/app-runtime.js';
|
|
11
|
-
import { failTask, startTask, succeedTask } from '../../lib/ui.js';
|
|
11
|
+
import { announceTargetEnv, failTask, startTask, succeedTask } from '../../lib/ui.js';
|
|
12
12
|
import { formatUnmanagedDbMessage, resolveDbRuntime } from './shared.js';
|
|
13
13
|
function formatDbStartFailure(envName, message) {
|
|
14
14
|
if (/does not exist/i.test(message)) {
|
|
@@ -52,6 +52,7 @@ export default class DbStart extends Command {
|
|
|
52
52
|
if (runtime.kind !== 'builtin') {
|
|
53
53
|
this.error(formatUnmanagedDbMessage('start', runtime));
|
|
54
54
|
}
|
|
55
|
+
announceTargetEnv(runtime.envName);
|
|
55
56
|
startTask(`Starting the built-in database for "${runtime.envName}"...`);
|
|
56
57
|
try {
|
|
57
58
|
const state = await startDockerContainer(runtime.containerName, {
|
package/dist/commands/db/stop.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { Command, Flags } from '@oclif/core';
|
|
10
10
|
import { formatMissingManagedAppEnvMessage, stopDockerContainer, } from '../../lib/app-runtime.js';
|
|
11
|
-
import { failTask, startTask, succeedTask } from '../../lib/ui.js';
|
|
11
|
+
import { announceTargetEnv, failTask, startTask, succeedTask } from '../../lib/ui.js';
|
|
12
12
|
import { formatUnmanagedDbMessage, resolveDbRuntime } from './shared.js';
|
|
13
13
|
function formatDbStopFailure(envName, message) {
|
|
14
14
|
if (/does not exist/i.test(message)) {
|
|
@@ -52,6 +52,7 @@ export default class DbStop extends Command {
|
|
|
52
52
|
if (runtime.kind !== 'builtin') {
|
|
53
53
|
this.error(formatUnmanagedDbMessage('stop', runtime));
|
|
54
54
|
}
|
|
55
|
+
announceTargetEnv(runtime.envName);
|
|
55
56
|
startTask(`Stopping the built-in database for "${runtime.envName}"...`);
|
|
56
57
|
try {
|
|
57
58
|
const state = await stopDockerContainer(runtime.containerName, {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { Args, Command, Flags } from '@oclif/core';
|
|
10
10
|
import { formatMissingManagedAppEnvMessage, resolveManagedAppRuntime } from '../../lib/app-runtime.js';
|
|
11
|
+
import { resolveBuiltinDbConnection } from '../../lib/builtin-db.js';
|
|
11
12
|
import { renderTable } from '../../lib/ui.js';
|
|
12
13
|
import { appRootPath, dbStatus, runtimeStatus, storagePath } from './shared.js';
|
|
13
14
|
function normalizeJsonValue(value) {
|
|
@@ -85,6 +86,9 @@ export default class EnvInfo extends Command {
|
|
|
85
86
|
this.error(formatMissingManagedAppEnvMessage(requestedEnv));
|
|
86
87
|
}
|
|
87
88
|
const auth = runtime.env.auth;
|
|
89
|
+
const builtinDbConnection = (runtime.kind === 'local' || runtime.kind === 'docker') && runtime.env.config.builtinDb
|
|
90
|
+
? await resolveBuiltinDbConnection(runtime)
|
|
91
|
+
: undefined;
|
|
88
92
|
const appGroup = {
|
|
89
93
|
appRootPath: appRootPath(runtime),
|
|
90
94
|
storagePath: storagePath(runtime),
|
|
@@ -101,8 +105,8 @@ export default class EnvInfo extends Command {
|
|
|
101
105
|
builtinDb: runtime.env.config.builtinDb,
|
|
102
106
|
dbDialect: runtime.env.config.dbDialect,
|
|
103
107
|
builtinDbImage: runtime.env.config.builtinDbImage,
|
|
104
|
-
dbHost: runtime.env.config.dbHost,
|
|
105
|
-
dbPort: runtime.env.config.dbPort,
|
|
108
|
+
dbHost: builtinDbConnection?.dbHost ?? runtime.env.config.dbHost,
|
|
109
|
+
dbPort: builtinDbConnection?.dbPort ?? runtime.env.config.dbPort,
|
|
106
110
|
dbDatabase: runtime.env.config.dbDatabase,
|
|
107
111
|
dbUser: runtime.env.config.dbUser,
|
|
108
112
|
dbPassword: maskSecret(runtime.env.config.dbPassword, showSecrets),
|
|
@@ -141,7 +141,7 @@ export async function dbStatus(runtime) {
|
|
|
141
141
|
return '-';
|
|
142
142
|
}
|
|
143
143
|
const dbDialect = String(runtime.env.config.dbDialect ?? 'postgres').trim() || 'postgres';
|
|
144
|
-
const containerName = buildDockerDbContainerName(runtime.envName, dbDialect, runtime.workspaceName);
|
|
144
|
+
const containerName = buildDockerDbContainerName(runtime.envName, dbDialect, runtime.dockerContainerPrefix || runtime.workspaceName);
|
|
145
145
|
return await dockerStatus(containerName);
|
|
146
146
|
}
|
|
147
147
|
export async function runtimeStatus(runtime) {
|
package/dist/commands/install.js
CHANGED
|
@@ -17,12 +17,14 @@ import { exit } from 'node:process';
|
|
|
17
17
|
import { runPromptCatalog, } from "../lib/prompt-catalog.js";
|
|
18
18
|
import { applyCliLocale, localeText, resolveCliLocale, translateCli, } from "../lib/cli-locale.js";
|
|
19
19
|
import { resolveConfiguredEnvPath, resolveDefaultConfigScope, resolveEnvRoot, resolveEnvRelativePath, } from '../lib/cli-home.js';
|
|
20
|
+
import { defaultDockerContainerPrefix, defaultDockerNetworkName, } from '../lib/app-runtime.js';
|
|
21
|
+
import { resolveDockerContainerPrefix, resolveDockerNetworkName, } from '../lib/cli-config.js';
|
|
20
22
|
import { findAvailableTcpPort, validateAvailableTcpPort, validateTcpPort, validateEnvKey, } from "../lib/prompt-validators.js";
|
|
21
23
|
import { validateExternalDbConfig } from "../lib/db-connection-check.js";
|
|
22
24
|
import { formatMissingManagedAppEnvMessage } from '../lib/app-runtime.js';
|
|
23
25
|
import { run, runNocoBaseCommand } from '../lib/run-npm.js';
|
|
24
26
|
import { startTask, stopTask, updateTask } from '../lib/ui.js';
|
|
25
|
-
import {
|
|
27
|
+
import { getEnv, upsertEnv } from '../lib/auth-store.js';
|
|
26
28
|
import { buildStoredEnvConfig } from '../lib/env-config.js';
|
|
27
29
|
import Download, { defaultDockerRegistryForLang, } from './download.js';
|
|
28
30
|
import EnvAdd from "./env/add.js";
|
|
@@ -812,24 +814,23 @@ export default class Install extends Command {
|
|
|
812
814
|
const builtinDb = values.builtinDb === undefined ? undefined : Boolean(values.builtinDb);
|
|
813
815
|
const dbDialect = Install.toOptionalPromptString(values.dbDialect);
|
|
814
816
|
const appRootPath = Install.toOptionalPromptString(values.appRootPath);
|
|
815
|
-
const
|
|
816
|
-
|
|
817
|
+
const dockerNetworkName = await Install.resolveResumeDockerNetworkName();
|
|
818
|
+
const dockerContainerPrefix = await Install.resolveResumeDockerContainerPrefix();
|
|
817
819
|
return {
|
|
818
820
|
envName,
|
|
819
|
-
...(
|
|
821
|
+
...(dockerNetworkName ? { dockerNetworkName } : {}),
|
|
822
|
+
...(dockerContainerPrefix ? { dockerContainerPrefix } : {}),
|
|
820
823
|
...(source ? { source } : {}),
|
|
821
824
|
...(builtinDb !== undefined ? { builtinDb } : {}),
|
|
822
825
|
...(dbDialect ? { dbDialect } : {}),
|
|
823
826
|
...(appRootPath ? { appRootPath } : {}),
|
|
824
827
|
};
|
|
825
828
|
}
|
|
826
|
-
static async
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
const stored = String(config.name ?? '').trim();
|
|
832
|
-
return stored || Install.defaultWorkspaceName();
|
|
829
|
+
static async resolveResumeDockerNetworkName() {
|
|
830
|
+
return await resolveDockerNetworkName({ scope: resolveDefaultConfigScope() });
|
|
831
|
+
}
|
|
832
|
+
static async resolveResumeDockerContainerPrefix() {
|
|
833
|
+
return await resolveDockerContainerPrefix({ scope: resolveDefaultConfigScope() });
|
|
833
834
|
}
|
|
834
835
|
static async isResumeManagedPortReuse(params) {
|
|
835
836
|
if (params.target === 'app') {
|
|
@@ -837,13 +838,13 @@ export default class Install extends Command {
|
|
|
837
838
|
&& params.context.appRootPath) {
|
|
838
839
|
return await Install.isLocalPm2ProcessUsingPort(params.context.appRootPath, params.port);
|
|
839
840
|
}
|
|
840
|
-
const containerName = Install.buildDockerAppContainerName(params.context.envName, params.context.
|
|
841
|
+
const containerName = Install.buildDockerAppContainerName(params.context.envName, params.context.dockerContainerPrefix);
|
|
841
842
|
return await Install.isDockerContainerPublishingPort(containerName, params.port);
|
|
842
843
|
}
|
|
843
844
|
if (!params.context.builtinDb || params.context.source === 'docker') {
|
|
844
845
|
return false;
|
|
845
846
|
}
|
|
846
|
-
const containerName = Install.buildBuiltinDbContainerName(params.context.envName, params.context.dbDialect ?? 'postgres', params.context.
|
|
847
|
+
const containerName = Install.buildBuiltinDbContainerName(params.context.envName, params.context.dbDialect ?? 'postgres', params.context.dockerContainerPrefix);
|
|
847
848
|
return await Install.isDockerContainerPublishingPort(containerName, params.port);
|
|
848
849
|
}
|
|
849
850
|
static async isDockerContainerPublishingPort(containerName, port) {
|
|
@@ -1183,27 +1184,33 @@ export default class Install extends Command {
|
|
|
1183
1184
|
.replace(/^-+|-+$/g, '');
|
|
1184
1185
|
return normalized || 'nocobase';
|
|
1185
1186
|
}
|
|
1186
|
-
static
|
|
1187
|
-
return Install.sanitizeDockerResourceName(
|
|
1187
|
+
static defaultDockerNetworkName() {
|
|
1188
|
+
return Install.sanitizeDockerResourceName(defaultDockerNetworkName());
|
|
1188
1189
|
}
|
|
1189
|
-
static
|
|
1190
|
-
|
|
1191
|
-
|
|
1190
|
+
static defaultDockerContainerPrefix() {
|
|
1191
|
+
return Install.sanitizeDockerResourceName(defaultDockerContainerPrefix(resolveEnvRoot(resolveDefaultConfigScope())));
|
|
1192
|
+
}
|
|
1193
|
+
static buildBuiltinDbContainerPrefix(containerPrefix) {
|
|
1194
|
+
const storedName = String(containerPrefix ?? '').trim();
|
|
1192
1195
|
return storedName
|
|
1193
1196
|
? Install.sanitizeDockerResourceName(storedName)
|
|
1194
|
-
: Install.
|
|
1197
|
+
: Install.defaultDockerContainerPrefix();
|
|
1195
1198
|
}
|
|
1196
|
-
static
|
|
1197
|
-
|
|
1199
|
+
static buildManagedDockerNetworkName(networkName) {
|
|
1200
|
+
const storedName = String(networkName ?? '').trim();
|
|
1201
|
+
return storedName
|
|
1202
|
+
? Install.sanitizeDockerResourceName(storedName)
|
|
1203
|
+
: Install.defaultDockerNetworkName();
|
|
1198
1204
|
}
|
|
1199
|
-
static buildBuiltinDbNetworkName(envName,
|
|
1200
|
-
|
|
1205
|
+
static buildBuiltinDbNetworkName(envName, networkName) {
|
|
1206
|
+
void envName;
|
|
1207
|
+
return Install.buildManagedDockerNetworkName(networkName);
|
|
1201
1208
|
}
|
|
1202
|
-
static buildBuiltinDbContainerName(envName, dbDialect,
|
|
1203
|
-
return Install.sanitizeDockerResourceName(`${Install.
|
|
1209
|
+
static buildBuiltinDbContainerName(envName, dbDialect, containerPrefix) {
|
|
1210
|
+
return Install.sanitizeDockerResourceName(`${Install.buildBuiltinDbContainerPrefix(containerPrefix)}-${envName}-${dbDialect}`);
|
|
1204
1211
|
}
|
|
1205
|
-
static buildDockerAppContainerName(envName,
|
|
1206
|
-
return Install.sanitizeDockerResourceName(`${Install.
|
|
1212
|
+
static buildDockerAppContainerName(envName, containerPrefix) {
|
|
1213
|
+
return Install.sanitizeDockerResourceName(`${Install.buildBuiltinDbContainerPrefix(containerPrefix)}-${envName}-app`);
|
|
1207
1214
|
}
|
|
1208
1215
|
static buildInitAppEnvVars(params) {
|
|
1209
1216
|
const out = {};
|
|
@@ -1229,8 +1236,8 @@ export default class Install extends Command {
|
|
|
1229
1236
|
const dbPort = String(params.dbPort ?? defaultDbPortForDialect(dbDialect)).trim()
|
|
1230
1237
|
|| defaultDbPortForDialect(dbDialect);
|
|
1231
1238
|
const defaultDbDatabase = defaultDbDatabaseForDialect(dbDialect);
|
|
1232
|
-
const networkName = Install.buildBuiltinDbNetworkName(params.envName, params.workspaceName);
|
|
1233
|
-
const containerName = Install.buildBuiltinDbContainerName(params.envName, dbDialect, params.workspaceName);
|
|
1239
|
+
const networkName = Install.buildBuiltinDbNetworkName(params.envName, params.dockerNetworkName ?? params.workspaceName);
|
|
1240
|
+
const containerName = Install.buildBuiltinDbContainerName(params.envName, dbDialect, params.dockerContainerPrefix ?? params.workspaceName);
|
|
1234
1241
|
const dbHostInput = String(params.dbHost ?? '').trim();
|
|
1235
1242
|
const dbHost = Install.shouldPublishBuiltinDbPort(params.source)
|
|
1236
1243
|
? (dbHostInput
|
|
@@ -1520,6 +1527,8 @@ export default class Install extends Command {
|
|
|
1520
1527
|
const plan = Install.buildBuiltinDbPlan({
|
|
1521
1528
|
envName: params.envName,
|
|
1522
1529
|
workspaceName: params.workspaceName,
|
|
1530
|
+
dockerNetworkName: params.dockerNetworkName,
|
|
1531
|
+
dockerContainerPrefix: params.dockerContainerPrefix,
|
|
1523
1532
|
storagePath,
|
|
1524
1533
|
source: params.downloadResults.source,
|
|
1525
1534
|
dbDialect: params.dbResults.dbDialect,
|
|
@@ -1567,7 +1576,7 @@ export default class Install extends Command {
|
|
|
1567
1576
|
const dbPassword = String(params.dbResults.dbPassword ?? DEFAULT_INSTALL_DB_PASSWORD) || DEFAULT_INSTALL_DB_PASSWORD;
|
|
1568
1577
|
const appKey = crypto.randomBytes(32).toString('hex');
|
|
1569
1578
|
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';
|
|
1570
|
-
const containerName = Install.buildDockerAppContainerName(params.envName, params.workspaceName);
|
|
1579
|
+
const containerName = Install.buildDockerAppContainerName(params.envName, params.dockerContainerPrefix ?? params.workspaceName);
|
|
1571
1580
|
const initEnvVars = Install.buildInitAppEnvVars({
|
|
1572
1581
|
appResults: params.appResults,
|
|
1573
1582
|
rootResults: params.rootResults,
|
|
@@ -1615,11 +1624,12 @@ export default class Install extends Command {
|
|
|
1615
1624
|
}
|
|
1616
1625
|
async installDockerApp(params) {
|
|
1617
1626
|
const networkName = params.builtinDbPlan?.networkName
|
|
1618
|
-
?? Install.buildBuiltinDbNetworkName(params.envName, params.workspaceName);
|
|
1627
|
+
?? Install.buildBuiltinDbNetworkName(params.envName, params.dockerNetworkName ?? params.workspaceName);
|
|
1619
1628
|
await this.ensureDockerNetwork(networkName);
|
|
1620
1629
|
const plan = Install.buildDockerAppPlan({
|
|
1621
1630
|
envName: params.envName,
|
|
1622
1631
|
workspaceName: params.workspaceName,
|
|
1632
|
+
dockerContainerPrefix: params.dockerContainerPrefix,
|
|
1623
1633
|
appResults: params.appResults,
|
|
1624
1634
|
downloadResults: params.downloadResults,
|
|
1625
1635
|
dbResults: params.dbResults,
|
|
@@ -2076,8 +2086,11 @@ export default class Install extends Command {
|
|
|
2076
2086
|
const source = String(downloadResultsValue(downloadResults, 'source') ?? '').trim();
|
|
2077
2087
|
const usesDockerResources = Boolean(dbResults.builtinDb)
|
|
2078
2088
|
|| (Boolean(appResults.fetchSource) && source === 'docker');
|
|
2079
|
-
const
|
|
2080
|
-
? await
|
|
2089
|
+
const dockerNetworkName = usesDockerResources
|
|
2090
|
+
? await resolveDockerNetworkName({ scope: resolveDefaultConfigScope() })
|
|
2091
|
+
: undefined;
|
|
2092
|
+
const dockerContainerPrefix = usesDockerResources
|
|
2093
|
+
? await resolveDockerContainerPrefix({ scope: resolveDefaultConfigScope() })
|
|
2081
2094
|
: undefined;
|
|
2082
2095
|
await Install.ensureExternalDbReadyForInstall(dbResults);
|
|
2083
2096
|
if (!parsed.resume) {
|
|
@@ -2095,7 +2108,8 @@ export default class Install extends Command {
|
|
|
2095
2108
|
if (Boolean(dbResults.builtinDb)) {
|
|
2096
2109
|
builtinDbPlan = await this.startBuiltinDb({
|
|
2097
2110
|
envName,
|
|
2098
|
-
|
|
2111
|
+
dockerNetworkName,
|
|
2112
|
+
dockerContainerPrefix,
|
|
2099
2113
|
appResults,
|
|
2100
2114
|
downloadResults,
|
|
2101
2115
|
dbResults,
|
|
@@ -2119,7 +2133,8 @@ export default class Install extends Command {
|
|
|
2119
2133
|
});
|
|
2120
2134
|
dockerAppPlan = await this.installDockerApp({
|
|
2121
2135
|
envName,
|
|
2122
|
-
|
|
2136
|
+
dockerNetworkName,
|
|
2137
|
+
dockerContainerPrefix,
|
|
2123
2138
|
appResults,
|
|
2124
2139
|
downloadResults,
|
|
2125
2140
|
dbResults,
|