@nocobase/cli 2.2.0-beta.7 → 2.2.0-beta.9

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.
Files changed (34) hide show
  1. package/assets/env-proxy/nginx/app.conf.tpl +23 -0
  2. package/assets/env-proxy/nginx/nocobase.conf.tpl +5 -0
  3. package/assets/env-proxy/nginx/snippets/dist-location.conf +5 -0
  4. package/assets/env-proxy/nginx/snippets/gzip.conf +17 -0
  5. package/assets/env-proxy/nginx/snippets/log-format-http.conf +13 -0
  6. package/assets/env-proxy/nginx/snippets/maps-http.conf +14 -0
  7. package/assets/env-proxy/nginx/snippets/mime-types.conf +98 -0
  8. package/assets/env-proxy/nginx/snippets/proxy-location.conf +18 -0
  9. package/assets/env-proxy/nginx/snippets/spa-location.conf +6 -0
  10. package/assets/env-proxy/nginx/snippets/uploads-location.conf +21 -0
  11. package/dist/commands/app/start.js +4 -1
  12. package/dist/commands/install.js +53 -138
  13. package/dist/commands/proxy/caddy/generate.js +93 -7
  14. package/dist/commands/proxy/nginx/generate.js +98 -7
  15. package/dist/commands/revision/create.js +1 -1
  16. package/dist/commands/self/update.js +2 -2
  17. package/dist/commands/source/download.js +16 -12
  18. package/dist/lib/app-managed-resources.js +3 -4
  19. package/dist/lib/auth-store.js +82 -6
  20. package/dist/lib/cli-config.js +71 -1
  21. package/dist/lib/docker-image.js +94 -6
  22. package/dist/lib/env-auth.js +291 -45
  23. package/dist/lib/env-config.js +5 -0
  24. package/dist/lib/env-proxy-config.js +48 -0
  25. package/dist/lib/env-proxy.js +164 -58
  26. package/dist/lib/prompt-validators.js +1 -1
  27. package/dist/lib/proxy-caddy.js +77 -9
  28. package/dist/lib/proxy-nginx.js +71 -11
  29. package/dist/lib/run-npm.js +4 -0
  30. package/dist/lib/self-manager.js +251 -46
  31. package/dist/lib/startup-update.js +1 -1
  32. package/dist/locale/en-US.json +2 -2
  33. package/dist/locale/zh-CN.json +2 -2
  34. package/package.json +3 -2
