@nocobase/cli 2.2.0-alpha.1 → 2.2.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/env-proxy/nginx/snippets/proxy-location.conf +1 -0
- package/assets/env-proxy/nginx/snippets/uploads-location.conf +4 -1
- package/bin/early-locale.js +89 -0
- package/bin/node-version.js +35 -0
- package/bin/run.js +9 -0
- package/bin/windows-admin.js +60 -0
- package/dist/commands/app/destroy.js +4 -3
- package/dist/commands/app/restart.js +38 -0
- package/dist/commands/app/shared.js +49 -3
- package/dist/commands/app/start.js +95 -0
- package/dist/commands/app/upgrade.js +11 -0
- package/dist/commands/config/set.js +1 -0
- package/dist/commands/env/info.js +11 -1
- package/dist/commands/examples/prompts-stages.js +2 -2
- package/dist/commands/examples/prompts-test.js +2 -2
- package/dist/commands/init.js +152 -14
- package/dist/commands/install.js +256 -109
- package/dist/commands/license/activate.js +4 -1
- package/dist/commands/license/shared.js +24 -15
- package/dist/commands/portal/config.js +88 -0
- package/dist/commands/portal/create.js +104 -0
- package/dist/commands/portal/deploy.js +81 -0
- package/dist/commands/portal/destroy.js +104 -0
- package/dist/commands/portal/dev.js +71 -0
- package/dist/commands/portal/index.js +20 -0
- package/dist/commands/portal/info.js +82 -0
- package/dist/commands/portal/list.js +98 -0
- package/dist/commands/portal/pull.js +84 -0
- package/dist/commands/portal/push.js +79 -0
- package/dist/commands/proxy/caddy/generate.js +93 -7
- package/dist/commands/proxy/nginx/generate.js +98 -7
- package/dist/commands/revision/create.js +1 -1
- package/dist/commands/self/check.js +1 -1
- package/dist/commands/self/update.js +4 -4
- package/dist/commands/skills/check.js +4 -5
- package/dist/commands/skills/install.js +18 -1
- package/dist/commands/skills/update.js +19 -4
- package/dist/commands/source/dev.js +10 -6
- package/dist/commands/source/download.js +85 -16
- package/dist/lib/api-command-compat.js +51 -8
- package/dist/lib/app-managed-resources.js +104 -5
- package/dist/lib/auth-store.js +105 -13
- package/dist/lib/cli-config.js +93 -2
- package/dist/lib/docker-image.js +94 -6
- package/dist/lib/env-auth.js +291 -45
- package/dist/lib/env-config.js +14 -0
- package/dist/lib/env-proxy-config.js +48 -0
- package/dist/lib/env-proxy.js +266 -61
- package/dist/lib/hook-script.js +160 -0
- package/dist/lib/managed-init-env.js +6 -1
- package/dist/lib/portal-command-env.js +31 -0
- package/dist/lib/portal-config.js +133 -0
- package/dist/lib/portal-configure.js +117 -0
- package/dist/lib/portal-create.js +433 -0
- package/dist/lib/portal-deploy.js +283 -0
- package/dist/lib/portal-destroy.js +100 -0
- package/dist/lib/portal-dev.js +79 -0
- package/dist/lib/portal-env-files.js +53 -0
- package/dist/lib/portal-info.js +31 -0
- package/dist/lib/portal-list.js +211 -0
- package/dist/lib/portal-source.js +523 -0
- package/dist/lib/prompt-catalog-terminal.js +32 -19
- package/dist/lib/prompt-validators.js +1 -1
- package/dist/lib/prompt-web-ui.js +20 -13
- package/dist/lib/proxy-caddy.js +77 -9
- package/dist/lib/proxy-nginx.js +71 -11
- package/dist/lib/run-npm.js +21 -16
- package/dist/lib/self-manager.js +254 -46
- package/dist/lib/skills-manager.js +116 -23
- package/dist/lib/source-publish.js +2 -2
- package/dist/lib/startup-update.js +1 -1
- package/dist/lib/ui.js +28 -1
- package/dist/locale/en-US.json +227 -43
- package/dist/locale/zh-CN.json +227 -43
- package/package.json +11 -2
- package/scripts/build.mjs +0 -34
- package/scripts/clean.mjs +0 -9
- package/tsconfig.json +0 -19
package/dist/lib/auth-store.js
CHANGED
|
@@ -11,7 +11,9 @@ import path from 'node:path';
|
|
|
11
11
|
import { resolveAppPublicPath } from './app-public-path.js';
|
|
12
12
|
import { resolveCliHomeDir, resolveConfiguredEnvPath, resolveEnvRelativePath } from './cli-home.js';
|
|
13
13
|
import { normalizeCliLocale } from './cli-locale.js';
|
|
14
|
+
import { normalizeEnvProxyConfig, normalizeEnvProxyProviderConfig, } from './env-proxy-config.js';
|
|
14
15
|
import { inferConfiguredAppPathFromLegacyConfig, resolveConfiguredAppPath, resolveConfiguredSourcePath, resolveConfiguredStoragePath, } from './env-paths.js';
|
|
16
|
+
import { ENV_CONFIG_SCHEMA_VERSION, normalizeEnvConfigSchemaVersion } from './env-config.js';
|
|
15
17
|
import { cleanupCurrentSessionAfterEnvRemoval, resolveEffectiveCurrentEnv, setSessionCurrentEnv, } from './session-store.js';
|
|
16
18
|
function normalizeStoredEnvKind(value) {
|
|
17
19
|
const kind = String(value ?? '').trim();
|
|
@@ -76,14 +78,18 @@ function normalizeEnvConfigEntry(entry) {
|
|
|
76
78
|
if (!entry) {
|
|
77
79
|
return entry;
|
|
78
80
|
}
|
|
79
|
-
const { kind: _kind, apiBaseUrl: _apiBaseUrl, baseUrl: _baseUrl, apibaseUrl: _legacyApiBaseUrl, ...rest } = entry;
|
|
81
|
+
const { kind: _kind, apiBaseUrl: _apiBaseUrl, baseUrl: _baseUrl, apibaseUrl: _legacyApiBaseUrl, schemaVersion: _schemaVersion, ...rest } = entry;
|
|
80
82
|
const normalizedKind = resolveEnvKind(entry);
|
|
81
83
|
const apiBaseUrl = readEnvApiBaseUrl(entry);
|
|
84
|
+
const schemaVersion = normalizeEnvConfigSchemaVersion(entry.schemaVersion);
|
|
85
|
+
const proxy = normalizeEnvProxyConfig(entry.proxy);
|
|
82
86
|
return {
|
|
83
87
|
...rest,
|
|
88
|
+
...(schemaVersion ? { schemaVersion } : {}),
|
|
84
89
|
...(normalizedKind ? { kind: normalizedKind } : {}),
|
|
85
90
|
...(apiBaseUrl !== undefined ? { apiBaseUrl } : {}),
|
|
86
91
|
...(normalizeOptionalString(entry.appPublicPath) ? { appPublicPath: resolveAppPublicPath(entry.appPublicPath) } : {}),
|
|
92
|
+
...(proxy ? { proxy } : {}),
|
|
87
93
|
};
|
|
88
94
|
}
|
|
89
95
|
function normalizeAuthConfig(config) {
|
|
@@ -91,51 +97,68 @@ function normalizeAuthConfig(config) {
|
|
|
91
97
|
const locale = normalizeOptionalCliLocale(settings.locale);
|
|
92
98
|
const defaultUiHost = normalizeOptionalString(settings.init?.defaultUiHost);
|
|
93
99
|
const defaultApiHost = normalizeOptionalString(settings.init?.defaultApiHost);
|
|
100
|
+
const defaultPortalTemplate = normalizeOptionalString(settings.init?.defaultPortalTemplate);
|
|
94
101
|
const updatePolicy = normalizeOptionalCliUpdatePolicy(settings.update?.policy);
|
|
95
102
|
const logRetentionDays = typeof settings.log?.retentionDays === 'number' && Number.isInteger(settings.log.retentionDays)
|
|
96
103
|
? settings.log.retentionDays
|
|
97
104
|
: undefined;
|
|
98
105
|
const logEnabled = typeof settings.log?.enabled === 'boolean' ? settings.log.enabled : undefined;
|
|
106
|
+
const hasBinSettings = settings.bin?.docker ||
|
|
107
|
+
settings.bin?.caddy ||
|
|
108
|
+
settings.bin?.git ||
|
|
109
|
+
settings.bin?.nginx ||
|
|
110
|
+
settings.bin?.pnpm ||
|
|
111
|
+
settings.bin?.yarn;
|
|
112
|
+
const hasProxySettings = settings.proxy?.nbCliRoot ||
|
|
113
|
+
settings.proxy?.caddyDriver ||
|
|
114
|
+
settings.proxy?.nginxDriver ||
|
|
115
|
+
settings.proxy?.upstreamHost ||
|
|
116
|
+
settings.proxy?.host;
|
|
99
117
|
return {
|
|
100
118
|
name: config.name || config.dockerResourcePrefix,
|
|
101
119
|
settings: {
|
|
102
120
|
...(locale ? { locale } : {}),
|
|
103
|
-
...(defaultUiHost || defaultApiHost
|
|
121
|
+
...(defaultUiHost || defaultApiHost || defaultPortalTemplate
|
|
104
122
|
? {
|
|
105
123
|
init: {
|
|
106
124
|
...(defaultUiHost ? { defaultUiHost } : {}),
|
|
107
125
|
...(defaultApiHost ? { defaultApiHost } : {}),
|
|
126
|
+
...(defaultPortalTemplate ? { defaultPortalTemplate } : {}),
|
|
108
127
|
},
|
|
109
128
|
}
|
|
110
129
|
: {}),
|
|
111
130
|
...(updatePolicy ? { update: { policy: updatePolicy } } : {}),
|
|
112
131
|
...(settings.license?.pkgUrl ? { license: { pkgUrl: normalizeOptionalString(settings.license.pkgUrl) } } : {}),
|
|
113
132
|
...(settings.docker?.network || settings.docker?.containerPrefix
|
|
133
|
+
|| settings.docker?.nbImageRegistry || settings.docker?.nbImageVariant
|
|
114
134
|
? {
|
|
115
135
|
docker: {
|
|
116
136
|
...(settings.docker?.network ? { network: normalizeOptionalString(settings.docker.network) } : {}),
|
|
117
137
|
...(settings.docker?.containerPrefix
|
|
118
138
|
? { containerPrefix: normalizeOptionalString(settings.docker.containerPrefix) }
|
|
119
139
|
: {}),
|
|
140
|
+
...(settings.docker?.nbImageRegistry
|
|
141
|
+
? { nbImageRegistry: normalizeOptionalString(settings.docker.nbImageRegistry) }
|
|
142
|
+
: {}),
|
|
143
|
+
...(settings.docker?.nbImageVariant
|
|
144
|
+
? { nbImageVariant: normalizeOptionalString(settings.docker.nbImageVariant) }
|
|
145
|
+
: {}),
|
|
120
146
|
},
|
|
121
147
|
}
|
|
122
148
|
: {}),
|
|
123
|
-
...(
|
|
149
|
+
...(hasBinSettings
|
|
124
150
|
? {
|
|
125
151
|
bin: {
|
|
126
152
|
...(settings.bin?.docker ? { docker: normalizeOptionalString(settings.bin.docker) } : {}),
|
|
127
153
|
...(settings.bin?.caddy ? { caddy: normalizeOptionalString(settings.bin.caddy) } : {}),
|
|
128
154
|
...(settings.bin?.git ? { git: normalizeOptionalString(settings.bin.git) } : {}),
|
|
129
155
|
...(settings.bin?.nginx ? { nginx: normalizeOptionalString(settings.bin.nginx) } : {}),
|
|
156
|
+
...(settings.bin?.pnpm ? { pnpm: normalizeOptionalString(settings.bin.pnpm) } : {}),
|
|
130
157
|
...(settings.bin?.yarn ? { yarn: normalizeOptionalString(settings.bin.yarn) } : {}),
|
|
131
158
|
},
|
|
132
159
|
}
|
|
133
160
|
: {}),
|
|
134
|
-
...(
|
|
135
|
-
settings.proxy?.caddyDriver ||
|
|
136
|
-
settings.proxy?.nginxDriver ||
|
|
137
|
-
settings.proxy?.upstreamHost ||
|
|
138
|
-
settings.proxy?.host
|
|
161
|
+
...(hasProxySettings
|
|
139
162
|
? {
|
|
140
163
|
proxy: {
|
|
141
164
|
...(settings.proxy?.nbCliRoot ? { nbCliRoot: normalizeOptionalString(settings.proxy.nbCliRoot) } : {}),
|
|
@@ -366,7 +389,13 @@ function areAuthConfigsEquivalent(left, right) {
|
|
|
366
389
|
async function writeEnv(envName, updater, options = {}) {
|
|
367
390
|
const config = await loadExactAuthConfig(options);
|
|
368
391
|
const previous = config.envs[envName];
|
|
369
|
-
|
|
392
|
+
const next = updater(previous);
|
|
393
|
+
config.envs[envName] = {
|
|
394
|
+
...next,
|
|
395
|
+
schemaVersion: normalizeEnvConfigSchemaVersion(next.schemaVersion) ??
|
|
396
|
+
normalizeEnvConfigSchemaVersion(previous?.schemaVersion) ??
|
|
397
|
+
ENV_CONFIG_SCHEMA_VERSION,
|
|
398
|
+
};
|
|
370
399
|
await saveAuthConfig(config, options);
|
|
371
400
|
}
|
|
372
401
|
function normalizeConfiguredAuthType(value) {
|
|
@@ -377,18 +406,19 @@ export function resolveConfiguredAuthType(config) {
|
|
|
377
406
|
}
|
|
378
407
|
export async function upsertEnv(envName, config, options = {}) {
|
|
379
408
|
await writeEnv(envName, (previous) => {
|
|
380
|
-
const { apiBaseUrl: _apiBaseUrl, baseUrl: _baseUrl, apibaseUrl: _legacyApiBaseUrl, accessToken, authType, authUsername, ...rest } = config;
|
|
409
|
+
const { apiBaseUrl: _apiBaseUrl, baseUrl: _baseUrl, apibaseUrl: _legacyApiBaseUrl, accessToken, authType, authUsername, schemaVersion, ...rest } = config;
|
|
381
410
|
const nextApiBaseUrl = readEnvApiBaseUrl(config);
|
|
382
411
|
const previousApiBaseUrl = readEnvApiBaseUrl(previous);
|
|
383
412
|
const baseUrlChanged = previousApiBaseUrl !== nextApiBaseUrl;
|
|
384
413
|
const previousAuthType = resolveConfiguredAuthType(previous);
|
|
385
414
|
const requestedAuthType = normalizeConfiguredAuthType(authType);
|
|
386
|
-
const
|
|
415
|
+
const nextAccessToken = normalizeOptionalString(accessToken);
|
|
416
|
+
const nextAuthType = requestedAuthType ?? (nextAccessToken ? 'token' : previousAuthType);
|
|
387
417
|
const nextAuthUsername = nextAuthType === 'basic' ? normalizeOptionalString(authUsername) ?? previous?.authUsername : undefined;
|
|
388
|
-
const nextAuth =
|
|
418
|
+
const nextAuth = nextAccessToken
|
|
389
419
|
? {
|
|
390
420
|
type: 'token',
|
|
391
|
-
accessToken,
|
|
421
|
+
accessToken: nextAccessToken,
|
|
392
422
|
}
|
|
393
423
|
: nextAuthType === 'oauth' && !baseUrlChanged && previous?.auth?.type === 'oauth'
|
|
394
424
|
? previous.auth
|
|
@@ -396,6 +426,9 @@ export async function upsertEnv(envName, config, options = {}) {
|
|
|
396
426
|
const authChanged = !areAuthConfigsEquivalent(previous?.auth, nextAuth);
|
|
397
427
|
const authTypeChanged = previousAuthType !== nextAuthType;
|
|
398
428
|
const authUsernameChanged = previous?.authUsername !== nextAuthUsername;
|
|
429
|
+
const nextSchemaVersion = normalizeEnvConfigSchemaVersion(schemaVersion) ??
|
|
430
|
+
normalizeEnvConfigSchemaVersion(previous?.schemaVersion) ??
|
|
431
|
+
ENV_CONFIG_SCHEMA_VERSION;
|
|
399
432
|
return {
|
|
400
433
|
...previous,
|
|
401
434
|
apiBaseUrl: nextApiBaseUrl,
|
|
@@ -403,6 +436,7 @@ export async function upsertEnv(envName, config, options = {}) {
|
|
|
403
436
|
authUsername: nextAuthUsername,
|
|
404
437
|
auth: nextAuth,
|
|
405
438
|
...rest,
|
|
439
|
+
schemaVersion: nextSchemaVersion,
|
|
406
440
|
runtime: baseUrlChanged || authChanged || authTypeChanged || authUsernameChanged ? undefined : previous?.runtime,
|
|
407
441
|
};
|
|
408
442
|
}, options);
|
|
@@ -487,6 +521,64 @@ export async function setEnvRuntime(envName, runtime, options = {}) {
|
|
|
487
521
|
};
|
|
488
522
|
await saveAuthConfig(config, options);
|
|
489
523
|
}
|
|
524
|
+
export function resolveEnvProxyEntry(config, provider) {
|
|
525
|
+
const proxy = normalizeEnvProxyConfig(config?.proxy);
|
|
526
|
+
const resolved = {
|
|
527
|
+
...(proxy?.host ? { host: proxy.host } : {}),
|
|
528
|
+
...(proxy?.port !== undefined ? { port: proxy.port } : {}),
|
|
529
|
+
...((provider === 'nginx' ? proxy?.nginx : proxy?.caddy) ?? {}),
|
|
530
|
+
};
|
|
531
|
+
return Object.keys(resolved).length > 0 ? resolved : undefined;
|
|
532
|
+
}
|
|
533
|
+
export async function setEnvProxyEntry(envName, provider, entry, options = {}) {
|
|
534
|
+
await writeEnv(envName, (previous) => {
|
|
535
|
+
const currentProxy = normalizeEnvProxyConfig(previous?.proxy) ?? {};
|
|
536
|
+
const nextEntry = normalizeEnvProxyProviderConfig(entry);
|
|
537
|
+
const nextProxy = { ...currentProxy };
|
|
538
|
+
if (nextEntry && 'host' in nextEntry) {
|
|
539
|
+
const host = normalizeOptionalString(nextEntry.host);
|
|
540
|
+
if (host) {
|
|
541
|
+
nextProxy.host = host;
|
|
542
|
+
}
|
|
543
|
+
else {
|
|
544
|
+
delete nextProxy.host;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
if (nextEntry && 'port' in nextEntry) {
|
|
548
|
+
const portValue = nextEntry.port;
|
|
549
|
+
const port = typeof portValue === 'number' && Number.isInteger(portValue) && portValue >= 1 && portValue <= 65535
|
|
550
|
+
? portValue
|
|
551
|
+
: undefined;
|
|
552
|
+
if (port !== undefined) {
|
|
553
|
+
nextProxy.port = port;
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
delete nextProxy.port;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
const providerConfig = nextEntry && Object.keys(nextEntry).some((key) => key !== 'host' && key !== 'port')
|
|
560
|
+
? Object.fromEntries(Object.entries(nextEntry).filter(([key]) => key !== 'host' && key !== 'port'))
|
|
561
|
+
: undefined;
|
|
562
|
+
if (provider === 'nginx') {
|
|
563
|
+
if (providerConfig && Object.keys(providerConfig).length > 0) {
|
|
564
|
+
nextProxy.nginx = providerConfig;
|
|
565
|
+
}
|
|
566
|
+
else {
|
|
567
|
+
delete nextProxy.nginx;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
else if (providerConfig && Object.keys(providerConfig).length > 0) {
|
|
571
|
+
nextProxy.caddy = providerConfig;
|
|
572
|
+
}
|
|
573
|
+
else {
|
|
574
|
+
delete nextProxy.caddy;
|
|
575
|
+
}
|
|
576
|
+
return {
|
|
577
|
+
...previous,
|
|
578
|
+
proxy: nextProxy,
|
|
579
|
+
};
|
|
580
|
+
}, options);
|
|
581
|
+
}
|
|
490
582
|
export async function clearEnvRootSetup(envName, options = {}) {
|
|
491
583
|
const config = await loadExactAuthConfig(options);
|
|
492
584
|
const current = config.envs[envName];
|
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';
|
|
@@ -16,6 +17,7 @@ export const DEFAULT_DOCKER_BIN = 'docker';
|
|
|
16
17
|
export const DEFAULT_CADDY_BIN = 'caddy';
|
|
17
18
|
export const DEFAULT_GIT_BIN = 'git';
|
|
18
19
|
export const DEFAULT_NGINX_BIN = 'nginx';
|
|
20
|
+
export const DEFAULT_PNPM_BIN = 'pnpm';
|
|
19
21
|
export const PROXY_PROVIDER_OPTIONS = ['nginx', 'caddy'];
|
|
20
22
|
export const DEFAULT_PROXY_PROVIDER = 'nginx';
|
|
21
23
|
export const NGINX_PROXY_DRIVER_OPTIONS = ['local', 'docker'];
|
|
@@ -32,14 +34,18 @@ export const SUPPORTED_CLI_CONFIG_KEYS = [
|
|
|
32
34
|
'locale',
|
|
33
35
|
'default-ui-host',
|
|
34
36
|
'default-api-host',
|
|
37
|
+
'default-portal-template',
|
|
35
38
|
'update.policy',
|
|
36
39
|
'license.pkg-url',
|
|
37
40
|
'docker.network',
|
|
38
41
|
'docker.container-prefix',
|
|
42
|
+
'nb-image-registry',
|
|
43
|
+
'nb-image-variant',
|
|
39
44
|
'bin.docker',
|
|
40
45
|
'bin.caddy',
|
|
41
46
|
'bin.git',
|
|
42
47
|
'bin.nginx',
|
|
48
|
+
'bin.pnpm',
|
|
43
49
|
'proxy.nb-cli-root',
|
|
44
50
|
'proxy.caddy-driver',
|
|
45
51
|
'proxy.nginx-driver',
|
|
@@ -115,7 +121,10 @@ function pruneSettings(config) {
|
|
|
115
121
|
delete config.settings.locale;
|
|
116
122
|
}
|
|
117
123
|
const init = config.settings?.init;
|
|
118
|
-
if (init &&
|
|
124
|
+
if (init &&
|
|
125
|
+
!trimValue(init.defaultUiHost) &&
|
|
126
|
+
!trimValue(init.defaultApiHost) &&
|
|
127
|
+
!trimValue(init.defaultPortalTemplate)) {
|
|
119
128
|
delete config.settings?.init;
|
|
120
129
|
}
|
|
121
130
|
const update = config.settings?.update;
|
|
@@ -127,7 +136,11 @@ function pruneSettings(config) {
|
|
|
127
136
|
delete config.settings?.license;
|
|
128
137
|
}
|
|
129
138
|
const docker = config.settings?.docker;
|
|
130
|
-
if (docker &&
|
|
139
|
+
if (docker &&
|
|
140
|
+
!trimValue(docker.network) &&
|
|
141
|
+
!trimValue(docker.containerPrefix) &&
|
|
142
|
+
!trimValue(docker.nbImageRegistry) &&
|
|
143
|
+
!trimValue(docker.nbImageVariant)) {
|
|
131
144
|
delete config.settings?.docker;
|
|
132
145
|
}
|
|
133
146
|
const bin = config.settings?.bin;
|
|
@@ -136,6 +149,7 @@ function pruneSettings(config) {
|
|
|
136
149
|
!trimValue(bin.caddy) &&
|
|
137
150
|
!trimValue(bin.git) &&
|
|
138
151
|
!trimValue(bin.nginx) &&
|
|
152
|
+
!trimValue(bin.pnpm) &&
|
|
139
153
|
!trimValue(bin.yarn)) {
|
|
140
154
|
delete config.settings?.bin;
|
|
141
155
|
}
|
|
@@ -171,6 +185,8 @@ export function getExplicitCliConfigValue(config, key) {
|
|
|
171
185
|
return trimValue(config.settings?.init?.defaultUiHost);
|
|
172
186
|
case 'default-api-host':
|
|
173
187
|
return trimValue(config.settings?.init?.defaultApiHost);
|
|
188
|
+
case 'default-portal-template':
|
|
189
|
+
return trimValue(config.settings?.init?.defaultPortalTemplate);
|
|
174
190
|
case 'update.policy':
|
|
175
191
|
return normalizeCliUpdatePolicy(config.settings?.update?.policy);
|
|
176
192
|
case 'license.pkg-url':
|
|
@@ -179,6 +195,10 @@ export function getExplicitCliConfigValue(config, key) {
|
|
|
179
195
|
return trimValue(config.settings?.docker?.network);
|
|
180
196
|
case 'docker.container-prefix':
|
|
181
197
|
return trimValue(config.settings?.docker?.containerPrefix);
|
|
198
|
+
case 'nb-image-registry':
|
|
199
|
+
return normalizeNbImageRegistry(config.settings?.docker?.nbImageRegistry);
|
|
200
|
+
case 'nb-image-variant':
|
|
201
|
+
return normalizeNbImageVariant(config.settings?.docker?.nbImageVariant);
|
|
182
202
|
case 'bin.docker':
|
|
183
203
|
return trimValue(config.settings?.bin?.docker);
|
|
184
204
|
case 'bin.caddy':
|
|
@@ -187,6 +207,8 @@ export function getExplicitCliConfigValue(config, key) {
|
|
|
187
207
|
return trimValue(config.settings?.bin?.git);
|
|
188
208
|
case 'bin.nginx':
|
|
189
209
|
return trimValue(config.settings?.bin?.nginx);
|
|
210
|
+
case 'bin.pnpm':
|
|
211
|
+
return trimValue(config.settings?.bin?.pnpm);
|
|
190
212
|
case 'proxy.nb-cli-root':
|
|
191
213
|
return trimValue(config.settings?.proxy?.nbCliRoot);
|
|
192
214
|
case 'proxy.caddy-driver':
|
|
@@ -217,6 +239,8 @@ export function getEffectiveCliConfigValue(config, key) {
|
|
|
217
239
|
return '127.0.0.1';
|
|
218
240
|
case 'default-api-host':
|
|
219
241
|
return '127.0.0.1';
|
|
242
|
+
case 'default-portal-template':
|
|
243
|
+
return explicit ?? '';
|
|
220
244
|
case 'update.policy':
|
|
221
245
|
return explicit ?? DEFAULT_UPDATE_POLICY;
|
|
222
246
|
case 'license.pkg-url':
|
|
@@ -225,6 +249,12 @@ export function getEffectiveCliConfigValue(config, key) {
|
|
|
225
249
|
return trimValue(config.name) || DEFAULT_DOCKER_NETWORK;
|
|
226
250
|
case 'docker.container-prefix':
|
|
227
251
|
return trimValue(config.name) || DEFAULT_DOCKER_CONTAINER_PREFIX;
|
|
252
|
+
case 'nb-image-registry':
|
|
253
|
+
return explicit ?? (resolveCliLocale(undefined, { configuredLocale: trimValue(config.settings?.locale) }) === 'zh-CN'
|
|
254
|
+
? 'aliyun'
|
|
255
|
+
: DEFAULT_NB_IMAGE_REGISTRY);
|
|
256
|
+
case 'nb-image-variant':
|
|
257
|
+
return explicit ?? DEFAULT_NB_IMAGE_VARIANT;
|
|
228
258
|
case 'bin.docker':
|
|
229
259
|
return DEFAULT_DOCKER_BIN;
|
|
230
260
|
case 'bin.caddy':
|
|
@@ -233,6 +263,8 @@ export function getEffectiveCliConfigValue(config, key) {
|
|
|
233
263
|
return DEFAULT_GIT_BIN;
|
|
234
264
|
case 'bin.nginx':
|
|
235
265
|
return DEFAULT_NGINX_BIN;
|
|
266
|
+
case 'bin.pnpm':
|
|
267
|
+
return DEFAULT_PNPM_BIN;
|
|
236
268
|
case 'proxy.nb-cli-root':
|
|
237
269
|
return explicit ?? resolveCliHomeRoot();
|
|
238
270
|
case 'proxy.caddy-driver':
|
|
@@ -298,6 +330,20 @@ export function normalizeCliConfigValue(key, value) {
|
|
|
298
330
|
}
|
|
299
331
|
return driver;
|
|
300
332
|
}
|
|
333
|
+
if (key === 'nb-image-registry') {
|
|
334
|
+
const registry = normalizeNbImageRegistry(normalized);
|
|
335
|
+
if (!registry) {
|
|
336
|
+
throw new Error(`Config key "${key}" must be one of: ${NB_IMAGE_REGISTRY_OPTIONS.join(', ')}`);
|
|
337
|
+
}
|
|
338
|
+
return registry;
|
|
339
|
+
}
|
|
340
|
+
if (key === 'nb-image-variant') {
|
|
341
|
+
const variant = normalizeNbImageVariant(normalized);
|
|
342
|
+
if (!variant) {
|
|
343
|
+
throw new Error(`Config key "${key}" must be one of: ${NB_IMAGE_VARIANT_OPTIONS.join(', ')}`);
|
|
344
|
+
}
|
|
345
|
+
return variant;
|
|
346
|
+
}
|
|
301
347
|
return normalized;
|
|
302
348
|
}
|
|
303
349
|
export async function loadCliConfig(options = {}) {
|
|
@@ -339,6 +385,12 @@ export async function setCliConfigValue(key, value, options = {}) {
|
|
|
339
385
|
defaultApiHost: normalized,
|
|
340
386
|
};
|
|
341
387
|
break;
|
|
388
|
+
case 'default-portal-template':
|
|
389
|
+
config.settings.init = {
|
|
390
|
+
...(config.settings.init ?? {}),
|
|
391
|
+
defaultPortalTemplate: normalized,
|
|
392
|
+
};
|
|
393
|
+
break;
|
|
342
394
|
case 'update.policy':
|
|
343
395
|
config.settings.update = {
|
|
344
396
|
...(config.settings.update ?? {}),
|
|
@@ -363,6 +415,18 @@ export async function setCliConfigValue(key, value, options = {}) {
|
|
|
363
415
|
containerPrefix: normalized,
|
|
364
416
|
};
|
|
365
417
|
break;
|
|
418
|
+
case 'nb-image-registry':
|
|
419
|
+
config.settings.docker = {
|
|
420
|
+
...(config.settings.docker ?? {}),
|
|
421
|
+
nbImageRegistry: normalized,
|
|
422
|
+
};
|
|
423
|
+
break;
|
|
424
|
+
case 'nb-image-variant':
|
|
425
|
+
config.settings.docker = {
|
|
426
|
+
...(config.settings.docker ?? {}),
|
|
427
|
+
nbImageVariant: normalized,
|
|
428
|
+
};
|
|
429
|
+
break;
|
|
366
430
|
case 'bin.docker':
|
|
367
431
|
config.settings.bin = {
|
|
368
432
|
...(config.settings.bin ?? {}),
|
|
@@ -387,6 +451,12 @@ export async function setCliConfigValue(key, value, options = {}) {
|
|
|
387
451
|
nginx: normalized,
|
|
388
452
|
};
|
|
389
453
|
break;
|
|
454
|
+
case 'bin.pnpm':
|
|
455
|
+
config.settings.bin = {
|
|
456
|
+
...(config.settings.bin ?? {}),
|
|
457
|
+
pnpm: normalized,
|
|
458
|
+
};
|
|
459
|
+
break;
|
|
390
460
|
case 'proxy.nb-cli-root':
|
|
391
461
|
config.settings.proxy = {
|
|
392
462
|
...(config.settings.proxy ?? {}),
|
|
@@ -456,6 +526,11 @@ export async function deleteCliConfigValue(key, options = {}) {
|
|
|
456
526
|
delete config.settings.init.defaultApiHost;
|
|
457
527
|
}
|
|
458
528
|
break;
|
|
529
|
+
case 'default-portal-template':
|
|
530
|
+
if (config.settings.init) {
|
|
531
|
+
delete config.settings.init.defaultPortalTemplate;
|
|
532
|
+
}
|
|
533
|
+
break;
|
|
459
534
|
case 'update.policy':
|
|
460
535
|
if (config.settings.update) {
|
|
461
536
|
delete config.settings.update.policy;
|
|
@@ -476,6 +551,16 @@ export async function deleteCliConfigValue(key, options = {}) {
|
|
|
476
551
|
delete config.settings.docker.containerPrefix;
|
|
477
552
|
}
|
|
478
553
|
break;
|
|
554
|
+
case 'nb-image-registry':
|
|
555
|
+
if (config.settings.docker) {
|
|
556
|
+
delete config.settings.docker.nbImageRegistry;
|
|
557
|
+
}
|
|
558
|
+
break;
|
|
559
|
+
case 'nb-image-variant':
|
|
560
|
+
if (config.settings.docker) {
|
|
561
|
+
delete config.settings.docker.nbImageVariant;
|
|
562
|
+
}
|
|
563
|
+
break;
|
|
479
564
|
case 'bin.docker':
|
|
480
565
|
if (config.settings.bin) {
|
|
481
566
|
delete config.settings.bin.docker;
|
|
@@ -496,6 +581,11 @@ export async function deleteCliConfigValue(key, options = {}) {
|
|
|
496
581
|
delete config.settings.bin.nginx;
|
|
497
582
|
}
|
|
498
583
|
break;
|
|
584
|
+
case 'bin.pnpm':
|
|
585
|
+
if (config.settings.bin) {
|
|
586
|
+
delete config.settings.bin.pnpm;
|
|
587
|
+
}
|
|
588
|
+
break;
|
|
499
589
|
case 'proxy.nb-cli-root':
|
|
500
590
|
if (config.settings.proxy) {
|
|
501
591
|
delete config.settings.proxy.nbCliRoot;
|
|
@@ -556,6 +646,7 @@ const CONFIGURABLE_COMMAND_KEYS = {
|
|
|
556
646
|
caddy: 'bin.caddy',
|
|
557
647
|
git: 'bin.git',
|
|
558
648
|
nginx: 'bin.nginx',
|
|
649
|
+
pnpm: 'bin.pnpm',
|
|
559
650
|
yarn: 'bin.yarn',
|
|
560
651
|
};
|
|
561
652
|
export function isConfigurableCommandName(value) {
|
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
|
+
}
|