@nocobase/cli 2.1.0-beta.35 → 2.1.0-beta.37
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 +1 -1
- package/README.zh-CN.md +1 -1
- package/bin/run.js +3 -2
- package/dist/commands/app/upgrade.js +38 -16
- package/dist/commands/backup/create.js +147 -0
- package/dist/commands/backup/index.js +20 -0
- package/dist/commands/backup/restore.js +105 -0
- package/dist/commands/config/delete.js +4 -0
- package/dist/commands/config/get.js +4 -0
- package/dist/commands/config/set.js +5 -1
- package/dist/commands/env/add.js +129 -15
- package/dist/commands/env/auth.js +145 -12
- package/dist/commands/env/info.js +52 -8
- package/dist/commands/env/list.js +2 -2
- package/dist/commands/env/shared.js +41 -3
- package/dist/commands/init.js +254 -136
- package/dist/commands/install.js +447 -272
- package/dist/commands/license/activate.js +6 -4
- package/dist/commands/source/publish.js +17 -0
- package/dist/commands/v1.js +210 -0
- package/dist/lib/app-managed-resources.js +20 -1
- package/dist/lib/app-runtime.js +13 -4
- package/dist/lib/auth-store.js +69 -18
- package/dist/lib/backup.js +171 -0
- package/dist/lib/bootstrap.js +23 -13
- package/dist/lib/cli-config.js +99 -4
- package/dist/lib/cli-locale.js +19 -7
- package/dist/lib/db-connection-check.js +61 -0
- package/dist/lib/env-auth.js +79 -0
- package/dist/lib/env-config.js +8 -1
- package/dist/lib/prompt-validators.js +23 -5
- package/dist/lib/prompt-web-ui.js +143 -19
- package/dist/lib/run-npm.js +166 -30
- package/dist/lib/skills-manager.js +74 -4
- package/dist/lib/source-publish.js +20 -1
- package/dist/lib/source-registry.js +2 -2
- package/dist/locale/en-US.json +36 -5
- package/dist/locale/zh-CN.json +36 -5
- package/package.json +6 -3
package/dist/commands/install.js
CHANGED
|
@@ -7,27 +7,26 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
import { Command, Flags } from '@oclif/core';
|
|
10
|
-
import { spawn } from 'node:child_process';
|
|
11
10
|
import crypto from 'node:crypto';
|
|
12
|
-
import { mkdir } from 'node:fs/promises';
|
|
11
|
+
import { access, mkdir } from 'node:fs/promises';
|
|
13
12
|
import path from 'node:path';
|
|
14
13
|
import { exit } from 'node:process';
|
|
15
14
|
import { runPromptCatalog, } from "../lib/prompt-catalog.js";
|
|
16
|
-
import { applyCliLocale, localeText, resolveCliLocale, translateCli
|
|
15
|
+
import { applyCliLocale, localeText, resolveCliLocale, translateCli } from "../lib/cli-locale.js";
|
|
17
16
|
import { resolveConfiguredEnvPath, resolveDefaultConfigScope, resolveEnvRoot, resolveEnvRelativePath, } from '../lib/cli-home.js';
|
|
18
|
-
import { defaultDockerContainerPrefix, defaultDockerNetworkName
|
|
19
|
-
import { resolveDockerContainerPrefix, resolveDockerNetworkName
|
|
20
|
-
import { DEFAULT_DOCKER_VERSION, resolveDockerImageRef
|
|
17
|
+
import { defaultDockerContainerPrefix, defaultDockerNetworkName } from '../lib/app-runtime.js';
|
|
18
|
+
import { resolveDockerContainerPrefix, resolveDockerNetworkName } from '../lib/cli-config.js';
|
|
19
|
+
import { DEFAULT_DOCKER_VERSION, resolveDockerImageRef } from "../lib/docker-image.js";
|
|
21
20
|
import { findAvailableTcpPort, validateAvailableTcpPort, validateTcpPort, validateEnvKey, } from "../lib/prompt-validators.js";
|
|
22
|
-
import { validateExternalDbConfig } from "../lib/db-connection-check.js";
|
|
21
|
+
import { validateExternalDbConfig, validateMysqlLowerCaseTableNamesCompatibility } from "../lib/db-connection-check.js";
|
|
23
22
|
import { formatMissingManagedAppEnvMessage } from '../lib/app-runtime.js';
|
|
24
|
-
import { run, runNocoBaseCommand } from '../lib/run-npm.js';
|
|
25
|
-
import { printInfo, printStage, printVerbose, printWarning, setVerboseMode
|
|
23
|
+
import { commandOutput, commandSucceeds, run, runNocoBaseCommand } from '../lib/run-npm.js';
|
|
24
|
+
import { printInfo, printStage, printVerbose, printWarning, setVerboseMode } from '../lib/ui.js';
|
|
26
25
|
import { omitKeys, upperFirst } from "../lib/object-utils.js";
|
|
27
26
|
import { getEnv, setCurrentEnv, upsertEnv } from '../lib/auth-store.js';
|
|
28
27
|
import { buildStoredEnvConfig } from '../lib/env-config.js';
|
|
29
|
-
import { resolveDockerEnvFileArg
|
|
30
|
-
import Download, { defaultDockerRegistryForLang
|
|
28
|
+
import { resolveDockerEnvFileArg } from "../lib/docker-env-file.js";
|
|
29
|
+
import Download, { defaultDockerRegistryForLang } from './download.js';
|
|
31
30
|
import EnvAdd from "./env/add.js";
|
|
32
31
|
const DEFAULT_INSTALL_ENV_NAME = 'local';
|
|
33
32
|
const DEFAULT_INSTALL_LANG = 'en-US';
|
|
@@ -136,6 +135,20 @@ const INSTALL_LANGUAGE_OPTIONS = Object.entries(INSTALL_LANGUAGE_CODES).map(([va
|
|
|
136
135
|
label: `${label} (${value})`,
|
|
137
136
|
}));
|
|
138
137
|
const installText = (key, values) => localeText(`commands.install.${key}`, values);
|
|
138
|
+
function formatDeferredAuthMessage(envName, authType) {
|
|
139
|
+
const normalizedAuthType = String(authType ?? '').trim();
|
|
140
|
+
const nextStep = `Authentication was skipped for env "${envName}". Run \`nb env auth ${envName}\` to finish setup.`;
|
|
141
|
+
if (normalizedAuthType === 'basic') {
|
|
142
|
+
return `${nextStep} You will be prompted for a username and password.`;
|
|
143
|
+
}
|
|
144
|
+
if (normalizedAuthType === 'token') {
|
|
145
|
+
return `${nextStep} You will be prompted for an access token.`;
|
|
146
|
+
}
|
|
147
|
+
if (normalizedAuthType === 'oauth') {
|
|
148
|
+
return `${nextStep} A browser sign-in flow will be started.`;
|
|
149
|
+
}
|
|
150
|
+
return nextStep;
|
|
151
|
+
}
|
|
139
152
|
function argvHasToken(argv, tokens) {
|
|
140
153
|
return tokens.some((t) => argv.includes(t));
|
|
141
154
|
}
|
|
@@ -143,9 +156,7 @@ function isInstallDbDialect(value) {
|
|
|
143
156
|
return INSTALL_DB_DIALECTS.includes(value);
|
|
144
157
|
}
|
|
145
158
|
function downloadVersionPromptValue(version) {
|
|
146
|
-
return version === 'latest' || version === 'beta' || version === 'alpha'
|
|
147
|
-
? version
|
|
148
|
-
: 'other';
|
|
159
|
+
return version === 'latest' || version === 'beta' || version === 'alpha' ? version : 'other';
|
|
149
160
|
}
|
|
150
161
|
function supportsBuiltinDbDialect(value) {
|
|
151
162
|
const dialect = String(value ?? '').trim();
|
|
@@ -160,22 +171,16 @@ function defaultBuiltinDbImageForDialect(value) {
|
|
|
160
171
|
const defaults = resolveCliLocale(process.env.NB_LOCALE) === 'zh-CN'
|
|
161
172
|
? DEFAULT_INSTALL_BUILTIN_DB_IMAGES_ZH_CN
|
|
162
173
|
: DEFAULT_INSTALL_BUILTIN_DB_IMAGES;
|
|
163
|
-
return supportsBuiltinDbDialect(dialect)
|
|
164
|
-
? defaults[dialect]
|
|
165
|
-
: defaults.postgres;
|
|
174
|
+
return supportsBuiltinDbDialect(dialect) ? defaults[dialect] : defaults.postgres;
|
|
166
175
|
}
|
|
167
176
|
function defaultDbDatabaseForDialect(value) {
|
|
168
|
-
return String(value ?? '').trim() === 'kingbase'
|
|
169
|
-
? 'kingbase'
|
|
170
|
-
: DEFAULT_INSTALL_DB_DATABASE;
|
|
177
|
+
return String(value ?? '').trim() === 'kingbase' ? 'kingbase' : DEFAULT_INSTALL_DB_DATABASE;
|
|
171
178
|
}
|
|
172
179
|
function defaultDbHostForBuiltinDb(values) {
|
|
173
|
-
return
|
|
174
|
-
? DEFAULT_INSTALL_BUILTIN_DB_HOST
|
|
175
|
-
: DEFAULT_INSTALL_DB_HOST;
|
|
180
|
+
return values.builtinDb ? DEFAULT_INSTALL_BUILTIN_DB_HOST : DEFAULT_INSTALL_DB_HOST;
|
|
176
181
|
}
|
|
177
182
|
function validateBuiltinDbEnabled(value, values) {
|
|
178
|
-
if (!
|
|
183
|
+
if (!value) {
|
|
179
184
|
return undefined;
|
|
180
185
|
}
|
|
181
186
|
const dialect = String(values.dbDialect ?? 'postgres').trim() || 'postgres';
|
|
@@ -192,7 +197,14 @@ async function validateExternalDbPromptField(value, values) {
|
|
|
192
197
|
if (typeof value === 'string' && value.trim() === '') {
|
|
193
198
|
return undefined;
|
|
194
199
|
}
|
|
195
|
-
|
|
200
|
+
const connectionError = await validateExternalDbConfig(values);
|
|
201
|
+
if (connectionError) {
|
|
202
|
+
return connectionError;
|
|
203
|
+
}
|
|
204
|
+
if (!Object.prototype.hasOwnProperty.call(values, 'dbUnderscored')) {
|
|
205
|
+
return undefined;
|
|
206
|
+
}
|
|
207
|
+
return await validateMysqlLowerCaseTableNamesCompatibility(values);
|
|
196
208
|
}
|
|
197
209
|
function defaultInstallAppRootPath(envName) {
|
|
198
210
|
const name = String(envName ?? DEFAULT_INSTALL_ENV_NAME).trim() || DEFAULT_INSTALL_ENV_NAME;
|
|
@@ -211,53 +223,39 @@ function pickPresetKeys(source, keys) {
|
|
|
211
223
|
}
|
|
212
224
|
return out;
|
|
213
225
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
cwd: options?.cwd,
|
|
218
|
-
env: {
|
|
219
|
-
...process.env,
|
|
220
|
-
...options?.env,
|
|
221
|
-
},
|
|
222
|
-
stdio: 'ignore',
|
|
223
|
-
});
|
|
224
|
-
child.once('error', () => resolve(false));
|
|
225
|
-
child.once('close', (code) => resolve(code === 0));
|
|
226
|
-
});
|
|
226
|
+
function optionalEnvString(value) {
|
|
227
|
+
const text = String(value ?? '').trim();
|
|
228
|
+
return text || undefined;
|
|
227
229
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
}
|
|
258
|
-
reject(new Error(`${command} exited with code ${code}: ${stderr.trim()}`));
|
|
259
|
-
});
|
|
260
|
-
});
|
|
230
|
+
function optionalEnvBoolean(value) {
|
|
231
|
+
if (value === undefined || value === null) {
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
return Boolean(value);
|
|
235
|
+
}
|
|
236
|
+
function pushOptionalEnvArg(args, key, value) {
|
|
237
|
+
if (typeof value === 'string') {
|
|
238
|
+
if (!value) {
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
args.push('-e', `${key}=${value}`);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
if (typeof value === 'boolean') {
|
|
245
|
+
args.push('-e', `${key}=${String(value)}`);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
function setOptionalEnvVar(out, key, value) {
|
|
249
|
+
if (typeof value === 'string') {
|
|
250
|
+
if (!value) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
out[key] = value;
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
if (typeof value === 'boolean') {
|
|
257
|
+
out[key] = String(value);
|
|
258
|
+
}
|
|
261
259
|
}
|
|
262
260
|
export default class Install extends Command {
|
|
263
261
|
ensuredDockerNetworks = new Set();
|
|
@@ -279,7 +277,7 @@ export default class Install extends Command {
|
|
|
279
277
|
'<%= config.bin %> <%= command.id %> --env app1 --root-nickname "Super Admin"',
|
|
280
278
|
'<%= config.bin %> <%= command.id %> --env myenv --app-root-path=./myenv/source/ --storage-path=./myenv/storage/',
|
|
281
279
|
'<%= config.bin %> <%= command.id %> --env dev -y --app-root-path=./dev/source/',
|
|
282
|
-
'<%= config.bin %> <%= command.id %> --env dev -y --
|
|
280
|
+
'<%= config.bin %> <%= command.id %> --env dev -y --skip-download --source git --app-root-path=./dev/source/',
|
|
283
281
|
];
|
|
284
282
|
static flags = {
|
|
285
283
|
yes: Flags.boolean({
|
|
@@ -314,14 +312,24 @@ export default class Install extends Command {
|
|
|
314
312
|
}),
|
|
315
313
|
'auth-type': Flags.string({
|
|
316
314
|
char: 'a',
|
|
317
|
-
description: 'Authentication: token (API key) or oauth (browser login via `nb env auth`)',
|
|
318
|
-
options: ['token', 'oauth'],
|
|
315
|
+
description: 'Authentication: basic (username/password login), token (API key), or oauth (browser login via `nb env auth`)',
|
|
316
|
+
options: ['basic', 'token', 'oauth'],
|
|
319
317
|
}),
|
|
320
318
|
'access-token': Flags.string({
|
|
321
319
|
char: 't',
|
|
322
320
|
aliases: ['token'],
|
|
323
321
|
description: 'API key or access token when using --auth-type token',
|
|
324
322
|
}),
|
|
323
|
+
username: Flags.string({
|
|
324
|
+
description: 'Username when using --auth-type basic',
|
|
325
|
+
}),
|
|
326
|
+
password: Flags.string({
|
|
327
|
+
description: 'Password when using --auth-type basic',
|
|
328
|
+
}),
|
|
329
|
+
'skip-auth': Flags.boolean({
|
|
330
|
+
description: 'Save the env auth mode now and finish authentication later with `nb env auth`',
|
|
331
|
+
default: false,
|
|
332
|
+
}),
|
|
325
333
|
lang: Flags.string({ description: 'Language for the installed NocoBase app', char: 'l', required: false }),
|
|
326
334
|
force: Flags.boolean({
|
|
327
335
|
description: 'Reconfigure an existing env and replace conflicting runtime resources when needed',
|
|
@@ -380,8 +388,19 @@ export default class Install extends Command {
|
|
|
380
388
|
'db-password': Flags.string({
|
|
381
389
|
description: 'Database password for the app',
|
|
382
390
|
}),
|
|
383
|
-
'
|
|
384
|
-
description: '
|
|
391
|
+
'db-schema': Flags.string({
|
|
392
|
+
description: 'Database schema for the app',
|
|
393
|
+
}),
|
|
394
|
+
'db-table-prefix': Flags.string({
|
|
395
|
+
description: 'Database table prefix for the app',
|
|
396
|
+
}),
|
|
397
|
+
'db-underscored': Flags.boolean({
|
|
398
|
+
allowNo: true,
|
|
399
|
+
description: 'Use underscored database naming for the app',
|
|
400
|
+
default: false,
|
|
401
|
+
}),
|
|
402
|
+
'skip-download': Flags.boolean({
|
|
403
|
+
description: 'Skip the download step and reuse an existing local app directory or Docker image',
|
|
385
404
|
default: false,
|
|
386
405
|
}),
|
|
387
406
|
...omitKeys(Download.flags, ['yes']),
|
|
@@ -428,12 +447,6 @@ export default class Install extends Command {
|
|
|
428
447
|
placeholder: installText('prompts.storagePath.placeholder'),
|
|
429
448
|
initialValue: (values) => defaultInstallStoragePath(values.env ?? values.appName),
|
|
430
449
|
},
|
|
431
|
-
fetchSource: {
|
|
432
|
-
type: 'boolean',
|
|
433
|
-
message: installText('prompts.fetchSource.message'),
|
|
434
|
-
initialValue: true,
|
|
435
|
-
yesInitialValue: true,
|
|
436
|
-
},
|
|
437
450
|
};
|
|
438
451
|
static dbPrompts = {
|
|
439
452
|
dbDialect: {
|
|
@@ -461,8 +474,7 @@ export default class Install extends Command {
|
|
|
461
474
|
message: installText('prompts.builtinDbImage.message'),
|
|
462
475
|
placeholder: installText('prompts.builtinDbImage.placeholder'),
|
|
463
476
|
initialValue: (values) => defaultBuiltinDbImageForDialect(values.dbDialect),
|
|
464
|
-
hidden: (values) => !
|
|
465
|
-
|| !supportsBuiltinDbDialect(values.dbDialect),
|
|
477
|
+
hidden: (values) => !values.builtinDb || !supportsBuiltinDbDialect(values.dbDialect),
|
|
466
478
|
required: true,
|
|
467
479
|
},
|
|
468
480
|
dbHost: {
|
|
@@ -482,8 +494,7 @@ export default class Install extends Command {
|
|
|
482
494
|
initialValue: (values) => defaultDbPortForDialect(values.dbDialect),
|
|
483
495
|
required: true,
|
|
484
496
|
validate: Install.validateDbPort,
|
|
485
|
-
hidden: (values) => Boolean(values.builtinDb)
|
|
486
|
-
&& String(values.source ?? '').trim() === 'docker',
|
|
497
|
+
hidden: (values) => Boolean(values.builtinDb) && String(values.source ?? '').trim() === 'docker',
|
|
487
498
|
},
|
|
488
499
|
dbDatabase: {
|
|
489
500
|
type: 'text',
|
|
@@ -508,6 +519,27 @@ export default class Install extends Command {
|
|
|
508
519
|
required: true,
|
|
509
520
|
validate: validateExternalDbPromptField,
|
|
510
521
|
},
|
|
522
|
+
dbSchema: {
|
|
523
|
+
type: 'text',
|
|
524
|
+
message: installText('prompts.dbSchema.message'),
|
|
525
|
+
placeholder: installText('prompts.dbSchema.placeholder'),
|
|
526
|
+
hidden: (values) => String(values.dbDialect ?? '').trim() !== 'postgres',
|
|
527
|
+
},
|
|
528
|
+
dbTablePrefix: {
|
|
529
|
+
type: 'text',
|
|
530
|
+
message: installText('prompts.dbTablePrefix.message'),
|
|
531
|
+
placeholder: installText('prompts.dbTablePrefix.placeholder'),
|
|
532
|
+
},
|
|
533
|
+
dbUnderscored: {
|
|
534
|
+
type: 'boolean',
|
|
535
|
+
message: installText('prompts.dbUnderscored.message'),
|
|
536
|
+
initialValue: false,
|
|
537
|
+
yesInitialValue: false,
|
|
538
|
+
validate: (value, values) => validateExternalDbPromptField(value, {
|
|
539
|
+
...values,
|
|
540
|
+
dbUnderscored: Boolean(value),
|
|
541
|
+
}),
|
|
542
|
+
},
|
|
511
543
|
};
|
|
512
544
|
static rootUserPrompts = {
|
|
513
545
|
rootUsername: {
|
|
@@ -602,9 +634,8 @@ export default class Install extends Command {
|
|
|
602
634
|
* Booleans with defaults are only preset when the user passed the flag on argv (see `download`).
|
|
603
635
|
* Does not include `env` — use {@link buildEnvPresetValuesFromFlags} for {@link Install.envPrompts}.
|
|
604
636
|
*/
|
|
605
|
-
static buildPresetValuesFromFlags(flags) {
|
|
637
|
+
static buildPresetValuesFromFlags(flags, argv = process.argv.slice(2)) {
|
|
606
638
|
const preset = {};
|
|
607
|
-
const argv = process.argv.slice(2);
|
|
608
639
|
const apiBaseUrl = Install.toOptionalPromptString(flags['api-base-url']);
|
|
609
640
|
if (apiBaseUrl) {
|
|
610
641
|
preset.apiBaseUrl = apiBaseUrl;
|
|
@@ -621,9 +652,18 @@ export default class Install extends Command {
|
|
|
621
652
|
preset.authType = authType;
|
|
622
653
|
}
|
|
623
654
|
}
|
|
655
|
+
if (flags['skip-auth']) {
|
|
656
|
+
preset.skipAuth = true;
|
|
657
|
+
}
|
|
624
658
|
if (flags['access-token'] !== undefined || flags.token !== undefined) {
|
|
625
659
|
preset.accessToken = String(flags['access-token'] ?? flags.token ?? '');
|
|
626
660
|
}
|
|
661
|
+
if (flags.username !== undefined) {
|
|
662
|
+
preset.username = String(flags.username ?? '').trim();
|
|
663
|
+
}
|
|
664
|
+
if (flags.password !== undefined) {
|
|
665
|
+
preset.password = String(flags.password ?? '');
|
|
666
|
+
}
|
|
627
667
|
if (flags.lang !== undefined) {
|
|
628
668
|
const v = String(flags.lang).trim();
|
|
629
669
|
if (v) {
|
|
@@ -663,8 +703,15 @@ export default class Install extends Command {
|
|
|
663
703
|
if (flags['root-nickname'] !== undefined) {
|
|
664
704
|
preset.rootNickname = String(flags['root-nickname'] ?? '').trim();
|
|
665
705
|
}
|
|
666
|
-
if (argvHasToken(argv, ['--
|
|
667
|
-
preset.
|
|
706
|
+
if (argvHasToken(argv, ['--skip-download'])) {
|
|
707
|
+
preset.skipDownload = flags['skip-download'];
|
|
708
|
+
if (flags['skip-download']) {
|
|
709
|
+
preset.dockerSave = false;
|
|
710
|
+
preset.replace = false;
|
|
711
|
+
preset.devDependencies = false;
|
|
712
|
+
preset.build = false;
|
|
713
|
+
preset.buildDts = false;
|
|
714
|
+
}
|
|
668
715
|
}
|
|
669
716
|
if (argvHasToken(argv, ['--builtin-db', '--no-builtin-db'])) {
|
|
670
717
|
preset.builtinDb = flags['builtin-db'];
|
|
@@ -709,20 +756,34 @@ export default class Install extends Command {
|
|
|
709
756
|
if (flags['db-password'] !== undefined) {
|
|
710
757
|
preset.dbPassword = String(flags['db-password'] ?? '');
|
|
711
758
|
}
|
|
759
|
+
if (flags['db-schema'] !== undefined) {
|
|
760
|
+
const v = String(flags['db-schema'] ?? '').trim();
|
|
761
|
+
if (v) {
|
|
762
|
+
preset.dbSchema = v;
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
if (flags['db-table-prefix'] !== undefined) {
|
|
766
|
+
const v = String(flags['db-table-prefix'] ?? '').trim();
|
|
767
|
+
if (v) {
|
|
768
|
+
preset.dbTablePrefix = v;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
if (argvHasToken(argv, ['--db-underscored', '--no-db-underscored'])) {
|
|
772
|
+
preset.dbUnderscored = flags['db-underscored'];
|
|
773
|
+
}
|
|
712
774
|
return preset;
|
|
713
775
|
}
|
|
714
|
-
static buildAppPresetValuesFromFlags(flags) {
|
|
715
|
-
return pickPresetKeys(Install.buildPresetValuesFromFlags(flags), [
|
|
776
|
+
static buildAppPresetValuesFromFlags(flags, argv = process.argv.slice(2)) {
|
|
777
|
+
return pickPresetKeys(Install.buildPresetValuesFromFlags(flags, argv), [
|
|
716
778
|
'lang',
|
|
717
779
|
'force',
|
|
718
780
|
'appRootPath',
|
|
719
781
|
'appPort',
|
|
720
782
|
'storagePath',
|
|
721
|
-
'fetchSource',
|
|
722
783
|
]);
|
|
723
784
|
}
|
|
724
|
-
static buildDbPresetValuesFromFlags(flags) {
|
|
725
|
-
return pickPresetKeys(Install.buildPresetValuesFromFlags(flags), [
|
|
785
|
+
static buildDbPresetValuesFromFlags(flags, argv = process.argv.slice(2)) {
|
|
786
|
+
return pickPresetKeys(Install.buildPresetValuesFromFlags(flags, argv), [
|
|
726
787
|
'builtinDb',
|
|
727
788
|
'dbDialect',
|
|
728
789
|
'builtinDbImage',
|
|
@@ -731,23 +792,49 @@ export default class Install extends Command {
|
|
|
731
792
|
'dbDatabase',
|
|
732
793
|
'dbUser',
|
|
733
794
|
'dbPassword',
|
|
795
|
+
'dbSchema',
|
|
796
|
+
'dbTablePrefix',
|
|
797
|
+
'dbUnderscored',
|
|
734
798
|
]);
|
|
735
799
|
}
|
|
736
|
-
static buildRootPresetValuesFromFlags(flags) {
|
|
737
|
-
return pickPresetKeys(Install.buildPresetValuesFromFlags(flags), [
|
|
800
|
+
static buildRootPresetValuesFromFlags(flags, argv = process.argv.slice(2)) {
|
|
801
|
+
return pickPresetKeys(Install.buildPresetValuesFromFlags(flags, argv), [
|
|
738
802
|
'rootUsername',
|
|
739
803
|
'rootEmail',
|
|
740
804
|
'rootPassword',
|
|
741
805
|
'rootNickname',
|
|
742
806
|
]);
|
|
743
807
|
}
|
|
744
|
-
static buildEnvAddPresetValuesFromFlags(flags) {
|
|
745
|
-
return pickPresetKeys(Install.buildPresetValuesFromFlags(flags), [
|
|
808
|
+
static buildEnvAddPresetValuesFromFlags(flags, argv = process.argv.slice(2)) {
|
|
809
|
+
return pickPresetKeys(Install.buildPresetValuesFromFlags(flags, argv), [
|
|
746
810
|
'apiBaseUrl',
|
|
747
811
|
'authType',
|
|
812
|
+
'username',
|
|
813
|
+
'password',
|
|
748
814
|
'accessToken',
|
|
749
815
|
]);
|
|
750
816
|
}
|
|
817
|
+
buildEnvAddPromptsForInstall(parsed) {
|
|
818
|
+
const apiBaseUrlPrompt = {
|
|
819
|
+
...EnvAdd.prompts.apiBaseUrl,
|
|
820
|
+
validate: undefined,
|
|
821
|
+
};
|
|
822
|
+
const prompts = {
|
|
823
|
+
...EnvAdd.prompts,
|
|
824
|
+
apiBaseUrl: apiBaseUrlPrompt,
|
|
825
|
+
};
|
|
826
|
+
if (!parsed['skip-auth']) {
|
|
827
|
+
return prompts;
|
|
828
|
+
}
|
|
829
|
+
const accessTokenPrompt = {
|
|
830
|
+
...EnvAdd.prompts.accessToken,
|
|
831
|
+
hidden: () => true,
|
|
832
|
+
};
|
|
833
|
+
return {
|
|
834
|
+
...prompts,
|
|
835
|
+
accessToken: accessTokenPrompt,
|
|
836
|
+
};
|
|
837
|
+
}
|
|
751
838
|
static toOptionalPromptString(value) {
|
|
752
839
|
if (value === undefined || value === null) {
|
|
753
840
|
return undefined;
|
|
@@ -813,9 +900,13 @@ export default class Install extends Command {
|
|
|
813
900
|
if (validationError) {
|
|
814
901
|
throw new Error(validationError);
|
|
815
902
|
}
|
|
903
|
+
const compatibilityError = await validateMysqlLowerCaseTableNamesCompatibility(dbResults);
|
|
904
|
+
if (compatibilityError) {
|
|
905
|
+
throw new Error(compatibilityError);
|
|
906
|
+
}
|
|
816
907
|
}
|
|
817
908
|
static async readResumePortValidationContext(values) {
|
|
818
|
-
if (!
|
|
909
|
+
if (!values.resume) {
|
|
819
910
|
return undefined;
|
|
820
911
|
}
|
|
821
912
|
const envName = Install.toOptionalPromptString(values.env);
|
|
@@ -846,8 +937,7 @@ export default class Install extends Command {
|
|
|
846
937
|
}
|
|
847
938
|
static async isResumeManagedPortReuse(params) {
|
|
848
939
|
if (params.target === 'app') {
|
|
849
|
-
if ((params.context.source === 'npm' || params.context.source === 'git')
|
|
850
|
-
&& params.context.appRootPath) {
|
|
940
|
+
if ((params.context.source === 'npm' || params.context.source === 'git') && params.context.appRootPath) {
|
|
851
941
|
return await Install.isLocalPm2ProcessUsingPort(params.context.appRootPath, params.port);
|
|
852
942
|
}
|
|
853
943
|
const containerName = Install.buildDockerAppContainerName(params.context.envName, params.context.dockerContainerPrefix);
|
|
@@ -863,19 +953,13 @@ export default class Install extends Command {
|
|
|
863
953
|
if (!containerName || !port) {
|
|
864
954
|
return false;
|
|
865
955
|
}
|
|
866
|
-
const exists = await commandSucceeds('docker', [
|
|
867
|
-
'container',
|
|
868
|
-
'inspect',
|
|
869
|
-
containerName,
|
|
870
|
-
]);
|
|
956
|
+
const exists = await commandSucceeds('docker', ['container', 'inspect', containerName]);
|
|
871
957
|
if (!exists) {
|
|
872
958
|
return false;
|
|
873
959
|
}
|
|
874
960
|
try {
|
|
875
961
|
const output = await commandOutput('docker', ['port', containerName]);
|
|
876
|
-
return output
|
|
877
|
-
.split(/\r?\n/)
|
|
878
|
-
.some((line) => line.includes(`:${port}`));
|
|
962
|
+
return output.split(/\r?\n/).some((line) => line.includes(`:${port}`));
|
|
879
963
|
}
|
|
880
964
|
catch {
|
|
881
965
|
return false;
|
|
@@ -917,39 +1001,34 @@ export default class Install extends Command {
|
|
|
917
1001
|
const dbDatabase = Install.toOptionalPromptString(config.dbDatabase);
|
|
918
1002
|
const dbUser = Install.toOptionalPromptString(config.dbUser);
|
|
919
1003
|
const dbPassword = Install.toOptionalPromptString(config.dbPassword);
|
|
1004
|
+
const dbSchema = Install.toOptionalPromptString(config.dbSchema);
|
|
1005
|
+
const dbTablePrefix = Install.toOptionalPromptString(config.dbTablePrefix);
|
|
1006
|
+
const dbUnderscored = typeof config.dbUnderscored === 'boolean' ? config.dbUnderscored : undefined;
|
|
920
1007
|
const builtinDbImage = Install.toOptionalPromptString(config.builtinDbImage);
|
|
921
1008
|
const rootUsername = Install.toOptionalPromptString(config.rootUsername);
|
|
922
1009
|
const rootEmail = Install.toOptionalPromptString(config.rootEmail);
|
|
923
1010
|
const rootPassword = Install.toOptionalPromptString(config.rootPassword);
|
|
924
1011
|
const rootNickname = Install.toOptionalPromptString(config.rootNickname);
|
|
925
1012
|
const auth = config.auth;
|
|
1013
|
+
const savedAuthType = Install.toOptionalPromptString(config.authType) ?? Install.toOptionalPromptString(auth?.type);
|
|
926
1014
|
const appPreset = {
|
|
927
1015
|
...(appRootPath ? { appRootPath } : {}),
|
|
928
1016
|
...(appPort ? { appPort } : {}),
|
|
929
1017
|
...(storagePath ? { storagePath } : {}),
|
|
930
|
-
...(source
|
|
931
|
-
? { fetchSource: true }
|
|
932
|
-
: appRootPath
|
|
933
|
-
? { fetchSource: false }
|
|
934
|
-
: {}),
|
|
935
1018
|
};
|
|
936
1019
|
const downloadPreset = {
|
|
937
1020
|
...(source ? { source } : {}),
|
|
938
1021
|
...(downloadVersion
|
|
939
1022
|
? {
|
|
940
1023
|
version: downloadVersionPromptValue(downloadVersion),
|
|
941
|
-
...(downloadVersionPromptValue(downloadVersion) === 'other'
|
|
942
|
-
? { otherVersion: downloadVersion }
|
|
943
|
-
: {}),
|
|
1024
|
+
...(downloadVersionPromptValue(downloadVersion) === 'other' ? { otherVersion: downloadVersion } : {}),
|
|
944
1025
|
}
|
|
945
1026
|
: {}),
|
|
946
1027
|
...(dockerRegistry ? { dockerRegistry } : {}),
|
|
947
1028
|
...(dockerPlatform ? { dockerPlatform } : {}),
|
|
948
1029
|
...(gitUrl ? { gitUrl } : {}),
|
|
949
1030
|
...(npmRegistry ? { npmRegistry } : {}),
|
|
950
|
-
...(typeof config.devDependencies === 'boolean'
|
|
951
|
-
? { devDependencies: config.devDependencies }
|
|
952
|
-
: {}),
|
|
1031
|
+
...(typeof config.devDependencies === 'boolean' ? { devDependencies: config.devDependencies } : {}),
|
|
953
1032
|
...(typeof config.build === 'boolean' ? { build: config.build } : {}),
|
|
954
1033
|
...(typeof config.buildDts === 'boolean' ? { buildDts: config.buildDts } : {}),
|
|
955
1034
|
};
|
|
@@ -962,6 +1041,9 @@ export default class Install extends Command {
|
|
|
962
1041
|
...(dbDatabase ? { dbDatabase } : {}),
|
|
963
1042
|
...(dbUser ? { dbUser } : {}),
|
|
964
1043
|
...(dbPassword ? { dbPassword } : {}),
|
|
1044
|
+
...(dbSchema ? { dbSchema } : {}),
|
|
1045
|
+
...(dbTablePrefix ? { dbTablePrefix } : {}),
|
|
1046
|
+
...(dbUnderscored !== undefined ? { dbUnderscored } : {}),
|
|
965
1047
|
};
|
|
966
1048
|
const rootPreset = {
|
|
967
1049
|
...(rootUsername ? { rootUsername } : {}),
|
|
@@ -970,13 +1052,20 @@ export default class Install extends Command {
|
|
|
970
1052
|
...(rootNickname ? { rootNickname } : {}),
|
|
971
1053
|
};
|
|
972
1054
|
const envAddPreset = {};
|
|
973
|
-
if (
|
|
1055
|
+
if (savedAuthType === 'token') {
|
|
974
1056
|
envAddPreset.authType = 'token';
|
|
975
1057
|
if (Install.toOptionalPromptString(auth.accessToken)) {
|
|
976
1058
|
envAddPreset.accessToken = String(auth.accessToken);
|
|
977
1059
|
}
|
|
978
1060
|
}
|
|
979
|
-
else if (
|
|
1061
|
+
else if (savedAuthType === 'basic') {
|
|
1062
|
+
envAddPreset.authType = 'basic';
|
|
1063
|
+
const authUsername = Install.toOptionalPromptString(config.authUsername) ?? rootUsername;
|
|
1064
|
+
if (authUsername) {
|
|
1065
|
+
envAddPreset.username = authUsername;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
else if (savedAuthType === 'oauth') {
|
|
980
1069
|
envAddPreset.authType = 'oauth';
|
|
981
1070
|
}
|
|
982
1071
|
return {
|
|
@@ -1060,8 +1149,7 @@ export default class Install extends Command {
|
|
|
1060
1149
|
}
|
|
1061
1150
|
static shouldPublishBuiltinDbPortForValues(values) {
|
|
1062
1151
|
const builtinDb = values.builtinDb === undefined ? true : Boolean(values.builtinDb);
|
|
1063
|
-
return builtinDb
|
|
1064
|
-
&& Install.shouldPublishBuiltinDbPort(values.source);
|
|
1152
|
+
return builtinDb && Install.shouldPublishBuiltinDbPort(values.source);
|
|
1065
1153
|
}
|
|
1066
1154
|
static async buildDbPromptInitialValues(params) {
|
|
1067
1155
|
if (params.flags['db-port'] !== undefined) {
|
|
@@ -1117,9 +1205,8 @@ export default class Install extends Command {
|
|
|
1117
1205
|
* Resolve the effective preset `values` for the embedded download step.
|
|
1118
1206
|
* Explicit download flags win; otherwise `-y` falls back to the docker + alpha quickstart path.
|
|
1119
1207
|
*/
|
|
1120
|
-
static buildDownloadPresetValuesForInstall(flags, appResults, envName, yes) {
|
|
1208
|
+
static buildDownloadPresetValuesForInstall(flags, appResults, envName, yes, argv = process.argv.slice(2)) {
|
|
1121
1209
|
const preset = {};
|
|
1122
|
-
const argv = process.argv.slice(2);
|
|
1123
1210
|
const appRoot = String(appResults.appRootPath ?? '').trim() || defaultInstallAppRootPath(envName);
|
|
1124
1211
|
const lang = String(appResults.lang ?? DEFAULT_INSTALL_LANG).trim() || DEFAULT_INSTALL_LANG;
|
|
1125
1212
|
preset.lang = lang;
|
|
@@ -1158,8 +1245,7 @@ export default class Install extends Command {
|
|
|
1158
1245
|
}
|
|
1159
1246
|
}
|
|
1160
1247
|
if (flags['npm-registry'] !== undefined) {
|
|
1161
|
-
preset.npmRegistry =
|
|
1162
|
-
typeof flags['npm-registry'] === 'string' ? flags['npm-registry'] : '';
|
|
1248
|
+
preset.npmRegistry = typeof flags['npm-registry'] === 'string' ? flags['npm-registry'] : '';
|
|
1163
1249
|
}
|
|
1164
1250
|
if (flags.resume && !argvHasToken(argv, ['--replace', '-r'])) {
|
|
1165
1251
|
preset.replace = true;
|
|
@@ -1203,15 +1289,11 @@ export default class Install extends Command {
|
|
|
1203
1289
|
}
|
|
1204
1290
|
static buildBuiltinDbContainerPrefix(containerPrefix) {
|
|
1205
1291
|
const storedName = String(containerPrefix ?? '').trim();
|
|
1206
|
-
return storedName
|
|
1207
|
-
? Install.sanitizeDockerResourceName(storedName)
|
|
1208
|
-
: Install.defaultDockerContainerPrefix();
|
|
1292
|
+
return storedName ? Install.sanitizeDockerResourceName(storedName) : Install.defaultDockerContainerPrefix();
|
|
1209
1293
|
}
|
|
1210
1294
|
static buildManagedDockerNetworkName(networkName) {
|
|
1211
1295
|
const storedName = String(networkName ?? '').trim();
|
|
1212
|
-
return storedName
|
|
1213
|
-
? Install.sanitizeDockerResourceName(storedName)
|
|
1214
|
-
: Install.defaultDockerNetworkName();
|
|
1296
|
+
return storedName ? Install.sanitizeDockerResourceName(storedName) : Install.defaultDockerNetworkName();
|
|
1215
1297
|
}
|
|
1216
1298
|
static buildBuiltinDbNetworkName(envName, networkName) {
|
|
1217
1299
|
void envName;
|
|
@@ -1244,25 +1326,19 @@ export default class Install extends Command {
|
|
|
1244
1326
|
}
|
|
1245
1327
|
static buildBuiltinDbPlan(params) {
|
|
1246
1328
|
const dbDialect = String(params.dbDialect ?? 'postgres').trim() || 'postgres';
|
|
1247
|
-
const dbPort = String(params.dbPort ?? defaultDbPortForDialect(dbDialect)).trim()
|
|
1248
|
-
|| defaultDbPortForDialect(dbDialect);
|
|
1329
|
+
const dbPort = String(params.dbPort ?? defaultDbPortForDialect(dbDialect)).trim() || defaultDbPortForDialect(dbDialect);
|
|
1249
1330
|
const defaultDbDatabase = defaultDbDatabaseForDialect(dbDialect);
|
|
1250
1331
|
const networkName = Install.buildBuiltinDbNetworkName(params.envName, params.dockerNetworkName ?? params.workspaceName);
|
|
1251
1332
|
const containerName = Install.buildBuiltinDbContainerName(params.envName, dbDialect, params.dockerContainerPrefix ?? params.workspaceName);
|
|
1252
1333
|
const dbHostInput = String(params.dbHost ?? '').trim();
|
|
1253
1334
|
const dbHost = Install.shouldPublishBuiltinDbPort(params.source)
|
|
1254
|
-
?
|
|
1255
|
-
&& dbHostInput !== DEFAULT_INSTALL_BUILTIN_DB_HOST
|
|
1256
|
-
&& dbHostInput !== containerName
|
|
1335
|
+
? dbHostInput && dbHostInput !== DEFAULT_INSTALL_BUILTIN_DB_HOST && dbHostInput !== containerName
|
|
1257
1336
|
? dbHostInput
|
|
1258
|
-
: DEFAULT_INSTALL_DB_HOST
|
|
1259
|
-
:
|
|
1260
|
-
&& dbHostInput !== DEFAULT_INSTALL_DB_HOST
|
|
1261
|
-
&& dbHostInput !== 'localhost'
|
|
1337
|
+
: DEFAULT_INSTALL_DB_HOST
|
|
1338
|
+
: dbHostInput && dbHostInput !== DEFAULT_INSTALL_DB_HOST && dbHostInput !== 'localhost'
|
|
1262
1339
|
? dbHostInput
|
|
1263
|
-
: containerName
|
|
1264
|
-
const storagePath = resolveConfiguredEnvPath(params.storagePath)
|
|
1265
|
-
?? resolveEnvRelativePath(defaultInstallStoragePath(params.envName));
|
|
1340
|
+
: containerName;
|
|
1341
|
+
const storagePath = resolveConfiguredEnvPath(params.storagePath) ?? resolveEnvRelativePath(defaultInstallStoragePath(params.envName));
|
|
1266
1342
|
if (dbDialect === 'postgres') {
|
|
1267
1343
|
const image = String(params.builtinDbImage ?? '').trim() || defaultBuiltinDbImageForDialect(dbDialect);
|
|
1268
1344
|
const dataDir = path.resolve(storagePath, 'db', 'postgres');
|
|
@@ -1293,12 +1369,9 @@ export default class Install extends Command {
|
|
|
1293
1369
|
dbDialect,
|
|
1294
1370
|
dbHost,
|
|
1295
1371
|
dbPort,
|
|
1296
|
-
dbDatabase: String(params.dbDatabase ?? defaultDbDatabase).trim()
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|| DEFAULT_INSTALL_DB_USER,
|
|
1300
|
-
dbPassword: String(params.dbPassword ?? DEFAULT_INSTALL_DB_PASSWORD)
|
|
1301
|
-
|| DEFAULT_INSTALL_DB_PASSWORD,
|
|
1372
|
+
dbDatabase: String(params.dbDatabase ?? defaultDbDatabase).trim() || defaultDbDatabase,
|
|
1373
|
+
dbUser: String(params.dbUser ?? DEFAULT_INSTALL_DB_USER).trim() || DEFAULT_INSTALL_DB_USER,
|
|
1374
|
+
dbPassword: String(params.dbPassword ?? DEFAULT_INSTALL_DB_PASSWORD) || DEFAULT_INSTALL_DB_PASSWORD,
|
|
1302
1375
|
networkName,
|
|
1303
1376
|
containerName,
|
|
1304
1377
|
dataDir,
|
|
@@ -1484,11 +1557,7 @@ export default class Install extends Command {
|
|
|
1484
1557
|
}
|
|
1485
1558
|
}
|
|
1486
1559
|
async dockerContainerExists(name) {
|
|
1487
|
-
return await commandSucceeds('docker', [
|
|
1488
|
-
'container',
|
|
1489
|
-
'inspect',
|
|
1490
|
-
name,
|
|
1491
|
-
]);
|
|
1560
|
+
return await commandSucceeds('docker', ['container', 'inspect', name]);
|
|
1492
1561
|
}
|
|
1493
1562
|
async removeDockerContainer(name) {
|
|
1494
1563
|
await run('docker', ['rm', '-f', name], {
|
|
@@ -1538,8 +1607,7 @@ export default class Install extends Command {
|
|
|
1538
1607
|
});
|
|
1539
1608
|
}
|
|
1540
1609
|
async startBuiltinDb(params) {
|
|
1541
|
-
const storagePath = String(params.appResults.storagePath ?? '').trim()
|
|
1542
|
-
|| defaultInstallStoragePath(params.envName);
|
|
1610
|
+
const storagePath = String(params.appResults.storagePath ?? '').trim() || defaultInstallStoragePath(params.envName);
|
|
1543
1611
|
const plan = Install.buildBuiltinDbPlan({
|
|
1544
1612
|
envName: params.envName,
|
|
1545
1613
|
workspaceName: params.workspaceName,
|
|
@@ -1577,25 +1645,25 @@ export default class Install extends Command {
|
|
|
1577
1645
|
return plan;
|
|
1578
1646
|
}
|
|
1579
1647
|
static async buildDockerAppPlan(params) {
|
|
1580
|
-
const dockerRegistry = String(downloadResultsValue(params.downloadResults, 'dockerRegistry') ?? '').trim()
|
|
1581
|
-
|
|
1648
|
+
const dockerRegistry = String(downloadResultsValue(params.downloadResults, 'dockerRegistry') ?? '').trim() ||
|
|
1649
|
+
defaultDockerRegistryForLang(process.env.NB_LOCALE);
|
|
1582
1650
|
const version = String(downloadResultsValue(params.downloadResults, 'version') ?? '').trim() || DEFAULT_DOCKER_VERSION;
|
|
1583
1651
|
const imageRef = resolveDockerImageRef(dockerRegistry, version, {
|
|
1584
1652
|
defaultRegistry: defaultDockerRegistryForLang(process.env.NB_LOCALE),
|
|
1585
1653
|
defaultVersion: DEFAULT_DOCKER_VERSION,
|
|
1586
1654
|
});
|
|
1587
1655
|
const appPort = String(params.appResults.appPort ?? DEFAULT_INSTALL_APP_PORT).trim() || DEFAULT_INSTALL_APP_PORT;
|
|
1588
|
-
const storagePath = resolveConfiguredEnvPath(String(params.appResults.storagePath ?? '').trim()
|
|
1589
|
-
|| defaultInstallStoragePath(params.envName))
|
|
1590
|
-
?? resolveEnvRelativePath(defaultInstallStoragePath(params.envName));
|
|
1656
|
+
const storagePath = resolveConfiguredEnvPath(String(params.appResults.storagePath ?? '').trim() || defaultInstallStoragePath(params.envName)) ?? resolveEnvRelativePath(defaultInstallStoragePath(params.envName));
|
|
1591
1657
|
const dbDialect = String(params.dbResults.dbDialect ?? 'postgres').trim() || 'postgres';
|
|
1592
1658
|
const dbHost = String(params.dbResults.dbHost ?? DEFAULT_INSTALL_DB_HOST).trim() || DEFAULT_INSTALL_DB_HOST;
|
|
1593
|
-
const dbPort = String(params.dbResults.dbPort ?? defaultDbPortForDialect(dbDialect)).trim()
|
|
1594
|
-
|
|
1595
|
-
const dbDatabase = String(params.dbResults.dbDatabase ?? DEFAULT_INSTALL_DB_DATABASE).trim()
|
|
1596
|
-
|| DEFAULT_INSTALL_DB_DATABASE;
|
|
1659
|
+
const dbPort = String(params.dbResults.dbPort ?? defaultDbPortForDialect(dbDialect)).trim() ||
|
|
1660
|
+
defaultDbPortForDialect(dbDialect);
|
|
1661
|
+
const dbDatabase = String(params.dbResults.dbDatabase ?? DEFAULT_INSTALL_DB_DATABASE).trim() || DEFAULT_INSTALL_DB_DATABASE;
|
|
1597
1662
|
const dbUser = String(params.dbResults.dbUser ?? DEFAULT_INSTALL_DB_USER).trim() || DEFAULT_INSTALL_DB_USER;
|
|
1598
1663
|
const dbPassword = String(params.dbResults.dbPassword ?? DEFAULT_INSTALL_DB_PASSWORD) || DEFAULT_INSTALL_DB_PASSWORD;
|
|
1664
|
+
const dbSchema = optionalEnvString(params.dbResults.dbSchema);
|
|
1665
|
+
const dbTablePrefix = optionalEnvString(params.dbResults.dbTablePrefix);
|
|
1666
|
+
const dbUnderscored = optionalEnvBoolean(params.dbResults.dbUnderscored);
|
|
1599
1667
|
const appKey = crypto.randomBytes(32).toString('hex');
|
|
1600
1668
|
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';
|
|
1601
1669
|
const containerName = Install.buildDockerAppContainerName(params.envName, params.dockerContainerPrefix ?? params.workspaceName);
|
|
@@ -1623,7 +1691,11 @@ export default class Install extends Command {
|
|
|
1623
1691
|
for (const [key, value] of Object.entries(initEnvVars)) {
|
|
1624
1692
|
args.push('-e', `${key}=${value}`);
|
|
1625
1693
|
}
|
|
1626
|
-
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
|
|
1694
|
+
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`);
|
|
1695
|
+
pushOptionalEnvArg(args, 'DB_SCHEMA', dbSchema);
|
|
1696
|
+
pushOptionalEnvArg(args, 'DB_TABLE_PREFIX', dbTablePrefix);
|
|
1697
|
+
pushOptionalEnvArg(args, 'DB_UNDERSCORED', dbUnderscored);
|
|
1698
|
+
args.push(imageRef);
|
|
1627
1699
|
return {
|
|
1628
1700
|
source: 'docker',
|
|
1629
1701
|
networkName: params.networkName,
|
|
@@ -1651,8 +1723,8 @@ export default class Install extends Command {
|
|
|
1651
1723
|
return 'created';
|
|
1652
1724
|
}
|
|
1653
1725
|
async installDockerApp(params) {
|
|
1654
|
-
const networkName = params.builtinDbPlan?.networkName
|
|
1655
|
-
|
|
1726
|
+
const networkName = params.builtinDbPlan?.networkName ??
|
|
1727
|
+
Install.buildBuiltinDbNetworkName(params.envName, params.dockerNetworkName ?? params.workspaceName);
|
|
1656
1728
|
await this.ensureDockerNetwork(networkName);
|
|
1657
1729
|
const plan = await Install.buildDockerAppPlan({
|
|
1658
1730
|
envName: params.envName,
|
|
@@ -1699,26 +1771,26 @@ export default class Install extends Command {
|
|
|
1699
1771
|
Install.pushDownloadArgIfValue(argv, '--source', results.source);
|
|
1700
1772
|
Install.pushDownloadArgIfValue(argv, '--version', downloadResultsValue(results, 'version'));
|
|
1701
1773
|
Install.pushDownloadArgIfValue(argv, '--output-dir', source === 'npm' || source === 'git'
|
|
1702
|
-
?
|
|
1703
|
-
|
|
1774
|
+
? resolveConfiguredEnvPath(results.outputDir) ??
|
|
1775
|
+
resolveConfiguredEnvPath(String(results.outputDir ?? '').trim() || defaultInstallAppRootPath(results.env))
|
|
1704
1776
|
: results.outputDir);
|
|
1705
1777
|
Install.pushDownloadArgIfValue(argv, '--git-url', results.gitUrl);
|
|
1706
1778
|
Install.pushDownloadArgIfValue(argv, '--docker-registry', results.dockerRegistry);
|
|
1707
1779
|
Install.pushDownloadArgIfValue(argv, '--docker-platform', results.dockerPlatform);
|
|
1708
1780
|
Install.pushDownloadArgIfValue(argv, '--npm-registry', results.npmRegistry);
|
|
1709
|
-
if (
|
|
1781
|
+
if (results.replace) {
|
|
1710
1782
|
argv.push('--replace');
|
|
1711
1783
|
}
|
|
1712
|
-
if (
|
|
1784
|
+
if (results.devDependencies) {
|
|
1713
1785
|
argv.push('--dev-dependencies');
|
|
1714
1786
|
}
|
|
1715
|
-
if (
|
|
1787
|
+
if (results.dockerSave) {
|
|
1716
1788
|
argv.push('--docker-save');
|
|
1717
1789
|
}
|
|
1718
|
-
if (results.build !== undefined && !
|
|
1790
|
+
if (results.build !== undefined && !results.build) {
|
|
1719
1791
|
argv.push('--no-build');
|
|
1720
1792
|
}
|
|
1721
|
-
if (
|
|
1793
|
+
if (results.buildDts) {
|
|
1722
1794
|
argv.push('--build-dts');
|
|
1723
1795
|
}
|
|
1724
1796
|
return argv;
|
|
@@ -1728,15 +1800,26 @@ export default class Install extends Command {
|
|
|
1728
1800
|
if (projectRoot) {
|
|
1729
1801
|
return projectRoot;
|
|
1730
1802
|
}
|
|
1731
|
-
const outputDir = String(params.downloadResults.outputDir ?? '').trim()
|
|
1732
|
-
|
|
1733
|
-
|
|
1803
|
+
const outputDir = String(params.downloadResults.outputDir ?? '').trim() ||
|
|
1804
|
+
String(params.appResults.appRootPath ?? '').trim() ||
|
|
1805
|
+
defaultInstallAppRootPath(params.envName);
|
|
1734
1806
|
return resolveConfiguredEnvPath(outputDir) ?? resolveEnvRelativePath(defaultInstallAppRootPath(params.envName));
|
|
1735
1807
|
}
|
|
1736
1808
|
static resolveLocalProjectConfigPath(params) {
|
|
1737
|
-
return (String(params.downloadResults.outputDir ?? '').trim()
|
|
1738
|
-
|
|
1739
|
-
|
|
1809
|
+
return (String(params.downloadResults.outputDir ?? '').trim() ||
|
|
1810
|
+
String(params.appResults.appRootPath ?? '').trim() ||
|
|
1811
|
+
defaultInstallAppRootPath(params.envName));
|
|
1812
|
+
}
|
|
1813
|
+
static buildSkipDownloadValues(envName, appResults) {
|
|
1814
|
+
const appRoot = String(appResults.appRootPath ?? '').trim() || defaultInstallAppRootPath(envName);
|
|
1815
|
+
return {
|
|
1816
|
+
outputDir: appRoot,
|
|
1817
|
+
replace: false,
|
|
1818
|
+
dockerSave: false,
|
|
1819
|
+
devDependencies: false,
|
|
1820
|
+
build: false,
|
|
1821
|
+
buildDts: false,
|
|
1822
|
+
};
|
|
1740
1823
|
}
|
|
1741
1824
|
commandStdio(verbose) {
|
|
1742
1825
|
return verbose ? 'inherit' : 'ignore';
|
|
@@ -1746,7 +1829,41 @@ export default class Install extends Command {
|
|
|
1746
1829
|
verbose: params.verbose,
|
|
1747
1830
|
compactLog: true,
|
|
1748
1831
|
});
|
|
1749
|
-
return await this.config.runCommand('source:download', argv);
|
|
1832
|
+
return (await this.config.runCommand('source:download', argv));
|
|
1833
|
+
}
|
|
1834
|
+
async ensureSkippedDownloadInputsReady(params) {
|
|
1835
|
+
if (params.source === 'docker') {
|
|
1836
|
+
const dockerRegistry = String(downloadResultsValue(params.downloadResults, 'dockerRegistry') ?? '').trim() ||
|
|
1837
|
+
defaultDockerRegistryForLang(process.env.NB_LOCALE);
|
|
1838
|
+
const version = String(downloadResultsValue(params.downloadResults, 'version') ?? '').trim() || DEFAULT_DOCKER_VERSION;
|
|
1839
|
+
const imageRef = resolveDockerImageRef(dockerRegistry, version, {
|
|
1840
|
+
defaultRegistry: defaultDockerRegistryForLang(process.env.NB_LOCALE),
|
|
1841
|
+
defaultVersion: DEFAULT_DOCKER_VERSION,
|
|
1842
|
+
});
|
|
1843
|
+
const imageExists = await commandSucceeds('docker', ['image', 'inspect', imageRef]);
|
|
1844
|
+
if (!imageExists) {
|
|
1845
|
+
throw new Error(translateCli('commands.install.messages.skipDownloadDockerImageMissing', {
|
|
1846
|
+
imageRef,
|
|
1847
|
+
}));
|
|
1848
|
+
}
|
|
1849
|
+
return;
|
|
1850
|
+
}
|
|
1851
|
+
if (params.source === 'npm' || params.source === 'git') {
|
|
1852
|
+
const projectRoot = Install.resolveLocalProjectRoot({
|
|
1853
|
+
envName: params.envName,
|
|
1854
|
+
appResults: params.appResults,
|
|
1855
|
+
downloadResults: params.downloadResults,
|
|
1856
|
+
});
|
|
1857
|
+
try {
|
|
1858
|
+
await access(projectRoot);
|
|
1859
|
+
await access(path.join(projectRoot, 'package.json'));
|
|
1860
|
+
}
|
|
1861
|
+
catch {
|
|
1862
|
+
throw new Error(translateCli('commands.install.messages.skipDownloadLocalAppMissing', {
|
|
1863
|
+
projectRoot,
|
|
1864
|
+
}));
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1750
1867
|
}
|
|
1751
1868
|
async downloadLocalApp(params) {
|
|
1752
1869
|
const result = await this.downloadManagedSource({
|
|
@@ -1767,36 +1884,32 @@ export default class Install extends Command {
|
|
|
1767
1884
|
return downloadedProjectRoot;
|
|
1768
1885
|
}
|
|
1769
1886
|
static buildLocalAppEnvVars(params) {
|
|
1770
|
-
const configuredStoragePath = String(params.appResults.storagePath ?? '').trim()
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
const dbDialect = String(params.dbResults.dbDialect ?? 'postgres').trim()
|
|
1775
|
-
|| 'postgres';
|
|
1887
|
+
const configuredStoragePath = String(params.appResults.storagePath ?? '').trim() || defaultInstallStoragePath(params.envName);
|
|
1888
|
+
const storagePath = resolveConfiguredEnvPath(configuredStoragePath) ??
|
|
1889
|
+
resolveEnvRelativePath(defaultInstallStoragePath(params.envName));
|
|
1890
|
+
const dbDialect = String(params.dbResults.dbDialect ?? 'postgres').trim() || 'postgres';
|
|
1776
1891
|
const appKey = crypto.randomBytes(32).toString('hex');
|
|
1777
1892
|
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';
|
|
1778
1893
|
const env = {
|
|
1779
1894
|
STORAGE_PATH: storagePath,
|
|
1780
|
-
APP_PORT: String(params.appResults.appPort ?? DEFAULT_INSTALL_APP_PORT).trim()
|
|
1781
|
-
|| DEFAULT_INSTALL_APP_PORT,
|
|
1895
|
+
APP_PORT: String(params.appResults.appPort ?? DEFAULT_INSTALL_APP_PORT).trim() || DEFAULT_INSTALL_APP_PORT,
|
|
1782
1896
|
APP_KEY: appKey,
|
|
1783
1897
|
TZ: timeZone,
|
|
1784
1898
|
DB_DIALECT: dbDialect,
|
|
1785
|
-
DB_HOST: String(params.dbResults.dbHost ?? DEFAULT_INSTALL_DB_HOST).trim()
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
DB_USER: String(params.dbResults.dbUser ?? DEFAULT_INSTALL_DB_USER).trim()
|
|
1792
|
-
|| DEFAULT_INSTALL_DB_USER,
|
|
1793
|
-
DB_PASSWORD: String(params.dbResults.dbPassword ?? DEFAULT_INSTALL_DB_PASSWORD)
|
|
1794
|
-
|| DEFAULT_INSTALL_DB_PASSWORD,
|
|
1899
|
+
DB_HOST: String(params.dbResults.dbHost ?? DEFAULT_INSTALL_DB_HOST).trim() || DEFAULT_INSTALL_DB_HOST,
|
|
1900
|
+
DB_PORT: String(params.dbResults.dbPort ?? defaultDbPortForDialect(dbDialect)).trim() ||
|
|
1901
|
+
defaultDbPortForDialect(dbDialect),
|
|
1902
|
+
DB_DATABASE: String(params.dbResults.dbDatabase ?? DEFAULT_INSTALL_DB_DATABASE).trim() || DEFAULT_INSTALL_DB_DATABASE,
|
|
1903
|
+
DB_USER: String(params.dbResults.dbUser ?? DEFAULT_INSTALL_DB_USER).trim() || DEFAULT_INSTALL_DB_USER,
|
|
1904
|
+
DB_PASSWORD: String(params.dbResults.dbPassword ?? DEFAULT_INSTALL_DB_PASSWORD) || DEFAULT_INSTALL_DB_PASSWORD,
|
|
1795
1905
|
...Install.buildInitAppEnvVars({
|
|
1796
1906
|
appResults: params.appResults,
|
|
1797
1907
|
rootResults: params.rootResults,
|
|
1798
1908
|
}),
|
|
1799
1909
|
};
|
|
1910
|
+
setOptionalEnvVar(env, 'DB_SCHEMA', optionalEnvString(params.dbResults.dbSchema));
|
|
1911
|
+
setOptionalEnvVar(env, 'DB_TABLE_PREFIX', optionalEnvString(params.dbResults.dbTablePrefix));
|
|
1912
|
+
setOptionalEnvVar(env, 'DB_UNDERSCORED', optionalEnvBoolean(params.dbResults.dbUnderscored));
|
|
1800
1913
|
return env;
|
|
1801
1914
|
}
|
|
1802
1915
|
async startLocalApp(params) {
|
|
@@ -1838,10 +1951,8 @@ export default class Install extends Command {
|
|
|
1838
1951
|
};
|
|
1839
1952
|
}
|
|
1840
1953
|
static resolveApiBaseUrl(params) {
|
|
1841
|
-
const appPort = String(params.appResults.appPort ?? DEFAULT_INSTALL_APP_PORT).trim()
|
|
1842
|
-
|
|
1843
|
-
return (String(params.envAddResults.apiBaseUrl ?? '').trim()
|
|
1844
|
-
|| `http://127.0.0.1:${appPort}/api`);
|
|
1954
|
+
const appPort = String(params.appResults.appPort ?? DEFAULT_INSTALL_APP_PORT).trim() || DEFAULT_INSTALL_APP_PORT;
|
|
1955
|
+
return String(params.envAddResults.apiBaseUrl ?? '').trim() || `http://127.0.0.1:${appPort}/api`;
|
|
1845
1956
|
}
|
|
1846
1957
|
static buildHealthCheckUrl(apiBaseUrl) {
|
|
1847
1958
|
return `${apiBaseUrl.replace(/\/+$/, '')}/__health_check`;
|
|
@@ -1870,9 +1981,7 @@ export default class Install extends Command {
|
|
|
1870
1981
|
const body = Install.formatHealthCheckMessage(text);
|
|
1871
1982
|
return {
|
|
1872
1983
|
ok: response.ok && text.trim().toLowerCase() === 'ok',
|
|
1873
|
-
message: response.ok
|
|
1874
|
-
? `HTTP ${response.status}: ${body}`
|
|
1875
|
-
: `HTTP ${response.status}: ${body}`,
|
|
1984
|
+
message: response.ok ? `HTTP ${response.status}: ${body}` : `HTTP ${response.status}: ${body}`,
|
|
1876
1985
|
};
|
|
1877
1986
|
}
|
|
1878
1987
|
catch (error) {
|
|
@@ -1936,28 +2045,42 @@ export default class Install extends Command {
|
|
|
1936
2045
|
if (!params.appReady) {
|
|
1937
2046
|
return;
|
|
1938
2047
|
}
|
|
1939
|
-
const authType = String(params.envAddResults.authType ?? 'oauth').trim()
|
|
1940
|
-
|
|
2048
|
+
const authType = String(params.envAddResults.authType ?? 'oauth').trim() || 'oauth';
|
|
2049
|
+
if (params.skipAuth) {
|
|
2050
|
+
printInfo(formatDeferredAuthMessage(params.envName, authType));
|
|
2051
|
+
return;
|
|
2052
|
+
}
|
|
1941
2053
|
if (authType === 'oauth') {
|
|
1942
2054
|
await this.config.runCommand('env:auth', [params.envName]);
|
|
1943
2055
|
}
|
|
2056
|
+
else if (authType === 'basic') {
|
|
2057
|
+
const authArgv = [params.envName, '--auth-type', 'basic'];
|
|
2058
|
+
const username = String(params.envAddResults.username ?? '').trim();
|
|
2059
|
+
const password = String(params.envAddResults.password ?? '');
|
|
2060
|
+
if (username) {
|
|
2061
|
+
authArgv.push('--username', username);
|
|
2062
|
+
}
|
|
2063
|
+
if (password) {
|
|
2064
|
+
authArgv.push('--password', password);
|
|
2065
|
+
}
|
|
2066
|
+
await this.config.runCommand('env:auth', authArgv);
|
|
2067
|
+
}
|
|
1944
2068
|
await this.config.runCommand('env:update', [params.envName]);
|
|
1945
2069
|
}
|
|
1946
2070
|
static buildSavedEnvConfig(params) {
|
|
1947
|
-
const appPort = String(params.appResults.appPort ?? DEFAULT_INSTALL_APP_PORT).trim()
|
|
1948
|
-
|
|
1949
|
-
const storagePath = String(params.appResults.storagePath ?? '').trim()
|
|
1950
|
-
|| defaultInstallStoragePath(params.envName);
|
|
2071
|
+
const appPort = String(params.appResults.appPort ?? DEFAULT_INSTALL_APP_PORT).trim() || DEFAULT_INSTALL_APP_PORT;
|
|
2072
|
+
const storagePath = String(params.appResults.storagePath ?? '').trim() || defaultInstallStoragePath(params.envName);
|
|
1951
2073
|
const envFile = String(params.appResults.envFile ?? '').trim() || undefined;
|
|
1952
2074
|
const apiBaseUrl = Install.resolveApiBaseUrl({
|
|
1953
2075
|
appResults: params.appResults,
|
|
1954
2076
|
envAddResults: params.envAddResults,
|
|
1955
2077
|
});
|
|
1956
|
-
const authType = String(params.envAddResults.authType ?? 'oauth').trim()
|
|
1957
|
-
|
|
2078
|
+
const authType = String(params.envAddResults.authType ?? 'oauth').trim() || 'oauth';
|
|
2079
|
+
const authUsername = authType === 'basic' ? String(params.envAddResults.username ?? params.rootResults.rootUsername ?? '').trim() : '';
|
|
1958
2080
|
return buildStoredEnvConfig({
|
|
1959
2081
|
apiBaseUrl,
|
|
1960
2082
|
authType,
|
|
2083
|
+
...(authUsername ? { authUsername } : {}),
|
|
1961
2084
|
accessToken: params.envAddResults.accessToken,
|
|
1962
2085
|
source: downloadResultsValue(params.downloadResults, 'source'),
|
|
1963
2086
|
downloadVersion: downloadResultsValue(params.downloadResults, 'version'),
|
|
@@ -1982,6 +2105,9 @@ export default class Install extends Command {
|
|
|
1982
2105
|
dbDatabase: params.dbResults.dbDatabase,
|
|
1983
2106
|
dbUser: params.dbResults.dbUser,
|
|
1984
2107
|
dbPassword: params.dbResults.dbPassword,
|
|
2108
|
+
dbSchema: params.dbResults.dbSchema,
|
|
2109
|
+
dbTablePrefix: params.dbResults.dbTablePrefix,
|
|
2110
|
+
dbUnderscored: params.dbResults.dbUnderscored,
|
|
1985
2111
|
rootUsername: params.rootResults.rootUsername,
|
|
1986
2112
|
rootEmail: params.rootResults.rootEmail,
|
|
1987
2113
|
rootPassword: params.rootResults.rootPassword,
|
|
@@ -1989,6 +2115,7 @@ export default class Install extends Command {
|
|
|
1989
2115
|
});
|
|
1990
2116
|
}
|
|
1991
2117
|
async collectPromptResults(parsed, yes) {
|
|
2118
|
+
const commandArgv = this.argv ?? process.argv.slice(2);
|
|
1992
2119
|
const resumePreset = await this.resolveResumePresetValues(parsed, yes);
|
|
1993
2120
|
const envPreset = {
|
|
1994
2121
|
...(resumePreset?.envPreset ?? {}),
|
|
@@ -2004,7 +2131,7 @@ export default class Install extends Command {
|
|
|
2004
2131
|
const envName = String(envResults.env ?? '').trim() || DEFAULT_INSTALL_ENV_NAME;
|
|
2005
2132
|
const appPreset = {
|
|
2006
2133
|
...(resumePreset?.appPreset ?? {}),
|
|
2007
|
-
...Install.buildAppPresetValuesFromFlags(parsed),
|
|
2134
|
+
...Install.buildAppPresetValuesFromFlags(parsed, commandArgv),
|
|
2008
2135
|
};
|
|
2009
2136
|
const appCatalog = Install.buildAppPromptsCatalog(envName, {
|
|
2010
2137
|
resume: parsed.resume,
|
|
@@ -2014,52 +2141,58 @@ export default class Install extends Command {
|
|
|
2014
2141
|
envName,
|
|
2015
2142
|
flags: {
|
|
2016
2143
|
...parsed,
|
|
2017
|
-
'app-root-path': parsed['app-root-path']
|
|
2018
|
-
|
|
2019
|
-
'
|
|
2020
|
-
?? Install.toOptionalPromptString(appPreset.appPort),
|
|
2021
|
-
'storage-path': parsed['storage-path']
|
|
2022
|
-
?? Install.toOptionalPromptString(appPreset.storagePath),
|
|
2144
|
+
'app-root-path': parsed['app-root-path'] ?? Install.toOptionalPromptString(appPreset.appRootPath),
|
|
2145
|
+
'app-port': parsed['app-port'] ?? Install.toOptionalPromptString(appPreset.appPort),
|
|
2146
|
+
'storage-path': parsed['storage-path'] ?? Install.toOptionalPromptString(appPreset.storagePath),
|
|
2023
2147
|
},
|
|
2024
2148
|
}),
|
|
2025
2149
|
values: appPreset,
|
|
2026
2150
|
yesInitialValues: { resume: parsed.resume },
|
|
2027
2151
|
yes,
|
|
2028
2152
|
});
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
downloadOpts.values
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2153
|
+
const downloadOpts = Install.buildDownloadPromptOptionsForInstall(appResults, envName);
|
|
2154
|
+
downloadOpts.values = {
|
|
2155
|
+
...(resumePreset?.downloadPreset ?? {}),
|
|
2156
|
+
...downloadOpts.values,
|
|
2157
|
+
...Install.buildDownloadPresetValuesForInstall(parsed, appResults, envName, yes, commandArgv),
|
|
2158
|
+
...(parsed['skip-download'] ? Install.buildSkipDownloadValues(envName, appResults) : {}),
|
|
2159
|
+
};
|
|
2160
|
+
downloadOpts.yes = yes;
|
|
2161
|
+
const downloadResults = await runPromptCatalog(Download.prompts, downloadOpts);
|
|
2162
|
+
if (parsed['skip-download']) {
|
|
2163
|
+
delete downloadResults.outputDir;
|
|
2164
|
+
delete downloadResults.replace;
|
|
2165
|
+
delete downloadResults.dockerSave;
|
|
2166
|
+
delete downloadResults.devDependencies;
|
|
2167
|
+
delete downloadResults.build;
|
|
2168
|
+
delete downloadResults.buildDts;
|
|
2039
2169
|
}
|
|
2040
2170
|
const dbPreset = {
|
|
2041
2171
|
...(resumePreset?.dbPreset ?? {}),
|
|
2042
|
-
...Install.buildDbPresetValuesFromFlags(parsed),
|
|
2172
|
+
...Install.buildDbPresetValuesFromFlags(parsed, commandArgv),
|
|
2043
2173
|
};
|
|
2044
|
-
const
|
|
2174
|
+
const promptedDbResults = await runPromptCatalog(Install.buildDbPromptsCatalog(envName, downloadResults, {
|
|
2045
2175
|
resume: parsed.resume,
|
|
2046
2176
|
}), {
|
|
2047
2177
|
initialValues: {
|
|
2048
2178
|
...downloadResults,
|
|
2049
|
-
...await Install.buildDbPromptInitialValues({
|
|
2179
|
+
...(await Install.buildDbPromptInitialValues({
|
|
2050
2180
|
flags: {
|
|
2051
2181
|
...parsed,
|
|
2052
|
-
'db-port': parsed['db-port']
|
|
2053
|
-
?? Install.toOptionalPromptString(dbPreset.dbPort),
|
|
2182
|
+
'db-port': parsed['db-port'] ?? Install.toOptionalPromptString(dbPreset.dbPort),
|
|
2054
2183
|
},
|
|
2055
2184
|
downloadResults,
|
|
2056
2185
|
dbPreset,
|
|
2057
|
-
}),
|
|
2186
|
+
})),
|
|
2058
2187
|
},
|
|
2059
2188
|
values: dbPreset,
|
|
2060
2189
|
yes,
|
|
2061
2190
|
});
|
|
2062
|
-
const
|
|
2191
|
+
const dbResults = {
|
|
2192
|
+
...pickPresetKeys(dbPreset, ['dbSchema', 'dbTablePrefix', 'dbUnderscored']),
|
|
2193
|
+
...promptedDbResults,
|
|
2194
|
+
};
|
|
2195
|
+
const rootPreset = Install.buildRootPresetValuesFromFlags(parsed, commandArgv);
|
|
2063
2196
|
const rootResults = await runPromptCatalog(Install.rootUserPrompts, {
|
|
2064
2197
|
initialValues: {},
|
|
2065
2198
|
values: {
|
|
@@ -2068,24 +2201,45 @@ export default class Install extends Command {
|
|
|
2068
2201
|
},
|
|
2069
2202
|
yes,
|
|
2070
2203
|
});
|
|
2071
|
-
const envAddPromptsForInstall =
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2204
|
+
const envAddPromptsForInstall = this.buildEnvAddPromptsForInstall(parsed);
|
|
2205
|
+
const envAddResumePreset = resumePreset?.envAddPreset ?? {};
|
|
2206
|
+
const envAddFlagValues = Install.buildEnvAddPresetValuesFromFlags(parsed, commandArgv);
|
|
2207
|
+
const envAddPreset = {
|
|
2208
|
+
...envAddResumePreset,
|
|
2209
|
+
...envAddFlagValues,
|
|
2077
2210
|
};
|
|
2078
|
-
const
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2211
|
+
const resolvedEnvAddAuthType = String(envAddPreset.authType ?? '').trim();
|
|
2212
|
+
const envAddInitialValues = {
|
|
2213
|
+
apiBaseUrl: `http://127.0.0.1:${appResults.appPort ?? DEFAULT_INSTALL_APP_PORT}/api`,
|
|
2214
|
+
...envAddResumePreset,
|
|
2215
|
+
...(!parsed['skip-auth'] && resolvedEnvAddAuthType === 'basic'
|
|
2216
|
+
? {
|
|
2217
|
+
...(!Object.prototype.hasOwnProperty.call(envAddResumePreset, 'username') &&
|
|
2218
|
+
!Object.prototype.hasOwnProperty.call(envAddFlagValues, 'username') &&
|
|
2219
|
+
rootResults.rootUsername !== undefined
|
|
2220
|
+
? { username: String(rootResults.rootUsername).trim() }
|
|
2221
|
+
: {}),
|
|
2222
|
+
...(!Object.prototype.hasOwnProperty.call(envAddFlagValues, 'password') &&
|
|
2223
|
+
rootResults.rootPassword !== undefined
|
|
2224
|
+
? { password: String(rootResults.rootPassword ?? '') }
|
|
2225
|
+
: {}),
|
|
2226
|
+
}
|
|
2227
|
+
: {}),
|
|
2228
|
+
};
|
|
2229
|
+
const promptedEnvAddResults = await runPromptCatalog(envAddPromptsForInstall, {
|
|
2230
|
+
initialValues: envAddInitialValues,
|
|
2082
2231
|
values: {
|
|
2083
2232
|
name: envName,
|
|
2084
|
-
...(
|
|
2085
|
-
...
|
|
2233
|
+
...(parsed['skip-auth'] ? { skipAuth: true } : {}),
|
|
2234
|
+
...envAddFlagValues,
|
|
2086
2235
|
},
|
|
2087
2236
|
yes,
|
|
2088
2237
|
});
|
|
2238
|
+
const envAddResults = {
|
|
2239
|
+
...pickPresetKeys(envAddInitialValues, ['username', 'password']),
|
|
2240
|
+
...promptedEnvAddResults,
|
|
2241
|
+
...pickPresetKeys(envAddFlagValues, ['username', 'password']),
|
|
2242
|
+
};
|
|
2089
2243
|
return {
|
|
2090
2244
|
envName,
|
|
2091
2245
|
envResults,
|
|
@@ -2103,6 +2257,9 @@ export default class Install extends Command {
|
|
|
2103
2257
|
const parsed = {
|
|
2104
2258
|
...flags,
|
|
2105
2259
|
};
|
|
2260
|
+
if (parsed['skip-auth'] && (parsed['access-token'] !== undefined || parsed.token !== undefined)) {
|
|
2261
|
+
this.error('--skip-auth cannot be used with --access-token or --token.');
|
|
2262
|
+
}
|
|
2106
2263
|
setVerboseMode(Boolean(parsed.verbose));
|
|
2107
2264
|
const commandStdio = this.commandStdio(parsed.verbose);
|
|
2108
2265
|
if (!parsed['no-intro']) {
|
|
@@ -2115,16 +2272,23 @@ export default class Install extends Command {
|
|
|
2115
2272
|
: 'Resuming setup from the saved workspace config');
|
|
2116
2273
|
}
|
|
2117
2274
|
const promptResults = await this.collectPromptResults(parsed, flags.yes);
|
|
2118
|
-
const { envName, appResults, downloadResults, dbResults, rootResults, envAddResults
|
|
2275
|
+
const { envName, appResults, downloadResults, dbResults, rootResults, envAddResults } = promptResults;
|
|
2119
2276
|
const source = String(downloadResultsValue(downloadResults, 'source') ?? '').trim();
|
|
2120
|
-
const usesDockerResources = Boolean(dbResults.builtinDb)
|
|
2121
|
-
|| (Boolean(appResults.fetchSource) && source === 'docker');
|
|
2277
|
+
const usesDockerResources = Boolean(dbResults.builtinDb) || source === 'docker';
|
|
2122
2278
|
const dockerNetworkName = usesDockerResources
|
|
2123
2279
|
? await resolveDockerNetworkName({ scope: resolveDefaultConfigScope() })
|
|
2124
2280
|
: undefined;
|
|
2125
2281
|
const dockerContainerPrefix = usesDockerResources
|
|
2126
2282
|
? await resolveDockerContainerPrefix({ scope: resolveDefaultConfigScope() })
|
|
2127
2283
|
: undefined;
|
|
2284
|
+
if (parsed['skip-download']) {
|
|
2285
|
+
await this.ensureSkippedDownloadInputsReady({
|
|
2286
|
+
source,
|
|
2287
|
+
envName,
|
|
2288
|
+
appResults,
|
|
2289
|
+
downloadResults,
|
|
2290
|
+
});
|
|
2291
|
+
}
|
|
2128
2292
|
await Install.ensureExternalDbReadyForInstall(dbResults);
|
|
2129
2293
|
if (!parsed.resume) {
|
|
2130
2294
|
if (!parsed['skip-save-env-log']) {
|
|
@@ -2143,7 +2307,7 @@ export default class Install extends Command {
|
|
|
2143
2307
|
}
|
|
2144
2308
|
}
|
|
2145
2309
|
let builtinDbPlan;
|
|
2146
|
-
if (
|
|
2310
|
+
if (dbResults.builtinDb) {
|
|
2147
2311
|
builtinDbPlan = await this.startBuiltinDb({
|
|
2148
2312
|
envName,
|
|
2149
2313
|
dockerNetworkName,
|
|
@@ -2163,14 +2327,16 @@ export default class Install extends Command {
|
|
|
2163
2327
|
}
|
|
2164
2328
|
let dockerAppPlan;
|
|
2165
2329
|
let localAppPlan;
|
|
2166
|
-
if (
|
|
2330
|
+
if (source === 'docker' || source === 'npm' || source === 'git') {
|
|
2167
2331
|
this.logStage('Preparing application');
|
|
2168
2332
|
if (source === 'docker') {
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2333
|
+
if (!parsed['skip-download']) {
|
|
2334
|
+
await this.downloadManagedSource({
|
|
2335
|
+
downloadResults,
|
|
2336
|
+
verbose: parsed.verbose,
|
|
2337
|
+
});
|
|
2338
|
+
printInfo('Application image ready.');
|
|
2339
|
+
}
|
|
2174
2340
|
dockerAppPlan = await this.installDockerApp({
|
|
2175
2341
|
envName,
|
|
2176
2342
|
dockerNetworkName,
|
|
@@ -2188,13 +2354,21 @@ export default class Install extends Command {
|
|
|
2188
2354
|
}
|
|
2189
2355
|
else if (source === 'npm' || source === 'git') {
|
|
2190
2356
|
const localSource = source === 'npm' ? 'npm' : 'git';
|
|
2191
|
-
const projectRoot =
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2357
|
+
const projectRoot = parsed['skip-download']
|
|
2358
|
+
? Install.resolveLocalProjectRoot({
|
|
2359
|
+
envName,
|
|
2360
|
+
appResults,
|
|
2361
|
+
downloadResults,
|
|
2362
|
+
})
|
|
2363
|
+
: await this.downloadLocalApp({
|
|
2364
|
+
envName,
|
|
2365
|
+
appResults,
|
|
2366
|
+
downloadResults,
|
|
2367
|
+
verbose: parsed.verbose,
|
|
2368
|
+
});
|
|
2369
|
+
if (!parsed['skip-download']) {
|
|
2370
|
+
printInfo('Application files ready.');
|
|
2371
|
+
}
|
|
2198
2372
|
localAppPlan = await this.startLocalApp({
|
|
2199
2373
|
envName,
|
|
2200
2374
|
source: localSource,
|
|
@@ -2235,6 +2409,7 @@ export default class Install extends Command {
|
|
|
2235
2409
|
envName,
|
|
2236
2410
|
envAddResults,
|
|
2237
2411
|
appReady: Boolean(dockerAppPlan || localAppPlan),
|
|
2412
|
+
skipAuth: Boolean(parsed['skip-auth']),
|
|
2238
2413
|
});
|
|
2239
2414
|
if (!dockerAppPlan && !localAppPlan) {
|
|
2240
2415
|
printInfo(`Install config for "${envName}" has been saved.`);
|