@@ -0,0 +1,23 @@
1
+ # Rendered by `nb env proxy`.
2
+ # Context:
3
+ # publicBasePath={{publicBasePath}}
4
+ # apiBasePath={{apiBasePath}}
5
+ # wsPath={{wsPath}}
6
+ # v2PublicPath={{v2PublicPath}}
7
+ # backendUrl={{backendUrl}}
8
+ # snippetsDir={{snippetsDir}}
9
+ # uploadsDir={{uploadsDir}}
10
+ # distRootDir={{distRootDir}}
11
+ # entryDir={{entryDir}}
12
+ # publicDir={{publicDir}}
13
+
14
+ server {
15
+ listen 80;
16
+ server_name _;
17
+
18
+ # Add custom directives or locations above the managed block as needed.
19
+
20
+ {{managedConfigBlock}}
21
+
22
+ # Add custom directives or locations below the managed block as needed.
23
+ }
@@ -0,0 +1,5 @@
1
+ # Managed by `nb env proxy`. Changes will be overwritten.
2
+
3
+ include {{snippetsDir}}/log-format-http.conf;
4
+ include {{snippetsDir}}/maps-http.conf;
5
+ include {{appConfigIncludePath}};
@@ -0,0 +1,5 @@
1
+ expires 365d;
2
+ add_header Cache-Control "public" always;
3
+
4
+ access_log off;
5
+ autoindex off;
@@ -0,0 +1,17 @@
1
+ gzip on;
2
+ gzip_types
3
+ text/plain
4
+ text/css
5
+ text/xml
6
+ text/markdown
7
+ text/javascript
8
+ application/javascript
9
+ application/json
10
+ application/manifest+json
11
+ application/atom+xml
12
+ application/rss+xml
13
+ application/xml
14
+ application/xml+rss
15
+ application/xhtml+xml
16
+ application/wasm
17
+ image/svg+xml;
@@ -0,0 +1,13 @@
1
+ log_format apm '"$time_local" client=$remote_addr '
2
+ 'method=$request_method request="$request" '
3
+ 'request_length=$request_length '
4
+ 'status=$status bytes_sent=$bytes_sent '
5
+ 'body_bytes_sent=$body_bytes_sent '
6
+ 'referer=$http_referer '
7
+ 'user_agent="$http_user_agent" '
8
+ 'upstream_addr=$upstream_addr '
9
+ 'upstream_status=$upstream_status '
10
+ 'request_time=$request_time '
11
+ 'upstream_response_time=$upstream_response_time '
12
+ 'upstream_connect_time=$upstream_connect_time '
13
+ 'upstream_header_time=$upstream_header_time';
@@ -0,0 +1,14 @@
1
+ map $http_upgrade $connection_upgrade {
2
+ default upgrade;
3
+ "" close;
4
+ }
5
+
6
+ map $http_x_forwarded_proto $upstream_x_forwarded_proto {
7
+ default $http_x_forwarded_proto;
8
+ "" $scheme;
9
+ }
10
+
11
+ map $http_host $final_host {
12
+ default $http_host;
13
+ "" $host;
14
+ }
@@ -0,0 +1,98 @@
1
+ types {
2
+ text/html html htm shtml;
3
+ text/css css;
4
+ text/xml xml;
5
+ image/gif gif;
6
+ image/jpeg jpeg jpg;
7
+ application/javascript js mjs;
8
+ application/atom+xml atom;
9
+ application/rss+xml rss;
10
+
11
+ text/mathml mml;
12
+ text/plain txt;
13
+ text/vnd.sun.j2me.app-descriptor jad;
14
+ text/vnd.wap.wml wml;
15
+ text/x-component htc;
16
+
17
+ image/avif avif;
18
+ image/png png;
19
+ image/svg+xml svg svgz;
20
+ image/tiff tif tiff;
21
+ image/vnd.wap.wbmp wbmp;
22
+ image/webp webp;
23
+ image/x-icon ico;
24
+ image/x-jng jng;
25
+ image/x-ms-bmp bmp;
26
+
27
+ font/woff woff;
28
+ font/woff2 woff2;
29
+
30
+ application/java-archive jar war ear;
31
+ application/json json;
32
+ application/mac-binhex40 hqx;
33
+ application/msword doc;
34
+ application/pdf pdf;
35
+ application/postscript ps eps ai;
36
+ application/rtf rtf;
37
+ application/vnd.apple.mpegurl m3u8;
38
+ application/vnd.google-earth.kml+xml kml;
39
+ application/vnd.google-earth.kmz kmz;
40
+ application/vnd.ms-excel xls;
41
+ application/vnd.ms-fontobject eot;
42
+ application/vnd.ms-powerpoint ppt;
43
+ application/vnd.oasis.opendocument.graphics odg;
44
+ application/vnd.oasis.opendocument.presentation odp;
45
+ application/vnd.oasis.opendocument.spreadsheet ods;
46
+ application/vnd.oasis.opendocument.text odt;
47
+ application/vnd.openxmlformats-officedocument.presentationml.presentation
48
+ pptx;
49
+ application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
50
+ xlsx;
51
+ application/vnd.openxmlformats-officedocument.wordprocessingml.document
52
+ docx;
53
+ application/vnd.wap.wmlc wmlc;
54
+ application/wasm wasm;
55
+ application/x-7z-compressed 7z;
56
+ application/x-cocoa cco;
57
+ application/x-java-archive-diff jardiff;
58
+ application/x-java-jnlp-file jnlp;
59
+ application/x-makeself run;
60
+ application/x-perl pl pm;
61
+ application/x-pilot prc pdb;
62
+ application/x-rar-compressed rar;
63
+ application/x-redhat-package-manager rpm;
64
+ application/x-sea sea;
65
+ application/x-shockwave-flash swf;
66
+ application/x-stuffit sit;
67
+ application/x-tcl tcl tk;
68
+ application/x-x509-ca-cert der pem crt;
69
+ application/x-xpinstall xpi;
70
+ application/xhtml+xml xhtml;
71
+ application/xspf+xml xspf;
72
+ application/zip zip;
73
+
74
+ application/octet-stream bin exe dll;
75
+ application/octet-stream deb;
76
+ application/octet-stream dmg;
77
+ application/octet-stream iso img;
78
+ application/octet-stream msi msp msm;
79
+
80
+ audio/midi mid midi kar;
81
+ audio/mpeg mp3;
82
+ audio/ogg ogg;
83
+ audio/x-m4a m4a;
84
+ audio/x-realaudio ra;
85
+
86
+ video/3gpp 3gpp 3gp;
87
+ video/mp2t ts;
88
+ video/mp4 mp4;
89
+ video/mpeg mpeg mpg;
90
+ video/quicktime mov;
91
+ video/webm webm;
92
+ video/x-flv flv;
93
+ video/x-m4v m4v;
94
+ video/x-mng mng;
95
+ video/x-ms-asf asx asf;
96
+ video/x-ms-wmv wmv;
97
+ video/x-msvideo avi;
98
+ }
@@ -0,0 +1,18 @@
1
+ proxy_http_version 1.1;
2
+
3
+ proxy_set_header Upgrade $http_upgrade;
4
+ proxy_set_header Connection $connection_upgrade;
5
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
6
+ proxy_set_header X-Forwarded-Proto $upstream_x_forwarded_proto;
7
+ proxy_set_header Host $final_host;
8
+ proxy_set_header Referer $http_referer;
9
+ proxy_set_header User-Agent $http_user_agent;
10
+
11
+ add_header Cache-Control "no-cache, no-store" always;
12
+ proxy_cache_bypass $http_upgrade;
13
+
14
+ proxy_connect_timeout 600;
15
+ proxy_send_timeout 600;
16
+ proxy_read_timeout 600;
17
+ send_timeout 600;
18
+ proxy_buffering off;
@@ -0,0 +1,6 @@
1
+ add_header Cache-Control "no-store, no-cache, must-revalidate" always;
2
+ add_header X-Robots-Tag "noindex, nofollow" always;
3
+
4
+ if_modified_since off;
5
+ expires off;
6
+ etag off;
@@ -0,0 +1,21 @@
1
+ add_header Cache-Control "public" always;
2
+ add_header X-Content-Type-Options "nosniff" always;
3
+
4
+ access_log off;
5
+ autoindex off;
6
+
7
+ # Force potentially renderable uploaded files to download.
8
+ location ~* \.(?:htm|html|svg|svgz|xhtml)$ {
9
+ add_header Cache-Control "public" always;
10
+ add_header X-Content-Type-Options "nosniff" always;
11
+ add_header Content-Disposition "attachment" always;
12
+ }
13
+
14
+ # Let Markdown files render as plain Markdown text.
15
+ location ~* \.md$ {
16
+ default_type text/markdown;
17
+
18
+ add_header Cache-Control "public" always;
19
+ add_header X-Content-Type-Options "nosniff" always;
20
+ add_header Content-Disposition "inline" always;
21
+ }
@@ -37,6 +37,9 @@ function buildLicenseSyncArgv(envName, options) {
37
37
  }
