@nocobase/cli 2.2.0-test.16 → 3.0.0-alpha.1
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/dist/commands/app/start.js +1 -21
- package/dist/commands/config/set.js +1 -1
- package/dist/commands/init.js +12 -121
- package/dist/commands/install.js +39 -55
- package/dist/commands/portal/config.js +88 -0
- package/dist/commands/portal/create.js +7 -6
- package/dist/commands/portal/deploy.js +2 -2
- package/dist/commands/portal/destroy.js +6 -6
- package/dist/commands/portal/dev.js +3 -3
- package/dist/commands/portal/index.js +1 -1
- package/dist/commands/portal/info.js +3 -3
- package/dist/commands/portal/list.js +5 -5
- package/dist/commands/portal/pull.js +11 -4
- package/dist/commands/portal/push.js +4 -4
- package/dist/lib/api-client.js +7 -0
- package/dist/lib/env-auth.js +2 -2
- package/dist/lib/env-config.js +1 -1
- package/dist/lib/env-proxy.js +68 -6
- package/dist/lib/managed-env-file.js +58 -2
- package/dist/lib/managed-init-env.js +1 -1
- package/dist/lib/naming.js +9 -0
- package/dist/lib/portal-config.js +133 -0
- package/dist/lib/portal-configure.js +117 -0
- package/dist/lib/portal-create.js +24 -79
- package/dist/lib/portal-deploy.js +23 -15
- package/dist/lib/portal-destroy.js +3 -3
- package/dist/lib/portal-dev.js +3 -3
- package/dist/lib/portal-info.js +2 -2
- package/dist/lib/portal-list.js +32 -18
- package/dist/lib/portal-source.js +150 -43
- package/dist/lib/proxy-caddy.js +2 -0
- package/dist/lib/proxy-nginx.js +1 -0
- package/dist/locale/en-US.json +67 -43
- package/dist/locale/zh-CN.json +59 -35
- package/nocobase-ctl.config.json +111 -0
- package/package.json +4 -3
- package/dist/lib/portal-template.js +0 -190
|
@@ -14,7 +14,6 @@ import { AppHealthCheckError, formatAppUrl, isAppReady, resolveManagedAppApiBase
|
|
|
14
14
|
import { ensureBuiltinDbReady, ensureLocalPostinstall, ensureSavedLocalSource, recreateSavedDockerApp, } from '../../lib/app-managed-resources.js';
|
|
15
15
|
import { clearEnvRootSetup, getEnv, upsertEnv } from '../../lib/auth-store.js';
|
|
16
16
|
import { buildInitAppEnvVarsFromConfig, isPreparedSetupState } from '../../lib/managed-init-env.js';
|
|
17
|
-
import { prepareInitialPortalTemplate } from '../../lib/portal-template.js';
|
|
18
17
|
import { resolveAppUrlFromApiBaseUrl } from '../env/shared.js';
|
|
19
18
|
import { readManagedRuntimeEnvValues } from '../../lib/managed-env-file.js';
|
|
20
19
|
import { run } from '../../lib/run-npm.js';
|
|
@@ -182,19 +181,6 @@ async function finalizePreparedEnv(envName) {
|
|
|
182
181
|
setupState: 'installed',
|
|
183
182
|
});
|
|
184
183
|
}
|
|
185
|
-
async function prepareInitialPortalForRuntime(runtime, verbose) {
|
|
186
|
-
await prepareInitialPortalTemplate({
|
|
187
|
-
developmentMode: runtime.env.config?.developmentMode,
|
|
188
|
-
portalName: runtime.env.config?.portalName,
|
|
189
|
-
portalTemplate: runtime.env.config?.portalTemplate,
|
|
190
|
-
npmRegistry: runtime.env.config?.npmRegistry,
|
|
191
|
-
storagePath: runtime.env.storagePath || runtime.env.config?.storagePath,
|
|
192
|
-
verbose,
|
|
193
|
-
onStartTask: startTask,
|
|
194
|
-
onSucceedTask: succeedTask,
|
|
195
|
-
onFailTask: failTask,
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
184
|
export default class AppStart extends Command {
|
|
199
185
|
static hidden = false;
|
|
200
186
|
static description = 'Start NocoBase for the selected env. When applicable, the CLI synchronizes licensed commercial plugins first, then prepares and starts the app or recreates the saved Docker container.';
|
|
@@ -263,7 +249,7 @@ export default class AppStart extends Command {
|
|
|
263
249
|
}
|
|
264
250
|
const daemonFlagWasProvided = argvHasToken(this.argv, ['--daemon', '--no-daemon']);
|
|
265
251
|
const runtime = await resolveManagedAppRuntime(requestedEnv);
|
|
266
|
-
const preparedInitEnvVars = buildInitAppEnvVarsFromConfig(runtime?.env.config
|
|
252
|
+
const preparedInitEnvVars = buildInitAppEnvVarsFromConfig(runtime?.env.config);
|
|
267
253
|
const isPreparedEnv = isPreparedSetupState(runtime?.env.config?.setupState);
|
|
268
254
|
const hookCommand = resolveHookCommand(flags['hook-command']);
|
|
269
255
|
const hookPhase = resolveAppStartHookPhase({
|
|
@@ -336,9 +322,6 @@ export default class AppStart extends Command {
|
|
|
336
322
|
command: hookCommand,
|
|
337
323
|
});
|
|
338
324
|
}
|
|
339
|
-
if (isPreparedEnv) {
|
|
340
|
-
await prepareInitialPortalForRuntime(runtime, flags.verbose);
|
|
341
|
-
}
|
|
342
325
|
await recreateSavedDockerApp(runtime, {
|
|
343
326
|
initEnvVars: isPreparedEnv ? preparedInitEnvVars : undefined,
|
|
344
327
|
verbose: flags.verbose,
|
|
@@ -487,9 +470,6 @@ export default class AppStart extends Command {
|
|
|
487
470
|
command: hookCommand,
|
|
488
471
|
});
|
|
489
472
|
}
|
|
490
|
-
if (isPreparedEnv) {
|
|
491
|
-
await prepareInitialPortalForRuntime(runtime, flags.verbose);
|
|
492
|
-
}
|
|
493
473
|
await runLocalNocoBaseCommand(runtime, npmArgs, {
|
|
494
474
|
env: startEnv,
|
|
495
475
|
stdio: commandStdio,
|
|
@@ -14,7 +14,7 @@ export default class ConfigSet extends Command {
|
|
|
14
14
|
static description = 'Set a CLI configuration value for a supported configuration key.';
|
|
15
15
|
static examples = [
|
|
16
16
|
'<%= config.bin %> <%= command.id %> locale zh-CN',
|
|
17
|
-
'<%= config.bin %> <%= command.id %> default-portal-template
|
|
17
|
+
'<%= config.bin %> <%= command.id %> default-portal-template @nocobase/portal-template-default',
|
|
18
18
|
'<%= config.bin %> <%= command.id %> update.policy prompt',
|
|
19
19
|
'<%= config.bin %> <%= command.id %> docker.network nocobase',
|
|
20
20
|
'<%= config.bin %> <%= command.id %> docker.container-prefix nb',
|
package/dist/commands/init.js
CHANGED
|
@@ -27,17 +27,14 @@ import { omitKeys, pickKeys } from "../lib/object-utils.js";
|
|
|
27
27
|
import { ENV_CONFIG_SCHEMA_VERSION } from '../lib/env-config.js';
|
|
28
28
|
import { printInfo, printStage, printVerbose, printWarning } from '../lib/ui.js';
|
|
29
29
|
import { persistHookScript } from '../lib/hook-script.js';
|
|
30
|
+
import { ensureManagedEnvFileDefaults } from '../lib/managed-env-file.js';
|
|
30
31
|
import Download from "./download.js";
|
|
31
32
|
import EnvAdd from "./env/add.js";
|
|
32
33
|
import Install, { defaultDbPortForDialect } from "./install.js";
|
|
33
34
|
const DEFAULT_INIT_API_BASE_URL = 'http://localhost:13000/api';
|
|
34
35
|
const DEFAULT_INIT_APP_NAME = 'local';
|
|
35
|
-
const DEFAULT_INIT_DEVELOPMENT_MODE = 'no-code';
|
|
36
|
-
const DEFAULT_INIT_PORTAL_NAME = 'admin';
|
|
37
|
-
const DEFAULT_INIT_PORTAL_TEMPLATE = 'git@github.com:nocobase/admin-starter.git';
|
|
38
36
|
const DOWNLOAD_OUTPUT_DIR_PROMPT = Download.prompts.outputDir;
|
|
39
37
|
const INIT_SETUP_MODES = ['install-new', 'manage-local', 'connect-remote'];
|
|
40
|
-
const INIT_DEVELOPMENT_MODES = ['no-code', 'vibe-coding'];
|
|
41
38
|
const INIT_ENV_ADD_FLAG_NAMES = [
|
|
42
39
|
'locale',
|
|
43
40
|
'default-api-base-url',
|
|
@@ -84,9 +81,6 @@ function isInstallNewSetupMode(values) {
|
|
|
84
81
|
function isInstallLikeSetupMode(values) {
|
|
85
82
|
return !isRemoteSetupMode(values);
|
|
86
83
|
}
|
|
87
|
-
function isVibeCodingMode(values) {
|
|
88
|
-
return String(values.developmentMode ?? DEFAULT_INIT_DEVELOPMENT_MODE).trim() === 'vibe-coding';
|
|
89
|
-
}
|
|
90
84
|
function remoteConnectionOnly(def) {
|
|
91
85
|
return withExtraHidden(def, (values) => !isRemoteSetupMode(values));
|
|
92
86
|
}
|
|
@@ -394,43 +388,6 @@ Prompt modes:
|
|
|
394
388
|
devDependencies: installLikeDownloadExecutionOnly(Download.prompts.devDependencies),
|
|
395
389
|
build: installLikeDownloadExecutionOnly(Download.prompts.build),
|
|
396
390
|
buildDts: installLikeDownloadExecutionOnly(Download.prompts.buildDts),
|
|
397
|
-
developmentMode: installNewOnly({
|
|
398
|
-
type: 'select',
|
|
399
|
-
variant: 'radio',
|
|
400
|
-
message: initText('prompts.developmentMode.message'),
|
|
401
|
-
options: [
|
|
402
|
-
{
|
|
403
|
-
value: 'no-code',
|
|
404
|
-
label: initText('prompts.developmentMode.noCodeLabel'),
|
|
405
|
-
hint: initText('prompts.developmentMode.noCodeHint'),
|
|
406
|
-
},
|
|
407
|
-
{
|
|
408
|
-
value: 'vibe-coding',
|
|
409
|
-
label: initText('prompts.developmentMode.vibeCodingLabel'),
|
|
410
|
-
hint: initText('prompts.developmentMode.vibeCodingHint'),
|
|
411
|
-
},
|
|
412
|
-
],
|
|
413
|
-
initialValue: DEFAULT_INIT_DEVELOPMENT_MODE,
|
|
414
|
-
yesInitialValue: DEFAULT_INIT_DEVELOPMENT_MODE,
|
|
415
|
-
required: true,
|
|
416
|
-
}),
|
|
417
|
-
portalName: installNewOnly({
|
|
418
|
-
type: 'text',
|
|
419
|
-
message: initText('prompts.portalName.message'),
|
|
420
|
-
placeholder: DEFAULT_INIT_PORTAL_NAME,
|
|
421
|
-
initialValue: DEFAULT_INIT_PORTAL_NAME,
|
|
422
|
-
yesInitialValue: DEFAULT_INIT_PORTAL_NAME,
|
|
423
|
-
hidden: (values) => !isVibeCodingMode(values),
|
|
424
|
-
required: true,
|
|
425
|
-
}),
|
|
426
|
-
portalTemplate: installNewOnly({
|
|
427
|
-
type: 'text',
|
|
428
|
-
message: initText('prompts.portalTemplate.message'),
|
|
429
|
-
placeholder: DEFAULT_INIT_PORTAL_TEMPLATE,
|
|
430
|
-
yesInitialValue: DEFAULT_INIT_PORTAL_TEMPLATE,
|
|
431
|
-
hidden: (values) => !isVibeCodingMode(values),
|
|
432
|
-
required: true,
|
|
433
|
-
}),
|
|
434
391
|
dbDialect: installLikeOnly(Install.dbPrompts.dbDialect),
|
|
435
392
|
builtinDb: installLikeOnly(Install.dbPrompts.builtinDb),
|
|
436
393
|
builtinDbImage: installLikeOnly(Install.dbPrompts.builtinDbImage),
|
|
@@ -456,13 +413,6 @@ Prompt modes:
|
|
|
456
413
|
...Init.prompts,
|
|
457
414
|
installApiBaseUrl: createInstallConnectionApiBaseUrlPrompt(options.defaultApiHost),
|
|
458
415
|
};
|
|
459
|
-
const defaultPortalTemplate = String(options.defaultPortalTemplate ?? '').trim();
|
|
460
|
-
if (defaultPortalTemplate) {
|
|
461
|
-
prompts.portalTemplate = {
|
|
462
|
-
...prompts.portalTemplate,
|
|
463
|
-
yesInitialValue: defaultPortalTemplate,
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
416
|
if (flags['skip-auth']) {
|
|
467
417
|
const accessTokenPrompt = {
|
|
468
418
|
...EnvAdd.prompts.accessToken,
|
|
@@ -512,16 +462,6 @@ Prompt modes:
|
|
|
512
462
|
description: 'Setup mode: install a new app, manage a local app by reusing its database, or connect a remote app',
|
|
513
463
|
options: [...INIT_SETUP_MODES],
|
|
514
464
|
}),
|
|
515
|
-
'development-mode': Flags.string({
|
|
516
|
-
description: 'Initial development mode: no-code or vibe-coding',
|
|
517
|
-
options: [...INIT_DEVELOPMENT_MODES],
|
|
518
|
-
}),
|
|
519
|
-
'portal-name': Flags.string({
|
|
520
|
-
description: 'Initial portal name when --development-mode vibe-coding is used',
|
|
521
|
-
}),
|
|
522
|
-
'portal-template': Flags.string({
|
|
523
|
-
description: 'Initial portal template Git URL or local path when --development-mode vibe-coding is used',
|
|
524
|
-
}),
|
|
525
465
|
ui: Flags.boolean({
|
|
526
466
|
description: 'Open the guided setup flow in a local browser form (not valid with --yes)',
|
|
527
467
|
default: false,
|
|
@@ -639,8 +579,7 @@ Prompt modes:
|
|
|
639
579
|
const dynamicInitialValues = await Init.buildDynamicInitialValuesForInstall(normalizedFlags, presetValues);
|
|
640
580
|
const defaultUiHost = await resolveDefaultUiHost();
|
|
641
581
|
const defaultApiHost = await resolveDefaultApiHost();
|
|
642
|
-
const
|
|
643
|
-
const promptCatalog = this.buildPromptCatalog(normalizedFlags, { defaultApiHost, defaultPortalTemplate });
|
|
582
|
+
const promptCatalog = this.buildPromptCatalog(normalizedFlags, { defaultApiHost });
|
|
644
583
|
if (useBrowserUi) {
|
|
645
584
|
presetValues = await runPromptCatalogWebUI({
|
|
646
585
|
stages: Init.buildWebUiStages(promptCatalog),
|
|
@@ -669,7 +608,7 @@ Prompt modes:
|
|
|
669
608
|
? { setupMode: normalizeInitSetupMode(presetValues.hasNocobase) }
|
|
670
609
|
: {}),
|
|
671
610
|
},
|
|
672
|
-
yesInitialValues:
|
|
611
|
+
yesInitialValues: {},
|
|
673
612
|
values: presetValues,
|
|
674
613
|
yes: normalizedFlags.yes || useBrowserUi || !interactive,
|
|
675
614
|
hooks: {
|
|
@@ -742,8 +681,7 @@ Prompt modes:
|
|
|
742
681
|
}
|
|
743
682
|
static async buildDynamicInitialValuesForInstall(flags, presetValues) {
|
|
744
683
|
const out = {};
|
|
745
|
-
const shouldResolveAppInitialValues = !Object.prototype.hasOwnProperty.call(presetValues, 'appPort')
|
|
746
|
-
!Object.prototype.hasOwnProperty.call(presetValues, 'portalTemplate');
|
|
684
|
+
const shouldResolveAppInitialValues = !Object.prototype.hasOwnProperty.call(presetValues, 'appPort');
|
|
747
685
|
if (shouldResolveAppInitialValues) {
|
|
748
686
|
const appInitialValues = await Install.buildAppPromptInitialValues({
|
|
749
687
|
envName: String(presetValues.appName ?? '').trim(),
|
|
@@ -752,20 +690,12 @@ Prompt modes:
|
|
|
752
690
|
'app-path': flags['app-path'] ?? '',
|
|
753
691
|
'app-root-path': flags['app-root-path'] ?? '',
|
|
754
692
|
'storage-path': flags['storage-path'] ?? '',
|
|
755
|
-
'portal-template': flags['portal-template'] ??
|
|
756
|
-
(Object.prototype.hasOwnProperty.call(presetValues, 'portalTemplate')
|
|
757
|
-
? String(presetValues.portalTemplate ?? '')
|
|
758
|
-
: undefined),
|
|
759
693
|
},
|
|
760
694
|
warnOnPortFallback: false,
|
|
761
695
|
});
|
|
762
696
|
if (appInitialValues.appPort !== undefined && !Object.prototype.hasOwnProperty.call(presetValues, 'appPort')) {
|
|
763
697
|
out.appPort = appInitialValues.appPort;
|
|
764
698
|
}
|
|
765
|
-
if (appInitialValues.portalTemplate !== undefined &&
|
|
766
|
-
!Object.prototype.hasOwnProperty.call(presetValues, 'portalTemplate')) {
|
|
767
|
-
out.portalTemplate = appInitialValues.portalTemplate;
|
|
768
|
-
}
|
|
769
699
|
}
|
|
770
700
|
const downloadSeed = { ...presetValues };
|
|
771
701
|
if (flags.yes && !Object.prototype.hasOwnProperty.call(downloadSeed, 'source')) {
|
|
@@ -844,13 +774,6 @@ Prompt modes:
|
|
|
844
774
|
buildDts: c.buildDts,
|
|
845
775
|
},
|
|
846
776
|
},
|
|
847
|
-
{
|
|
848
|
-
sectionTitle: initText('webUi.developmentMode.title'),
|
|
849
|
-
sectionDescription: initText('webUi.developmentMode.description'),
|
|
850
|
-
catalog: {
|
|
851
|
-
developmentMode: c.developmentMode,
|
|
852
|
-
},
|
|
853
|
-
},
|
|
854
777
|
{
|
|
855
778
|
sectionTitle: initText('webUi.configureDatabase.title'),
|
|
856
779
|
sectionDescription: initText('webUi.configureDatabase.description'),
|
|
@@ -951,15 +874,6 @@ Prompt modes:
|
|
|
951
874
|
if (flags['app-public-path'] !== undefined && String(flags['app-public-path']).trim() !== '') {
|
|
952
875
|
preset.appPublicPath = String(flags['app-public-path']).trim();
|
|
953
876
|
}
|
|
954
|
-
if (flags['development-mode'] !== undefined && String(flags['development-mode']).trim() !== '') {
|
|
955
|
-
preset.developmentMode = String(flags['development-mode']).trim();
|
|
956
|
-
}
|
|
957
|
-
if (flags['portal-name'] !== undefined && String(flags['portal-name']).trim() !== '') {
|
|
958
|
-
preset.portalName = String(flags['portal-name']).trim();
|
|
959
|
-
}
|
|
960
|
-
if (flags['portal-template'] !== undefined && String(flags['portal-template']).trim() !== '') {
|
|
961
|
-
preset.portalTemplate = String(flags['portal-template']).trim();
|
|
962
|
-
}
|
|
963
877
|
if (flags['root-username'] !== undefined) {
|
|
964
878
|
preset.rootUsername = String(flags['root-username'] ?? '').trim();
|
|
965
879
|
}
|
|
@@ -1097,9 +1011,6 @@ Prompt modes:
|
|
|
1097
1011
|
const existingEnv = await getEnv(envName, { scope: resolveDefaultConfigScope() });
|
|
1098
1012
|
const appPort = String(results.appPort ?? '').trim();
|
|
1099
1013
|
const appPublicPath = String(results.appPublicPath ?? '').trim();
|
|
1100
|
-
const developmentMode = String(results.developmentMode ?? '').trim();
|
|
1101
|
-
const portalName = String(results.portalName ?? '').trim();
|
|
1102
|
-
const portalTemplate = String(results.portalTemplate ?? '').trim();
|
|
1103
1014
|
const source = String(results.source ?? '').trim();
|
|
1104
1015
|
const version = resolveInitDownloadVersion(results);
|
|
1105
1016
|
const dockerRegistry = String(results.dockerRegistry ?? '').trim();
|
|
@@ -1126,7 +1037,8 @@ Prompt modes:
|
|
|
1126
1037
|
const dbSchema = String(results.dbSchema ?? '').trim();
|
|
1127
1038
|
const dbTablePrefix = String(results.dbTablePrefix ?? '').trim();
|
|
1128
1039
|
const apiBaseUrl = String(results.apiBaseUrl ?? '').trim();
|
|
1129
|
-
const
|
|
1040
|
+
const authTypeInput = String(results.authType ?? '').trim();
|
|
1041
|
+
const authType = authTypeInput === 'basic' || authTypeInput === 'token' || authTypeInput === 'oauth' ? authTypeInput : 'oauth';
|
|
1130
1042
|
const authUsername = authType === 'basic' ? String(results.username ?? results.rootUsername ?? '').trim() : '';
|
|
1131
1043
|
const accessToken = String(results.accessToken ?? '');
|
|
1132
1044
|
const skipDownload = results.skipDownload === true;
|
|
@@ -1147,7 +1059,7 @@ Prompt modes:
|
|
|
1147
1059
|
: Boolean(results.builtinDb);
|
|
1148
1060
|
results.appKey = appKey;
|
|
1149
1061
|
results.timeZone = timeZone;
|
|
1150
|
-
|
|
1062
|
+
const savedEnvConfig = {
|
|
1151
1063
|
schemaVersion: ENV_CONFIG_SCHEMA_VERSION,
|
|
1152
1064
|
...(source === 'docker'
|
|
1153
1065
|
? { kind: 'docker' }
|
|
@@ -1172,9 +1084,6 @@ Prompt modes:
|
|
|
1172
1084
|
...(storagePath && !areConfiguredPathsEquivalent(storagePath, derivedStoragePath) ? { storagePath } : {}),
|
|
1173
1085
|
...(appPort ? { appPort } : {}),
|
|
1174
1086
|
...(appPublicPath ? { appPublicPath } : {}),
|
|
1175
|
-
...(developmentMode && developmentMode !== DEFAULT_INIT_DEVELOPMENT_MODE ? { developmentMode } : {}),
|
|
1176
|
-
...(portalName ? { portalName } : {}),
|
|
1177
|
-
...(portalTemplate ? { portalTemplate } : {}),
|
|
1178
1087
|
...(appKey ? { appKey } : {}),
|
|
1179
1088
|
...(timeZone ? { timezone: timeZone } : {}),
|
|
1180
1089
|
...(!skipDownload && results.devDependencies !== undefined
|
|
@@ -1195,7 +1104,11 @@ Prompt modes:
|
|
|
1195
1104
|
...(results.dbUnderscored !== undefined ? { dbUnderscored: Boolean(results.dbUnderscored) } : {}),
|
|
1196
1105
|
setupState: 'prepared',
|
|
1197
1106
|
...(String(results.lang ?? '').trim() ? { lang: String(results.lang ?? '').trim() } : {}),
|
|
1198
|
-
}
|
|
1107
|
+
};
|
|
1108
|
+
await upsertEnv(envName, savedEnvConfig, { scope: resolveDefaultConfigScope() });
|
|
1109
|
+
if (source === 'docker' || appPath) {
|
|
1110
|
+
await ensureManagedEnvFileDefaults(envName, savedEnvConfig);
|
|
1111
|
+
}
|
|
1199
1112
|
}
|
|
1200
1113
|
buildEnvAddArgv(results) {
|
|
1201
1114
|
const argv = [String(results.appName ?? DEFAULT_INIT_APP_NAME)];
|
|
@@ -1299,18 +1212,6 @@ Prompt modes:
|
|
|
1299
1212
|
if (appPublicPath) {
|
|
1300
1213
|
argv.push('--app-public-path', appPublicPath);
|
|
1301
1214
|
}
|
|
1302
|
-
const developmentMode = String(results.developmentMode ?? '').trim();
|
|
1303
|
-
if (developmentMode && developmentMode !== DEFAULT_INIT_DEVELOPMENT_MODE) {
|
|
1304
|
-
argv.push('--development-mode', developmentMode);
|
|
1305
|
-
}
|
|
1306
|
-
const portalName = String(results.portalName ?? '').trim();
|
|
1307
|
-
if (portalName) {
|
|
1308
|
-
argv.push('--portal-name', portalName);
|
|
1309
|
-
}
|
|
1310
|
-
const portalTemplate = String(results.portalTemplate ?? '').trim();
|
|
1311
|
-
if (portalTemplate) {
|
|
1312
|
-
argv.push('--portal-template', portalTemplate);
|
|
1313
|
-
}
|
|
1314
1215
|
if (flags.force) {
|
|
1315
1216
|
argv.push('--force');
|
|
1316
1217
|
}
|
|
@@ -1508,16 +1409,6 @@ Prompt modes:
|
|
|
1508
1409
|
delete normalized.rootPassword;
|
|
1509
1410
|
delete normalized.rootNickname;
|
|
1510
1411
|
}
|
|
1511
|
-
const developmentMode = normalizeConnectionString(normalized.developmentMode) || DEFAULT_INIT_DEVELOPMENT_MODE;
|
|
1512
|
-
normalized.developmentMode = developmentMode;
|
|
1513
|
-
if (developmentMode === 'vibe-coding') {
|
|
1514
|
-
normalized.portalName = normalizeConnectionString(normalized.portalName) || DEFAULT_INIT_PORTAL_NAME;
|
|
1515
|
-
normalized.portalTemplate = normalizeConnectionString(normalized.portalTemplate);
|
|
1516
|
-
}
|
|
1517
|
-
else {
|
|
1518
|
-
delete normalized.portalName;
|
|
1519
|
-
delete normalized.portalTemplate;
|
|
1520
|
-
}
|
|
1521
1412
|
delete normalized.installApiBaseUrl;
|
|
1522
1413
|
delete normalized.installAuthType;
|
|
1523
1414
|
delete normalized.installUsername;
|
package/dist/commands/install.js
CHANGED
|
@@ -29,7 +29,7 @@ import { buildStoredEnvConfig } from '../lib/env-config.js';
|
|
|
29
29
|
import { resolveDockerEnvFileArg } from "../lib/docker-env-file.js";
|
|
30
30
|
import { startDockerLogFollower } from '../lib/docker-log-stream.js';
|
|
31
31
|
import { buildInitAppEnvVarsFromConfig } from '../lib/managed-init-env.js';
|
|
32
|
-
import {
|
|
32
|
+
import { ensureManagedEnvFileDefaults } from '../lib/managed-env-file.js';
|
|
33
33
|
import { buildHookContext, persistHookScript, resolveHookScriptPath, runHookScriptHook, } from '../lib/hook-script.js';
|
|
34
34
|
import { areConfiguredPathsEquivalent, deriveConfiguredSourcePath, deriveConfiguredStoragePath, inferConfiguredAppPathFromLegacyConfig, } from '../lib/env-paths.js';
|
|
35
35
|
import Download from './download.js';
|
|
@@ -54,10 +54,10 @@ const DEFAULT_INSTALL_ROOT_EMAIL = 'admin@nocobase.com';
|
|
|
54
54
|
const DEFAULT_INSTALL_ROOT_PASSWORD = 'admin123';
|
|
55
55
|
const DEFAULT_INSTALL_ROOT_NICKNAME = 'Super Admin';
|
|
56
56
|
const DEFAULT_INSTALL_API_HOST = '127.0.0.1';
|
|
57
|
-
const
|
|
58
|
-
const DEFAULT_INSTALL_PORTAL_NAME = '
|
|
59
|
-
const DEFAULT_INSTALL_PORTAL_TEMPLATE = '
|
|
60
|
-
const
|
|
57
|
+
const DEFAULT_INSTALL_PORTAL_TYPE = 'ai';
|
|
58
|
+
const DEFAULT_INSTALL_PORTAL_NAME = 'main';
|
|
59
|
+
const DEFAULT_INSTALL_PORTAL_TEMPLATE = '@nocobase/portal-template-default';
|
|
60
|
+
const INSTALL_PORTAL_TYPES = ['no-code', 'ai'];
|
|
61
61
|
function toOptionalPromptString(value) {
|
|
62
62
|
const text = String(value ?? '').trim();
|
|
63
63
|
return text || undefined;
|
|
@@ -185,8 +185,8 @@ function defaultBuiltinDbImageForDialect(value, options) {
|
|
|
185
185
|
function defaultDbDatabaseForDialect(value) {
|
|
186
186
|
return String(value ?? '').trim() === 'kingbase' ? 'kingbase' : DEFAULT_INSTALL_DB_DATABASE;
|
|
187
187
|
}
|
|
188
|
-
function
|
|
189
|
-
return String(values.
|
|
188
|
+
function isAiMode(values) {
|
|
189
|
+
return String(values.portalType ?? DEFAULT_INSTALL_PORTAL_TYPE).trim() === 'ai';
|
|
190
190
|
}
|
|
191
191
|
function supportsDbSchemaPrompt(value) {
|
|
192
192
|
const dialect = String(value ?? '').trim();
|
|
@@ -412,15 +412,15 @@ export default class Install extends Command {
|
|
|
412
412
|
'app-public-path': Flags.string({
|
|
413
413
|
description: 'Public path for the local app, for example / or /console/',
|
|
414
414
|
}),
|
|
415
|
-
'
|
|
416
|
-
description: 'Initial
|
|
417
|
-
options: [...
|
|
415
|
+
'portal-type': Flags.string({
|
|
416
|
+
description: 'Initial portal type for the installed app',
|
|
417
|
+
options: [...INSTALL_PORTAL_TYPES],
|
|
418
418
|
}),
|
|
419
419
|
'portal-name': Flags.string({
|
|
420
|
-
description: 'Initial portal name
|
|
420
|
+
description: 'Initial portal name',
|
|
421
421
|
}),
|
|
422
422
|
'portal-template': Flags.string({
|
|
423
|
-
description: 'Initial portal template
|
|
423
|
+
description: 'Initial portal template npm package or local path when --portal-type ai is used',
|
|
424
424
|
}),
|
|
425
425
|
'root-username': Flags.string({
|
|
426
426
|
description: 'Initial admin username for the installed app',
|
|
@@ -531,23 +531,23 @@ export default class Install extends Command {
|
|
|
531
531
|
yesInitialValue: '/',
|
|
532
532
|
validate: validateAppPublicPath,
|
|
533
533
|
},
|
|
534
|
-
|
|
534
|
+
portalType: {
|
|
535
535
|
type: 'select',
|
|
536
|
-
message: installText('prompts.
|
|
536
|
+
message: installText('prompts.portalType.message'),
|
|
537
537
|
options: [
|
|
538
538
|
{
|
|
539
539
|
value: 'no-code',
|
|
540
|
-
label: installText('prompts.
|
|
541
|
-
hint: installText('prompts.
|
|
540
|
+
label: installText('prompts.portalType.noCodeLabel'),
|
|
541
|
+
hint: installText('prompts.portalType.noCodeHint'),
|
|
542
542
|
},
|
|
543
543
|
{
|
|
544
|
-
value: '
|
|
545
|
-
label: installText('prompts.
|
|
546
|
-
hint: installText('prompts.
|
|
544
|
+
value: 'ai',
|
|
545
|
+
label: installText('prompts.portalType.aiLabel'),
|
|
546
|
+
hint: installText('prompts.portalType.aiHint'),
|
|
547
547
|
},
|
|
548
548
|
],
|
|
549
|
-
initialValue:
|
|
550
|
-
yesInitialValue:
|
|
549
|
+
initialValue: DEFAULT_INSTALL_PORTAL_TYPE,
|
|
550
|
+
yesInitialValue: DEFAULT_INSTALL_PORTAL_TYPE,
|
|
551
551
|
required: true,
|
|
552
552
|
},
|
|
553
553
|
portalName: {
|
|
@@ -556,7 +556,6 @@ export default class Install extends Command {
|
|
|
556
556
|
placeholder: DEFAULT_INSTALL_PORTAL_NAME,
|
|
557
557
|
initialValue: DEFAULT_INSTALL_PORTAL_NAME,
|
|
558
558
|
yesInitialValue: DEFAULT_INSTALL_PORTAL_NAME,
|
|
559
|
-
hidden: (values) => !isVibeCodingMode(values),
|
|
560
559
|
required: true,
|
|
561
560
|
},
|
|
562
561
|
portalTemplate: {
|
|
@@ -564,7 +563,7 @@ export default class Install extends Command {
|
|
|
564
563
|
message: installText('prompts.portalTemplate.message'),
|
|
565
564
|
placeholder: DEFAULT_INSTALL_PORTAL_TEMPLATE,
|
|
566
565
|
yesInitialValue: DEFAULT_INSTALL_PORTAL_TEMPLATE,
|
|
567
|
-
hidden: (values) => !
|
|
566
|
+
hidden: (values) => !isAiMode(values),
|
|
568
567
|
required: true,
|
|
569
568
|
},
|
|
570
569
|
};
|
|
@@ -826,10 +825,10 @@ export default class Install extends Command {
|
|
|
826
825
|
preset.appPublicPath = v;
|
|
827
826
|
}
|
|
828
827
|
}
|
|
829
|
-
if (flags['
|
|
830
|
-
const v = String(flags['
|
|
828
|
+
if (flags['portal-type'] !== undefined) {
|
|
829
|
+
const v = String(flags['portal-type'] ?? '').trim();
|
|
831
830
|
if (v) {
|
|
832
|
-
preset.
|
|
831
|
+
preset.portalType = v;
|
|
833
832
|
}
|
|
834
833
|
}
|
|
835
834
|
if (flags['portal-name'] !== undefined) {
|
|
@@ -935,7 +934,7 @@ export default class Install extends Command {
|
|
|
935
934
|
'appPort',
|
|
936
935
|
'storagePath',
|
|
937
936
|
'appPublicPath',
|
|
938
|
-
'
|
|
937
|
+
'portalType',
|
|
939
938
|
'portalName',
|
|
940
939
|
'portalTemplate',
|
|
941
940
|
]);
|
|
@@ -1187,7 +1186,7 @@ export default class Install extends Command {
|
|
|
1187
1186
|
const rootPassword = Install.toOptionalPromptString(config.rootPassword);
|
|
1188
1187
|
const rootNickname = Install.toOptionalPromptString(config.rootNickname);
|
|
1189
1188
|
const lang = Install.toOptionalPromptString(config.lang);
|
|
1190
|
-
const
|
|
1189
|
+
const portalType = Install.toOptionalPromptString(config.portalType);
|
|
1191
1190
|
const portalName = Install.toOptionalPromptString(config.portalName);
|
|
1192
1191
|
const portalTemplate = Install.toOptionalPromptString(config.portalTemplate);
|
|
1193
1192
|
const auth = config.auth;
|
|
@@ -1199,7 +1198,7 @@ export default class Install extends Command {
|
|
|
1199
1198
|
...(appPort ? { appPort } : {}),
|
|
1200
1199
|
...(storagePath ? { storagePath } : {}),
|
|
1201
1200
|
...(appPublicPath ? { appPublicPath } : {}),
|
|
1202
|
-
...(
|
|
1201
|
+
...(portalType ? { portalType } : {}),
|
|
1203
1202
|
...(portalName ? { portalName } : {}),
|
|
1204
1203
|
...(portalTemplate ? { portalTemplate } : {}),
|
|
1205
1204
|
...(hookScript ? { hookScript } : {}),
|
|
@@ -1524,7 +1523,7 @@ export default class Install extends Command {
|
|
|
1524
1523
|
rootEmail: String(params.rootResults.rootEmail ?? ''),
|
|
1525
1524
|
rootPassword: String(params.rootResults.rootPassword ?? ''),
|
|
1526
1525
|
rootNickname: String(params.rootResults.rootNickname ?? ''),
|
|
1527
|
-
|
|
1526
|
+
portalType: String(params.appResults.portalType ?? ''),
|
|
1528
1527
|
portalName: String(params.appResults.portalName ?? ''),
|
|
1529
1528
|
portalTemplate: String(params.appResults.portalTemplate ?? ''),
|
|
1530
1529
|
}, options);
|
|
@@ -1882,7 +1881,7 @@ export default class Install extends Command {
|
|
|
1882
1881
|
const initEnvVars = Install.buildInitAppEnvVars({
|
|
1883
1882
|
appResults: params.appResults,
|
|
1884
1883
|
rootResults: params.rootResults,
|
|
1885
|
-
}
|
|
1884
|
+
});
|
|
1886
1885
|
const containerPort = resolveDockerImageContainerPort(imageRef);
|
|
1887
1886
|
const args = [
|
|
1888
1887
|
'run',
|
|
@@ -2159,7 +2158,7 @@ export default class Install extends Command {
|
|
|
2159
2158
|
...Install.buildInitAppEnvVars({
|
|
2160
2159
|
appResults: params.appResults,
|
|
2161
2160
|
rootResults: params.rootResults,
|
|
2162
|
-
}
|
|
2161
|
+
}),
|
|
2163
2162
|
};
|
|
2164
2163
|
setOptionalEnvVar(env, 'APP_PUBLIC_PATH', Install.toOptionalPromptString(params.appResults.appPublicPath));
|
|
2165
2164
|
setOptionalEnvVar(env, 'DB_SCHEMA', optionalEnvString(params.dbResults.dbSchema));
|
|
@@ -2318,9 +2317,13 @@ export default class Install extends Command {
|
|
|
2318
2317
|
}
|
|
2319
2318
|
async saveInstalledEnv(params) {
|
|
2320
2319
|
const defaultApiHost = await resolveDefaultApiHost();
|
|
2321
|
-
|
|
2320
|
+
const savedEnvConfig = Install.buildSavedEnvConfig(params, { defaultApiHost });
|
|
2321
|
+
await upsertEnv(params.envName, savedEnvConfig, {
|
|
2322
2322
|
scope: resolveDefaultConfigScope(),
|
|
2323
2323
|
});
|
|
2324
|
+
if (params.ensureEnvFileDefaults !== false) {
|
|
2325
|
+
await ensureManagedEnvFileDefaults(params.envName, savedEnvConfig);
|
|
2326
|
+
}
|
|
2324
2327
|
await setCurrentEnv(params.envName, { scope: resolveDefaultConfigScope() });
|
|
2325
2328
|
}
|
|
2326
2329
|
async syncInstalledEnvConnection(params) {
|
|
@@ -2356,19 +2359,6 @@ export default class Install extends Command {
|
|
|
2356
2359
|
}
|
|
2357
2360
|
return argv;
|
|
2358
2361
|
}
|
|
2359
|
-
async prepareInitialPortalIfNeeded(params) {
|
|
2360
|
-
await prepareInitialPortalTemplate({
|
|
2361
|
-
developmentMode: Install.toOptionalPromptString(params.appResults.developmentMode),
|
|
2362
|
-
portalName: Install.toOptionalPromptString(params.appResults.portalName),
|
|
2363
|
-
portalTemplate: Install.toOptionalPromptString(params.appResults.portalTemplate),
|
|
2364
|
-
npmRegistry: Install.toOptionalPromptString(params.appResults.npmRegistry),
|
|
2365
|
-
storagePath: Install.resolveAbsoluteStoragePath(params.envName, params.appResults),
|
|
2366
|
-
verbose: params.verbose,
|
|
2367
|
-
onStartTask: (message) => this.logStage(message),
|
|
2368
|
-
onSucceedTask: (message) => printInfo(message),
|
|
2369
|
-
onFailTask: (message) => printWarning(message),
|
|
2370
|
-
});
|
|
2371
|
-
}
|
|
2372
2362
|
async runInstallHookIfNeeded(params) {
|
|
2373
2363
|
const appPath = Install.resolveAbsoluteAppPath(params.envName, params.appResults);
|
|
2374
2364
|
const savedHookScript = Install.toOptionalPromptString(params.appResults.hookScript);
|
|
@@ -2412,7 +2402,7 @@ export default class Install extends Command {
|
|
|
2412
2402
|
const appRootPath = Install.toOptionalPromptString(params.appResults.appRootPath);
|
|
2413
2403
|
const storagePath = Install.toOptionalPromptString(params.appResults.storagePath);
|
|
2414
2404
|
const appPublicPath = Install.toOptionalPromptString(params.appResults.appPublicPath);
|
|
2415
|
-
const
|
|
2405
|
+
const portalType = Install.toOptionalPromptString(params.appResults.portalType);
|
|
2416
2406
|
const portalName = Install.toOptionalPromptString(params.appResults.portalName);
|
|
2417
2407
|
const portalTemplate = Install.toOptionalPromptString(params.appResults.portalTemplate);
|
|
2418
2408
|
const derivedAppRootPath = appPath ? deriveConfiguredSourcePath(appPath) : undefined;
|
|
@@ -2449,7 +2439,7 @@ export default class Install extends Command {
|
|
|
2449
2439
|
...(appPublicPath ? { appPublicPath } : {}),
|
|
2450
2440
|
...(envFile ? { envFile } : {}),
|
|
2451
2441
|
lang: params.appResults.lang,
|
|
2452
|
-
|
|
2442
|
+
portalType,
|
|
2453
2443
|
portalName,
|
|
2454
2444
|
portalTemplate,
|
|
2455
2445
|
appKey: params.appResults.appKey,
|
|
@@ -2675,6 +2665,7 @@ export default class Install extends Command {
|
|
|
2675
2665
|
dbResults,
|
|
2676
2666
|
rootResults,
|
|
2677
2667
|
envAddResults,
|
|
2668
|
+
ensureEnvFileDefaults: false,
|
|
2678
2669
|
});
|
|
2679
2670
|
if (!parsed['skip-save-env-log']) {
|
|
2680
2671
|
printInfo(`Saved env config for "${envName}".`);
|
|
@@ -2742,13 +2733,6 @@ export default class Install extends Command {
|
|
|
2742
2733
|
envAddResults,
|
|
2743
2734
|
});
|
|
2744
2735
|
}
|
|
2745
|
-
if (shouldStartApp) {
|
|
2746
|
-
await this.prepareInitialPortalIfNeeded({
|
|
2747
|
-
envName,
|
|
2748
|
-
appResults,
|
|
2749
|
-
verbose: parsed.verbose,
|
|
2750
|
-
});
|
|
2751
|
-
}
|
|
2752
2736
|
if (shouldStartApp) {
|
|
2753
2737
|
this.logStage('Starting NocoBase');
|
|
2754
2738
|
await this.config.runCommand('app:start', this.buildAppStartArgv({ envName, verbose: parsed.verbose }));
|