@nocobase/cli 2.2.0-alpha.4 → 2.2.0-alpha.5
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/dist/commands/install.js +34 -35
- package/dist/commands/proxy/caddy/generate.js +11 -11
- package/dist/commands/proxy/nginx/generate.js +11 -11
- package/dist/commands/revision/create.js +1 -1
- package/dist/commands/source/download.js +16 -12
- package/dist/lib/app-managed-resources.js +3 -2
- package/dist/lib/auth-store.js +7 -0
- package/dist/lib/cli-config.js +52 -1
- package/dist/lib/docker-image.js +94 -6
- package/dist/lib/env-proxy.js +19 -3
- package/package.json +2 -2
package/dist/commands/install.js
CHANGED
|
@@ -13,11 +13,11 @@ import path from 'node:path';
|
|
|
13
13
|
import { exit } from 'node:process';
|
|
14
14
|
import { appendAppPublicPath } from '../lib/app-public-path.js';
|
|
15
15
|
import { runPromptCatalog, } from "../lib/prompt-catalog.js";
|
|
16
|
-
import { applyCliLocale, localeText,
|
|
16
|
+
import { applyCliLocale, localeText, translateCli } from "../lib/cli-locale.js";
|
|
17
17
|
import { resolveConfiguredEnvPath, resolveDefaultConfigScope, resolveEnvRoot, resolveEnvRelativePath, } from '../lib/cli-home.js';
|
|
18
18
|
import { defaultDockerContainerPrefix, defaultDockerNetworkName, managedAppLifecycleEnvVars, } from '../lib/app-runtime.js';
|
|
19
|
-
import { resolveDefaultApiHost, resolveDockerContainerPrefix, resolveDockerNetworkName } from '../lib/cli-config.js';
|
|
20
|
-
import { DEFAULT_DOCKER_VERSION, resolveDockerImageRef } from "../lib/docker-image.js";
|
|
19
|
+
import { getCliConfigValue, resolveDefaultApiHost, resolveDockerContainerPrefix, resolveDockerNetworkName, } from '../lib/cli-config.js';
|
|
20
|
+
import { DEFAULT_DOCKER_VERSION, DEFAULT_NB_IMAGE_VARIANT, inferNbImageRegistryFromRepository, normalizeNbImageVariant, resolveBuiltinDbImage, resolveDockerImageContainerPort, resolveDockerImageRef, resolveOfficialDockerRegistry, } from "../lib/docker-image.js";
|
|
21
21
|
import { findAvailableTcpPort, validateAppPublicPath, validateAvailableTcpPort, validateTcpPort, validateEnvKey, } from "../lib/prompt-validators.js";
|
|
22
22
|
import { validateExternalDbConfig, validateMysqlLowerCaseTableNamesCompatibility } from "../lib/db-connection-check.js";
|
|
23
23
|
import { formatMissingManagedAppEnvMessage } from '../lib/app-runtime.js';
|
|
@@ -31,7 +31,7 @@ import { startDockerLogFollower } from '../lib/docker-log-stream.js';
|
|
|
31
31
|
import { buildInitAppEnvVarsFromConfig } from '../lib/managed-init-env.js';
|
|
32
32
|
import { buildHookContext, persistHookScript, resolveHookScriptPath, runHookScriptHook, } from '../lib/hook-script.js';
|
|
33
33
|
import { areConfiguredPathsEquivalent, deriveConfiguredSourcePath, deriveConfiguredStoragePath, inferConfiguredAppPathFromLegacyConfig, } from '../lib/env-paths.js';
|
|
34
|
-
import Download
|
|
34
|
+
import Download from './download.js';
|
|
35
35
|
import EnvAdd from "./env/add.js";
|
|
36
36
|
import { resolveAppUrlFromApiBaseUrl } from "./env/shared.js";
|
|
37
37
|
const DEFAULT_INSTALL_ENV_NAME = 'local';
|
|
@@ -45,18 +45,6 @@ const DEFAULT_INSTALL_DB_PORTS = {
|
|
|
45
45
|
mariadb: '3306',
|
|
46
46
|
kingbase: '54321',
|
|
47
47
|
};
|
|
48
|
-
const DEFAULT_INSTALL_BUILTIN_DB_IMAGES = {
|
|
49
|
-
postgres: 'postgres:16',
|
|
50
|
-
mysql: 'mysql:8',
|
|
51
|
-
mariadb: 'mariadb:11',
|
|
52
|
-
kingbase: 'registry.cn-shanghai.aliyuncs.com/nocobase/kingbase:v009r001c001b0030_single_x86',
|
|
53
|
-
};
|
|
54
|
-
const DEFAULT_INSTALL_BUILTIN_DB_IMAGES_ZH_CN = {
|
|
55
|
-
postgres: 'registry.cn-shanghai.aliyuncs.com/nocobase/postgres:16',
|
|
56
|
-
mysql: 'registry.cn-shanghai.aliyuncs.com/nocobase/mysql:8',
|
|
57
|
-
mariadb: 'registry.cn-shanghai.aliyuncs.com/nocobase/mariadb:11',
|
|
58
|
-
kingbase: 'registry.cn-shanghai.aliyuncs.com/nocobase/kingbase:v009r001c001b0030_single_x86',
|
|
59
|
-
};
|
|
60
48
|
const DEFAULT_INSTALL_DB_DATABASE = 'nocobase';
|
|
61
49
|
const DEFAULT_INSTALL_DB_USER = 'nocobase';
|
|
62
50
|
const DEFAULT_INSTALL_DB_PASSWORD = 'nocobase';
|
|
@@ -179,18 +167,15 @@ function downloadVersionPromptValue(version) {
|
|
|
179
167
|
}
|
|
180
168
|
function supportsBuiltinDbDialect(value) {
|
|
181
169
|
const dialect = String(value ?? '').trim();
|
|
182
|
-
return
|
|
170
|
+
return INSTALL_DB_DIALECTS.includes(dialect);
|
|
183
171
|
}
|
|
184
172
|
export function defaultDbPortForDialect(value) {
|
|
185
173
|
const dialect = String(value ?? 'postgres').trim();
|
|
186
174
|
return DEFAULT_INSTALL_DB_PORTS[isInstallDbDialect(dialect) ? dialect : 'postgres'];
|
|
187
175
|
}
|
|
188
|
-
function defaultBuiltinDbImageForDialect(value) {
|
|
176
|
+
function defaultBuiltinDbImageForDialect(value, options) {
|
|
189
177
|
const dialect = String(value ?? 'postgres').trim();
|
|
190
|
-
|
|
191
|
-
? DEFAULT_INSTALL_BUILTIN_DB_IMAGES_ZH_CN
|
|
192
|
-
: DEFAULT_INSTALL_BUILTIN_DB_IMAGES;
|
|
193
|
-
return supportsBuiltinDbDialect(dialect) ? defaults[dialect] : defaults.postgres;
|
|
178
|
+
return resolveBuiltinDbImage(dialect, { registry: options?.registry });
|
|
194
179
|
}
|
|
195
180
|
function defaultDbDatabaseForDialect(value) {
|
|
196
181
|
return String(value ?? '').trim() === 'kingbase' ? 'kingbase' : DEFAULT_INSTALL_DB_DATABASE;
|
|
@@ -1279,19 +1264,25 @@ export default class Install extends Command {
|
|
|
1279
1264
|
return builtinDb && Install.shouldPublishBuiltinDbPort(values.source);
|
|
1280
1265
|
}
|
|
1281
1266
|
static async buildDbPromptInitialValues(params) {
|
|
1282
|
-
|
|
1283
|
-
return {};
|
|
1284
|
-
}
|
|
1267
|
+
const configuredRegistry = await getCliConfigValue('nb-image-registry');
|
|
1285
1268
|
const values = {
|
|
1286
1269
|
...params.downloadResults,
|
|
1287
1270
|
...params.dbPreset,
|
|
1288
1271
|
};
|
|
1272
|
+
const dockerRegistry = String(values.dockerRegistry ?? '').trim() || resolveOfficialDockerRegistry(configuredRegistry);
|
|
1273
|
+
const dialect = String(values.dbDialect ?? 'postgres').trim() || 'postgres';
|
|
1274
|
+
const initialValues = values.builtinDb !== false && params.dbPreset.builtinDbImage === undefined
|
|
1275
|
+
? { builtinDbImage: defaultBuiltinDbImageForDialect(dialect, { registry: dockerRegistry }) }
|
|
1276
|
+
: {};
|
|
1277
|
+
if (params.flags['db-port'] !== undefined) {
|
|
1278
|
+
return initialValues;
|
|
1279
|
+
}
|
|
1289
1280
|
if (!Install.shouldPublishBuiltinDbPortForValues(values)) {
|
|
1290
|
-
return
|
|
1281
|
+
return initialValues;
|
|
1291
1282
|
}
|
|
1292
|
-
const dialect = String(values.dbDialect ?? 'postgres').trim() || 'postgres';
|
|
1293
1283
|
const defaultPort = defaultDbPortForDialect(dialect);
|
|
1294
1284
|
return {
|
|
1285
|
+
...initialValues,
|
|
1295
1286
|
dbPort: await Install.resolveAvailableDefaultPort(defaultPort, {
|
|
1296
1287
|
label: `Default ${dialect} port`,
|
|
1297
1288
|
warn: params.warnOnPortFallback ?? true,
|
|
@@ -1302,12 +1293,13 @@ export default class Install extends Command {
|
|
|
1302
1293
|
* When install runs {@link Download.prompts} after app prompts, align the download
|
|
1303
1294
|
* output directory with app settings, while Docker registry defaults follow the CLI locale.
|
|
1304
1295
|
*/
|
|
1305
|
-
static buildDownloadPromptOptionsForInstall(appResults, envName) {
|
|
1296
|
+
static async buildDownloadPromptOptionsForInstall(appResults, envName) {
|
|
1306
1297
|
const appRoot = resolveConfiguredSourcePathValue(appResults, envName);
|
|
1307
1298
|
const lang = String(appResults.lang ?? DEFAULT_INSTALL_LANG).trim() || DEFAULT_INSTALL_LANG;
|
|
1299
|
+
const dockerRegistry = resolveOfficialDockerRegistry(await getCliConfigValue('nb-image-registry'));
|
|
1308
1300
|
const initialValues = {
|
|
1309
1301
|
lang,
|
|
1310
|
-
dockerRegistry
|
|
1302
|
+
dockerRegistry,
|
|
1311
1303
|
outputDir: appRoot,
|
|
1312
1304
|
};
|
|
1313
1305
|
const values = {
|
|
@@ -1760,12 +1752,15 @@ export default class Install extends Command {
|
|
|
1760
1752
|
return plan;
|
|
1761
1753
|
}
|
|
1762
1754
|
static async buildDockerAppPlan(params) {
|
|
1755
|
+
const configuredRegistry = await getCliConfigValue('nb-image-registry');
|
|
1756
|
+
const configuredVariant = normalizeNbImageVariant(await getCliConfigValue('nb-image-variant')) ?? DEFAULT_NB_IMAGE_VARIANT;
|
|
1763
1757
|
const dockerRegistry = String(downloadResultsValue(params.downloadResults, 'dockerRegistry') ?? '').trim() ||
|
|
1764
|
-
|
|
1758
|
+
resolveOfficialDockerRegistry(configuredRegistry);
|
|
1765
1759
|
const version = String(downloadResultsValue(params.downloadResults, 'version') ?? '').trim() || DEFAULT_DOCKER_VERSION;
|
|
1766
1760
|
const imageRef = resolveDockerImageRef(dockerRegistry, version, {
|
|
1767
|
-
defaultRegistry:
|
|
1761
|
+
defaultRegistry: resolveOfficialDockerRegistry(configuredRegistry),
|
|
1768
1762
|
defaultVersion: DEFAULT_DOCKER_VERSION,
|
|
1763
|
+
variant: inferNbImageRegistryFromRepository(dockerRegistry) ? configuredVariant : undefined,
|
|
1769
1764
|
});
|
|
1770
1765
|
const appPort = String(params.appResults.appPort ?? DEFAULT_INSTALL_APP_PORT).trim() || DEFAULT_INSTALL_APP_PORT;
|
|
1771
1766
|
const configuredStoragePath = resolveConfiguredStoragePathValue(params.appResults, params.envName);
|
|
@@ -1792,6 +1787,7 @@ export default class Install extends Command {
|
|
|
1792
1787
|
appResults: params.appResults,
|
|
1793
1788
|
rootResults: params.rootResults,
|
|
1794
1789
|
});
|
|
1790
|
+
const containerPort = resolveDockerImageContainerPort(imageRef);
|
|
1795
1791
|
const args = [
|
|
1796
1792
|
'run',
|
|
1797
1793
|
'-d',
|
|
@@ -1800,7 +1796,7 @@ export default class Install extends Command {
|
|
|
1800
1796
|
'--network',
|
|
1801
1797
|
params.networkName,
|
|
1802
1798
|
'-p',
|
|
1803
|
-
`${appPort}
|
|
1799
|
+
`${appPort}:${containerPort}`,
|
|
1804
1800
|
];
|
|
1805
1801
|
if (envFile) {
|
|
1806
1802
|
args.push('--env-file', envFile);
|
|
@@ -1990,12 +1986,15 @@ export default class Install extends Command {
|
|
|
1990
1986
|
}
|
|
1991
1987
|
async ensureSkippedDownloadInputsReady(params) {
|
|
1992
1988
|
if (params.source === 'docker') {
|
|
1989
|
+
const configuredRegistry = await getCliConfigValue('nb-image-registry');
|
|
1990
|
+
const configuredVariant = normalizeNbImageVariant(await getCliConfigValue('nb-image-variant')) ?? DEFAULT_NB_IMAGE_VARIANT;
|
|
1993
1991
|
const dockerRegistry = String(downloadResultsValue(params.downloadResults, 'dockerRegistry') ?? '').trim() ||
|
|
1994
|
-
|
|
1992
|
+
resolveOfficialDockerRegistry(configuredRegistry);
|
|
1995
1993
|
const version = String(downloadResultsValue(params.downloadResults, 'version') ?? '').trim() || DEFAULT_DOCKER_VERSION;
|
|
1996
1994
|
const imageRef = resolveDockerImageRef(dockerRegistry, version, {
|
|
1997
|
-
defaultRegistry:
|
|
1995
|
+
defaultRegistry: resolveOfficialDockerRegistry(configuredRegistry),
|
|
1998
1996
|
defaultVersion: DEFAULT_DOCKER_VERSION,
|
|
1997
|
+
variant: inferNbImageRegistryFromRepository(dockerRegistry) ? configuredVariant : undefined,
|
|
1999
1998
|
});
|
|
2000
1999
|
const imageExists = await commandSucceeds('docker', ['image', 'inspect', imageRef]);
|
|
2001
2000
|
if (!imageExists) {
|
|
@@ -2391,7 +2390,7 @@ export default class Install extends Command {
|
|
|
2391
2390
|
if (resumePreset?.appPreset?.hookScript !== undefined && appResults.hookScript === undefined) {
|
|
2392
2391
|
appResults.hookScript = resumePreset.appPreset.hookScript;
|
|
2393
2392
|
}
|
|
2394
|
-
const downloadOpts = Install.buildDownloadPromptOptionsForInstall(appResults, envName);
|
|
2393
|
+
const downloadOpts = await Install.buildDownloadPromptOptionsForInstall(appResults, envName);
|
|
2395
2394
|
downloadOpts.values = {
|
|
2396
2395
|
...(resumePreset?.downloadPreset ?? {}),
|
|
2397
2396
|
...downloadOpts.values,
|
|
@@ -17,7 +17,7 @@ export default class ProxyCaddyGenerate extends Command {
|
|
|
17
17
|
'<%= config.bin %> proxy caddy generate --host app1.example.com',
|
|
18
18
|
'<%= config.bin %> proxy caddy generate --env app1 --host app1.example.com',
|
|
19
19
|
'<%= config.bin %> proxy caddy generate --env app1 --host app1.example.com --port 8080',
|
|
20
|
-
'<%= config.bin %> proxy caddy generate --manual --name default --
|
|
20
|
+
'<%= config.bin %> proxy caddy generate --manual --name default --storage-path /path/to/storage --dist-root-path /path/to/dist-client --runtime-version 2.1.0 --upstream-port 13000',
|
|
21
21
|
];
|
|
22
22
|
static flags = {
|
|
23
23
|
env: Flags.string({
|
|
@@ -31,9 +31,6 @@ export default class ProxyCaddyGenerate extends Command {
|
|
|
31
31
|
name: Flags.string({
|
|
32
32
|
description: 'Output bundle name used under .nocobase/proxy/caddy in manual mode',
|
|
33
33
|
}),
|
|
34
|
-
'app-port': Flags.string({
|
|
35
|
-
description: 'Upstream NocoBase app port in manual mode',
|
|
36
|
-
}),
|
|
37
34
|
'storage-path': Flags.string({
|
|
38
35
|
description: 'Path to the NocoBase storage directory in manual mode',
|
|
39
36
|
}),
|
|
@@ -49,6 +46,9 @@ export default class ProxyCaddyGenerate extends Command {
|
|
|
49
46
|
'upstream-host': Flags.string({
|
|
50
47
|
description: 'Upstream host used by caddy reverse_proxy in manual mode',
|
|
51
48
|
}),
|
|
49
|
+
'upstream-port': Flags.string({
|
|
50
|
+
description: 'Upstream port used by caddy reverse_proxy in manual mode',
|
|
51
|
+
}),
|
|
52
52
|
'cdn-base-url': Flags.string({
|
|
53
53
|
description: 'Client asset CDN base URL used when generating runtime HTML',
|
|
54
54
|
}),
|
|
@@ -73,16 +73,16 @@ export default class ProxyCaddyGenerate extends Command {
|
|
|
73
73
|
}
|
|
74
74
|
if (manual) {
|
|
75
75
|
const name = flags.name?.trim() || undefined;
|
|
76
|
-
const
|
|
77
|
-
const
|
|
76
|
+
const requestedUpstreamPort = flags['upstream-port']?.trim() || undefined;
|
|
77
|
+
const upstreamPort = normalizeProxyListenPort(requestedUpstreamPort);
|
|
78
78
|
const storagePath = flags['storage-path']?.trim() || undefined;
|
|
79
79
|
const distRootPath = flags['dist-root-path']?.trim() || undefined;
|
|
80
80
|
const runtimeVersion = flags['runtime-version']?.trim() || undefined;
|
|
81
|
-
if (
|
|
82
|
-
this.error(`Invalid manual
|
|
81
|
+
if (requestedUpstreamPort && !upstreamPort) {
|
|
82
|
+
this.error(`Invalid manual upstream port "${requestedUpstreamPort}". Use an integer between 1 and 65535.`);
|
|
83
83
|
}
|
|
84
|
-
if (!name || !
|
|
85
|
-
this.error('Manual mode requires `--name`, `--
|
|
84
|
+
if (!name || !upstreamPort || !storagePath || !distRootPath || !runtimeVersion) {
|
|
85
|
+
this.error('Manual mode requires `--name`, `--upstream-port`, `--storage-path`, `--dist-root-path`, and `--runtime-version`.');
|
|
86
86
|
}
|
|
87
87
|
const driver = await getCaddyProxyDriver();
|
|
88
88
|
const runtimeContext = await resolveCaddyProxyRuntimeContext();
|
|
@@ -91,12 +91,12 @@ export default class ProxyCaddyGenerate extends Command {
|
|
|
91
91
|
try {
|
|
92
92
|
const { bundle, status } = await writeManualCaddyProxyBundle({
|
|
93
93
|
name,
|
|
94
|
-
appPort,
|
|
95
94
|
storagePath,
|
|
96
95
|
distRootPath,
|
|
97
96
|
runtimeVersion,
|
|
98
97
|
appPublicPath: flags['app-public-path']?.trim() || undefined,
|
|
99
98
|
upstreamHost: flags['upstream-host']?.trim() || undefined,
|
|
99
|
+
upstreamPort,
|
|
100
100
|
cdnBaseUrl: flags['cdn-base-url']?.trim() || undefined,
|
|
101
101
|
}, {
|
|
102
102
|
host: flags.host?.trim() || undefined,
|
|
@@ -16,7 +16,7 @@ export default class ProxyNginxGenerate extends Command {
|
|
|
16
16
|
'<%= config.bin %> proxy nginx generate --host app1.example.com',
|
|
17
17
|
'<%= config.bin %> proxy nginx generate --env app1 --host app1.example.com',
|
|
18
18
|
'<%= config.bin %> proxy nginx generate --env app1 --host app1.example.com --port 8080',
|
|
19
|
-
'<%= config.bin %> proxy nginx generate --manual --name default --
|
|
19
|
+
'<%= config.bin %> proxy nginx generate --manual --name default --storage-path /path/to/storage --dist-root-path /path/to/dist-client --runtime-version 2.1.0 --upstream-port 13000',
|
|
20
20
|
];
|
|
21
21
|
static flags = {
|
|
22
22
|
env: Flags.string({
|
|
@@ -30,9 +30,6 @@ export default class ProxyNginxGenerate extends Command {
|
|
|
30
30
|
name: Flags.string({
|
|
31
31
|
description: 'Output bundle name used under .nocobase/proxy/nginx in manual mode',
|
|
32
32
|
}),
|
|
33
|
-
'app-port': Flags.string({
|
|
34
|
-
description: 'Upstream NocoBase app port in manual mode',
|
|
35
|
-
}),
|
|
36
33
|
'storage-path': Flags.string({
|
|
37
34
|
description: 'Path to the NocoBase storage directory in manual mode',
|
|
38
35
|
}),
|
|
@@ -48,6 +45,9 @@ export default class ProxyNginxGenerate extends Command {
|
|
|
48
45
|
'upstream-host': Flags.string({
|
|
49
46
|
description: 'Upstream host used by nginx proxy_pass in manual mode',
|
|
50
47
|
}),
|
|
48
|
+
'upstream-port': Flags.string({
|
|
49
|
+
description: 'Upstream port used by nginx proxy_pass in manual mode',
|
|
50
|
+
}),
|
|
51
51
|
'cdn-base-url': Flags.string({
|
|
52
52
|
description: 'Client asset CDN base URL used when generating runtime HTML',
|
|
53
53
|
}),
|
|
@@ -76,16 +76,16 @@ export default class ProxyNginxGenerate extends Command {
|
|
|
76
76
|
}
|
|
77
77
|
if (manual) {
|
|
78
78
|
const name = flags.name?.trim() || undefined;
|
|
79
|
-
const
|
|
80
|
-
const
|
|
79
|
+
const requestedUpstreamPort = flags['upstream-port']?.trim() || undefined;
|
|
80
|
+
const upstreamPort = normalizeProxyListenPort(requestedUpstreamPort);
|
|
81
81
|
const storagePath = flags['storage-path']?.trim() || undefined;
|
|
82
82
|
const distRootPath = flags['dist-root-path']?.trim() || undefined;
|
|
83
83
|
const runtimeVersion = flags['runtime-version']?.trim() || undefined;
|
|
84
|
-
if (
|
|
85
|
-
this.error(`Invalid manual
|
|
84
|
+
if (requestedUpstreamPort && !upstreamPort) {
|
|
85
|
+
this.error(`Invalid manual upstream port "${requestedUpstreamPort}". Use an integer between 1 and 65535.`);
|
|
86
86
|
}
|
|
87
|
-
if (!name || !
|
|
88
|
-
this.error('Manual mode requires `--name`, `--
|
|
87
|
+
if (!name || !upstreamPort || !storagePath || !distRootPath || !runtimeVersion) {
|
|
88
|
+
this.error('Manual mode requires `--name`, `--upstream-port`, `--storage-path`, `--dist-root-path`, and `--runtime-version`.');
|
|
89
89
|
}
|
|
90
90
|
const driver = await getNginxProxyDriver();
|
|
91
91
|
const runtimeContext = await resolveNginxProxyRuntimeContext();
|
|
@@ -94,12 +94,12 @@ export default class ProxyNginxGenerate extends Command {
|
|
|
94
94
|
try {
|
|
95
95
|
const { bundle, status } = await writeManualNginxProxyBundle({
|
|
96
96
|
name,
|
|
97
|
-
appPort,
|
|
98
97
|
storagePath,
|
|
99
98
|
distRootPath,
|
|
100
99
|
runtimeVersion,
|
|
101
100
|
appPublicPath: flags['app-public-path']?.trim() || undefined,
|
|
102
101
|
upstreamHost: flags['upstream-host']?.trim() || undefined,
|
|
102
|
+
upstreamPort,
|
|
103
103
|
cdnBaseUrl: flags['cdn-base-url']?.trim() || undefined,
|
|
104
104
|
}, {
|
|
105
105
|
host: flags.host?.trim() || undefined,
|
|
@@ -12,9 +12,10 @@ import path from 'node:path';
|
|
|
12
12
|
import { stdin as stdinStream, stdout as stdoutStream } from 'node:process';
|
|
13
13
|
import { runPromptCatalog, } from "../../lib/prompt-catalog.js";
|
|
14
14
|
import { applyCliLocale, CLI_LOCALE_FLAG_DESCRIPTION, CLI_LOCALE_FLAG_OPTIONS, localeText, resolveCliLocale, translateCli, } from "../../lib/cli-locale.js";
|
|
15
|
-
import { DEFAULT_DOCKER_REGISTRY, DEFAULT_DOCKER_REGISTRY_ZH_CN, resolveDockerImageRef, } from "../../lib/docker-image.js";
|
|
15
|
+
import { DEFAULT_DOCKER_REGISTRY, DEFAULT_DOCKER_REGISTRY_ZH_CN, resolveOfficialDockerRegistry, resolveDockerImageRef, } from "../../lib/docker-image.js";
|
|
16
16
|
import { getEnv } from '../../lib/auth-store.js';
|
|
17
17
|
import { resolveDefaultConfigScope } from '../../lib/cli-home.js';
|
|
18
|
+
import { getCliConfigValue } from '../../lib/cli-config.js';
|
|
18
19
|
import { buildBeforeDependencyInstallHookContext, runBeforeDependencyInstallHook, } from '../../lib/hook-script.js';
|
|
19
20
|
import { run } from "../../lib/run-npm.js";
|
|
20
21
|
import { printVerbose, setVerboseMode, startTask, stopTask, updateTask } from '../../lib/ui.js';
|
|
@@ -450,9 +451,9 @@ export default class SourceDownload extends Command {
|
|
|
450
451
|
}
|
|
451
452
|
return outputAbs;
|
|
452
453
|
}
|
|
453
|
-
dockerTarPath(flags, outputAbs) {
|
|
454
|
+
async dockerTarPath(flags, outputAbs) {
|
|
454
455
|
const imageRef = resolveDockerImageRef(flags['docker-registry'], flags.version, {
|
|
455
|
-
defaultRegistry:
|
|
456
|
+
defaultRegistry: await this.resolveConfiguredDockerRegistryDefault(),
|
|
456
457
|
defaultVersion: 'latest',
|
|
457
458
|
});
|
|
458
459
|
const safeBase = imageRef.replace(/[\\/:]/g, '-');
|
|
@@ -462,9 +463,11 @@ export default class SourceDownload extends Command {
|
|
|
462
463
|
* Defaults for prompts only. Keys present in **`preset`** are omitted so `runPromptCatalog` uses
|
|
463
464
|
* **`values`** (preset) alone for those steps — no duplicate prefill for skipped prompts.
|
|
464
465
|
*/
|
|
465
|
-
|
|
466
|
+
async resolveConfiguredDockerRegistryDefault() {
|
|
467
|
+
return resolveOfficialDockerRegistry(await getCliConfigValue('nb-image-registry'));
|
|
468
|
+
}
|
|
469
|
+
buildInitialValuesFromParsed(flags, preset, defaultDockerRegistry) {
|
|
466
470
|
const initialValues = {};
|
|
467
|
-
const localeDefaultDockerRegistry = defaultDockerRegistryForLang(flags.locale ?? process.env.NB_LOCALE);
|
|
468
471
|
const source = flags.source?.trim();
|
|
469
472
|
if (source) {
|
|
470
473
|
initialValues.source = source;
|
|
@@ -488,7 +491,7 @@ export default class SourceDownload extends Command {
|
|
|
488
491
|
initialValues.dockerRegistry = String(flags['docker-registry'] ?? '').trim();
|
|
489
492
|
}
|
|
490
493
|
else {
|
|
491
|
-
initialValues.dockerRegistry =
|
|
494
|
+
initialValues.dockerRegistry = defaultDockerRegistry;
|
|
492
495
|
}
|
|
493
496
|
initialValues.dockerPlatform = normalizeDockerPlatform(flags['docker-platform']);
|
|
494
497
|
initialValues.dockerSave = flags['docker-save'];
|
|
@@ -569,7 +572,7 @@ export default class SourceDownload extends Command {
|
|
|
569
572
|
}
|
|
570
573
|
return flags.build;
|
|
571
574
|
}
|
|
572
|
-
mapCatalogResultsToResolved(results, flags) {
|
|
575
|
+
mapCatalogResultsToResolved(results, flags, defaultDockerRegistry) {
|
|
573
576
|
const source = String(results.source);
|
|
574
577
|
const version = resolveVersionFromResults(results, flags.version) || 'latest';
|
|
575
578
|
const devDependencies = source === 'npm' ? Boolean(results.devDependencies) : undefined;
|
|
@@ -583,7 +586,7 @@ export default class SourceDownload extends Command {
|
|
|
583
586
|
const dockerRegistry = source === 'docker'
|
|
584
587
|
? results.dockerRegistry !== undefined
|
|
585
588
|
? String(results.dockerRegistry).trim() || undefined
|
|
586
|
-
: flags['docker-registry']?.trim() ||
|
|
589
|
+
: flags['docker-registry']?.trim() || defaultDockerRegistry
|
|
587
590
|
: undefined;
|
|
588
591
|
const dockerPlatform = source === 'docker'
|
|
589
592
|
? normalizeDockerPlatform(results.dockerPlatform !== undefined ? results.dockerPlatform : flags['docker-platform'])
|
|
@@ -628,7 +631,8 @@ export default class SourceDownload extends Command {
|
|
|
628
631
|
this.error('Download source is required in non-interactive mode. Use --source npm, --source git, or --source docker.');
|
|
629
632
|
}
|
|
630
633
|
const presetValues = this.buildPresetValuesFromFlags(flags);
|
|
631
|
-
const
|
|
634
|
+
const defaultDockerRegistry = await this.resolveConfiguredDockerRegistryDefault();
|
|
635
|
+
const initialValues = this.buildInitialValuesFromParsed(flags, presetValues, defaultDockerRegistry);
|
|
632
636
|
const results = await runPromptCatalog(SourceDownload.prompts, {
|
|
633
637
|
initialValues,
|
|
634
638
|
values: presetValues,
|
|
@@ -654,7 +658,7 @@ export default class SourceDownload extends Command {
|
|
|
654
658
|
if (flags['docker-save'] && source !== 'docker') {
|
|
655
659
|
this.error('--docker-save is only available when --source docker is selected.');
|
|
656
660
|
}
|
|
657
|
-
return this.mapCatalogResultsToResolved(results, flags);
|
|
661
|
+
return this.mapCatalogResultsToResolved(results, flags, defaultDockerRegistry);
|
|
658
662
|
}
|
|
659
663
|
npmRegistryUrl(flags) {
|
|
660
664
|
const url = flags['npm-registry']?.trim();
|
|
@@ -784,7 +788,7 @@ export default class SourceDownload extends Command {
|
|
|
784
788
|
}
|
|
785
789
|
async downloadFromDocker(flags) {
|
|
786
790
|
const imageRef = resolveDockerImageRef(flags['docker-registry'], flags.version, {
|
|
787
|
-
defaultRegistry:
|
|
791
|
+
defaultRegistry: await this.resolveConfiguredDockerRegistryDefault(),
|
|
788
792
|
defaultVersion: 'latest',
|
|
789
793
|
});
|
|
790
794
|
const platform = dockerPlatformArg(flags['docker-platform']);
|
|
@@ -811,7 +815,7 @@ export default class SourceDownload extends Command {
|
|
|
811
815
|
await fsp.rm(outAbs, { recursive: true, force: true });
|
|
812
816
|
}
|
|
813
817
|
await fsp.mkdir(outAbs, { recursive: true });
|
|
814
|
-
const tarPath = this.dockerTarPath(flags, outAbs);
|
|
818
|
+
const tarPath = await this.dockerTarPath(flags, outAbs);
|
|
815
819
|
this.log(`Saving Docker image tarball to ${tarPath}`);
|
|
816
820
|
await this.runExternalCommand('docker', ['save', '-o', tarPath, imageRef], {
|
|
817
821
|
errorName: 'docker save',
|
|
@@ -14,7 +14,7 @@ import { dockerContainerExists, managedAppLifecycleEnvVars, runLocalNocoBaseComm
|
|
|
14
14
|
import { deriveBuiltinDbConnection, resolveBuiltinDbConnection } from './builtin-db.js';
|
|
15
15
|
import { resolveConfiguredStoragePath } from './env-paths.js';
|
|
16
16
|
import { resolveDockerEnvFileArg } from "./docker-env-file.js";
|
|
17
|
-
import { DEFAULT_DOCKER_REGISTRY, DEFAULT_DOCKER_VERSION, resolveDockerImageRef, } from "./docker-image.js";
|
|
17
|
+
import { DEFAULT_DOCKER_REGISTRY, DEFAULT_DOCKER_VERSION, resolveDockerImageContainerPort, resolveDockerImageRef, } from "./docker-image.js";
|
|
18
18
|
import { resolveHookScriptPath } from './hook-script.js';
|
|
19
19
|
import { commandSucceeds, ensureDockerDaemonRunning, run } from './run-npm.js';
|
|
20
20
|
import Install from '../commands/install.js';
|
|
@@ -192,6 +192,7 @@ export async function buildSavedDockerRunArgs(runtime, options) {
|
|
|
192
192
|
defaultRegistry: DEFAULT_DOCKER_REGISTRY,
|
|
193
193
|
defaultVersion: DEFAULT_DOCKER_VERSION,
|
|
194
194
|
});
|
|
195
|
+
const containerPort = resolveDockerImageContainerPort(imageRef);
|
|
195
196
|
const missing = [];
|
|
196
197
|
if (!storagePath) {
|
|
197
198
|
missing.push('storagePath');
|
|
@@ -233,7 +234,7 @@ export async function buildSavedDockerRunArgs(runtime, options) {
|
|
|
233
234
|
args.push('--platform', dockerPlatform);
|
|
234
235
|
}
|
|
235
236
|
if (appPort) {
|
|
236
|
-
args.push('-p', `${appPort}
|
|
237
|
+
args.push('-p', `${appPort}:${containerPort}`);
|
|
237
238
|
}
|
|
238
239
|
if (envFile) {
|
|
239
240
|
args.push('--env-file', envFile);
|
package/dist/lib/auth-store.js
CHANGED
|
@@ -125,12 +125,19 @@ function normalizeAuthConfig(config) {
|
|
|
125
125
|
...(updatePolicy ? { update: { policy: updatePolicy } } : {}),
|
|
126
126
|
...(settings.license?.pkgUrl ? { license: { pkgUrl: normalizeOptionalString(settings.license.pkgUrl) } } : {}),
|
|
127
127
|
...(settings.docker?.network || settings.docker?.containerPrefix
|
|
128
|
+
|| settings.docker?.nbImageRegistry || settings.docker?.nbImageVariant
|
|
128
129
|
? {
|
|
129
130
|
docker: {
|
|
130
131
|
...(settings.docker?.network ? { network: normalizeOptionalString(settings.docker.network) } : {}),
|
|
131
132
|
...(settings.docker?.containerPrefix
|
|
132
133
|
? { containerPrefix: normalizeOptionalString(settings.docker.containerPrefix) }
|
|
133
134
|
: {}),
|
|
135
|
+
...(settings.docker?.nbImageRegistry
|
|
136
|
+
? { nbImageRegistry: normalizeOptionalString(settings.docker.nbImageRegistry) }
|
|
137
|
+
: {}),
|
|
138
|
+
...(settings.docker?.nbImageVariant
|
|
139
|
+
? { nbImageVariant: normalizeOptionalString(settings.docker.nbImageVariant) }
|
|
140
|
+
: {}),
|
|
134
141
|
},
|
|
135
142
|
}
|
|
136
143
|
: {}),
|
package/dist/lib/cli-config.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import { loadExactAuthConfig, saveAuthConfig } from './auth-store.js';
|
|
10
10
|
import { resolveCliHomeRoot, resolveDefaultConfigScope } from './cli-home.js';
|
|
11
11
|
import { CLI_LOCALE_FLAG_OPTIONS, normalizeCliLocale, resolveCliLocale } from './cli-locale.js';
|
|
12
|
+
import { DEFAULT_NB_IMAGE_REGISTRY, DEFAULT_NB_IMAGE_VARIANT, NB_IMAGE_REGISTRY_OPTIONS, NB_IMAGE_VARIANT_OPTIONS, normalizeNbImageRegistry, normalizeNbImageVariant, } from './docker-image.js';
|
|
12
13
|
export const DEFAULT_LICENSE_PKG_URL = 'https://pkg.nocobase.com/';
|
|
13
14
|
export const DEFAULT_DOCKER_NETWORK = 'nocobase';
|
|
14
15
|
export const DEFAULT_DOCKER_CONTAINER_PREFIX = 'nb';
|
|
@@ -37,6 +38,8 @@ export const SUPPORTED_CLI_CONFIG_KEYS = [
|
|
|
37
38
|
'license.pkg-url',
|
|
38
39
|
'docker.network',
|
|
39
40
|
'docker.container-prefix',
|
|
41
|
+
'nb-image-registry',
|
|
42
|
+
'nb-image-variant',
|
|
40
43
|
'bin.docker',
|
|
41
44
|
'bin.caddy',
|
|
42
45
|
'bin.git',
|
|
@@ -129,7 +132,11 @@ function pruneSettings(config) {
|
|
|
129
132
|
delete config.settings?.license;
|
|
130
133
|
}
|
|
131
134
|
const docker = config.settings?.docker;
|
|
132
|
-
if (docker &&
|
|
135
|
+
if (docker &&
|
|
136
|
+
!trimValue(docker.network) &&
|
|
137
|
+
!trimValue(docker.containerPrefix) &&
|
|
138
|
+
!trimValue(docker.nbImageRegistry) &&
|
|
139
|
+
!trimValue(docker.nbImageVariant)) {
|
|
133
140
|
delete config.settings?.docker;
|
|
134
141
|
}
|
|
135
142
|
const bin = config.settings?.bin;
|
|
@@ -182,6 +189,10 @@ export function getExplicitCliConfigValue(config, key) {
|
|
|
182
189
|
return trimValue(config.settings?.docker?.network);
|
|
183
190
|
case 'docker.container-prefix':
|
|
184
191
|
return trimValue(config.settings?.docker?.containerPrefix);
|
|
192
|
+
case 'nb-image-registry':
|
|
193
|
+
return normalizeNbImageRegistry(config.settings?.docker?.nbImageRegistry);
|
|
194
|
+
case 'nb-image-variant':
|
|
195
|
+
return normalizeNbImageVariant(config.settings?.docker?.nbImageVariant);
|
|
185
196
|
case 'bin.docker':
|
|
186
197
|
return trimValue(config.settings?.bin?.docker);
|
|
187
198
|
case 'bin.caddy':
|
|
@@ -230,6 +241,10 @@ export function getEffectiveCliConfigValue(config, key) {
|
|
|
230
241
|
return trimValue(config.name) || DEFAULT_DOCKER_NETWORK;
|
|
231
242
|
case 'docker.container-prefix':
|
|
232
243
|
return trimValue(config.name) || DEFAULT_DOCKER_CONTAINER_PREFIX;
|
|
244
|
+
case 'nb-image-registry':
|
|
245
|
+
return explicit ?? DEFAULT_NB_IMAGE_REGISTRY;
|
|
246
|
+
case 'nb-image-variant':
|
|
247
|
+
return explicit ?? DEFAULT_NB_IMAGE_VARIANT;
|
|
233
248
|
case 'bin.docker':
|
|
234
249
|
return DEFAULT_DOCKER_BIN;
|
|
235
250
|
case 'bin.caddy':
|
|
@@ -305,6 +320,20 @@ export function normalizeCliConfigValue(key, value) {
|
|
|
305
320
|
}
|
|
306
321
|
return driver;
|
|
307
322
|
}
|
|
323
|
+
if (key === 'nb-image-registry') {
|
|
324
|
+
const registry = normalizeNbImageRegistry(normalized);
|
|
325
|
+
if (!registry) {
|
|
326
|
+
throw new Error(`Config key "${key}" must be one of: ${NB_IMAGE_REGISTRY_OPTIONS.join(', ')}`);
|
|
327
|
+
}
|
|
328
|
+
return registry;
|
|
329
|
+
}
|
|
330
|
+
if (key === 'nb-image-variant') {
|
|
331
|
+
const variant = normalizeNbImageVariant(normalized);
|
|
332
|
+
if (!variant) {
|
|
333
|
+
throw new Error(`Config key "${key}" must be one of: ${NB_IMAGE_VARIANT_OPTIONS.join(', ')}`);
|
|
334
|
+
}
|
|
335
|
+
return variant;
|
|
336
|
+
}
|
|
308
337
|
return normalized;
|
|
309
338
|
}
|
|
310
339
|
export async function loadCliConfig(options = {}) {
|
|
@@ -370,6 +399,18 @@ export async function setCliConfigValue(key, value, options = {}) {
|
|
|
370
399
|
containerPrefix: normalized,
|
|
371
400
|
};
|
|
372
401
|
break;
|
|
402
|
+
case 'nb-image-registry':
|
|
403
|
+
config.settings.docker = {
|
|
404
|
+
...(config.settings.docker ?? {}),
|
|
405
|
+
nbImageRegistry: normalized,
|
|
406
|
+
};
|
|
407
|
+
break;
|
|
408
|
+
case 'nb-image-variant':
|
|
409
|
+
config.settings.docker = {
|
|
410
|
+
...(config.settings.docker ?? {}),
|
|
411
|
+
nbImageVariant: normalized,
|
|
412
|
+
};
|
|
413
|
+
break;
|
|
373
414
|
case 'bin.docker':
|
|
374
415
|
config.settings.bin = {
|
|
375
416
|
...(config.settings.bin ?? {}),
|
|
@@ -489,6 +530,16 @@ export async function deleteCliConfigValue(key, options = {}) {
|
|
|
489
530
|
delete config.settings.docker.containerPrefix;
|
|
490
531
|
}
|
|
491
532
|
break;
|
|
533
|
+
case 'nb-image-registry':
|
|
534
|
+
if (config.settings.docker) {
|
|
535
|
+
delete config.settings.docker.nbImageRegistry;
|
|
536
|
+
}
|
|
537
|
+
break;
|
|
538
|
+
case 'nb-image-variant':
|
|
539
|
+
if (config.settings.docker) {
|
|
540
|
+
delete config.settings.docker.nbImageVariant;
|
|
541
|
+
}
|
|
542
|
+
break;
|
|
492
543
|
case 'bin.docker':
|
|
493
544
|
if (config.settings.bin) {
|
|
494
545
|
delete config.settings.bin.docker;
|
package/dist/lib/docker-image.js
CHANGED
|
@@ -9,7 +9,30 @@
|
|
|
9
9
|
export const DEFAULT_DOCKER_REGISTRY = 'nocobase/nocobase';
|
|
10
10
|
export const DEFAULT_DOCKER_REGISTRY_ZH_CN = 'registry.cn-shanghai.aliyuncs.com/nocobase/nocobase';
|
|
11
11
|
export const DEFAULT_DOCKER_VERSION = 'alpha';
|
|
12
|
+
export const NB_IMAGE_REGISTRY_OPTIONS = ['dockerhub', 'aliyun'];
|
|
13
|
+
export const DEFAULT_NB_IMAGE_REGISTRY = 'dockerhub';
|
|
14
|
+
export const NB_IMAGE_VARIANT_OPTIONS = ['standard', 'no-nginx', 'full', 'full-no-nginx'];
|
|
15
|
+
export const DEFAULT_NB_IMAGE_VARIANT = 'full';
|
|
12
16
|
export const DOCKER_IMAGE_FULL_SUFFIX = '-full';
|
|
17
|
+
export const DOCKER_IMAGE_NO_NGINX_SUFFIX = '-no-nginx';
|
|
18
|
+
export const DOCKER_IMAGE_FULL_NO_NGINX_SUFFIX = '-full-no-nginx';
|
|
19
|
+
export const DEFAULT_KINGBASE_IMAGE = 'registry.cn-shanghai.aliyuncs.com/nocobase/kingbase:v009r001c001b0030_single_x86';
|
|
20
|
+
const OFFICIAL_DOCKER_REGISTRY_REPOSITORIES = {
|
|
21
|
+
dockerhub: DEFAULT_DOCKER_REGISTRY,
|
|
22
|
+
aliyun: DEFAULT_DOCKER_REGISTRY_ZH_CN,
|
|
23
|
+
};
|
|
24
|
+
const DEFAULT_BUILTIN_DB_IMAGES = {
|
|
25
|
+
postgres: 'postgres:16',
|
|
26
|
+
mysql: 'mysql:8',
|
|
27
|
+
mariadb: 'mariadb:11',
|
|
28
|
+
kingbase: DEFAULT_KINGBASE_IMAGE,
|
|
29
|
+
};
|
|
30
|
+
const ALIYUN_BUILTIN_DB_IMAGES = {
|
|
31
|
+
postgres: 'registry.cn-shanghai.aliyuncs.com/nocobase/postgres:16',
|
|
32
|
+
mysql: 'registry.cn-shanghai.aliyuncs.com/nocobase/mysql:8',
|
|
33
|
+
mariadb: 'registry.cn-shanghai.aliyuncs.com/nocobase/mariadb:11',
|
|
34
|
+
kingbase: DEFAULT_KINGBASE_IMAGE,
|
|
35
|
+
};
|
|
13
36
|
const OFFICIAL_FULL_IMAGE_REGISTRIES = new Set([
|
|
14
37
|
DEFAULT_DOCKER_REGISTRY,
|
|
15
38
|
DEFAULT_DOCKER_REGISTRY_ZH_CN,
|
|
@@ -17,21 +40,86 @@ const OFFICIAL_FULL_IMAGE_REGISTRIES = new Set([
|
|
|
17
40
|
function trimValue(value) {
|
|
18
41
|
return String(value ?? '').trim();
|
|
19
42
|
}
|
|
43
|
+
export function normalizeNbImageRegistry(value) {
|
|
44
|
+
const normalized = trimValue(value);
|
|
45
|
+
if (!normalized) {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
return NB_IMAGE_REGISTRY_OPTIONS.includes(normalized)
|
|
49
|
+
? normalized
|
|
50
|
+
: undefined;
|
|
51
|
+
}
|
|
52
|
+
export function normalizeNbImageVariant(value) {
|
|
53
|
+
const normalized = trimValue(value);
|
|
54
|
+
if (!normalized) {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
return NB_IMAGE_VARIANT_OPTIONS.includes(normalized)
|
|
58
|
+
? normalized
|
|
59
|
+
: undefined;
|
|
60
|
+
}
|
|
61
|
+
export function resolveOfficialDockerRegistry(value) {
|
|
62
|
+
const registry = normalizeNbImageRegistry(value) ?? DEFAULT_NB_IMAGE_REGISTRY;
|
|
63
|
+
return OFFICIAL_DOCKER_REGISTRY_REPOSITORIES[registry];
|
|
64
|
+
}
|
|
65
|
+
export function inferNbImageRegistryFromRepository(value) {
|
|
66
|
+
const repository = trimValue(value);
|
|
67
|
+
return Object.entries(OFFICIAL_DOCKER_REGISTRY_REPOSITORIES).find(([, candidate]) => candidate === repository)?.[0];
|
|
68
|
+
}
|
|
69
|
+
function hasKnownVariantSuffix(tag) {
|
|
70
|
+
return (tag.endsWith(DOCKER_IMAGE_FULL_NO_NGINX_SUFFIX) ||
|
|
71
|
+
tag.endsWith(DOCKER_IMAGE_NO_NGINX_SUFFIX) ||
|
|
72
|
+
tag.endsWith(DOCKER_IMAGE_FULL_SUFFIX));
|
|
73
|
+
}
|
|
20
74
|
export function shouldUseFullDockerImageTag(registry) {
|
|
21
75
|
return OFFICIAL_FULL_IMAGE_REGISTRIES.has(trimValue(registry));
|
|
22
76
|
}
|
|
23
|
-
export function normalizeDockerImageTag(registry, version) {
|
|
77
|
+
export function normalizeDockerImageTag(registry, version, options) {
|
|
24
78
|
const tag = trimValue(version) || DEFAULT_DOCKER_VERSION;
|
|
25
|
-
if (
|
|
79
|
+
if (hasKnownVariantSuffix(tag)) {
|
|
26
80
|
return tag;
|
|
27
81
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
82
|
+
const explicitVariant = normalizeNbImageVariant(options?.variant) ?? normalizeNbImageVariant(options?.defaultVariant);
|
|
83
|
+
const inferredVariant = shouldUseFullDockerImageTag(registry) ? DEFAULT_NB_IMAGE_VARIANT : 'standard';
|
|
84
|
+
const variant = explicitVariant ?? inferredVariant;
|
|
85
|
+
switch (variant) {
|
|
86
|
+
case 'standard':
|
|
87
|
+
return tag;
|
|
88
|
+
case 'no-nginx':
|
|
89
|
+
return `${tag}${DOCKER_IMAGE_NO_NGINX_SUFFIX}`;
|
|
90
|
+
case 'full':
|
|
91
|
+
return `${tag}${DOCKER_IMAGE_FULL_SUFFIX}`;
|
|
92
|
+
case 'full-no-nginx':
|
|
93
|
+
return `${tag}${DOCKER_IMAGE_FULL_NO_NGINX_SUFFIX}`;
|
|
94
|
+
}
|
|
31
95
|
}
|
|
32
96
|
export function resolveDockerImageRef(registry, version, options) {
|
|
33
97
|
const resolvedRegistry = trimValue(registry) || options?.defaultRegistry || DEFAULT_DOCKER_REGISTRY;
|
|
34
98
|
const rawVersion = trimValue(version) || options?.defaultVersion || DEFAULT_DOCKER_VERSION;
|
|
35
|
-
const normalizedTag = normalizeDockerImageTag(resolvedRegistry, rawVersion
|
|
99
|
+
const normalizedTag = normalizeDockerImageTag(resolvedRegistry, rawVersion, {
|
|
100
|
+
variant: options?.variant,
|
|
101
|
+
defaultVariant: options?.defaultVariant,
|
|
102
|
+
});
|
|
36
103
|
return `${resolvedRegistry}:${normalizedTag}`;
|
|
37
104
|
}
|
|
105
|
+
function extractDockerImageTag(imageRef) {
|
|
106
|
+
const ref = trimValue(imageRef);
|
|
107
|
+
const lastSlashIndex = ref.lastIndexOf('/');
|
|
108
|
+
const lastColonIndex = ref.lastIndexOf(':');
|
|
109
|
+
if (lastColonIndex <= lastSlashIndex) {
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
return ref.slice(lastColonIndex + 1) || undefined;
|
|
113
|
+
}
|
|
114
|
+
export function resolveDockerImageContainerPort(imageRef) {
|
|
115
|
+
const tag = extractDockerImageTag(imageRef);
|
|
116
|
+
return tag?.endsWith(DOCKER_IMAGE_NO_NGINX_SUFFIX) ? '13000' : '80';
|
|
117
|
+
}
|
|
118
|
+
export function resolveBuiltinDbImage(dbDialect, options) {
|
|
119
|
+
const dialect = trimValue(dbDialect) || 'postgres';
|
|
120
|
+
const configuredRegistry = normalizeNbImageRegistry(options?.registry) ??
|
|
121
|
+
inferNbImageRegistryFromRepository(options?.registry) ??
|
|
122
|
+
DEFAULT_NB_IMAGE_REGISTRY;
|
|
123
|
+
const defaults = configuredRegistry === 'aliyun' ? ALIYUN_BUILTIN_DB_IMAGES : DEFAULT_BUILTIN_DB_IMAGES;
|
|
124
|
+
return defaults[dialect] ?? defaults.postgres;
|
|
125
|
+
}
|
package/dist/lib/env-proxy.js
CHANGED
|
@@ -309,17 +309,30 @@ function createManualProxyEnvSettings(input) {
|
|
|
309
309
|
};
|
|
310
310
|
}
|
|
311
311
|
function normalizeManualNginxInput(input) {
|
|
312
|
+
const upstreamPort = trimValue(input.upstreamPort) ?? trimValue(input.appPort);
|
|
312
313
|
return {
|
|
313
314
|
name: String(input.name).trim(),
|
|
314
|
-
appPort: String(input.appPort).trim(),
|
|
315
315
|
storagePath: String(input.storagePath).trim(),
|
|
316
316
|
distRootPath: String(input.distRootPath).trim(),
|
|
317
317
|
runtimeVersion: String(input.runtimeVersion).trim(),
|
|
318
318
|
appPublicPath: trimValue(input.appPublicPath),
|
|
319
319
|
upstreamHost: trimValue(input.upstreamHost),
|
|
320
|
+
upstreamPort,
|
|
321
|
+
appPort: trimValue(input.appPort),
|
|
320
322
|
cdnBaseUrl: trimValue(input.cdnBaseUrl),
|
|
321
323
|
};
|
|
322
324
|
}
|
|
325
|
+
function normalizeProxyPort(value) {
|
|
326
|
+
const normalized = trimValue(value);
|
|
327
|
+
if (!normalized || !/^\d+$/.test(normalized)) {
|
|
328
|
+
return undefined;
|
|
329
|
+
}
|
|
330
|
+
const port = Number(normalized);
|
|
331
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
332
|
+
return undefined;
|
|
333
|
+
}
|
|
334
|
+
return normalized;
|
|
335
|
+
}
|
|
323
336
|
async function parseVersionFromPackageJson(content, sourceLabel) {
|
|
324
337
|
let parsed;
|
|
325
338
|
try {
|
|
@@ -563,7 +576,8 @@ function buildCaddyRuntimeConfig(context, variant) {
|
|
|
563
576
|
}
|
|
564
577
|
async function buildEnvProxyNginxRenderContext(source, options) {
|
|
565
578
|
const proxyHost = await resolveProxyUpstreamHost(options);
|
|
566
|
-
const
|
|
579
|
+
const upstreamPort = normalizeProxyPort(options?.upstreamPort) ?? source.apiPort;
|
|
580
|
+
const backendUrl = `http://${proxyHost}:${upstreamPort}`;
|
|
567
581
|
const cdnBaseUrl = source.settings.cdnBaseUrl ?? buildDefaultCdnBaseUrl(source.settings.appPublicPath, source.activeVersion);
|
|
568
582
|
const entryDir = resolveEnvProxyEntryDir(source.envName, { scope: options?.scope });
|
|
569
583
|
const publicDir = resolveEnvProxyNginxPublicOutputDir(source.envName, { scope: options?.scope });
|
|
@@ -637,7 +651,7 @@ async function resolveManualNginxBundleSource(input) {
|
|
|
637
651
|
storagePath: normalized.storagePath,
|
|
638
652
|
distRootPath: normalized.distRootPath,
|
|
639
653
|
settings: createManualProxyEnvSettings(normalized),
|
|
640
|
-
apiPort: normalized.
|
|
654
|
+
apiPort: normalized.upstreamPort,
|
|
641
655
|
activeVersion: normalized.runtimeVersion,
|
|
642
656
|
};
|
|
643
657
|
}
|
|
@@ -704,6 +718,7 @@ export async function buildManualEnvProxyNginxBundle(input, options) {
|
|
|
704
718
|
return await buildNginxBundleFromSource(await resolveManualNginxBundleSource(input), {
|
|
705
719
|
...options,
|
|
706
720
|
upstreamHost: trimValue(input.upstreamHost) ?? options?.upstreamHost,
|
|
721
|
+
upstreamPort: normalizeProxyPort(input.upstreamPort) ?? options?.upstreamPort,
|
|
707
722
|
});
|
|
708
723
|
}
|
|
709
724
|
async function buildNginxBundleFromSource(source, options) {
|
|
@@ -771,6 +786,7 @@ export async function buildManualEnvProxyCaddyBundle(input, options) {
|
|
|
771
786
|
return await buildCaddyBundleFromSource(await resolveManualNginxBundleSource(input), {
|
|
772
787
|
...options,
|
|
773
788
|
upstreamHost: trimValue(input.upstreamHost) ?? options?.upstreamHost,
|
|
789
|
+
upstreamPort: normalizeProxyPort(input.upstreamPort) ?? options?.upstreamPort,
|
|
774
790
|
});
|
|
775
791
|
}
|
|
776
792
|
async function buildCaddyBundleFromSource(source, options) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/cli",
|
|
3
|
-
"version": "2.2.0-alpha.
|
|
3
|
+
"version": "2.2.0-alpha.5",
|
|
4
4
|
"description": "NocoBase Command Line Tool",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/generated/command-registry.js",
|
|
@@ -144,5 +144,5 @@
|
|
|
144
144
|
"type": "git",
|
|
145
145
|
"url": "git+https://github.com/nocobase/nocobase.git"
|
|
146
146
|
},
|
|
147
|
-
"gitHead": "
|
|
147
|
+
"gitHead": "814ff497dd1233ca7218c9f7f2a016c2ead6516d"
|
|
148
148
|
}
|