38
38
  function resolveHookCommand(value) {
39
39
  const text = String(value ?? '').trim();
40
+ if (text === 'init') {
41
+ return text;
42
+ }
40
43
  if (text === 'app:restart' || text === 'app:upgrade') {
41
44
  return text;
42
45
  }
@@ -225,7 +228,7 @@ export default class AppStart extends Command {
225
228
  }),
226
229
  'hook-command': Flags.string({
227
230
  hidden: true,
228
- options: ['app:start', 'app:restart', 'app:upgrade'],
231
+ options: ['init', 'app:start', 'app:restart', 'app:upgrade'],
229
232
  }),
230
233
  };
231
234
  async run() {
@@ -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 = {
@@ -1468,8 +1460,6 @@ export default class Install extends Command {
1468
1460
  '-d',
1469
1461
  '--name',
1470
1462
  containerName,
1471
- '--restart',
1472
- 'always',
1473
1463
  '--network',
1474
1464
  networkName,
1475
1465
  '-e',
@@ -1512,8 +1502,6 @@ export default class Install extends Command {
1512
1502
  '-d',
1513
1503
  '--name',
1514
1504
  containerName,
1515
- '--restart',
1516
- 'always',
1517
1505
  '--network',
1518
1506
  networkName,
1519
1507
  '-e',
@@ -1558,8 +1546,6 @@ export default class Install extends Command {
1558
1546
  '-d',
1559
1547
  '--name',
1560
1548
  containerName,
1561
- '--restart',
1562
- 'always',
1563
1549
  '--network',
1564
1550
  networkName,
1565
1551
  '-e',
@@ -1604,8 +1590,6 @@ export default class Install extends Command {
1604
1590
  '-d',
1605
1591
  '--name',
1606
1592
  containerName,
1607
- '--restart',
1608
- 'always',
1609
1593
  '--network',
1610
1594
  networkName,
1611
1595
  '--platform',
@@ -1768,12 +1752,15 @@ export default class Install extends Command {
1768
1752
  return plan;
1769
1753
  }
1770
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;
1771
1757
  const dockerRegistry = String(downloadResultsValue(params.downloadResults, 'dockerRegistry') ?? '').trim() ||
1772
- defaultDockerRegistryForLang(process.env.NB_LOCALE);
1758
+ resolveOfficialDockerRegistry(configuredRegistry);
1773
1759
  const version = String(downloadResultsValue(params.downloadResults, 'version') ?? '').trim() || DEFAULT_DOCKER_VERSION;
1774
1760
  const imageRef = resolveDockerImageRef(dockerRegistry, version, {
1775
- defaultRegistry: defaultDockerRegistryForLang(process.env.NB_LOCALE),
1761
+ defaultRegistry: resolveOfficialDockerRegistry(configuredRegistry),
1776
1762
  defaultVersion: DEFAULT_DOCKER_VERSION,
1763
+ variant: inferNbImageRegistryFromRepository(dockerRegistry) ? configuredVariant : undefined,
1777
1764
  });
1778
1765
  const appPort = String(params.appResults.appPort ?? DEFAULT_INSTALL_APP_PORT).trim() || DEFAULT_INSTALL_APP_PORT;
1779
1766
  const configuredStoragePath = resolveConfiguredStoragePathValue(params.appResults, params.envName);
@@ -1800,17 +1787,16 @@ export default class Install extends Command {
1800
1787
  appResults: params.appResults,
1801
1788
  rootResults: params.rootResults,
1802
1789
  });
1790
+ const containerPort = resolveDockerImageContainerPort(imageRef);
1803
1791
  const args = [
1804
1792
  'run',
1805
1793
  '-d',
1806
1794
  '--name',
1807
1795
  containerName,
1808
- '--restart',
1809
- 'always',
1810
1796
  '--network',
1811
1797
  params.networkName,
1812
1798
  '-p',
1813
- `${appPort}:80`,
1799
+ `${appPort}:${containerPort}`,
1814
1800
  ];
1815
1801
  if (envFile) {
1816
1802
  args.push('--env-file', envFile);
@@ -2000,12 +1986,15 @@ export default class Install extends Command {
2000
1986
  }
2001
1987
  async ensureSkippedDownloadInputsReady(params) {
2002
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;
2003
1991
  const dockerRegistry = String(downloadResultsValue(params.downloadResults, 'dockerRegistry') ?? '').trim() ||
2004
- defaultDockerRegistryForLang(process.env.NB_LOCALE);
1992
+ resolveOfficialDockerRegistry(configuredRegistry);
2005
1993
  const version = String(downloadResultsValue(params.downloadResults, 'version') ?? '').trim() || DEFAULT_DOCKER_VERSION;
2006
1994
  const imageRef = resolveDockerImageRef(dockerRegistry, version, {
2007
- defaultRegistry: defaultDockerRegistryForLang(process.env.NB_LOCALE),
1995
+ defaultRegistry: resolveOfficialDockerRegistry(configuredRegistry),
2008
1996
  defaultVersion: DEFAULT_DOCKER_VERSION,
1997
+ variant: inferNbImageRegistryFromRepository(dockerRegistry) ? configuredVariant : undefined,
2009
1998
  });
2010
1999
  const imageExists = await commandSucceeds('docker', ['image', 'inspect', imageRef]);
2011
2000
  if (!imageExists) {
@@ -2264,6 +2253,13 @@ export default class Install extends Command {
2264
2253
  }
2265
2254
  await this.config.runCommand('env:update', [params.envName]);
2266
2255
  }
2256
+ buildAppStartArgv(params) {
2257
+ const argv = ['--env', params.envName, '--yes', '--no-sync-licensed-plugins', '--hook-command', 'init'];
2258
+ if (params.verbose) {
2259
+ argv.push('--verbose');
2260
+ }
2261
+ return argv;
2262
+ }
2267
2263
  async runInstallHookIfNeeded(params) {
2268
2264
  const appPath = Install.resolveAbsoluteAppPath(params.envName, params.appResults);
2269
2265
  const savedHookScript = Install.toOptionalPromptString(params.appResults.hookScript);
@@ -2401,7 +2397,7 @@ export default class Install extends Command {
2401
2397
  if (resumePreset?.appPreset?.hookScript !== undefined && appResults.hookScript === undefined) {
2402
2398
  appResults.hookScript = resumePreset.appPreset.hookScript;
2403
2399
  }
2404
- const downloadOpts = Install.buildDownloadPromptOptionsForInstall(appResults, envName);
2400
+ const downloadOpts = await Install.buildDownloadPromptOptionsForInstall(appResults, envName);
2405
2401
  downloadOpts.values = {
2406
2402
  ...(resumePreset?.downloadPreset ?? {}),
2407
2403
  ...downloadOpts.values,
@@ -2508,7 +2504,6 @@ export default class Install extends Command {
2508
2504
  const parsed = {
2509
2505
  ...flags,
2510
2506
  };
2511
- const defaultApiHost = await resolveDefaultApiHost();
2512
2507
  if (parsed['skip-auth'] && (parsed['access-token'] !== undefined || parsed.token !== undefined)) {
2513
2508
  this.error('--skip-auth cannot be used with --access-token or --token.');
2514
2509
  }
@@ -2588,8 +2583,7 @@ export default class Install extends Command {
2588
2583
  dbResults.dbUser = builtinDbPlan.dbUser;
2589
2584
  dbResults.dbPassword = builtinDbPlan.dbPassword;
2590
2585
  }
2591
- let dockerAppPlan;
2592
- let localAppPlan;
2586
+ let shouldStartApp = false;
2593
2587
  if (source === 'docker' || source === 'npm' || source === 'git') {
2594
2588
  this.logStage('Preparing application');
2595
2589
  if (source === 'docker') {
@@ -2601,111 +2595,28 @@ export default class Install extends Command {
2601
2595
  printInfo('Application image ready.');
2602
2596
  }
2603
2597
  if (!parsed['prepare-only']) {
2604
- await this.runInstallHookIfNeeded({
2605
- hookName: 'beforeAppInstall',
2606
- envName,
2607
- source,
2608
- appResults,
2609
- downloadResults,
2610
- dbResults,
2611
- rootResults,
2612
- envAddResults,
2613
- defaultApiHost,
2614
- });
2615
- dockerAppPlan = await this.installDockerApp({
2616
- envName,
2617
- dockerNetworkName,
2618
- dockerContainerPrefix,
2619
- appResults,
2620
- downloadResults,
2621
- dbResults,
2622
- rootResults,
2623
- builtinDbPlan,
2624
- force: parsed.force,
2625
- commandStdio,
2626
- });
2627
- appResults.appKey = dockerAppPlan.appKey;
2628
- appResults.timeZone = dockerAppPlan.timeZone;
2598
+ shouldStartApp = true;
2629
2599
  }
2630
2600
  }
2631
2601
  else if (source === 'npm' || source === 'git') {
2632
- const localSource = source === 'npm' ? 'npm' : 'git';
2633
- const projectRoot = parsed['skip-download'] || parsed['prepare-only']
2634
- ? Install.resolveLocalProjectRoot({
2635
- envName,
2636
- appResults,
2637
- downloadResults,
2638
- })
2639
- : await this.downloadLocalApp({
2602
+ if (!parsed['skip-download'] && !parsed['prepare-only']) {
2603
+ await this.downloadLocalApp({
2640
2604
  envName,
2641
2605
  appResults,
2642
2606
  downloadResults,
2643
2607
  verbose: parsed.verbose,
2644
2608
  });
2645
- if (!parsed['skip-download'] && !parsed['prepare-only']) {
2646
2609
  printInfo('Application files ready.');
2647
2610
  }
2648
2611
  if (!parsed['prepare-only']) {
2649
- await this.runInstallHookIfNeeded({
2650
- hookName: 'beforeAppInstall',
2651
- envName,
2652
- source,
2653
- appResults,
2654
- downloadResults,
2655
- dbResults,
2656
- rootResults,
2657
- envAddResults,
2658
- projectRoot,
2659
- defaultApiHost,
2660
- });
2661
- localAppPlan = await this.startLocalApp({
2662
- envName,
2663
- source: localSource,
2664
- projectRoot,
2665
- appResults,
2666
- dbResults,
2667
- rootResults,
2668
- commandStdio,
2669
- });
2670
- appResults.appKey = localAppPlan.appKey;
2671
- appResults.timeZone = localAppPlan.timeZone;
2612
+ shouldStartApp = true;
2672
2613
  }
2673
2614
  }
2674
2615
  }
2675
2616
  else {
2676
2617
  this.logDetail('Skipped app download and install.');
2677
2618
  }
2678
- if (dockerAppPlan || localAppPlan) {
2679
- this.logStage('Starting NocoBase');
2680
- await this.waitForAppHealthCheck(Install.resolveApiBaseUrl({
2681
- appResults,
2682
- envAddResults,
2683
- defaultApiHost,
2684
- }), {
2685
- containerName: dockerAppPlan?.containerName,
2686
- verbose: parsed.verbose,
2687
- });
2688
- const displayApiBaseUrl = Install.resolveApiBaseUrl({
2689
- appResults,
2690
- envAddResults,
2691
- defaultApiHost,
2692
- });
2693
- printInfo(`NocoBase is ready at ${formatInstallDisplayUrl(displayApiBaseUrl)}`);
2694
- appResults.setupState = 'installed';
2695
- await this.runInstallHookIfNeeded({
2696
- hookName: 'afterAppStart',
2697
- envName,
2698
- source,
2699
- appResults,
2700
- downloadResults,
2701
- dbResults,
2702
- rootResults,
2703
- envAddResults,
2704
- projectRoot: localAppPlan?.projectRoot,
2705
- defaultApiHost,
2706
- });
2707
- }
2708
- if (dockerAppPlan || localAppPlan || builtinDbPlan) {
2619
+ if (shouldStartApp || builtinDbPlan) {
2709
2620
  await this.saveInstalledEnv({
2710
2621
  envName,
2711
2622
  appResults,
@@ -2715,10 +2626,14 @@ export default class Install extends Command {
2715
2626
  envAddResults,
2716
2627
  });
2717
2628
  }
2629
+ if (shouldStartApp) {
2630
+ this.logStage('Starting NocoBase');
2631
+ await this.config.runCommand('app:start', this.buildAppStartArgv({ envName, verbose: parsed.verbose }));
2632
+ }
2718
2633
  await this.syncInstalledEnvConnection({
2719
2634
  envName,
2720
2635
  envAddResults,
2721
- appReady: Boolean(dockerAppPlan || localAppPlan),
2636
+ appReady: shouldStartApp,
2722
2637
  skipAuth: Boolean(parsed['skip-auth']),
2723
2638
  });
2724
2639
  if (!parsed['prepare-only']) {
@@ -2727,7 +2642,7 @@ export default class Install extends Command {
2727
2642
  if (parsed['prepare-only']) {
2728
2643
  printInfo(`Preparation complete for "${envName}". Activate the license, then run \`nb app start --env ${envName}\`.`);
2729
2644
  }
2730
- else if (!dockerAppPlan && !localAppPlan) {
2645
+ else if (!shouldStartApp) {
2731
2646
  printInfo(`Install config for "${envName}" has been saved.`);
2732
2647
  }
2733
2648
  }