@nocobase/cli 2.1.0-alpha.25 → 2.1.0-alpha.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -49
- package/README.zh-CN.md +40 -47
- package/dist/commands/app/down.js +259 -0
- package/dist/commands/app/logs.js +98 -0
- package/dist/commands/app/restart.js +75 -0
- package/dist/commands/app/start.js +252 -0
- package/dist/commands/app/stop.js +98 -0
- package/dist/commands/app/upgrade.js +579 -0
- package/dist/commands/build.js +3 -48
- package/dist/commands/config/delete.js +30 -0
- package/dist/commands/config/get.js +29 -0
- package/dist/commands/config/index.js +20 -0
- package/dist/commands/config/list.js +29 -0
- package/dist/commands/config/set.js +35 -0
- package/dist/commands/db/check.js +230 -0
- package/dist/commands/db/shared.js +1 -1
- package/dist/commands/dev.js +3 -147
- package/dist/commands/down.js +3 -188
- package/dist/commands/download.js +4 -856
- package/dist/commands/env/add.js +28 -23
- package/dist/commands/env/info.js +152 -0
- package/dist/commands/env/list.js +23 -9
- package/dist/commands/env/shared.js +158 -0
- package/dist/commands/{prompts-stages.js → examples/prompts-stages.js} +3 -3
- package/dist/commands/{prompts-test.js → examples/prompts-test.js} +3 -3
- package/dist/commands/init.js +83 -6
- package/dist/commands/install.js +361 -82
- package/dist/commands/license/activate.js +357 -0
- package/dist/commands/license/env.js +94 -0
- package/dist/commands/license/generate-id.js +107 -0
- package/dist/commands/license/id.js +52 -0
- package/dist/commands/license/index.js +20 -0
- package/dist/commands/license/plugins/clean.js +98 -0
- package/dist/commands/license/plugins/index.js +20 -0
- package/dist/commands/license/plugins/list.js +50 -0
- package/dist/commands/license/plugins/shared.js +325 -0
- package/dist/commands/license/plugins/sync.js +267 -0
- package/dist/commands/license/shared.js +411 -0
- package/dist/commands/license/status.js +50 -0
- package/dist/commands/logs.js +3 -88
- package/dist/commands/plugin/disable.js +64 -0
- package/dist/commands/plugin/enable.js +64 -0
- package/dist/commands/plugin/list.js +62 -0
- package/dist/commands/pm/disable.js +3 -54
- package/dist/commands/pm/enable.js +3 -54
- package/dist/commands/pm/list.js +3 -52
- package/dist/commands/restart.js +3 -65
- package/dist/commands/scaffold/migration.js +1 -1
- package/dist/commands/scaffold/plugin.js +1 -1
- package/dist/commands/skills/remove.js +71 -0
- package/dist/commands/skills/update.js +7 -0
- package/dist/commands/source/build.js +58 -0
- package/dist/commands/source/dev.js +157 -0
- package/dist/commands/source/download.js +866 -0
- package/dist/commands/source/test.js +467 -0
- package/dist/commands/start.js +3 -209
- package/dist/commands/stop.js +3 -88
- package/dist/commands/test.js +3 -457
- package/dist/commands/upgrade.js +3 -585
- package/dist/help/runtime-help.js +3 -0
- package/dist/lib/api-client.js +94 -9
- package/dist/lib/app-health.js +126 -0
- package/dist/lib/app-managed-resources.js +264 -0
- package/dist/lib/app-runtime.js +26 -10
- package/dist/lib/auth-store.js +29 -63
- package/dist/lib/build-config.js +8 -0
- package/dist/lib/cli-config.js +176 -0
- package/dist/lib/cli-home.js +12 -26
- package/dist/lib/cli-locale.js +15 -1
- package/dist/lib/db-connection-check.js +178 -0
- package/dist/lib/env-config.js +80 -0
- package/dist/lib/generated-command.js +23 -3
- package/dist/lib/plugin-storage.js +127 -0
- package/dist/lib/prompt-validators.js +4 -4
- package/dist/lib/prompt-web-ui.js +13 -6
- package/dist/lib/runtime-generator.js +89 -10
- package/dist/lib/self-manager.js +57 -2
- package/dist/lib/skills-manager.js +34 -7
- package/dist/lib/startup-update.js +85 -7
- package/dist/locale/en-US.json +16 -13
- package/dist/locale/zh-CN.json +16 -13
- package/nocobase-ctl.config.json +82 -0
- package/package.json +41 -6
- package/dist/commands/ps.js +0 -119
|
@@ -0,0 +1,29 @@
|
|
|
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, getCliConfigValue } from '../../lib/cli-config.js';
|
|
11
|
+
export default class ConfigGet extends Command {
|
|
12
|
+
static summary = 'Get the effective CLI configuration value for a key';
|
|
13
|
+
static examples = [
|
|
14
|
+
'<%= config.bin %> <%= command.id %> license.pkg-url',
|
|
15
|
+
'<%= config.bin %> <%= command.id %> docker.network',
|
|
16
|
+
'<%= config.bin %> <%= command.id %> docker.container-prefix',
|
|
17
|
+
];
|
|
18
|
+
static args = {
|
|
19
|
+
key: Args.string({
|
|
20
|
+
description: 'Configuration key',
|
|
21
|
+
required: true,
|
|
22
|
+
}),
|
|
23
|
+
};
|
|
24
|
+
async run() {
|
|
25
|
+
const { args } = await this.parse(ConfigGet);
|
|
26
|
+
const key = assertSupportedCliConfigKey(args.key);
|
|
27
|
+
this.log(await getCliConfigValue(key));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Command, loadHelpClass } from '@oclif/core';
|
|
10
|
+
export default class Config extends Command {
|
|
11
|
+
static summary = 'Manage CLI configuration defaults';
|
|
12
|
+
async run() {
|
|
13
|
+
await this.parse(Config);
|
|
14
|
+
const Help = await loadHelpClass(this.config);
|
|
15
|
+
await new Help(this.config, this.config.pjson.oclif.helpOptions ?? this.config.pjson.helpOptions).showHelp([
|
|
16
|
+
this.id ?? 'config',
|
|
17
|
+
...this.argv,
|
|
18
|
+
]);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
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 } from '@oclif/core';
|
|
10
|
+
import { listExplicitCliConfigValues, SUPPORTED_CLI_CONFIG_KEYS } from '../../lib/cli-config.js';
|
|
11
|
+
import { renderTable } from '../../lib/ui.js';
|
|
12
|
+
export default class ConfigList extends Command {
|
|
13
|
+
static summary = 'List explicitly configured CLI settings';
|
|
14
|
+
static examples = [
|
|
15
|
+
'<%= config.bin %> <%= command.id %>',
|
|
16
|
+
];
|
|
17
|
+
async run() {
|
|
18
|
+
await this.parse(ConfigList);
|
|
19
|
+
const values = await listExplicitCliConfigValues();
|
|
20
|
+
const rows = SUPPORTED_CLI_CONFIG_KEYS
|
|
21
|
+
.filter((key) => Boolean(values[key]))
|
|
22
|
+
.map((key) => [key, values[key] ?? '']);
|
|
23
|
+
if (!rows.length) {
|
|
24
|
+
this.log('No CLI config values are set.');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
this.log(renderTable(['Key', 'Value'], rows));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
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 { checkExternalDbConnection, formatDbCheckAddress, readExternalDbConnectionConfig, } from "../../lib/db-connection-check.js";
|
|
12
|
+
import { commandOutput } from '../../lib/run-npm.js';
|
|
13
|
+
import { validateTcpPort } from "../../lib/prompt-validators.js";
|
|
14
|
+
const DEFAULT_DOCKER_REGISTRY = 'nocobase/nocobase';
|
|
15
|
+
const DEFAULT_DOCKER_VERSION = 'alpha';
|
|
16
|
+
function trimValue(value) {
|
|
17
|
+
const text = String(value ?? '').trim();
|
|
18
|
+
return text || undefined;
|
|
19
|
+
}
|
|
20
|
+
function resolveRequiredDbField(flagValue, envValue) {
|
|
21
|
+
return trimValue(flagValue) ?? trimValue(envValue);
|
|
22
|
+
}
|
|
23
|
+
function normalizeDockerPlatform(value) {
|
|
24
|
+
const text = trimValue(value);
|
|
25
|
+
if (!text || text === 'auto') {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
if (text === 'linux/amd64' || text === 'linux/arm64') {
|
|
29
|
+
return text;
|
|
30
|
+
}
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
function formatMissingFieldsMessage(missing, hasEnv) {
|
|
34
|
+
return [
|
|
35
|
+
'Missing database settings for connectivity check.',
|
|
36
|
+
`Required: ${missing.join(', ')}.`,
|
|
37
|
+
hasEnv
|
|
38
|
+
? 'Pass `--env <name>` to reuse a saved env, or provide the missing `--db-*` flags explicitly.'
|
|
39
|
+
: 'Provide all required `--db-*` flags explicitly, or pass `--env <name>` to reuse a saved env.',
|
|
40
|
+
].join('\n');
|
|
41
|
+
}
|
|
42
|
+
function resolveDbConfigFromFlags(flags, envConfig) {
|
|
43
|
+
return {
|
|
44
|
+
builtinDb: false,
|
|
45
|
+
dbDialect: resolveRequiredDbField(flags['db-dialect'], envConfig?.dbDialect),
|
|
46
|
+
dbHost: resolveRequiredDbField(flags['db-host'], envConfig?.dbHost),
|
|
47
|
+
dbPort: resolveRequiredDbField(flags['db-port'], envConfig?.dbPort),
|
|
48
|
+
dbDatabase: resolveRequiredDbField(flags['db-database'], envConfig?.dbDatabase),
|
|
49
|
+
dbUser: resolveRequiredDbField(flags['db-user'], envConfig?.dbUser),
|
|
50
|
+
dbPassword: flags['db-password'] !== undefined
|
|
51
|
+
? String(flags['db-password'] ?? '')
|
|
52
|
+
: envConfig?.dbPassword !== undefined
|
|
53
|
+
? String(envConfig.dbPassword ?? '')
|
|
54
|
+
: undefined,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function validateDbConfigOrThrow(command, dbConfig, hasEnv) {
|
|
58
|
+
const missing = [];
|
|
59
|
+
if (!dbConfig.dbDialect) {
|
|
60
|
+
missing.push('--db-dialect');
|
|
61
|
+
}
|
|
62
|
+
if (!dbConfig.dbHost) {
|
|
63
|
+
missing.push('--db-host');
|
|
64
|
+
}
|
|
65
|
+
if (!dbConfig.dbPort) {
|
|
66
|
+
missing.push('--db-port');
|
|
67
|
+
}
|
|
68
|
+
if (!dbConfig.dbDatabase) {
|
|
69
|
+
missing.push('--db-database');
|
|
70
|
+
}
|
|
71
|
+
if (!dbConfig.dbUser) {
|
|
72
|
+
missing.push('--db-user');
|
|
73
|
+
}
|
|
74
|
+
if (!dbConfig.dbPassword) {
|
|
75
|
+
missing.push('--db-password');
|
|
76
|
+
}
|
|
77
|
+
if (missing.length > 0) {
|
|
78
|
+
command.error(formatMissingFieldsMessage(missing, hasEnv));
|
|
79
|
+
}
|
|
80
|
+
const portError = validateTcpPort(dbConfig.dbPort);
|
|
81
|
+
if (portError) {
|
|
82
|
+
command.error(portError);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function resolveDbCheckInput(command, flags) {
|
|
86
|
+
const envName = flags.env?.trim() || undefined;
|
|
87
|
+
if (!envName) {
|
|
88
|
+
const dbConfig = resolveDbConfigFromFlags(flags);
|
|
89
|
+
validateDbConfigOrThrow(command, dbConfig, false);
|
|
90
|
+
return {
|
|
91
|
+
dbConfig,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const runtime = await resolveManagedAppRuntime(envName);
|
|
95
|
+
if (!runtime) {
|
|
96
|
+
command.error(formatMissingManagedAppEnvMessage(envName));
|
|
97
|
+
}
|
|
98
|
+
const dbConfig = resolveDbConfigFromFlags(flags, runtime.env.config);
|
|
99
|
+
validateDbConfigOrThrow(command, dbConfig, true);
|
|
100
|
+
return {
|
|
101
|
+
envName: runtime.envName,
|
|
102
|
+
kind: runtime.kind,
|
|
103
|
+
runtime: runtime,
|
|
104
|
+
dbConfig,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function buildConnectionConfigOrThrow(command, dbConfig) {
|
|
108
|
+
const connectionConfig = readExternalDbConnectionConfig(dbConfig);
|
|
109
|
+
if (!connectionConfig) {
|
|
110
|
+
command.error('Unsupported or incomplete database settings for connectivity check.');
|
|
111
|
+
}
|
|
112
|
+
return connectionConfig;
|
|
113
|
+
}
|
|
114
|
+
async function runExplicitDbCheck(command, dbConfig) {
|
|
115
|
+
const connectionConfig = buildConnectionConfigOrThrow(command, dbConfig);
|
|
116
|
+
const address = formatDbCheckAddress(connectionConfig);
|
|
117
|
+
const validationError = await checkExternalDbConnection(connectionConfig);
|
|
118
|
+
return {
|
|
119
|
+
ok: !validationError,
|
|
120
|
+
dialect: connectionConfig.dialect,
|
|
121
|
+
address,
|
|
122
|
+
error: validationError ?? null,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
async function runDockerDbCheck(command, runtime, dbConfig) {
|
|
126
|
+
const connectionConfig = buildConnectionConfigOrThrow(command, dbConfig);
|
|
127
|
+
const config = runtime.env.config ?? {};
|
|
128
|
+
const imageRef = `${trimValue(config.dockerRegistry) || DEFAULT_DOCKER_REGISTRY}:${trimValue(config.downloadVersion) || DEFAULT_DOCKER_VERSION}`;
|
|
129
|
+
const args = [
|
|
130
|
+
'run',
|
|
131
|
+
'--rm',
|
|
132
|
+
'--network',
|
|
133
|
+
runtime.dockerNetworkName || runtime.workspaceName,
|
|
134
|
+
];
|
|
135
|
+
const dockerPlatform = normalizeDockerPlatform(config.dockerPlatform);
|
|
136
|
+
if (dockerPlatform) {
|
|
137
|
+
args.push('--platform', dockerPlatform);
|
|
138
|
+
}
|
|
139
|
+
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');
|
|
140
|
+
const output = await commandOutput('docker', args, {
|
|
141
|
+
errorName: 'docker run',
|
|
142
|
+
});
|
|
143
|
+
let payload;
|
|
144
|
+
try {
|
|
145
|
+
payload = JSON.parse(output);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
command.error(`Failed to parse database check response from Docker: ${output}`);
|
|
149
|
+
}
|
|
150
|
+
const ok = Boolean(payload.ok);
|
|
151
|
+
const dialect = trimValue(payload.dialect) || connectionConfig.dialect;
|
|
152
|
+
const address = trimValue(payload.address) || formatDbCheckAddress(connectionConfig);
|
|
153
|
+
const error = trimValue(payload.error) || null;
|
|
154
|
+
return {
|
|
155
|
+
ok,
|
|
156
|
+
dialect,
|
|
157
|
+
address,
|
|
158
|
+
error,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
async function runDbCheckForRuntime(command, runtime, dbConfig) {
|
|
162
|
+
if (runtime.kind === 'docker') {
|
|
163
|
+
return await runDockerDbCheck(command, runtime, dbConfig);
|
|
164
|
+
}
|
|
165
|
+
if (runtime.kind === 'local') {
|
|
166
|
+
return await runExplicitDbCheck(command, dbConfig);
|
|
167
|
+
}
|
|
168
|
+
command.error(`Env "${runtime.envName}" does not support automatic database connectivity checks.`);
|
|
169
|
+
}
|
|
170
|
+
export default class DbCheck extends Command {
|
|
171
|
+
static description = 'Check whether a database is reachable using the selected env settings or explicit `--db-*` flags.';
|
|
172
|
+
static examples = [
|
|
173
|
+
'<%= config.bin %> <%= command.id %> --env app1',
|
|
174
|
+
'<%= config.bin %> <%= command.id %> --env app1 --db-password new-secret --json',
|
|
175
|
+
'<%= 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',
|
|
176
|
+
];
|
|
177
|
+
static flags = {
|
|
178
|
+
env: Flags.string({
|
|
179
|
+
char: 'e',
|
|
180
|
+
description: 'CLI env name to read saved database settings from. Defaults to the current env when omitted.',
|
|
181
|
+
}),
|
|
182
|
+
'db-dialect': Flags.string({
|
|
183
|
+
description: 'Database dialect: postgres, kingbase, mysql, or mariadb.',
|
|
184
|
+
options: ['postgres', 'kingbase', 'mysql', 'mariadb'],
|
|
185
|
+
}),
|
|
186
|
+
'db-host': Flags.string({
|
|
187
|
+
description: 'Database host name or IP address.',
|
|
188
|
+
}),
|
|
189
|
+
'db-port': Flags.string({
|
|
190
|
+
description: 'Database TCP port.',
|
|
191
|
+
}),
|
|
192
|
+
'db-database': Flags.string({
|
|
193
|
+
description: 'Database name.',
|
|
194
|
+
}),
|
|
195
|
+
'db-user': Flags.string({
|
|
196
|
+
description: 'Database username.',
|
|
197
|
+
}),
|
|
198
|
+
'db-password': Flags.string({
|
|
199
|
+
description: 'Database password.',
|
|
200
|
+
}),
|
|
201
|
+
json: Flags.boolean({
|
|
202
|
+
description: 'Output the check result as JSON.',
|
|
203
|
+
default: false,
|
|
204
|
+
}),
|
|
205
|
+
};
|
|
206
|
+
async run() {
|
|
207
|
+
const { flags } = await this.parse(DbCheck);
|
|
208
|
+
const input = await resolveDbCheckInput(this, flags);
|
|
209
|
+
const result = input.runtime
|
|
210
|
+
? await runDbCheckForRuntime(this, input.runtime, input.dbConfig)
|
|
211
|
+
: await runExplicitDbCheck(this, input.dbConfig);
|
|
212
|
+
if (flags.json) {
|
|
213
|
+
this.log(JSON.stringify({
|
|
214
|
+
ok: result.ok,
|
|
215
|
+
env: input.envName,
|
|
216
|
+
kind: input.kind,
|
|
217
|
+
dialect: result.dialect,
|
|
218
|
+
address: result.address,
|
|
219
|
+
error: result.error,
|
|
220
|
+
}, null, 2));
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (!result.ok) {
|
|
224
|
+
this.error(result.error ?? 'Database check failed.');
|
|
225
|
+
}
|
|
226
|
+
this.log(input.envName
|
|
227
|
+
? `Database check passed for env "${input.envName}" (${result.dialect} ${result.address}).`
|
|
228
|
+
: `Database check passed (${result.dialect} ${result.address}).`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
@@ -23,7 +23,7 @@ export async function resolveDbRuntime(envName) {
|
|
|
23
23
|
const source = runtime.kind === 'http' || runtime.kind === 'ssh' ? runtime.kind : runtime.source;
|
|
24
24
|
const dbDialect = String(runtime.env.config.dbDialect ?? 'postgres').trim() || 'postgres';
|
|
25
25
|
if ((runtime.kind === 'local' || runtime.kind === 'docker') && runtime.env.config.builtinDb) {
|
|
26
|
-
const containerName = buildDockerDbContainerName(runtime.envName, dbDialect, runtime.workspaceName);
|
|
26
|
+
const containerName = buildDockerDbContainerName(runtime.envName, dbDialect, runtime.dockerContainerPrefix || runtime.workspaceName);
|
|
27
27
|
return {
|
|
28
28
|
kind: 'builtin',
|
|
29
29
|
envName: runtime.envName,
|
package/dist/commands/dev.js
CHANGED
|
@@ -6,151 +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
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
function formatUnsupportedRuntimeMessage(kind, envName) {
|
|
13
|
-
if (kind === 'docker') {
|
|
14
|
-
return [
|
|
15
|
-
`Can't run dev mode for "${envName}".`,
|
|
16
|
-
'This env is managed by Docker, but `nb dev` requires a local npm or Git source directory.',
|
|
17
|
-
`Use \`nb logs --env ${envName}\` to inspect the Docker app, or create a source-based env with \`nb init --env ${envName} --source git\`.`,
|
|
18
|
-
].join('\n');
|
|
19
|
-
}
|
|
20
|
-
if (kind === 'ssh') {
|
|
21
|
-
return [
|
|
22
|
-
`Can't run dev mode for "${envName}" yet.`,
|
|
23
|
-
'SSH env support is reserved but not implemented yet.',
|
|
24
|
-
`Create a source-based env with \`nb init --env ${envName} --source git\` if you want local development mode right now.`,
|
|
25
|
-
].join('\n');
|
|
26
|
-
}
|
|
27
|
-
return [
|
|
28
|
-
`Can't run dev mode for "${envName}".`,
|
|
29
|
-
'This env only has an API connection, but `nb dev` requires a local npm or Git source directory.',
|
|
30
|
-
`Create a source-based env with \`nb init --env ${envName} --source git\` if you want local development mode.`,
|
|
31
|
-
].join('\n');
|
|
32
|
-
}
|
|
33
|
-
function appUrlForPort(port) {
|
|
34
|
-
const value = String(port ?? '').trim();
|
|
35
|
-
if (!value) {
|
|
36
|
-
return undefined;
|
|
37
|
-
}
|
|
38
|
-
return `http://127.0.0.1:${value}`;
|
|
39
|
-
}
|
|
40
|
-
async function isAppAlreadyRunning(appUrl) {
|
|
41
|
-
if (!appUrl) {
|
|
42
|
-
return false;
|
|
43
|
-
}
|
|
44
|
-
const controller = new AbortController();
|
|
45
|
-
const timeout = setTimeout(() => controller.abort(), 1500);
|
|
46
|
-
try {
|
|
47
|
-
const response = await fetch(`${appUrl}/api/__health_check`, {
|
|
48
|
-
signal: controller.signal,
|
|
49
|
-
});
|
|
50
|
-
const text = await response.text();
|
|
51
|
-
return response.ok && text.trim().toLowerCase() === 'ok';
|
|
52
|
-
}
|
|
53
|
-
catch (_error) {
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
finally {
|
|
57
|
-
clearTimeout(timeout);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
export default class Dev extends Command {
|
|
61
|
-
static description = 'Run NocoBase in local development mode for an npm or Git source env.';
|
|
62
|
-
static examples = [
|
|
63
|
-
'<%= config.bin %> <%= command.id %>',
|
|
64
|
-
'<%= config.bin %> <%= command.id %> --env app1',
|
|
65
|
-
'<%= config.bin %> <%= command.id %> --env app1 --db-sync',
|
|
66
|
-
'<%= config.bin %> <%= command.id %> --env app1 --port 12000',
|
|
67
|
-
'<%= config.bin %> <%= command.id %> --env app1 --client',
|
|
68
|
-
'<%= config.bin %> <%= command.id %> --env app1 --server',
|
|
69
|
-
'<%= config.bin %> <%= command.id %> --env app1 --inspect 9229',
|
|
70
|
-
];
|
|
71
|
-
static flags = {
|
|
72
|
-
env: Flags.string({
|
|
73
|
-
char: 'e',
|
|
74
|
-
description: 'CLI env name for dev mode. Defaults to the current env when omitted',
|
|
75
|
-
required: false,
|
|
76
|
-
}),
|
|
77
|
-
'db-sync': Flags.boolean({
|
|
78
|
-
description: 'Synchronize the database before starting dev mode',
|
|
79
|
-
required: false,
|
|
80
|
-
}),
|
|
81
|
-
port: Flags.string({
|
|
82
|
-
description: 'Development server port',
|
|
83
|
-
char: 'p',
|
|
84
|
-
required: false,
|
|
85
|
-
}),
|
|
86
|
-
client: Flags.boolean({
|
|
87
|
-
description: 'Run client dev mode only',
|
|
88
|
-
char: 'c',
|
|
89
|
-
required: false,
|
|
90
|
-
}),
|
|
91
|
-
server: Flags.boolean({
|
|
92
|
-
description: 'Run server dev mode only',
|
|
93
|
-
char: 's',
|
|
94
|
-
required: false,
|
|
95
|
-
}),
|
|
96
|
-
inspect: Flags.string({
|
|
97
|
-
description: 'Node.js inspect port for server debugging',
|
|
98
|
-
char: 'i',
|
|
99
|
-
required: false,
|
|
100
|
-
}),
|
|
101
|
-
};
|
|
102
|
-
async run() {
|
|
103
|
-
const { flags } = await this.parse(Dev);
|
|
104
|
-
const requestedEnv = flags.env?.trim() || undefined;
|
|
105
|
-
const runtime = await resolveManagedAppRuntime(requestedEnv);
|
|
106
|
-
if (!runtime) {
|
|
107
|
-
this.error(formatMissingManagedAppEnvMessage(requestedEnv));
|
|
108
|
-
}
|
|
109
|
-
if (runtime.kind === 'docker' || runtime.kind === 'http' || runtime.kind === 'ssh') {
|
|
110
|
-
this.error(formatUnsupportedRuntimeMessage(runtime.kind, runtime.envName));
|
|
111
|
-
}
|
|
112
|
-
const devPort = flags.port
|
|
113
|
-
|| (runtime.env.appPort !== undefined && runtime.env.appPort !== null
|
|
114
|
-
? String(runtime.env.appPort).trim()
|
|
115
|
-
: undefined);
|
|
116
|
-
const appUrl = appUrlForPort(devPort);
|
|
117
|
-
if (await isAppAlreadyRunning(appUrl)) {
|
|
118
|
-
this.error([
|
|
119
|
-
`NocoBase is already running for "${runtime.envName}"${appUrl ? ` at ${appUrl}` : ''}.`,
|
|
120
|
-
flags.port
|
|
121
|
-
? `Choose another dev port with --port, or stop the running app with \`nb stop --env ${runtime.envName}\` first.`
|
|
122
|
-
: `Run \`nb stop --env ${runtime.envName}\` before starting dev mode, or choose another dev port with --port.`,
|
|
123
|
-
].join('\n'));
|
|
124
|
-
}
|
|
125
|
-
const npmArgs = ['dev', '--rsbuild'];
|
|
126
|
-
if (flags['db-sync']) {
|
|
127
|
-
npmArgs.push('--db-sync');
|
|
128
|
-
}
|
|
129
|
-
if (devPort) {
|
|
130
|
-
npmArgs.push('--port', devPort);
|
|
131
|
-
}
|
|
132
|
-
if (flags.client) {
|
|
133
|
-
npmArgs.push('--client');
|
|
134
|
-
}
|
|
135
|
-
if (flags.server) {
|
|
136
|
-
npmArgs.push('--server');
|
|
137
|
-
}
|
|
138
|
-
if (flags.inspect) {
|
|
139
|
-
npmArgs.push('--inspect', flags.inspect);
|
|
140
|
-
}
|
|
141
|
-
printInfo(`Starting NocoBase dev mode for "${runtime.envName}" from ${runtime.projectRoot}. Press Ctrl+C to stop.`);
|
|
142
|
-
try {
|
|
143
|
-
await runLocalNocoBaseCommand(runtime, npmArgs, {
|
|
144
|
-
stdio: 'inherit',
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
catch (error) {
|
|
148
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
149
|
-
this.error([
|
|
150
|
-
`Couldn't start dev mode for "${runtime.envName}".`,
|
|
151
|
-
'Check that dependencies are installed and the saved env settings are valid, then try again.',
|
|
152
|
-
`Details: ${message}`,
|
|
153
|
-
].join('\n'));
|
|
154
|
-
}
|
|
155
|
-
}
|
|
9
|
+
import SourceDev from './source/dev.js';
|
|
10
|
+
export default class Dev extends SourceDev {
|
|
11
|
+
static hidden = true;
|
|
156
12
|
}
|