@nocobase/cli 2.1.0-alpha.25 → 2.1.0-alpha.27
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/README.md +61 -49
- package/README.zh-CN.md +40 -47
- package/dist/commands/app/down.js +259 -0
- package/dist/commands/app/logs.js +98 -0
- package/dist/commands/app/restart.js +75 -0
- package/dist/commands/app/start.js +252 -0
- package/dist/commands/app/stop.js +98 -0
- package/dist/commands/app/upgrade.js +579 -0
- package/dist/commands/build.js +3 -48
- package/dist/commands/config/delete.js +30 -0
- package/dist/commands/config/get.js +29 -0
- package/dist/commands/config/index.js +20 -0
- package/dist/commands/config/list.js +29 -0
- package/dist/commands/config/set.js +35 -0
- package/dist/commands/db/check.js +230 -0
- package/dist/commands/db/shared.js +1 -1
- package/dist/commands/dev.js +3 -147
- package/dist/commands/down.js +3 -188
- package/dist/commands/download.js +4 -856
- package/dist/commands/env/add.js +28 -23
- package/dist/commands/env/info.js +152 -0
- package/dist/commands/env/list.js +23 -9
- package/dist/commands/env/shared.js +158 -0
- package/dist/commands/{prompts-stages.js → examples/prompts-stages.js} +3 -3
- package/dist/commands/{prompts-test.js → examples/prompts-test.js} +3 -3
- package/dist/commands/init.js +83 -6
- package/dist/commands/install.js +361 -82
- package/dist/commands/license/activate.js +357 -0
- package/dist/commands/license/env.js +94 -0
- package/dist/commands/license/generate-id.js +107 -0
- package/dist/commands/license/id.js +52 -0
- package/dist/commands/license/index.js +20 -0
- package/dist/commands/license/plugins/clean.js +98 -0
- package/dist/commands/license/plugins/index.js +20 -0
- package/dist/commands/license/plugins/list.js +50 -0
- package/dist/commands/license/plugins/shared.js +325 -0
- package/dist/commands/license/plugins/sync.js +267 -0
- package/dist/commands/license/shared.js +411 -0
- package/dist/commands/license/status.js +50 -0
- package/dist/commands/logs.js +3 -88
- package/dist/commands/plugin/disable.js +64 -0
- package/dist/commands/plugin/enable.js +64 -0
- package/dist/commands/plugin/list.js +62 -0
- package/dist/commands/pm/disable.js +3 -54
- package/dist/commands/pm/enable.js +3 -54
- package/dist/commands/pm/list.js +3 -52
- package/dist/commands/restart.js +3 -65
- package/dist/commands/scaffold/migration.js +1 -1
- package/dist/commands/scaffold/plugin.js +1 -1
- package/dist/commands/skills/remove.js +71 -0
- package/dist/commands/skills/update.js +7 -0
- package/dist/commands/source/build.js +58 -0
- package/dist/commands/source/dev.js +157 -0
- package/dist/commands/source/download.js +866 -0
- package/dist/commands/source/test.js +467 -0
- package/dist/commands/start.js +3 -209
- package/dist/commands/stop.js +3 -88
- package/dist/commands/test.js +3 -457
- package/dist/commands/upgrade.js +3 -585
- package/dist/help/runtime-help.js +3 -0
- package/dist/lib/api-client.js +94 -9
- package/dist/lib/app-health.js +126 -0
- package/dist/lib/app-managed-resources.js +264 -0
- package/dist/lib/app-runtime.js +26 -10
- package/dist/lib/auth-store.js +29 -63
- package/dist/lib/build-config.js +8 -0
- package/dist/lib/cli-config.js +176 -0
- package/dist/lib/cli-home.js +12 -26
- package/dist/lib/cli-locale.js +15 -1
- package/dist/lib/db-connection-check.js +178 -0
- package/dist/lib/env-config.js +80 -0
- package/dist/lib/generated-command.js +23 -3
- package/dist/lib/plugin-storage.js +127 -0
- package/dist/lib/prompt-validators.js +4 -4
- package/dist/lib/prompt-web-ui.js +13 -6
- package/dist/lib/runtime-generator.js +89 -10
- package/dist/lib/self-manager.js +57 -2
- package/dist/lib/skills-manager.js +34 -7
- package/dist/lib/startup-update.js +85 -7
- package/dist/locale/en-US.json +16 -13
- package/dist/locale/zh-CN.json +16 -13
- package/nocobase-ctl.config.json +82 -0
- package/package.json +41 -6
- package/dist/commands/ps.js +0 -119
package/dist/commands/install.js
CHANGED
|
@@ -16,12 +16,16 @@ import path from 'node:path';
|
|
|
16
16
|
import { exit } from 'node:process';
|
|
17
17
|
import { runPromptCatalog, } from "../lib/prompt-catalog.js";
|
|
18
18
|
import { applyCliLocale, localeText, resolveCliLocale, translateCli, } from "../lib/cli-locale.js";
|
|
19
|
-
import { resolveConfiguredEnvPath, resolveDefaultConfigScope, resolveEnvRelativePath, } from '../lib/cli-home.js';
|
|
19
|
+
import { resolveConfiguredEnvPath, resolveDefaultConfigScope, resolveEnvRoot, resolveEnvRelativePath, } from '../lib/cli-home.js';
|
|
20
|
+
import { defaultDockerContainerPrefix, defaultDockerNetworkName, } from '../lib/app-runtime.js';
|
|
21
|
+
import { resolveDockerContainerPrefix, resolveDockerNetworkName, } from '../lib/cli-config.js';
|
|
20
22
|
import { findAvailableTcpPort, validateAvailableTcpPort, validateTcpPort, validateEnvKey, } from "../lib/prompt-validators.js";
|
|
23
|
+
import { validateExternalDbConfig } from "../lib/db-connection-check.js";
|
|
21
24
|
import { formatMissingManagedAppEnvMessage } from '../lib/app-runtime.js';
|
|
22
25
|
import { run, runNocoBaseCommand } from '../lib/run-npm.js';
|
|
23
26
|
import { startTask, stopTask, updateTask } from '../lib/ui.js';
|
|
24
|
-
import {
|
|
27
|
+
import { getEnv, upsertEnv } from '../lib/auth-store.js';
|
|
28
|
+
import { buildStoredEnvConfig } from '../lib/env-config.js';
|
|
25
29
|
import Download, { defaultDockerRegistryForLang, } from './download.js';
|
|
26
30
|
import EnvAdd from "./env/add.js";
|
|
27
31
|
const DEFAULT_INSTALL_ENV_NAME = 'local';
|
|
@@ -179,6 +183,16 @@ function validateBuiltinDbEnabled(value, values) {
|
|
|
179
183
|
}
|
|
180
184
|
return translateCli('commands.install.validation.builtinDbUnsupported', { dialect });
|
|
181
185
|
}
|
|
186
|
+
async function validateExternalDbPromptField(value, values) {
|
|
187
|
+
const builtinDb = values.builtinDb === undefined ? true : Boolean(values.builtinDb);
|
|
188
|
+
if (builtinDb) {
|
|
189
|
+
return undefined;
|
|
190
|
+
}
|
|
191
|
+
if (typeof value === 'string' && value.trim() === '') {
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
return await validateExternalDbConfig(values);
|
|
195
|
+
}
|
|
182
196
|
function defaultInstallAppRootPath(envName) {
|
|
183
197
|
const name = String(envName ?? DEFAULT_INSTALL_ENV_NAME).trim() || DEFAULT_INSTALL_ENV_NAME;
|
|
184
198
|
return `./${name}/source/`;
|
|
@@ -245,7 +259,8 @@ async function commandOutput(command, args, options) {
|
|
|
245
259
|
});
|
|
246
260
|
}
|
|
247
261
|
export default class Install extends Command {
|
|
248
|
-
static
|
|
262
|
+
static hidden = true;
|
|
263
|
+
static description = 'Install NocoBase: database, storage, admin user, and `nocobase-v1 install`. Optionally run `nb source download` first; distribution and image details are configured on `nb source download`, not here. Use `--resume` to continue an interrupted setup from the saved workspace env config.';
|
|
249
264
|
static examples = [
|
|
250
265
|
'<%= config.bin %> <%= command.id %>',
|
|
251
266
|
'<%= config.bin %> <%= command.id %> --env app1',
|
|
@@ -276,6 +291,25 @@ export default class Install extends Command {
|
|
|
276
291
|
char: 'e',
|
|
277
292
|
description: 'App/env name to create or update. Defaults app paths to ./<envName>/source/ and ./<envName>/storage/.',
|
|
278
293
|
}),
|
|
294
|
+
'default-api-base-url': Flags.string({
|
|
295
|
+
char: 'd',
|
|
296
|
+
hidden: true,
|
|
297
|
+
description: 'Default API base URL for HTTP API calls, including the /api prefix (e.g. http://localhost:13000/api)',
|
|
298
|
+
}),
|
|
299
|
+
'api-base-url': Flags.string({
|
|
300
|
+
char: 'u',
|
|
301
|
+
description: 'Root URL for HTTP API calls, including the /api prefix (e.g. http://localhost:13000/api)',
|
|
302
|
+
}),
|
|
303
|
+
'auth-type': Flags.string({
|
|
304
|
+
char: 'a',
|
|
305
|
+
description: 'Authentication: token (API key) or oauth (browser login via `nb env auth`)',
|
|
306
|
+
options: ['token', 'oauth'],
|
|
307
|
+
}),
|
|
308
|
+
'access-token': Flags.string({
|
|
309
|
+
char: 't',
|
|
310
|
+
aliases: ['token'],
|
|
311
|
+
description: 'API key or access token when using --auth-type token',
|
|
312
|
+
}),
|
|
279
313
|
lang: Flags.string({ description: 'Language for the installed NocoBase app', char: 'l', required: false }),
|
|
280
314
|
force: Flags.boolean({
|
|
281
315
|
description: 'Reconfigure an existing env and replace conflicting runtime resources when needed',
|
|
@@ -374,7 +408,7 @@ export default class Install extends Command {
|
|
|
374
408
|
type: 'text',
|
|
375
409
|
message: installText('prompts.appPort.message'),
|
|
376
410
|
placeholder: installText('prompts.appPort.placeholder'),
|
|
377
|
-
validate:
|
|
411
|
+
validate: Install.validateAppPort,
|
|
378
412
|
},
|
|
379
413
|
storagePath: {
|
|
380
414
|
type: 'text',
|
|
@@ -426,6 +460,7 @@ export default class Install extends Command {
|
|
|
426
460
|
initialValue: (values) => defaultDbHostForBuiltinDb(values),
|
|
427
461
|
yesInitialValue: DEFAULT_INSTALL_BUILTIN_DB_HOST,
|
|
428
462
|
required: true,
|
|
463
|
+
validate: validateExternalDbPromptField,
|
|
429
464
|
hidden: (values) => Boolean(values.builtinDb),
|
|
430
465
|
},
|
|
431
466
|
dbPort: {
|
|
@@ -434,7 +469,7 @@ export default class Install extends Command {
|
|
|
434
469
|
placeholder: installText('prompts.dbPort.placeholder'),
|
|
435
470
|
initialValue: (values) => defaultDbPortForDialect(values.dbDialect),
|
|
436
471
|
required: true,
|
|
437
|
-
validate:
|
|
472
|
+
validate: Install.validateDbPort,
|
|
438
473
|
hidden: (values) => Boolean(values.builtinDb)
|
|
439
474
|
&& String(values.source ?? '').trim() === 'docker',
|
|
440
475
|
},
|
|
@@ -443,6 +478,7 @@ export default class Install extends Command {
|
|
|
443
478
|
message: installText('prompts.dbDatabase.message'),
|
|
444
479
|
initialValue: (values) => defaultDbDatabaseForDialect(values.dbDialect),
|
|
445
480
|
required: true,
|
|
481
|
+
validate: validateExternalDbPromptField,
|
|
446
482
|
},
|
|
447
483
|
dbUser: {
|
|
448
484
|
type: 'text',
|
|
@@ -450,6 +486,7 @@ export default class Install extends Command {
|
|
|
450
486
|
initialValue: DEFAULT_INSTALL_DB_USER,
|
|
451
487
|
yesInitialValue: DEFAULT_INSTALL_DB_USER,
|
|
452
488
|
required: true,
|
|
489
|
+
validate: validateExternalDbPromptField,
|
|
453
490
|
},
|
|
454
491
|
dbPassword: {
|
|
455
492
|
type: 'password',
|
|
@@ -457,6 +494,7 @@ export default class Install extends Command {
|
|
|
457
494
|
initialValue: DEFAULT_INSTALL_DB_PASSWORD,
|
|
458
495
|
yesInitialValue: DEFAULT_INSTALL_DB_PASSWORD,
|
|
459
496
|
required: true,
|
|
497
|
+
validate: validateExternalDbPromptField,
|
|
460
498
|
},
|
|
461
499
|
};
|
|
462
500
|
static rootUserPrompts = {
|
|
@@ -492,7 +530,7 @@ export default class Install extends Command {
|
|
|
492
530
|
* App catalog with `env` seeded into `out` first so `storagePath`’s `initialValue(values)`
|
|
493
531
|
* sees `values.env` (same iteration order as {@link runPromptCatalog}).
|
|
494
532
|
*/
|
|
495
|
-
static buildAppPromptsCatalog(seedEnv) {
|
|
533
|
+
static buildAppPromptsCatalog(seedEnv, options) {
|
|
496
534
|
return {
|
|
497
535
|
seedEnv: {
|
|
498
536
|
type: 'run',
|
|
@@ -500,12 +538,27 @@ export default class Install extends Command {
|
|
|
500
538
|
values.env = seedEnv;
|
|
501
539
|
},
|
|
502
540
|
},
|
|
541
|
+
seedResume: {
|
|
542
|
+
type: 'run',
|
|
543
|
+
run: (values) => {
|
|
544
|
+
const record = values;
|
|
545
|
+
record.resume = Boolean(options?.resume);
|
|
546
|
+
},
|
|
547
|
+
},
|
|
503
548
|
...Install.appPrompts,
|
|
504
549
|
};
|
|
505
550
|
}
|
|
506
|
-
static buildDbPromptsCatalog(downloadResults) {
|
|
551
|
+
static buildDbPromptsCatalog(envName, downloadResults, options) {
|
|
507
552
|
const source = String(downloadResults.source ?? '').trim();
|
|
508
553
|
return {
|
|
554
|
+
seedEnv: {
|
|
555
|
+
type: 'run',
|
|
556
|
+
run: (values) => {
|
|
557
|
+
if (envName) {
|
|
558
|
+
values.env = envName;
|
|
559
|
+
}
|
|
560
|
+
},
|
|
561
|
+
},
|
|
509
562
|
seedDownloadSource: {
|
|
510
563
|
type: 'run',
|
|
511
564
|
run: (values) => {
|
|
@@ -514,6 +567,13 @@ export default class Install extends Command {
|
|
|
514
567
|
}
|
|
515
568
|
},
|
|
516
569
|
},
|
|
570
|
+
seedResume: {
|
|
571
|
+
type: 'run',
|
|
572
|
+
run: (values) => {
|
|
573
|
+
const record = values;
|
|
574
|
+
record.resume = Boolean(options?.resume);
|
|
575
|
+
},
|
|
576
|
+
},
|
|
517
577
|
...Install.dbPrompts,
|
|
518
578
|
};
|
|
519
579
|
}
|
|
@@ -533,6 +593,25 @@ export default class Install extends Command {
|
|
|
533
593
|
static buildPresetValuesFromFlags(flags) {
|
|
534
594
|
const preset = {};
|
|
535
595
|
const argv = process.argv.slice(2);
|
|
596
|
+
const apiBaseUrl = Install.toOptionalPromptString(flags['api-base-url']);
|
|
597
|
+
if (apiBaseUrl) {
|
|
598
|
+
preset.apiBaseUrl = apiBaseUrl;
|
|
599
|
+
}
|
|
600
|
+
else if (flags['default-api-base-url'] !== undefined) {
|
|
601
|
+
const defaultApiBaseUrl = Install.toOptionalPromptString(flags['default-api-base-url']);
|
|
602
|
+
if (defaultApiBaseUrl) {
|
|
603
|
+
preset.apiBaseUrl = defaultApiBaseUrl;
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
if (flags['auth-type'] !== undefined) {
|
|
607
|
+
const authType = Install.toOptionalPromptString(flags['auth-type']);
|
|
608
|
+
if (authType) {
|
|
609
|
+
preset.authType = authType;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
if (flags['access-token'] !== undefined || flags.token !== undefined) {
|
|
613
|
+
preset.accessToken = String(flags['access-token'] ?? flags.token ?? '');
|
|
614
|
+
}
|
|
536
615
|
if (flags.lang !== undefined) {
|
|
537
616
|
const v = String(flags.lang).trim();
|
|
538
617
|
if (v) {
|
|
@@ -650,6 +729,13 @@ export default class Install extends Command {
|
|
|
650
729
|
'rootNickname',
|
|
651
730
|
]);
|
|
652
731
|
}
|
|
732
|
+
static buildEnvAddPresetValuesFromFlags(flags) {
|
|
733
|
+
return pickPresetKeys(Install.buildPresetValuesFromFlags(flags), [
|
|
734
|
+
'apiBaseUrl',
|
|
735
|
+
'authType',
|
|
736
|
+
'accessToken',
|
|
737
|
+
]);
|
|
738
|
+
}
|
|
653
739
|
static toOptionalPromptString(value) {
|
|
654
740
|
if (value === undefined || value === null) {
|
|
655
741
|
return undefined;
|
|
@@ -657,6 +743,150 @@ export default class Install extends Command {
|
|
|
657
743
|
const text = String(value).trim();
|
|
658
744
|
return text || undefined;
|
|
659
745
|
}
|
|
746
|
+
static async validateAppPort(value, values) {
|
|
747
|
+
const formatError = validateTcpPort(value);
|
|
748
|
+
if (formatError) {
|
|
749
|
+
return formatError;
|
|
750
|
+
}
|
|
751
|
+
return await Install.validateResumeAwareTcpPort(value, values, 'app');
|
|
752
|
+
}
|
|
753
|
+
static async validateDbPort(value, values) {
|
|
754
|
+
const formatError = validateTcpPort(value);
|
|
755
|
+
if (formatError) {
|
|
756
|
+
return formatError;
|
|
757
|
+
}
|
|
758
|
+
const builtinDb = values.builtinDb === undefined ? true : Boolean(values.builtinDb);
|
|
759
|
+
const source = String(values.source ?? '').trim();
|
|
760
|
+
if (!builtinDb || source === 'docker') {
|
|
761
|
+
if (!builtinDb) {
|
|
762
|
+
return await validateExternalDbConfig({ ...values, dbPort: value });
|
|
763
|
+
}
|
|
764
|
+
return undefined;
|
|
765
|
+
}
|
|
766
|
+
return await Install.validateResumeAwareTcpPort(value, values, 'db');
|
|
767
|
+
}
|
|
768
|
+
static async validateResumeAwareTcpPort(value, values, target) {
|
|
769
|
+
const portError = await validateAvailableTcpPort(value);
|
|
770
|
+
if (!portError) {
|
|
771
|
+
return undefined;
|
|
772
|
+
}
|
|
773
|
+
const context = await Install.readResumePortValidationContext(values);
|
|
774
|
+
if (!context) {
|
|
775
|
+
return portError;
|
|
776
|
+
}
|
|
777
|
+
const port = Install.toOptionalPromptString(value);
|
|
778
|
+
if (!port) {
|
|
779
|
+
return portError;
|
|
780
|
+
}
|
|
781
|
+
const reusesManagedPort = await Install.isResumeManagedPortReuse({
|
|
782
|
+
target,
|
|
783
|
+
port,
|
|
784
|
+
context,
|
|
785
|
+
});
|
|
786
|
+
return reusesManagedPort ? undefined : portError;
|
|
787
|
+
}
|
|
788
|
+
static async ensureExternalDbReadyForInstall(dbResults) {
|
|
789
|
+
const builtinDb = dbResults.builtinDb === undefined ? true : Boolean(dbResults.builtinDb);
|
|
790
|
+
if (builtinDb) {
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
const dialect = String(dbResults.dbDialect ?? 'postgres').trim() || 'postgres';
|
|
794
|
+
const host = String(dbResults.dbHost ?? '').trim();
|
|
795
|
+
const port = String(dbResults.dbPort ?? '').trim();
|
|
796
|
+
const database = String(dbResults.dbDatabase ?? '').trim();
|
|
797
|
+
const address = host && port ? `${host}:${port}` : host || port || '(unknown address)';
|
|
798
|
+
const target = database ? `${address}/${database}` : address;
|
|
799
|
+
p.log.step(`Checking external ${dialect} database: ${target}`);
|
|
800
|
+
const validationError = await validateExternalDbConfig(dbResults);
|
|
801
|
+
if (validationError) {
|
|
802
|
+
throw new Error(validationError);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
static async readResumePortValidationContext(values) {
|
|
806
|
+
if (!Boolean(values.resume)) {
|
|
807
|
+
return undefined;
|
|
808
|
+
}
|
|
809
|
+
const envName = Install.toOptionalPromptString(values.env);
|
|
810
|
+
if (!envName) {
|
|
811
|
+
return undefined;
|
|
812
|
+
}
|
|
813
|
+
const source = Install.toOptionalPromptString(values.source);
|
|
814
|
+
const builtinDb = values.builtinDb === undefined ? undefined : Boolean(values.builtinDb);
|
|
815
|
+
const dbDialect = Install.toOptionalPromptString(values.dbDialect);
|
|
816
|
+
const appRootPath = Install.toOptionalPromptString(values.appRootPath);
|
|
817
|
+
const dockerNetworkName = await Install.resolveResumeDockerNetworkName();
|
|
818
|
+
const dockerContainerPrefix = await Install.resolveResumeDockerContainerPrefix();
|
|
819
|
+
return {
|
|
820
|
+
envName,
|
|
821
|
+
...(dockerNetworkName ? { dockerNetworkName } : {}),
|
|
822
|
+
...(dockerContainerPrefix ? { dockerContainerPrefix } : {}),
|
|
823
|
+
...(source ? { source } : {}),
|
|
824
|
+
...(builtinDb !== undefined ? { builtinDb } : {}),
|
|
825
|
+
...(dbDialect ? { dbDialect } : {}),
|
|
826
|
+
...(appRootPath ? { appRootPath } : {}),
|
|
827
|
+
};
|
|
828
|
+
}
|
|
829
|
+
static async resolveResumeDockerNetworkName() {
|
|
830
|
+
return await resolveDockerNetworkName({ scope: resolveDefaultConfigScope() });
|
|
831
|
+
}
|
|
832
|
+
static async resolveResumeDockerContainerPrefix() {
|
|
833
|
+
return await resolveDockerContainerPrefix({ scope: resolveDefaultConfigScope() });
|
|
834
|
+
}
|
|
835
|
+
static async isResumeManagedPortReuse(params) {
|
|
836
|
+
if (params.target === 'app') {
|
|
837
|
+
if ((params.context.source === 'npm' || params.context.source === 'git')
|
|
838
|
+
&& params.context.appRootPath) {
|
|
839
|
+
return await Install.isLocalPm2ProcessUsingPort(params.context.appRootPath, params.port);
|
|
840
|
+
}
|
|
841
|
+
const containerName = Install.buildDockerAppContainerName(params.context.envName, params.context.dockerContainerPrefix);
|
|
842
|
+
return await Install.isDockerContainerPublishingPort(containerName, params.port);
|
|
843
|
+
}
|
|
844
|
+
if (!params.context.builtinDb || params.context.source === 'docker') {
|
|
845
|
+
return false;
|
|
846
|
+
}
|
|
847
|
+
const containerName = Install.buildBuiltinDbContainerName(params.context.envName, params.context.dbDialect ?? 'postgres', params.context.dockerContainerPrefix);
|
|
848
|
+
return await Install.isDockerContainerPublishingPort(containerName, params.port);
|
|
849
|
+
}
|
|
850
|
+
static async isDockerContainerPublishingPort(containerName, port) {
|
|
851
|
+
if (!containerName || !port) {
|
|
852
|
+
return false;
|
|
853
|
+
}
|
|
854
|
+
const exists = await commandSucceeds('docker', [
|
|
855
|
+
'container',
|
|
856
|
+
'inspect',
|
|
857
|
+
containerName,
|
|
858
|
+
]);
|
|
859
|
+
if (!exists) {
|
|
860
|
+
return false;
|
|
861
|
+
}
|
|
862
|
+
try {
|
|
863
|
+
const output = await commandOutput('docker', ['port', containerName]);
|
|
864
|
+
return output
|
|
865
|
+
.split(/\r?\n/)
|
|
866
|
+
.some((line) => line.includes(`:${port}`));
|
|
867
|
+
}
|
|
868
|
+
catch {
|
|
869
|
+
return false;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
static async isLocalPm2ProcessUsingPort(appRootPath, port) {
|
|
873
|
+
const cwd = resolveConfiguredEnvPath(appRootPath);
|
|
874
|
+
if (!cwd) {
|
|
875
|
+
return false;
|
|
876
|
+
}
|
|
877
|
+
try {
|
|
878
|
+
const output = await commandOutput('pm2', ['jlist'], { cwd });
|
|
879
|
+
const rows = JSON.parse(output);
|
|
880
|
+
return rows.some((row) => {
|
|
881
|
+
const pmCwd = Install.toOptionalPromptString(row.pm2_env?.pm_cwd);
|
|
882
|
+
const appPort = Install.toOptionalPromptString(row.pm2_env?.env?.APP_PORT);
|
|
883
|
+
return Boolean(pmCwd && appPort && pmCwd === cwd && appPort === port);
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
catch {
|
|
887
|
+
return false;
|
|
888
|
+
}
|
|
889
|
+
}
|
|
660
890
|
static buildResumePresetValues(env) {
|
|
661
891
|
const envName = String(env.name ?? '').trim();
|
|
662
892
|
const config = env.config ?? {};
|
|
@@ -676,6 +906,10 @@ export default class Install extends Command {
|
|
|
676
906
|
const dbUser = Install.toOptionalPromptString(config.dbUser);
|
|
677
907
|
const dbPassword = Install.toOptionalPromptString(config.dbPassword);
|
|
678
908
|
const builtinDbImage = Install.toOptionalPromptString(config.builtinDbImage);
|
|
909
|
+
const rootUsername = Install.toOptionalPromptString(config.rootUsername);
|
|
910
|
+
const rootEmail = Install.toOptionalPromptString(config.rootEmail);
|
|
911
|
+
const rootPassword = Install.toOptionalPromptString(config.rootPassword);
|
|
912
|
+
const rootNickname = Install.toOptionalPromptString(config.rootNickname);
|
|
679
913
|
const auth = config.auth;
|
|
680
914
|
const appPreset = {
|
|
681
915
|
...(appRootPath ? { appRootPath } : {}),
|
|
@@ -717,6 +951,12 @@ export default class Install extends Command {
|
|
|
717
951
|
...(dbUser ? { dbUser } : {}),
|
|
718
952
|
...(dbPassword ? { dbPassword } : {}),
|
|
719
953
|
};
|
|
954
|
+
const rootPreset = {
|
|
955
|
+
...(rootUsername ? { rootUsername } : {}),
|
|
956
|
+
...(rootEmail ? { rootEmail } : {}),
|
|
957
|
+
...(rootPassword ? { rootPassword } : {}),
|
|
958
|
+
...(rootNickname ? { rootNickname } : {}),
|
|
959
|
+
};
|
|
720
960
|
const envAddPreset = {};
|
|
721
961
|
if (auth?.type === 'token') {
|
|
722
962
|
envAddPreset.authType = 'token';
|
|
@@ -734,6 +974,7 @@ export default class Install extends Command {
|
|
|
734
974
|
appPreset,
|
|
735
975
|
downloadPreset,
|
|
736
976
|
dbPreset,
|
|
977
|
+
rootPreset,
|
|
737
978
|
envAddPreset,
|
|
738
979
|
};
|
|
739
980
|
}
|
|
@@ -770,7 +1011,7 @@ export default class Install extends Command {
|
|
|
770
1011
|
throw new Error([
|
|
771
1012
|
`Cannot continue setup for "${env.name}" in non-interactive resume mode yet.`,
|
|
772
1013
|
`These setup-only flags are not saved in the env config: ${missingFlags.join(', ')}`,
|
|
773
|
-
`Run \`nb
|
|
1014
|
+
`Run \`nb init --env ${env.name} --resume\` without \`--yes\`, or pass those flags again.`,
|
|
774
1015
|
].join('\n'));
|
|
775
1016
|
}
|
|
776
1017
|
}
|
|
@@ -943,27 +1184,33 @@ export default class Install extends Command {
|
|
|
943
1184
|
.replace(/^-+|-+$/g, '');
|
|
944
1185
|
return normalized || 'nocobase';
|
|
945
1186
|
}
|
|
946
|
-
static
|
|
947
|
-
return Install.sanitizeDockerResourceName(
|
|
1187
|
+
static defaultDockerNetworkName() {
|
|
1188
|
+
return Install.sanitizeDockerResourceName(defaultDockerNetworkName());
|
|
948
1189
|
}
|
|
949
|
-
static
|
|
950
|
-
|
|
951
|
-
|
|
1190
|
+
static defaultDockerContainerPrefix() {
|
|
1191
|
+
return Install.sanitizeDockerResourceName(defaultDockerContainerPrefix(resolveEnvRoot(resolveDefaultConfigScope())));
|
|
1192
|
+
}
|
|
1193
|
+
static buildBuiltinDbContainerPrefix(containerPrefix) {
|
|
1194
|
+
const storedName = String(containerPrefix ?? '').trim();
|
|
952
1195
|
return storedName
|
|
953
1196
|
? Install.sanitizeDockerResourceName(storedName)
|
|
954
|
-
: Install.
|
|
1197
|
+
: Install.defaultDockerContainerPrefix();
|
|
955
1198
|
}
|
|
956
|
-
static
|
|
957
|
-
|
|
1199
|
+
static buildManagedDockerNetworkName(networkName) {
|
|
1200
|
+
const storedName = String(networkName ?? '').trim();
|
|
1201
|
+
return storedName
|
|
1202
|
+
? Install.sanitizeDockerResourceName(storedName)
|
|
1203
|
+
: Install.defaultDockerNetworkName();
|
|
958
1204
|
}
|
|
959
|
-
static buildBuiltinDbNetworkName(envName,
|
|
960
|
-
|
|
1205
|
+
static buildBuiltinDbNetworkName(envName, networkName) {
|
|
1206
|
+
void envName;
|
|
1207
|
+
return Install.buildManagedDockerNetworkName(networkName);
|
|
961
1208
|
}
|
|
962
|
-
static buildBuiltinDbContainerName(envName, dbDialect,
|
|
963
|
-
return Install.sanitizeDockerResourceName(`${Install.
|
|
1209
|
+
static buildBuiltinDbContainerName(envName, dbDialect, containerPrefix) {
|
|
1210
|
+
return Install.sanitizeDockerResourceName(`${Install.buildBuiltinDbContainerPrefix(containerPrefix)}-${envName}-${dbDialect}`);
|
|
964
1211
|
}
|
|
965
|
-
static buildDockerAppContainerName(envName,
|
|
966
|
-
return Install.sanitizeDockerResourceName(`${Install.
|
|
1212
|
+
static buildDockerAppContainerName(envName, containerPrefix) {
|
|
1213
|
+
return Install.sanitizeDockerResourceName(`${Install.buildBuiltinDbContainerPrefix(containerPrefix)}-${envName}-app`);
|
|
967
1214
|
}
|
|
968
1215
|
static buildInitAppEnvVars(params) {
|
|
969
1216
|
const out = {};
|
|
@@ -989,8 +1236,8 @@ export default class Install extends Command {
|
|
|
989
1236
|
const dbPort = String(params.dbPort ?? defaultDbPortForDialect(dbDialect)).trim()
|
|
990
1237
|
|| defaultDbPortForDialect(dbDialect);
|
|
991
1238
|
const defaultDbDatabase = defaultDbDatabaseForDialect(dbDialect);
|
|
992
|
-
const networkName = Install.buildBuiltinDbNetworkName(params.envName, params.workspaceName);
|
|
993
|
-
const containerName = Install.buildBuiltinDbContainerName(params.envName, dbDialect, params.workspaceName);
|
|
1239
|
+
const networkName = Install.buildBuiltinDbNetworkName(params.envName, params.dockerNetworkName ?? params.workspaceName);
|
|
1240
|
+
const containerName = Install.buildBuiltinDbContainerName(params.envName, dbDialect, params.dockerContainerPrefix ?? params.workspaceName);
|
|
994
1241
|
const dbHostInput = String(params.dbHost ?? '').trim();
|
|
995
1242
|
const dbHost = Install.shouldPublishBuiltinDbPort(params.source)
|
|
996
1243
|
? (dbHostInput
|
|
@@ -1280,6 +1527,8 @@ export default class Install extends Command {
|
|
|
1280
1527
|
const plan = Install.buildBuiltinDbPlan({
|
|
1281
1528
|
envName: params.envName,
|
|
1282
1529
|
workspaceName: params.workspaceName,
|
|
1530
|
+
dockerNetworkName: params.dockerNetworkName,
|
|
1531
|
+
dockerContainerPrefix: params.dockerContainerPrefix,
|
|
1283
1532
|
storagePath,
|
|
1284
1533
|
source: params.downloadResults.source,
|
|
1285
1534
|
dbDialect: params.dbResults.dbDialect,
|
|
@@ -1327,7 +1576,7 @@ export default class Install extends Command {
|
|
|
1327
1576
|
const dbPassword = String(params.dbResults.dbPassword ?? DEFAULT_INSTALL_DB_PASSWORD) || DEFAULT_INSTALL_DB_PASSWORD;
|
|
1328
1577
|
const appKey = crypto.randomBytes(32).toString('hex');
|
|
1329
1578
|
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';
|
|
1330
|
-
const containerName = Install.buildDockerAppContainerName(params.envName, params.workspaceName);
|
|
1579
|
+
const containerName = Install.buildDockerAppContainerName(params.envName, params.dockerContainerPrefix ?? params.workspaceName);
|
|
1331
1580
|
const initEnvVars = Install.buildInitAppEnvVars({
|
|
1332
1581
|
appResults: params.appResults,
|
|
1333
1582
|
rootResults: params.rootResults,
|
|
@@ -1375,11 +1624,12 @@ export default class Install extends Command {
|
|
|
1375
1624
|
}
|
|
1376
1625
|
async installDockerApp(params) {
|
|
1377
1626
|
const networkName = params.builtinDbPlan?.networkName
|
|
1378
|
-
?? Install.buildBuiltinDbNetworkName(params.envName, params.workspaceName);
|
|
1627
|
+
?? Install.buildBuiltinDbNetworkName(params.envName, params.dockerNetworkName ?? params.workspaceName);
|
|
1379
1628
|
await this.ensureDockerNetwork(networkName);
|
|
1380
1629
|
const plan = Install.buildDockerAppPlan({
|
|
1381
1630
|
envName: params.envName,
|
|
1382
1631
|
workspaceName: params.workspaceName,
|
|
1632
|
+
dockerContainerPrefix: params.dockerContainerPrefix,
|
|
1383
1633
|
appResults: params.appResults,
|
|
1384
1634
|
downloadResults: params.downloadResults,
|
|
1385
1635
|
dbResults: params.dbResults,
|
|
@@ -1468,7 +1718,7 @@ export default class Install extends Command {
|
|
|
1468
1718
|
p.log.step(source === 'docker'
|
|
1469
1719
|
? 'Downloading Docker image'
|
|
1470
1720
|
: 'Downloading local NocoBase app files');
|
|
1471
|
-
return await this.config.runCommand('download', argv);
|
|
1721
|
+
return await this.config.runCommand('source:download', argv);
|
|
1472
1722
|
}
|
|
1473
1723
|
async downloadLocalApp(params) {
|
|
1474
1724
|
const result = await this.downloadManagedSource({
|
|
@@ -1657,21 +1907,20 @@ export default class Install extends Command {
|
|
|
1657
1907
|
throw new Error(`The application did not become ready in time. Expected \`${healthCheckUrl}\` to respond with \`ok\`, but the last status was: ${Install.formatHealthCheckMessage(lastMessage)}.${logHint}`);
|
|
1658
1908
|
}
|
|
1659
1909
|
async saveInstalledEnv(params) {
|
|
1660
|
-
await
|
|
1661
|
-
}
|
|
1662
|
-
static pushArgIfValue(argv, flag, value) {
|
|
1663
|
-
const text = String(value ?? '').trim();
|
|
1664
|
-
if (text) {
|
|
1665
|
-
argv.push(flag, text);
|
|
1666
|
-
}
|
|
1910
|
+
await upsertEnv(params.envName, Install.buildSavedEnvConfig(params), { scope: resolveDefaultConfigScope() });
|
|
1667
1911
|
}
|
|
1668
|
-
|
|
1669
|
-
if (
|
|
1912
|
+
async syncInstalledEnvConnection(params) {
|
|
1913
|
+
if (!params.appReady) {
|
|
1670
1914
|
return;
|
|
1671
1915
|
}
|
|
1672
|
-
|
|
1916
|
+
const authType = String(params.envAddResults.authType ?? 'oauth').trim()
|
|
1917
|
+
|| 'oauth';
|
|
1918
|
+
if (authType === 'oauth') {
|
|
1919
|
+
await this.config.runCommand('env:auth', [params.envName]);
|
|
1920
|
+
}
|
|
1921
|
+
await this.config.runCommand('env:update', [params.envName]);
|
|
1673
1922
|
}
|
|
1674
|
-
static
|
|
1923
|
+
static buildSavedEnvConfig(params) {
|
|
1675
1924
|
const appPort = String(params.appResults.appPort ?? DEFAULT_INSTALL_APP_PORT).trim()
|
|
1676
1925
|
|| DEFAULT_INSTALL_APP_PORT;
|
|
1677
1926
|
const storagePath = String(params.appResults.storagePath ?? '').trim()
|
|
@@ -1682,42 +1931,37 @@ export default class Install extends Command {
|
|
|
1682
1931
|
});
|
|
1683
1932
|
const authType = String(params.envAddResults.authType ?? 'oauth').trim()
|
|
1684
1933
|
|| 'oauth';
|
|
1685
|
-
|
|
1686
|
-
params.envName,
|
|
1687
|
-
'--no-intro',
|
|
1688
|
-
'--api-base-url',
|
|
1934
|
+
return buildStoredEnvConfig({
|
|
1689
1935
|
apiBaseUrl,
|
|
1690
|
-
'--auth-type',
|
|
1691
1936
|
authType,
|
|
1692
|
-
|
|
1937
|
+
accessToken: params.envAddResults.accessToken,
|
|
1938
|
+
source: downloadResultsValue(params.downloadResults, 'source'),
|
|
1939
|
+
downloadVersion: downloadResultsValue(params.downloadResults, 'version'),
|
|
1940
|
+
dockerRegistry: downloadResultsValue(params.downloadResults, 'dockerRegistry'),
|
|
1941
|
+
dockerPlatform: downloadResultsValue(params.downloadResults, 'dockerPlatform'),
|
|
1942
|
+
gitUrl: downloadResultsValue(params.downloadResults, 'gitUrl'),
|
|
1943
|
+
npmRegistry: downloadResultsValue(params.downloadResults, 'npmRegistry'),
|
|
1944
|
+
devDependencies: downloadResultsValue(params.downloadResults, 'devDependencies'),
|
|
1945
|
+
build: downloadResultsValue(params.downloadResults, 'build'),
|
|
1946
|
+
buildDts: downloadResultsValue(params.downloadResults, 'buildDts'),
|
|
1947
|
+
appRootPath: params.appResults.appRootPath,
|
|
1693
1948
|
appPort,
|
|
1694
|
-
'--storage-path',
|
|
1695
1949
|
storagePath,
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
Install.pushArgIfValue(argv, '--builtin-db-image', params.dbResults.builtinDbImage);
|
|
1712
|
-
Install.pushArgIfValue(argv, '--db-host', params.dbResults.dbHost);
|
|
1713
|
-
Install.pushArgIfValue(argv, '--db-port', params.dbResults.dbPort);
|
|
1714
|
-
Install.pushArgIfValue(argv, '--db-database', params.dbResults.dbDatabase);
|
|
1715
|
-
Install.pushArgIfValue(argv, '--db-user', params.dbResults.dbUser);
|
|
1716
|
-
Install.pushArgIfValue(argv, '--db-password', params.dbResults.dbPassword);
|
|
1717
|
-
if (authType === 'token') {
|
|
1718
|
-
argv.push('--access-token', String(params.envAddResults.accessToken ?? ''));
|
|
1719
|
-
}
|
|
1720
|
-
return argv;
|
|
1950
|
+
appKey: params.appResults.appKey,
|
|
1951
|
+
timezone: params.appResults.timeZone,
|
|
1952
|
+
builtinDb: params.dbResults.builtinDb,
|
|
1953
|
+
dbDialect: params.dbResults.dbDialect,
|
|
1954
|
+
builtinDbImage: params.dbResults.builtinDbImage,
|
|
1955
|
+
dbHost: params.dbResults.dbHost,
|
|
1956
|
+
dbPort: params.dbResults.dbPort,
|
|
1957
|
+
dbDatabase: params.dbResults.dbDatabase,
|
|
1958
|
+
dbUser: params.dbResults.dbUser,
|
|
1959
|
+
dbPassword: params.dbResults.dbPassword,
|
|
1960
|
+
rootUsername: params.rootResults.rootUsername,
|
|
1961
|
+
rootEmail: params.rootResults.rootEmail,
|
|
1962
|
+
rootPassword: params.rootResults.rootPassword,
|
|
1963
|
+
rootNickname: params.rootResults.rootNickname,
|
|
1964
|
+
});
|
|
1721
1965
|
}
|
|
1722
1966
|
async collectPromptResults(parsed, yes) {
|
|
1723
1967
|
const resumePreset = await this.resolveResumePresetValues(parsed, yes);
|
|
@@ -1737,7 +1981,9 @@ export default class Install extends Command {
|
|
|
1737
1981
|
...(resumePreset?.appPreset ?? {}),
|
|
1738
1982
|
...Install.buildAppPresetValuesFromFlags(parsed),
|
|
1739
1983
|
};
|
|
1740
|
-
const appCatalog = Install.buildAppPromptsCatalog(envName
|
|
1984
|
+
const appCatalog = Install.buildAppPromptsCatalog(envName, {
|
|
1985
|
+
resume: parsed.resume,
|
|
1986
|
+
});
|
|
1741
1987
|
const appResults = await runPromptCatalog(appCatalog, {
|
|
1742
1988
|
initialValues: await Install.buildAppPromptInitialValues({
|
|
1743
1989
|
envName,
|
|
@@ -1752,6 +1998,7 @@ export default class Install extends Command {
|
|
|
1752
1998
|
},
|
|
1753
1999
|
}),
|
|
1754
2000
|
values: appPreset,
|
|
2001
|
+
yesInitialValues: { resume: parsed.resume },
|
|
1755
2002
|
yes,
|
|
1756
2003
|
});
|
|
1757
2004
|
let downloadResults = {};
|
|
@@ -1769,7 +2016,9 @@ export default class Install extends Command {
|
|
|
1769
2016
|
...(resumePreset?.dbPreset ?? {}),
|
|
1770
2017
|
...Install.buildDbPresetValuesFromFlags(parsed),
|
|
1771
2018
|
};
|
|
1772
|
-
const dbResults = await runPromptCatalog(Install.buildDbPromptsCatalog(downloadResults
|
|
2019
|
+
const dbResults = await runPromptCatalog(Install.buildDbPromptsCatalog(envName, downloadResults, {
|
|
2020
|
+
resume: parsed.resume,
|
|
2021
|
+
}), {
|
|
1773
2022
|
initialValues: {
|
|
1774
2023
|
...downloadResults,
|
|
1775
2024
|
...await Install.buildDbPromptInitialValues({
|
|
@@ -1788,7 +2037,10 @@ export default class Install extends Command {
|
|
|
1788
2037
|
const rootPreset = Install.buildRootPresetValuesFromFlags(parsed);
|
|
1789
2038
|
const rootResults = await runPromptCatalog(Install.rootUserPrompts, {
|
|
1790
2039
|
initialValues: {},
|
|
1791
|
-
values:
|
|
2040
|
+
values: {
|
|
2041
|
+
...(resumePreset?.rootPreset ?? {}),
|
|
2042
|
+
...rootPreset,
|
|
2043
|
+
},
|
|
1792
2044
|
yes,
|
|
1793
2045
|
});
|
|
1794
2046
|
const envAddResults = await runPromptCatalog(EnvAdd.prompts, {
|
|
@@ -1798,6 +2050,7 @@ export default class Install extends Command {
|
|
|
1798
2050
|
values: {
|
|
1799
2051
|
name: envName,
|
|
1800
2052
|
...(resumePreset?.envAddPreset ?? {}),
|
|
2053
|
+
...Install.buildEnvAddPresetValuesFromFlags(parsed),
|
|
1801
2054
|
},
|
|
1802
2055
|
yes,
|
|
1803
2056
|
});
|
|
@@ -1833,14 +2086,30 @@ export default class Install extends Command {
|
|
|
1833
2086
|
const source = String(downloadResultsValue(downloadResults, 'source') ?? '').trim();
|
|
1834
2087
|
const usesDockerResources = Boolean(dbResults.builtinDb)
|
|
1835
2088
|
|| (Boolean(appResults.fetchSource) && source === 'docker');
|
|
1836
|
-
const
|
|
1837
|
-
? await
|
|
2089
|
+
const dockerNetworkName = usesDockerResources
|
|
2090
|
+
? await resolveDockerNetworkName({ scope: resolveDefaultConfigScope() })
|
|
1838
2091
|
: undefined;
|
|
2092
|
+
const dockerContainerPrefix = usesDockerResources
|
|
2093
|
+
? await resolveDockerContainerPrefix({ scope: resolveDefaultConfigScope() })
|
|
2094
|
+
: undefined;
|
|
2095
|
+
await Install.ensureExternalDbReadyForInstall(dbResults);
|
|
2096
|
+
if (!parsed.resume) {
|
|
2097
|
+
await this.saveInstalledEnv({
|
|
2098
|
+
envName,
|
|
2099
|
+
appResults,
|
|
2100
|
+
downloadResults,
|
|
2101
|
+
dbResults,
|
|
2102
|
+
rootResults,
|
|
2103
|
+
envAddResults,
|
|
2104
|
+
});
|
|
2105
|
+
p.log.info(`Saved install config for env "${envName}"`);
|
|
2106
|
+
}
|
|
1839
2107
|
let builtinDbPlan;
|
|
1840
2108
|
if (Boolean(dbResults.builtinDb)) {
|
|
1841
2109
|
builtinDbPlan = await this.startBuiltinDb({
|
|
1842
2110
|
envName,
|
|
1843
|
-
|
|
2111
|
+
dockerNetworkName,
|
|
2112
|
+
dockerContainerPrefix,
|
|
1844
2113
|
appResults,
|
|
1845
2114
|
downloadResults,
|
|
1846
2115
|
dbResults,
|
|
@@ -1864,7 +2133,8 @@ export default class Install extends Command {
|
|
|
1864
2133
|
});
|
|
1865
2134
|
dockerAppPlan = await this.installDockerApp({
|
|
1866
2135
|
envName,
|
|
1867
|
-
|
|
2136
|
+
dockerNetworkName,
|
|
2137
|
+
dockerContainerPrefix,
|
|
1868
2138
|
appResults,
|
|
1869
2139
|
downloadResults,
|
|
1870
2140
|
dbResults,
|
|
@@ -1877,6 +2147,7 @@ export default class Install extends Command {
|
|
|
1877
2147
|
appResults.timeZone = dockerAppPlan.timeZone;
|
|
1878
2148
|
}
|
|
1879
2149
|
else if (source === 'npm' || source === 'git') {
|
|
2150
|
+
const localSource = source === 'npm' ? 'npm' : 'git';
|
|
1880
2151
|
const projectRoot = await this.downloadLocalApp({
|
|
1881
2152
|
envName,
|
|
1882
2153
|
appResults,
|
|
@@ -1885,7 +2156,7 @@ export default class Install extends Command {
|
|
|
1885
2156
|
});
|
|
1886
2157
|
localAppPlan = await this.startLocalApp({
|
|
1887
2158
|
envName,
|
|
1888
|
-
source,
|
|
2159
|
+
source: localSource,
|
|
1889
2160
|
projectRoot,
|
|
1890
2161
|
appResults,
|
|
1891
2162
|
dbResults,
|
|
@@ -1907,12 +2178,20 @@ export default class Install extends Command {
|
|
|
1907
2178
|
containerName: dockerAppPlan?.containerName,
|
|
1908
2179
|
});
|
|
1909
2180
|
}
|
|
1910
|
-
|
|
2181
|
+
if (dockerAppPlan || localAppPlan || builtinDbPlan) {
|
|
2182
|
+
await this.saveInstalledEnv({
|
|
2183
|
+
envName,
|
|
2184
|
+
appResults,
|
|
2185
|
+
downloadResults,
|
|
2186
|
+
dbResults,
|
|
2187
|
+
rootResults,
|
|
2188
|
+
envAddResults,
|
|
2189
|
+
});
|
|
2190
|
+
}
|
|
2191
|
+
await this.syncInstalledEnvConnection({
|
|
1911
2192
|
envName,
|
|
1912
|
-
appResults,
|
|
1913
|
-
downloadResults,
|
|
1914
|
-
dbResults,
|
|
1915
2193
|
envAddResults,
|
|
2194
|
+
appReady: Boolean(dockerAppPlan || localAppPlan),
|
|
1916
2195
|
});
|
|
1917
2196
|
p.outro(dockerAppPlan || localAppPlan
|
|
1918
2197
|
? `NocoBase is ready at http://127.0.0.1:${dockerAppPlan?.appPort ?? localAppPlan?.appPort}`
|