@nocobase/cli 2.1.0-alpha.46 → 2.1.0-alpha.47
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/LICENSE +201 -0
- package/README.md +63 -380
- package/assets/env-proxy/nginx/app.conf.tpl +23 -0
- package/assets/env-proxy/nginx/nocobase.conf.tpl +5 -0
- package/assets/env-proxy/nginx/snippets/dist-location.conf +5 -0
- package/assets/env-proxy/nginx/snippets/gzip.conf +17 -0
- package/assets/env-proxy/nginx/snippets/log-format-http.conf +13 -0
- package/assets/env-proxy/nginx/snippets/maps-http.conf +14 -0
- package/assets/env-proxy/nginx/snippets/mime-types.conf +98 -0
- package/assets/env-proxy/nginx/snippets/proxy-location.conf +17 -0
- package/assets/env-proxy/nginx/snippets/spa-location.conf +6 -0
- package/assets/env-proxy/nginx/snippets/uploads-location.conf +21 -0
- package/bin/run.js +40 -3
- package/dist/commands/app/autostart/disable.js +55 -0
- package/dist/commands/app/autostart/enable.js +55 -0
- package/dist/commands/app/autostart/list.js +37 -0
- package/dist/commands/app/autostart/run.js +84 -0
- package/dist/commands/app/autostart/shared.js +49 -0
- package/dist/commands/app/destroy.js +21 -12
- package/dist/commands/app/down.js +2 -2
- package/dist/commands/app/logs.js +2 -1
- package/dist/commands/app/restart.js +89 -24
- package/dist/commands/app/shared.js +3 -2
- package/dist/commands/app/start.js +142 -38
- package/dist/commands/app/stop.js +31 -2
- package/dist/commands/app/upgrade.js +9 -5
- package/dist/commands/config/delete.js +6 -1
- package/dist/commands/config/get.js +6 -1
- package/dist/commands/config/set.js +7 -2
- package/dist/commands/env/add.js +24 -44
- package/dist/commands/env/info.js +3 -2
- package/dist/commands/env/proxy/caddy.js +28 -0
- package/dist/commands/env/proxy/index.js +353 -0
- package/dist/commands/env/proxy/nginx.js +28 -0
- package/dist/commands/env/remove.js +112 -22
- package/dist/commands/env/shared.js +17 -9
- package/dist/commands/env/update.js +385 -21
- package/dist/commands/init.js +350 -98
- package/dist/commands/install.js +218 -75
- package/dist/commands/license/activate.js +63 -244
- package/dist/commands/license/plugins/shared.js +64 -13
- package/dist/commands/plugin/import.js +108 -0
- package/dist/commands/revision/create.js +89 -0
- package/dist/commands/source/test.js +13 -14
- package/dist/lib/app-health.js +5 -5
- package/dist/lib/app-managed-resources.js +24 -8
- package/dist/lib/app-public-path.js +80 -0
- package/dist/lib/app-runtime.js +10 -1
- package/dist/lib/auth-store.js +119 -4
- package/dist/lib/cli-config.js +191 -3
- package/dist/lib/cli-entry-error.js +8 -0
- package/dist/lib/command-log.js +284 -0
- package/dist/lib/docker-env-file.js +10 -2
- package/dist/lib/env-auth.js +4 -1
- package/dist/lib/env-command-config.js +45 -0
- package/dist/lib/env-config.js +7 -2
- package/dist/lib/env-guard.js +9 -10
- package/dist/lib/env-paths.js +101 -0
- package/dist/lib/env-proxy.js +1295 -0
- package/dist/lib/inquirer.js +4 -5
- package/dist/lib/managed-env-file.js +98 -0
- package/dist/lib/plugin-import.js +279 -0
- package/dist/lib/prompt-catalog-core.js +3 -2
- package/dist/lib/prompt-validators.js +14 -0
- package/dist/lib/prompt-web-ui.js +8 -1
- package/dist/lib/run-npm.js +56 -12
- package/dist/lib/skills-manager.js +3 -1
- package/dist/lib/source-publish.js +18 -1
- package/dist/lib/ui.js +2 -1
- package/dist/locale/en-US.json +116 -22
- package/dist/locale/zh-CN.json +113 -19
- package/package.json +5 -7
- package/scripts/build.mjs +34 -0
- package/scripts/clean.mjs +9 -0
- package/tsconfig.json +19 -0
- package/LICENSE.txt +0 -107
- package/README.zh-CN.md +0 -355
package/dist/commands/install.js
CHANGED
|
@@ -11,24 +11,27 @@ import crypto from 'node:crypto';
|
|
|
11
11
|
import { access, mkdir } from 'node:fs/promises';
|
|
12
12
|
import path from 'node:path';
|
|
13
13
|
import { exit } from 'node:process';
|
|
14
|
+
import { appendAppPublicPath } from '../lib/app-public-path.js';
|
|
14
15
|
import { runPromptCatalog, } from "../lib/prompt-catalog.js";
|
|
15
16
|
import { applyCliLocale, localeText, resolveCliLocale, translateCli } from "../lib/cli-locale.js";
|
|
16
17
|
import { resolveConfiguredEnvPath, resolveDefaultConfigScope, resolveEnvRoot, resolveEnvRelativePath, } from '../lib/cli-home.js';
|
|
17
18
|
import { defaultDockerContainerPrefix, defaultDockerNetworkName } from '../lib/app-runtime.js';
|
|
18
|
-
import { resolveDockerContainerPrefix, resolveDockerNetworkName } from '../lib/cli-config.js';
|
|
19
|
+
import { resolveDefaultApiHost, resolveDockerContainerPrefix, resolveDockerNetworkName } from '../lib/cli-config.js';
|
|
19
20
|
import { DEFAULT_DOCKER_VERSION, resolveDockerImageRef } from "../lib/docker-image.js";
|
|
20
|
-
import { findAvailableTcpPort, validateAvailableTcpPort, validateTcpPort, validateEnvKey, } from "../lib/prompt-validators.js";
|
|
21
|
+
import { findAvailableTcpPort, validateAppPublicPath, validateAvailableTcpPort, validateTcpPort, validateEnvKey, } from "../lib/prompt-validators.js";
|
|
21
22
|
import { validateExternalDbConfig, validateMysqlLowerCaseTableNamesCompatibility } from "../lib/db-connection-check.js";
|
|
22
23
|
import { formatMissingManagedAppEnvMessage } from '../lib/app-runtime.js';
|
|
23
|
-
import { commandOutput, commandSucceeds, run, runNocoBaseCommand } from '../lib/run-npm.js';
|
|
24
|
+
import { commandOutput, commandSucceeds, ensureDockerDaemonRunning, run, runNocoBaseCommand } from '../lib/run-npm.js';
|
|
24
25
|
import { printInfo, printStage, printVerbose, printWarning, setVerboseMode } from '../lib/ui.js';
|
|
25
26
|
import { omitKeys, upperFirst } from "../lib/object-utils.js";
|
|
26
|
-
import { getEnv, setCurrentEnv, upsertEnv } from '../lib/auth-store.js';
|
|
27
|
+
import { clearEnvRootSetup, getEnv, setCurrentEnv, upsertEnv } from '../lib/auth-store.js';
|
|
27
28
|
import { buildStoredEnvConfig } from '../lib/env-config.js';
|
|
28
29
|
import { resolveDockerEnvFileArg } from "../lib/docker-env-file.js";
|
|
29
30
|
import { startDockerLogFollower } from '../lib/docker-log-stream.js';
|
|
31
|
+
import { areConfiguredPathsEquivalent, deriveConfiguredSourcePath, deriveConfiguredStoragePath, inferConfiguredAppPathFromLegacyConfig, } from '../lib/env-paths.js';
|
|
30
32
|
import Download, { defaultDockerRegistryForLang } from './download.js';
|
|
31
33
|
import EnvAdd from "./env/add.js";
|
|
34
|
+
import { resolveAppUrlFromApiBaseUrl } from "./env/shared.js";
|
|
32
35
|
const DEFAULT_INSTALL_ENV_NAME = 'local';
|
|
33
36
|
const DEFAULT_INSTALL_LANG = 'en-US';
|
|
34
37
|
const DEFAULT_INSTALL_APP_PORT = '13000';
|
|
@@ -59,6 +62,19 @@ const DEFAULT_INSTALL_ROOT_USERNAME = 'nocobase';
|
|
|
59
62
|
const DEFAULT_INSTALL_ROOT_EMAIL = 'admin@nocobase.com';
|
|
60
63
|
const DEFAULT_INSTALL_ROOT_PASSWORD = 'admin123';
|
|
61
64
|
const DEFAULT_INSTALL_ROOT_NICKNAME = 'Super Admin';
|
|
65
|
+
const DEFAULT_INSTALL_API_HOST = '127.0.0.1';
|
|
66
|
+
function toOptionalPromptString(value) {
|
|
67
|
+
const text = String(value ?? '').trim();
|
|
68
|
+
return text || undefined;
|
|
69
|
+
}
|
|
70
|
+
function buildInstallApiBaseUrl(appResults, defaultApiHost = DEFAULT_INSTALL_API_HOST) {
|
|
71
|
+
const appPort = String(appResults.appPort ?? DEFAULT_INSTALL_APP_PORT).trim() || DEFAULT_INSTALL_APP_PORT;
|
|
72
|
+
const appPublicPath = String(appResults.appPublicPath ?? '').trim();
|
|
73
|
+
return `http://${defaultApiHost}:${appPort}${appendAppPublicPath(appPublicPath, 'api', { trailingSlash: false })}`;
|
|
74
|
+
}
|
|
75
|
+
function formatInstallDisplayUrl(apiBaseUrl) {
|
|
76
|
+
return resolveAppUrlFromApiBaseUrl(apiBaseUrl) || apiBaseUrl.replace(/\/api\/?$/, '');
|
|
77
|
+
}
|
|
62
78
|
const APP_HEALTH_CHECK_INTERVAL_MS = 2_000;
|
|
63
79
|
const APP_HEALTH_CHECK_TIMEOUT_MS = 600_000;
|
|
64
80
|
const APP_HEALTH_CHECK_REQUEST_TIMEOUT_MS = 5_000;
|
|
@@ -207,13 +223,41 @@ async function validateExternalDbPromptField(value, values) {
|
|
|
207
223
|
}
|
|
208
224
|
return await validateMysqlLowerCaseTableNamesCompatibility(values);
|
|
209
225
|
}
|
|
210
|
-
function
|
|
226
|
+
function defaultInstallAppPath(envName) {
|
|
211
227
|
const name = String(envName ?? DEFAULT_INSTALL_ENV_NAME).trim() || DEFAULT_INSTALL_ENV_NAME;
|
|
212
|
-
return `./${name}
|
|
228
|
+
return `./${name}/`;
|
|
229
|
+
}
|
|
230
|
+
function defaultInstallAppRootPath(envName) {
|
|
231
|
+
return deriveConfiguredSourcePath(defaultInstallAppPath(envName));
|
|
213
232
|
}
|
|
214
233
|
function defaultInstallStoragePath(envName) {
|
|
215
|
-
|
|
216
|
-
|
|
234
|
+
return deriveConfiguredStoragePath(defaultInstallAppPath(envName));
|
|
235
|
+
}
|
|
236
|
+
function resolveConfiguredAppPathValue(values) {
|
|
237
|
+
const explicitAppPath = toOptionalPromptString(values.appPath);
|
|
238
|
+
if (explicitAppPath) {
|
|
239
|
+
return explicitAppPath;
|
|
240
|
+
}
|
|
241
|
+
return inferConfiguredAppPathFromLegacyConfig({
|
|
242
|
+
appRootPath: toOptionalPromptString(values.appRootPath),
|
|
243
|
+
storagePath: toOptionalPromptString(values.storagePath),
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
function resolveConfiguredSourcePathValue(values, envName) {
|
|
247
|
+
const legacyAppRootPath = toOptionalPromptString(values.appRootPath);
|
|
248
|
+
if (legacyAppRootPath) {
|
|
249
|
+
return legacyAppRootPath;
|
|
250
|
+
}
|
|
251
|
+
const appPath = resolveConfiguredAppPathValue(values) ?? defaultInstallAppPath(envName);
|
|
252
|
+
return deriveConfiguredSourcePath(appPath);
|
|
253
|
+
}
|
|
254
|
+
function resolveConfiguredStoragePathValue(values, envName) {
|
|
255
|
+
const legacyStoragePath = toOptionalPromptString(values.storagePath);
|
|
256
|
+
if (legacyStoragePath) {
|
|
257
|
+
return legacyStoragePath;
|
|
258
|
+
}
|
|
259
|
+
const appPath = resolveConfiguredAppPathValue(values) ?? defaultInstallAppPath(envName);
|
|
260
|
+
return deriveConfiguredStoragePath(appPath);
|
|
217
261
|
}
|
|
218
262
|
function pickPresetKeys(source, keys) {
|
|
219
263
|
const out = {};
|
|
@@ -234,6 +278,15 @@ function optionalEnvBoolean(value) {
|
|
|
234
278
|
}
|
|
235
279
|
return Boolean(value);
|
|
236
280
|
}
|
|
281
|
+
function resolveExtractClientAssetsDefaultEnabled(value) {
|
|
282
|
+
const text = String(value ?? '')
|
|
283
|
+
.trim()
|
|
284
|
+
.toLowerCase();
|
|
285
|
+
if (!text) {
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
return !['0', 'false', 'no', 'off'].includes(text);
|
|
289
|
+
}
|
|
237
290
|
function pushOptionalEnvArg(args, key, value) {
|
|
238
291
|
if (typeof value === 'string') {
|
|
239
292
|
if (!value) {
|
|
@@ -276,9 +329,9 @@ export default class Install extends Command {
|
|
|
276
329
|
'<%= config.bin %> <%= command.id %> --env app1 -l zh-CN',
|
|
277
330
|
'<%= config.bin %> <%= command.id %> --env app1 --root-username nocobase --root-email admin@nocobase.com --root-password admin123',
|
|
278
331
|
'<%= config.bin %> <%= command.id %> --env app1 --root-nickname "Super Admin"',
|
|
279
|
-
'<%= config.bin %> <%= command.id %> --env myenv --app-
|
|
280
|
-
'<%= config.bin %> <%= command.id %> --env dev -y --app-
|
|
281
|
-
'<%= config.bin %> <%= command.id %> --env dev -y --skip-download --source git --app-
|
|
332
|
+
'<%= config.bin %> <%= command.id %> --env myenv --app-path=./myenv/',
|
|
333
|
+
'<%= config.bin %> <%= command.id %> --env dev -y --app-path=./dev/',
|
|
334
|
+
'<%= config.bin %> <%= command.id %> --env dev -y --skip-download --source git --app-path=./dev/',
|
|
282
335
|
];
|
|
283
336
|
static flags = {
|
|
284
337
|
yes: Flags.boolean({
|
|
@@ -300,7 +353,7 @@ export default class Install extends Command {
|
|
|
300
353
|
}),
|
|
301
354
|
env: Flags.string({
|
|
302
355
|
char: 'e',
|
|
303
|
-
description: 'App/env name to create or update. Defaults app
|
|
356
|
+
description: 'App/env name to create or update. Defaults the app path to ./<envName>/ and derives source/storage inside it.',
|
|
304
357
|
}),
|
|
305
358
|
'default-api-base-url': Flags.string({
|
|
306
359
|
char: 'd',
|
|
@@ -337,14 +390,24 @@ export default class Install extends Command {
|
|
|
337
390
|
char: 'f',
|
|
338
391
|
required: false,
|
|
339
392
|
}),
|
|
393
|
+
'app-path': Flags.string({
|
|
394
|
+
description: 'App directory for a local npm/git app (default: ./<envName>/)',
|
|
395
|
+
}),
|
|
340
396
|
'app-root-path': Flags.string({
|
|
341
|
-
|
|
397
|
+
hidden: true,
|
|
398
|
+
deprecated: true,
|
|
399
|
+
description: 'Legacy source directory for a local npm/git app',
|
|
342
400
|
}),
|
|
343
401
|
'app-port': Flags.string({
|
|
344
402
|
description: 'HTTP port for the local app (default: 13000, or an available port with --yes)',
|
|
345
403
|
}),
|
|
346
404
|
'storage-path': Flags.string({
|
|
347
|
-
|
|
405
|
+
hidden: true,
|
|
406
|
+
deprecated: true,
|
|
407
|
+
description: 'Legacy storage directory for uploads and managed database data',
|
|
408
|
+
}),
|
|
409
|
+
'app-public-path': Flags.string({
|
|
410
|
+
description: 'Public path for the local app, for example / or /console/',
|
|
348
411
|
}),
|
|
349
412
|
'root-username': Flags.string({
|
|
350
413
|
description: 'Initial admin username for the installed app',
|
|
@@ -416,39 +479,44 @@ export default class Install extends Command {
|
|
|
416
479
|
validate: validateEnvKey,
|
|
417
480
|
},
|
|
418
481
|
};
|
|
419
|
-
static appPrompts
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
482
|
+
static get appPrompts() {
|
|
483
|
+
return {
|
|
484
|
+
lang: {
|
|
485
|
+
type: 'select',
|
|
486
|
+
message: installText('prompts.lang.message'),
|
|
487
|
+
options: INSTALL_LANGUAGE_OPTIONS,
|
|
488
|
+
initialValue: DEFAULT_INSTALL_LANG,
|
|
489
|
+
yesInitialValue: DEFAULT_INSTALL_LANG,
|
|
490
|
+
},
|
|
491
|
+
// force: {
|
|
492
|
+
// type: 'boolean',
|
|
493
|
+
// message: 'Reinstall the application by clearing the database? (-f / --force)',
|
|
494
|
+
// initialValue: false,
|
|
495
|
+
// yesInitialValue: false,
|
|
496
|
+
// },
|
|
497
|
+
appPath: {
|
|
498
|
+
type: 'text',
|
|
499
|
+
message: installText('prompts.appPath.message', { root: resolveEnvRoot() }),
|
|
500
|
+
placeholder: installText('prompts.appPath.placeholder'),
|
|
501
|
+
initialValue: (values) => defaultInstallAppPath(values.env ?? values.appName),
|
|
502
|
+
hidden: (values) => Boolean(Install.toOptionalPromptString(values.appRootPath)),
|
|
503
|
+
},
|
|
504
|
+
appPort: {
|
|
505
|
+
type: 'text',
|
|
506
|
+
message: installText('prompts.appPort.message'),
|
|
507
|
+
placeholder: installText('prompts.appPort.placeholder'),
|
|
508
|
+
validate: Install.validateAppPort,
|
|
509
|
+
},
|
|
510
|
+
appPublicPath: {
|
|
511
|
+
type: 'text',
|
|
512
|
+
message: installText('prompts.appPublicPath.message'),
|
|
513
|
+
placeholder: installText('prompts.appPublicPath.placeholder'),
|
|
514
|
+
initialValue: '/',
|
|
515
|
+
yesInitialValue: '/',
|
|
516
|
+
validate: validateAppPublicPath,
|
|
517
|
+
},
|
|
518
|
+
};
|
|
519
|
+
}
|
|
452
520
|
static dbPrompts = {
|
|
453
521
|
dbDialect: {
|
|
454
522
|
type: 'select',
|
|
@@ -572,8 +640,8 @@ export default class Install extends Command {
|
|
|
572
640
|
},
|
|
573
641
|
};
|
|
574
642
|
/**
|
|
575
|
-
* App catalog with `env` seeded into `out` first so
|
|
576
|
-
*
|
|
643
|
+
* App catalog with `env` seeded into `out` first so app path defaults can see `values.env`
|
|
644
|
+
* (same iteration order as {@link runPromptCatalog}).
|
|
577
645
|
*/
|
|
578
646
|
static buildAppPromptsCatalog(seedEnv, options) {
|
|
579
647
|
return {
|
|
@@ -674,6 +742,12 @@ export default class Install extends Command {
|
|
|
674
742
|
if (argvHasToken(argv, ['--force', '-f'])) {
|
|
675
743
|
preset.force = flags.force;
|
|
676
744
|
}
|
|
745
|
+
if (flags['app-path'] !== undefined) {
|
|
746
|
+
const v = flags['app-path']?.trim();
|
|
747
|
+
if (v) {
|
|
748
|
+
preset.appPath = v;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
677
751
|
if (flags['app-root-path'] !== undefined) {
|
|
678
752
|
const v = flags['app-root-path']?.trim();
|
|
679
753
|
if (v) {
|
|
@@ -692,6 +766,12 @@ export default class Install extends Command {
|
|
|
692
766
|
preset.storagePath = v;
|
|
693
767
|
}
|
|
694
768
|
}
|
|
769
|
+
if (flags['app-public-path'] !== undefined) {
|
|
770
|
+
const v = String(flags['app-public-path'] ?? '').trim();
|
|
771
|
+
if (v) {
|
|
772
|
+
preset.appPublicPath = v;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
695
775
|
if (flags['root-username'] !== undefined) {
|
|
696
776
|
preset.rootUsername = String(flags['root-username'] ?? '').trim();
|
|
697
777
|
}
|
|
@@ -778,9 +858,11 @@ export default class Install extends Command {
|
|
|
778
858
|
return pickPresetKeys(Install.buildPresetValuesFromFlags(flags, argv), [
|
|
779
859
|
'lang',
|
|
780
860
|
'force',
|
|
861
|
+
'appPath',
|
|
781
862
|
'appRootPath',
|
|
782
863
|
'appPort',
|
|
783
864
|
'storagePath',
|
|
865
|
+
'appPublicPath',
|
|
784
866
|
]);
|
|
785
867
|
}
|
|
786
868
|
static buildDbPresetValuesFromFlags(flags, argv = process.argv.slice(2)) {
|
|
@@ -837,11 +919,7 @@ export default class Install extends Command {
|
|
|
837
919
|
};
|
|
838
920
|
}
|
|
839
921
|
static toOptionalPromptString(value) {
|
|
840
|
-
|
|
841
|
-
return undefined;
|
|
842
|
-
}
|
|
843
|
-
const text = String(value).trim();
|
|
844
|
-
return text || undefined;
|
|
922
|
+
return toOptionalPromptString(value);
|
|
845
923
|
}
|
|
846
924
|
static resolveManagedAppKey(value) {
|
|
847
925
|
return Install.toOptionalPromptString(value) ?? crypto.randomBytes(32).toString('hex');
|
|
@@ -849,6 +927,13 @@ export default class Install extends Command {
|
|
|
849
927
|
static resolveManagedTimeZone(value) {
|
|
850
928
|
return Install.toOptionalPromptString(value) ?? (Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC');
|
|
851
929
|
}
|
|
930
|
+
static formatLocalClientExtractWarning(envName, message) {
|
|
931
|
+
return [
|
|
932
|
+
`Client assets were not extracted for "${envName}".`,
|
|
933
|
+
'NocoBase will keep starting, but versioned client files for CDN or external distribution may be stale or missing.',
|
|
934
|
+
`Details: ${message}`,
|
|
935
|
+
].join('\n');
|
|
936
|
+
}
|
|
852
937
|
async ensureManagedAppRuntimeConfig(params) {
|
|
853
938
|
const savedEnv = await getEnv(params.envName, { scope: resolveDefaultConfigScope() });
|
|
854
939
|
const savedConfig = savedEnv?.config;
|
|
@@ -929,7 +1014,7 @@ export default class Install extends Command {
|
|
|
929
1014
|
const source = Install.toOptionalPromptString(values.source);
|
|
930
1015
|
const builtinDb = values.builtinDb === undefined ? undefined : Boolean(values.builtinDb);
|
|
931
1016
|
const dbDialect = Install.toOptionalPromptString(values.dbDialect);
|
|
932
|
-
const appRootPath =
|
|
1017
|
+
const appRootPath = resolveConfiguredSourcePathValue(values, envName);
|
|
933
1018
|
const dockerNetworkName = await Install.resolveResumeDockerNetworkName();
|
|
934
1019
|
const dockerContainerPrefix = await Install.resolveResumeDockerContainerPrefix();
|
|
935
1020
|
return {
|
|
@@ -1000,9 +1085,12 @@ export default class Install extends Command {
|
|
|
1000
1085
|
const envName = String(env.name ?? '').trim();
|
|
1001
1086
|
const config = env.config ?? {};
|
|
1002
1087
|
const source = Install.toOptionalPromptString(config.source);
|
|
1088
|
+
const appPath = Install.toOptionalPromptString(config.appPath) ?? inferConfiguredAppPathFromLegacyConfig(config);
|
|
1003
1089
|
const appRootPath = Install.toOptionalPromptString(config.appRootPath);
|
|
1004
1090
|
const appPort = Install.toOptionalPromptString(config.appPort);
|
|
1005
1091
|
const storagePath = Install.toOptionalPromptString(config.storagePath);
|
|
1092
|
+
const appPublicPath = Install.toOptionalPromptString(config.appPublicPath);
|
|
1093
|
+
const apiBaseUrl = Install.toOptionalPromptString(config.apiBaseUrl);
|
|
1006
1094
|
const downloadVersion = Install.toOptionalPromptString(config.downloadVersion);
|
|
1007
1095
|
const dockerRegistry = Install.toOptionalPromptString(config.dockerRegistry);
|
|
1008
1096
|
const dockerPlatform = Install.toOptionalPromptString(config.dockerPlatform);
|
|
@@ -1025,9 +1113,11 @@ export default class Install extends Command {
|
|
|
1025
1113
|
const auth = config.auth;
|
|
1026
1114
|
const savedAuthType = Install.toOptionalPromptString(config.authType) ?? Install.toOptionalPromptString(auth?.type);
|
|
1027
1115
|
const appPreset = {
|
|
1116
|
+
...(appPath ? { appPath } : {}),
|
|
1028
1117
|
...(appRootPath ? { appRootPath } : {}),
|
|
1029
1118
|
...(appPort ? { appPort } : {}),
|
|
1030
1119
|
...(storagePath ? { storagePath } : {}),
|
|
1120
|
+
...(appPublicPath ? { appPublicPath } : {}),
|
|
1031
1121
|
};
|
|
1032
1122
|
const downloadPreset = {
|
|
1033
1123
|
...(source ? { source } : {}),
|
|
@@ -1065,6 +1155,9 @@ export default class Install extends Command {
|
|
|
1065
1155
|
...(rootNickname ? { rootNickname } : {}),
|
|
1066
1156
|
};
|
|
1067
1157
|
const envAddPreset = {};
|
|
1158
|
+
if (apiBaseUrl) {
|
|
1159
|
+
envAddPreset.apiBaseUrl = apiBaseUrl;
|
|
1160
|
+
}
|
|
1068
1161
|
if (savedAuthType === 'token') {
|
|
1069
1162
|
envAddPreset.authType = 'token';
|
|
1070
1163
|
if (Install.toOptionalPromptString(auth.accessToken)) {
|
|
@@ -1146,6 +1239,9 @@ export default class Install extends Command {
|
|
|
1146
1239
|
static async buildAppPromptInitialValues(params) {
|
|
1147
1240
|
const initialValues = {};
|
|
1148
1241
|
const envName = params.envName ?? DEFAULT_INSTALL_ENV_NAME;
|
|
1242
|
+
if (params.flags['app-path'] === undefined && params.flags['app-root-path'] === undefined) {
|
|
1243
|
+
initialValues.appPath = defaultInstallAppPath(envName);
|
|
1244
|
+
}
|
|
1149
1245
|
if (params.flags['app-root-path'] === undefined) {
|
|
1150
1246
|
initialValues.appRootPath = defaultInstallAppRootPath(envName);
|
|
1151
1247
|
}
|
|
@@ -1189,7 +1285,7 @@ export default class Install extends Command {
|
|
|
1189
1285
|
* output directory with app settings, while Docker registry defaults follow the CLI locale.
|
|
1190
1286
|
*/
|
|
1191
1287
|
static buildDownloadPromptOptionsForInstall(appResults, envName) {
|
|
1192
|
-
const appRoot =
|
|
1288
|
+
const appRoot = resolveConfiguredSourcePathValue(appResults, envName);
|
|
1193
1289
|
const lang = String(appResults.lang ?? DEFAULT_INSTALL_LANG).trim() || DEFAULT_INSTALL_LANG;
|
|
1194
1290
|
const initialValues = {
|
|
1195
1291
|
lang,
|
|
@@ -1220,7 +1316,7 @@ export default class Install extends Command {
|
|
|
1220
1316
|
*/
|
|
1221
1317
|
static buildDownloadPresetValuesForInstall(flags, appResults, envName, yes, argv = process.argv.slice(2)) {
|
|
1222
1318
|
const preset = {};
|
|
1223
|
-
const appRoot =
|
|
1319
|
+
const appRoot = resolveConfiguredSourcePathValue(appResults, envName);
|
|
1224
1320
|
const lang = String(appResults.lang ?? DEFAULT_INSTALL_LANG).trim() || DEFAULT_INSTALL_LANG;
|
|
1225
1321
|
preset.lang = lang;
|
|
1226
1322
|
if (flags.source !== undefined && String(flags.source).trim() !== '') {
|
|
@@ -1351,7 +1447,8 @@ export default class Install extends Command {
|
|
|
1351
1447
|
: dbHostInput && dbHostInput !== DEFAULT_INSTALL_DB_HOST && dbHostInput !== 'localhost'
|
|
1352
1448
|
? dbHostInput
|
|
1353
1449
|
: containerName;
|
|
1354
|
-
const storagePath = resolveConfiguredEnvPath(params.storagePath) ??
|
|
1450
|
+
const storagePath = resolveConfiguredEnvPath(params.storagePath) ??
|
|
1451
|
+
resolveEnvRelativePath(resolveConfiguredStoragePathValue({ appPath: params.appPath, storagePath: params.storagePath }, params.envName));
|
|
1355
1452
|
if (dbDialect === 'postgres') {
|
|
1356
1453
|
const image = String(params.builtinDbImage ?? '').trim() || defaultBuiltinDbImageForDialect(dbDialect);
|
|
1357
1454
|
const dataDir = path.resolve(storagePath, 'db', 'postgres');
|
|
@@ -1542,6 +1639,7 @@ export default class Install extends Command {
|
|
|
1542
1639
|
if (this.ensuredDockerNetworks.has(name)) {
|
|
1543
1640
|
return;
|
|
1544
1641
|
}
|
|
1642
|
+
await ensureDockerDaemonRunning('prepare Docker resources for this environment');
|
|
1545
1643
|
printVerbose(`Checking Docker network: ${name}`);
|
|
1546
1644
|
const exists = await commandSucceeds('docker', ['network', 'inspect', name]);
|
|
1547
1645
|
if (exists) {
|
|
@@ -1620,12 +1718,13 @@ export default class Install extends Command {
|
|
|
1620
1718
|
});
|
|
1621
1719
|
}
|
|
1622
1720
|
async startBuiltinDb(params) {
|
|
1623
|
-
const storagePath =
|
|
1721
|
+
const storagePath = resolveConfiguredStoragePathValue(params.appResults, params.envName);
|
|
1624
1722
|
const plan = Install.buildBuiltinDbPlan({
|
|
1625
1723
|
envName: params.envName,
|
|
1626
1724
|
workspaceName: params.workspaceName,
|
|
1627
1725
|
dockerNetworkName: params.dockerNetworkName,
|
|
1628
1726
|
dockerContainerPrefix: params.dockerContainerPrefix,
|
|
1727
|
+
appPath: params.appResults.appPath,
|
|
1629
1728
|
storagePath,
|
|
1630
1729
|
source: params.downloadResults.source,
|
|
1631
1730
|
dbDialect: params.dbResults.dbDialect,
|
|
@@ -1666,7 +1765,9 @@ export default class Install extends Command {
|
|
|
1666
1765
|
defaultVersion: DEFAULT_DOCKER_VERSION,
|
|
1667
1766
|
});
|
|
1668
1767
|
const appPort = String(params.appResults.appPort ?? DEFAULT_INSTALL_APP_PORT).trim() || DEFAULT_INSTALL_APP_PORT;
|
|
1669
|
-
const
|
|
1768
|
+
const configuredStoragePath = resolveConfiguredStoragePathValue(params.appResults, params.envName);
|
|
1769
|
+
const storagePath = resolveConfiguredEnvPath(configuredStoragePath) ??
|
|
1770
|
+
resolveEnvRelativePath(defaultInstallStoragePath(params.envName));
|
|
1670
1771
|
const dbDialect = String(params.dbResults.dbDialect ?? 'postgres').trim() || 'postgres';
|
|
1671
1772
|
const dbHost = String(params.dbResults.dbHost ?? DEFAULT_INSTALL_DB_HOST).trim() || DEFAULT_INSTALL_DB_HOST;
|
|
1672
1773
|
const dbPort = String(params.dbResults.dbPort ?? defaultDbPortForDialect(dbDialect)).trim() ||
|
|
@@ -1677,7 +1778,9 @@ export default class Install extends Command {
|
|
|
1677
1778
|
const dbSchema = optionalEnvString(params.dbResults.dbSchema);
|
|
1678
1779
|
const dbTablePrefix = optionalEnvString(params.dbResults.dbTablePrefix);
|
|
1679
1780
|
const dbUnderscored = optionalEnvBoolean(params.dbResults.dbUnderscored);
|
|
1781
|
+
const extractClientAssets = resolveExtractClientAssetsDefaultEnabled(process.env.NOCOBASE_EXTRACT_CLIENT_ASSETS);
|
|
1680
1782
|
const appKey = Install.resolveManagedAppKey(params.appResults.appKey);
|
|
1783
|
+
const appPublicPath = Install.toOptionalPromptString(params.appResults.appPublicPath);
|
|
1681
1784
|
const timeZone = Install.resolveManagedTimeZone(params.appResults.timeZone);
|
|
1682
1785
|
const containerName = Install.buildDockerAppContainerName(params.envName, params.dockerContainerPrefix ?? params.workspaceName);
|
|
1683
1786
|
const configuredEnvFile = String(params.appResults.envFile ?? '').trim();
|
|
@@ -1705,9 +1808,11 @@ export default class Install extends Command {
|
|
|
1705
1808
|
args.push('-e', `${key}=${value}`);
|
|
1706
1809
|
}
|
|
1707
1810
|
args.push('-e', `APP_KEY=${appKey}`, '-e', `DB_DIALECT=${dbDialect}`, '-e', `DB_HOST=${dbHost}`, '-e', `DB_PORT=${dbPort}`, '-e', `DB_DATABASE=${dbDatabase}`, '-e', `DB_USER=${dbUser}`, '-e', `DB_PASSWORD=${dbPassword}`, '-e', `TZ=${timeZone}`, '-v', `${storagePath}:/app/nocobase/storage`);
|
|
1811
|
+
pushOptionalEnvArg(args, 'APP_PUBLIC_PATH', appPublicPath);
|
|
1708
1812
|
pushOptionalEnvArg(args, 'DB_SCHEMA', dbSchema);
|
|
1709
1813
|
pushOptionalEnvArg(args, 'DB_TABLE_PREFIX', dbTablePrefix);
|
|
1710
1814
|
pushOptionalEnvArg(args, 'DB_UNDERSCORED', dbUnderscored);
|
|
1815
|
+
pushOptionalEnvArg(args, 'NOCOBASE_EXTRACT_CLIENT_ASSETS', extractClientAssets);
|
|
1711
1816
|
args.push(imageRef);
|
|
1712
1817
|
return {
|
|
1713
1818
|
source: 'docker',
|
|
@@ -1814,17 +1919,15 @@ export default class Install extends Command {
|
|
|
1814
1919
|
return projectRoot;
|
|
1815
1920
|
}
|
|
1816
1921
|
const outputDir = String(params.downloadResults.outputDir ?? '').trim() ||
|
|
1817
|
-
|
|
1818
|
-
defaultInstallAppRootPath(params.envName);
|
|
1922
|
+
resolveConfiguredSourcePathValue(params.appResults, params.envName);
|
|
1819
1923
|
return resolveConfiguredEnvPath(outputDir) ?? resolveEnvRelativePath(defaultInstallAppRootPath(params.envName));
|
|
1820
1924
|
}
|
|
1821
1925
|
static resolveLocalProjectConfigPath(params) {
|
|
1822
1926
|
return (String(params.downloadResults.outputDir ?? '').trim() ||
|
|
1823
|
-
|
|
1824
|
-
defaultInstallAppRootPath(params.envName));
|
|
1927
|
+
resolveConfiguredSourcePathValue(params.appResults, params.envName));
|
|
1825
1928
|
}
|
|
1826
1929
|
static buildSkipDownloadValues(envName, appResults) {
|
|
1827
|
-
const appRoot =
|
|
1930
|
+
const appRoot = resolveConfiguredSourcePathValue(appResults, envName);
|
|
1828
1931
|
return {
|
|
1829
1932
|
outputDir: appRoot,
|
|
1830
1933
|
replace: false,
|
|
@@ -1897,7 +2000,7 @@ export default class Install extends Command {
|
|
|
1897
2000
|
return downloadedProjectRoot;
|
|
1898
2001
|
}
|
|
1899
2002
|
static buildLocalAppEnvVars(params) {
|
|
1900
|
-
const configuredStoragePath =
|
|
2003
|
+
const configuredStoragePath = resolveConfiguredStoragePathValue(params.appResults, params.envName);
|
|
1901
2004
|
const storagePath = resolveConfiguredEnvPath(configuredStoragePath) ??
|
|
1902
2005
|
resolveEnvRelativePath(defaultInstallStoragePath(params.envName));
|
|
1903
2006
|
const dbDialect = String(params.dbResults.dbDialect ?? 'postgres').trim() || 'postgres';
|
|
@@ -1920,6 +2023,7 @@ export default class Install extends Command {
|
|
|
1920
2023
|
rootResults: params.rootResults,
|
|
1921
2024
|
}),
|
|
1922
2025
|
};
|
|
2026
|
+
setOptionalEnvVar(env, 'APP_PUBLIC_PATH', Install.toOptionalPromptString(params.appResults.appPublicPath));
|
|
1923
2027
|
setOptionalEnvVar(env, 'DB_SCHEMA', optionalEnvString(params.dbResults.dbSchema));
|
|
1924
2028
|
setOptionalEnvVar(env, 'DB_TABLE_PREFIX', optionalEnvString(params.dbResults.dbTablePrefix));
|
|
1925
2029
|
setOptionalEnvVar(env, 'DB_UNDERSCORED', optionalEnvBoolean(params.dbResults.dbUnderscored));
|
|
@@ -1945,6 +2049,24 @@ export default class Install extends Command {
|
|
|
1945
2049
|
const message = error instanceof Error ? error.message : String(error);
|
|
1946
2050
|
this.logDetail(`Skipped local process cleanup before start: ${message}`);
|
|
1947
2051
|
}
|
|
2052
|
+
this.logDetail(`Running local postinstall in ${params.projectRoot}`);
|
|
2053
|
+
await runNocoBaseCommand(['postinstall'], {
|
|
2054
|
+
cwd: params.projectRoot,
|
|
2055
|
+
env,
|
|
2056
|
+
stdio: params.commandStdio ?? 'ignore',
|
|
2057
|
+
});
|
|
2058
|
+
this.logDetail(`Extracting local client assets in ${params.projectRoot}`);
|
|
2059
|
+
try {
|
|
2060
|
+
await runNocoBaseCommand(['client:extract'], {
|
|
2061
|
+
cwd: params.projectRoot,
|
|
2062
|
+
env,
|
|
2063
|
+
stdio: params.commandStdio ?? 'ignore',
|
|
2064
|
+
});
|
|
2065
|
+
}
|
|
2066
|
+
catch (error) {
|
|
2067
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2068
|
+
printWarning(Install.formatLocalClientExtractWarning(params.envName, message));
|
|
2069
|
+
}
|
|
1948
2070
|
this.logDetail(`Starting local NocoBase app from ${params.projectRoot}`);
|
|
1949
2071
|
await runNocoBaseCommand(args, {
|
|
1950
2072
|
cwd: params.projectRoot,
|
|
@@ -1964,8 +2086,8 @@ export default class Install extends Command {
|
|
|
1964
2086
|
};
|
|
1965
2087
|
}
|
|
1966
2088
|
static resolveApiBaseUrl(params) {
|
|
1967
|
-
|
|
1968
|
-
|
|
2089
|
+
return (String(params.envAddResults.apiBaseUrl ?? '').trim() ||
|
|
2090
|
+
buildInstallApiBaseUrl(params.appResults, params.defaultApiHost));
|
|
1969
2091
|
}
|
|
1970
2092
|
static buildHealthCheckUrl(apiBaseUrl) {
|
|
1971
2093
|
return `${apiBaseUrl.replace(/\/+$/, '')}/__health_check`;
|
|
@@ -2057,7 +2179,10 @@ export default class Install extends Command {
|
|
|
2057
2179
|
}
|
|
2058
2180
|
}
|
|
2059
2181
|
async saveInstalledEnv(params) {
|
|
2060
|
-
|
|
2182
|
+
const defaultApiHost = await resolveDefaultApiHost();
|
|
2183
|
+
await upsertEnv(params.envName, Install.buildSavedEnvConfig(params, { defaultApiHost }), {
|
|
2184
|
+
scope: resolveDefaultConfigScope(),
|
|
2185
|
+
});
|
|
2061
2186
|
await setCurrentEnv(params.envName, { scope: resolveDefaultConfigScope() });
|
|
2062
2187
|
}
|
|
2063
2188
|
async syncInstalledEnvConnection(params) {
|
|
@@ -2086,13 +2211,19 @@ export default class Install extends Command {
|
|
|
2086
2211
|
}
|
|
2087
2212
|
await this.config.runCommand('env:update', [params.envName]);
|
|
2088
2213
|
}
|
|
2089
|
-
static buildSavedEnvConfig(params) {
|
|
2214
|
+
static buildSavedEnvConfig(params, options = {}) {
|
|
2215
|
+
const appPath = resolveConfiguredAppPathValue(params.appResults);
|
|
2216
|
+
const appRootPath = Install.toOptionalPromptString(params.appResults.appRootPath);
|
|
2217
|
+
const storagePath = Install.toOptionalPromptString(params.appResults.storagePath);
|
|
2218
|
+
const appPublicPath = Install.toOptionalPromptString(params.appResults.appPublicPath);
|
|
2219
|
+
const derivedAppRootPath = appPath ? deriveConfiguredSourcePath(appPath) : undefined;
|
|
2220
|
+
const derivedStoragePath = appPath ? deriveConfiguredStoragePath(appPath) : undefined;
|
|
2090
2221
|
const appPort = String(params.appResults.appPort ?? DEFAULT_INSTALL_APP_PORT).trim() || DEFAULT_INSTALL_APP_PORT;
|
|
2091
|
-
const storagePath = String(params.appResults.storagePath ?? '').trim() || defaultInstallStoragePath(params.envName);
|
|
2092
2222
|
const envFile = String(params.appResults.envFile ?? '').trim() || undefined;
|
|
2093
2223
|
const apiBaseUrl = Install.resolveApiBaseUrl({
|
|
2094
2224
|
appResults: params.appResults,
|
|
2095
2225
|
envAddResults: params.envAddResults,
|
|
2226
|
+
defaultApiHost: options.defaultApiHost,
|
|
2096
2227
|
});
|
|
2097
2228
|
const authType = String(params.envAddResults.authType ?? 'oauth').trim() || 'oauth';
|
|
2098
2229
|
const authUsername = authType === 'basic' ? String(params.envAddResults.username ?? params.rootResults.rootUsername ?? '').trim() : '';
|
|
@@ -2110,9 +2241,11 @@ export default class Install extends Command {
|
|
|
2110
2241
|
devDependencies: downloadResultsValue(params.downloadResults, 'devDependencies'),
|
|
2111
2242
|
build: downloadResultsValue(params.downloadResults, 'build'),
|
|
2112
2243
|
buildDts: downloadResultsValue(params.downloadResults, 'buildDts'),
|
|
2113
|
-
|
|
2244
|
+
...(appPath ? { appPath } : {}),
|
|
2245
|
+
...(appRootPath && !areConfiguredPathsEquivalent(appRootPath, derivedAppRootPath) ? { appRootPath } : {}),
|
|
2114
2246
|
appPort,
|
|
2115
|
-
storagePath,
|
|
2247
|
+
...(storagePath && !areConfiguredPathsEquivalent(storagePath, derivedStoragePath) ? { storagePath } : {}),
|
|
2248
|
+
...(appPublicPath ? { appPublicPath } : {}),
|
|
2116
2249
|
...(envFile ? { envFile } : {}),
|
|
2117
2250
|
appKey: params.appResults.appKey,
|
|
2118
2251
|
timezone: params.appResults.timeZone,
|
|
@@ -2135,6 +2268,7 @@ export default class Install extends Command {
|
|
|
2135
2268
|
}
|
|
2136
2269
|
async collectPromptResults(parsed, yes) {
|
|
2137
2270
|
const commandArgv = this.argv ?? process.argv.slice(2);
|
|
2271
|
+
const defaultApiHost = await resolveDefaultApiHost();
|
|
2138
2272
|
const resumePreset = await this.resolveResumePresetValues(parsed, yes);
|
|
2139
2273
|
const envPreset = {
|
|
2140
2274
|
...(resumePreset?.envPreset ?? {}),
|
|
@@ -2160,6 +2294,7 @@ export default class Install extends Command {
|
|
|
2160
2294
|
envName,
|
|
2161
2295
|
flags: {
|
|
2162
2296
|
...parsed,
|
|
2297
|
+
'app-path': parsed['app-path'] ?? Install.toOptionalPromptString(appPreset.appPath),
|
|
2163
2298
|
'app-root-path': parsed['app-root-path'] ?? Install.toOptionalPromptString(appPreset.appRootPath),
|
|
2164
2299
|
'app-port': parsed['app-port'] ?? Install.toOptionalPromptString(appPreset.appPort),
|
|
2165
2300
|
'storage-path': parsed['storage-path'] ?? Install.toOptionalPromptString(appPreset.storagePath),
|
|
@@ -2229,7 +2364,7 @@ export default class Install extends Command {
|
|
|
2229
2364
|
};
|
|
2230
2365
|
const resolvedEnvAddAuthType = String(envAddPreset.authType ?? '').trim();
|
|
2231
2366
|
const envAddInitialValues = {
|
|
2232
|
-
apiBaseUrl:
|
|
2367
|
+
apiBaseUrl: buildInstallApiBaseUrl(appResults, defaultApiHost),
|
|
2233
2368
|
...envAddResumePreset,
|
|
2234
2369
|
...(!parsed['skip-auth'] && resolvedEnvAddAuthType === 'basic'
|
|
2235
2370
|
? {
|
|
@@ -2276,6 +2411,7 @@ export default class Install extends Command {
|
|
|
2276
2411
|
const parsed = {
|
|
2277
2412
|
...flags,
|
|
2278
2413
|
};
|
|
2414
|
+
const defaultApiHost = await resolveDefaultApiHost();
|
|
2279
2415
|
if (parsed['skip-auth'] && (parsed['access-token'] !== undefined || parsed.token !== undefined)) {
|
|
2280
2416
|
this.error('--skip-auth cannot be used with --access-token or --token.');
|
|
2281
2417
|
}
|
|
@@ -2413,11 +2549,17 @@ export default class Install extends Command {
|
|
|
2413
2549
|
await this.waitForAppHealthCheck(Install.resolveApiBaseUrl({
|
|
2414
2550
|
appResults,
|
|
2415
2551
|
envAddResults,
|
|
2552
|
+
defaultApiHost,
|
|
2416
2553
|
}), {
|
|
2417
2554
|
containerName: dockerAppPlan?.containerName,
|
|
2418
2555
|
verbose: parsed.verbose,
|
|
2419
2556
|
});
|
|
2420
|
-
|
|
2557
|
+
const displayApiBaseUrl = Install.resolveApiBaseUrl({
|
|
2558
|
+
appResults,
|
|
2559
|
+
envAddResults,
|
|
2560
|
+
defaultApiHost,
|
|
2561
|
+
});
|
|
2562
|
+
printInfo(`NocoBase is ready at ${formatInstallDisplayUrl(displayApiBaseUrl)}`);
|
|
2421
2563
|
}
|
|
2422
2564
|
if (dockerAppPlan || localAppPlan || builtinDbPlan) {
|
|
2423
2565
|
await this.saveInstalledEnv({
|
|
@@ -2435,6 +2577,7 @@ export default class Install extends Command {
|
|
|
2435
2577
|
appReady: Boolean(dockerAppPlan || localAppPlan),
|
|
2436
2578
|
skipAuth: Boolean(parsed['skip-auth']),
|
|
2437
2579
|
});
|
|
2580
|
+
await clearEnvRootSetup(envName, { scope: resolveDefaultConfigScope() });
|
|
2438
2581
|
if (!dockerAppPlan && !localAppPlan) {
|
|
2439
2582
|
printInfo(`Install config for "${envName}" has been saved.`);
|
|
2440
2583
|
}
|