@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.
@@ -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, resolveCliLocale, translateCli } from "../lib/cli-locale.js";
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, { defaultDockerRegistryForLang } from './download.js';
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 Object.prototype.hasOwnProperty.call(DEFAULT_INSTALL_BUILTIN_DB_IMAGES, dialect);
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
- const defaults = resolveCliLocale(process.env.NB_LOCALE) === 'zh-CN'
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
- if (params.flags['db-port'] !== undefined) {
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: defaultDockerRegistryForLang(process.env.NB_LOCALE),
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
- defaultDockerRegistryForLang(process.env.NB_LOCALE);
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: defaultDockerRegistryForLang(process.env.NB_LOCALE),
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}:80`,
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
- defaultDockerRegistryForLang(process.env.NB_LOCALE);
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: defaultDockerRegistryForLang(process.env.NB_LOCALE),
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 --app-port 13000 --storage-path /path/to/storage --dist-root-path /path/to/dist-client --runtime-version 2.1.0',
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 requestedAppPort = flags['app-port']?.trim() || undefined;
77
- const appPort = normalizeProxyListenPort(requestedAppPort);
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 (requestedAppPort && !appPort) {
82
- this.error(`Invalid manual app port "${requestedAppPort}". Use an integer between 1 and 65535.`);
81
+ if (requestedUpstreamPort && !upstreamPort) {
82
+ this.error(`Invalid manual upstream port "${requestedUpstreamPort}". Use an integer between 1 and 65535.`);
83
83
  }
84
- if (!name || !appPort || !storagePath || !distRootPath || !runtimeVersion) {
85
- this.error('Manual mode requires `--name`, `--app-port`, `--storage-path`, `--dist-root-path`, and `--runtime-version`.');
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 --app-port 13000 --storage-path /path/to/storage --dist-root-path /path/to/dist-client --runtime-version 2.1.0',
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 requestedAppPort = flags['app-port']?.trim() || undefined;
80
- const appPort = normalizeProxyListenPort(requestedAppPort);
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 (requestedAppPort && !appPort) {
85
- this.error(`Invalid manual app port "${requestedAppPort}". Use an integer between 1 and 65535.`);
84
+ if (requestedUpstreamPort && !upstreamPort) {
85
+ this.error(`Invalid manual upstream port "${requestedUpstreamPort}". Use an integer between 1 and 65535.`);
86
86
  }
87
- if (!name || !appPort || !storagePath || !distRootPath || !runtimeVersion) {
88
- this.error('Manual mode requires `--name`, `--app-port`, `--storage-path`, `--dist-root-path`, and `--runtime-version`.');
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,
@@ -100,7 +100,7 @@ export default class RevisionCreate extends Command {
100
100
  path: '/app:publishEvent',
101
101
  body: {
102
102
  plugin: 'plugin-version-control',
103
- command: 'revision:create',
103
+ command: 'revision.create',
104
104
  payload: {
105
105
  description,
106
106
  },
@@ -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: defaultDockerRegistryForLang(process.env.NB_LOCALE),
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
- buildInitialValuesFromParsed(flags, preset) {
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 = localeDefaultDockerRegistry;
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() || defaultDockerRegistryForLang(flags.locale ?? process.env.NB_LOCALE)
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 initialValues = this.buildInitialValuesFromParsed(flags, presetValues);
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: defaultDockerRegistryForLang(process.env.NB_LOCALE),
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}:80`);
237
+ args.push('-p', `${appPort}:${containerPort}`);
237
238
  }
238
239
  if (envFile) {
239
240
  args.push('--env-file', envFile);
@@ -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
  : {}),
@@ -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 && !trimValue(docker.network) && !trimValue(docker.containerPrefix)) {
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;
@@ -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 (!shouldUseFullDockerImageTag(registry)) {
79
+ if (hasKnownVariantSuffix(tag)) {
26
80
  return tag;
27
81
  }
28
- return tag.endsWith(DOCKER_IMAGE_FULL_SUFFIX)
29
- ? tag
30
- : `${tag}${DOCKER_IMAGE_FULL_SUFFIX}`;
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
+ }
@@ -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 backendUrl = `http://${proxyHost}:${source.apiPort}`;
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.appPort,
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.4",
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": "81bf8733db4bccf08a6bc5e6d97f274bce349161"
147
+ "gitHead": "814ff497dd1233ca7218c9f7f2a016c2ead6516d"
148
148
  }