@nocobase/cli 2.1.0-alpha.21 → 2.1.0-alpha.23
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/download.js +170 -37
- package/dist/commands/env/add.js +39 -12
- package/dist/commands/init.js +90 -47
- package/dist/commands/install.js +191 -57
- package/dist/commands/prompts-stages.js +6 -0
- package/dist/commands/prompts-test.js +6 -0
- package/dist/lib/api-client.js +49 -5
- package/dist/lib/cli-locale.js +115 -0
- package/dist/lib/env-auth.js +2 -2
- package/dist/lib/prompt-catalog.js +87 -58
- package/dist/lib/prompt-validators.js +9 -8
- package/dist/lib/prompt-web-ui.js +143 -74
- package/dist/lib/run-npm.js +10 -10
- package/dist/lib/runtime-generator.js +12 -1
- package/dist/locale/en-US.json +333 -0
- package/dist/locale/zh-CN.json +333 -0
- package/package.json +5 -3
package/dist/commands/install.js
CHANGED
|
@@ -15,6 +15,7 @@ import { mkdir } from 'node:fs/promises';
|
|
|
15
15
|
import path from 'node:path';
|
|
16
16
|
import { exit } from 'node:process';
|
|
17
17
|
import { runPromptCatalog, } from "../lib/prompt-catalog.js";
|
|
18
|
+
import { applyCliLocale, localeText, resolveCliLocale, translateCli, } from "../lib/cli-locale.js";
|
|
18
19
|
import { findAvailableTcpPort, validateAvailableTcpPort, validateTcpPort, validateEnvKey, } from "../lib/prompt-validators.js";
|
|
19
20
|
import { formatMissingManagedAppEnvMessage } from '../lib/app-runtime.js';
|
|
20
21
|
import { run, runNocoBaseCommand } from '../lib/run-npm.js';
|
|
@@ -33,11 +34,23 @@ const DEFAULT_INSTALL_DB_PORTS = {
|
|
|
33
34
|
mariadb: '3306',
|
|
34
35
|
kingbase: '54321',
|
|
35
36
|
};
|
|
37
|
+
const DEFAULT_INSTALL_BUILTIN_DB_IMAGES = {
|
|
38
|
+
postgres: 'postgres:16',
|
|
39
|
+
mysql: 'mysql:8',
|
|
40
|
+
mariadb: 'mariadb:11',
|
|
41
|
+
kingbase: 'registry.cn-shanghai.aliyuncs.com/nocobase/kingbase:v009r001c001b0030_single_x86',
|
|
42
|
+
};
|
|
43
|
+
const DEFAULT_INSTALL_BUILTIN_DB_IMAGES_ZH_CN = {
|
|
44
|
+
postgres: 'registry.cn-shanghai.aliyuncs.com/nocobase/postgres:16',
|
|
45
|
+
mysql: 'registry.cn-shanghai.aliyuncs.com/nocobase/mysql:8',
|
|
46
|
+
mariadb: 'registry.cn-shanghai.aliyuncs.com/nocobase/mariadb:11',
|
|
47
|
+
kingbase: 'registry.cn-shanghai.aliyuncs.com/nocobase/kingbase:v009r001c001b0030_single_x86',
|
|
48
|
+
};
|
|
36
49
|
const DEFAULT_INSTALL_DB_DATABASE = 'nocobase';
|
|
37
50
|
const DEFAULT_INSTALL_DB_USER = 'nocobase';
|
|
38
51
|
const DEFAULT_INSTALL_DB_PASSWORD = 'nocobase';
|
|
39
52
|
const DEFAULT_INSTALL_ROOT_USERNAME = 'nocobase';
|
|
40
|
-
const DEFAULT_INSTALL_ROOT_EMAIL = 'admin@
|
|
53
|
+
const DEFAULT_INSTALL_ROOT_EMAIL = 'admin@nocobase.com';
|
|
41
54
|
const DEFAULT_INSTALL_ROOT_PASSWORD = 'admin123';
|
|
42
55
|
const DEFAULT_INSTALL_ROOT_NICKNAME = 'Super Admin';
|
|
43
56
|
const CONFIG_SCOPE = 'project';
|
|
@@ -117,21 +130,50 @@ const INSTALL_LANGUAGE_OPTIONS = Object.entries(INSTALL_LANGUAGE_CODES).map(([va
|
|
|
117
130
|
value,
|
|
118
131
|
label: `${label} (${value})`,
|
|
119
132
|
}));
|
|
133
|
+
const installText = (key, values) => localeText(`commands.install.${key}`, values);
|
|
120
134
|
function argvHasToken(argv, tokens) {
|
|
121
135
|
return tokens.some((t) => argv.includes(t));
|
|
122
136
|
}
|
|
123
137
|
function isInstallDbDialect(value) {
|
|
124
138
|
return INSTALL_DB_DIALECTS.includes(value);
|
|
125
139
|
}
|
|
140
|
+
function supportsBuiltinDbDialect(value) {
|
|
141
|
+
const dialect = String(value ?? '').trim();
|
|
142
|
+
return Object.prototype.hasOwnProperty.call(DEFAULT_INSTALL_BUILTIN_DB_IMAGES, dialect);
|
|
143
|
+
}
|
|
126
144
|
export function defaultDbPortForDialect(value) {
|
|
127
145
|
const dialect = String(value ?? 'postgres').trim();
|
|
128
146
|
return DEFAULT_INSTALL_DB_PORTS[isInstallDbDialect(dialect) ? dialect : 'postgres'];
|
|
129
147
|
}
|
|
148
|
+
function defaultBuiltinDbImageForDialect(value) {
|
|
149
|
+
const dialect = String(value ?? 'postgres').trim();
|
|
150
|
+
const defaults = resolveCliLocale(process.env.NB_LOCALE) === 'zh-CN'
|
|
151
|
+
? DEFAULT_INSTALL_BUILTIN_DB_IMAGES_ZH_CN
|
|
152
|
+
: DEFAULT_INSTALL_BUILTIN_DB_IMAGES;
|
|
153
|
+
return supportsBuiltinDbDialect(dialect)
|
|
154
|
+
? defaults[dialect]
|
|
155
|
+
: defaults.postgres;
|
|
156
|
+
}
|
|
157
|
+
function defaultDbDatabaseForDialect(value) {
|
|
158
|
+
return String(value ?? '').trim() === 'kingbase'
|
|
159
|
+
? 'kingbase'
|
|
160
|
+
: DEFAULT_INSTALL_DB_DATABASE;
|
|
161
|
+
}
|
|
130
162
|
function defaultDbHostForBuiltinDb(values) {
|
|
131
163
|
return Boolean(values.builtinDb)
|
|
132
164
|
? DEFAULT_INSTALL_BUILTIN_DB_HOST
|
|
133
165
|
: DEFAULT_INSTALL_DB_HOST;
|
|
134
166
|
}
|
|
167
|
+
function validateBuiltinDbEnabled(value, values) {
|
|
168
|
+
if (!Boolean(value)) {
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
const dialect = String(values.dbDialect ?? 'postgres').trim() || 'postgres';
|
|
172
|
+
if (supportsBuiltinDbDialect(dialect)) {
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
return translateCli('commands.install.validation.builtinDbUnsupported', { dialect });
|
|
176
|
+
}
|
|
135
177
|
function defaultInstallAppRootPath(envName) {
|
|
136
178
|
const name = String(envName ?? DEFAULT_INSTALL_ENV_NAME).trim() || DEFAULT_INSTALL_ENV_NAME;
|
|
137
179
|
return `./${name}/source/`;
|
|
@@ -221,6 +263,10 @@ export default class Install extends Command {
|
|
|
221
263
|
description: 'Resume a previous unfinished setup for this env using the saved workspace env config',
|
|
222
264
|
default: false,
|
|
223
265
|
}),
|
|
266
|
+
verbose: Flags.boolean({
|
|
267
|
+
description: 'Show detailed command output',
|
|
268
|
+
default: false,
|
|
269
|
+
}),
|
|
224
270
|
env: Flags.string({
|
|
225
271
|
char: 'e',
|
|
226
272
|
description: 'App/env name to create or update. Defaults app paths to ./<envName>/source/ and ./<envName>/storage/.',
|
|
@@ -264,6 +310,9 @@ export default class Install extends Command {
|
|
|
264
310
|
description: 'Database dialect for the app',
|
|
265
311
|
options: ['postgres', 'mysql', 'mariadb', 'kingbase'],
|
|
266
312
|
}),
|
|
313
|
+
'builtin-db-image': Flags.string({
|
|
314
|
+
description: 'Docker image for the built-in database container (default follows the selected database)',
|
|
315
|
+
}),
|
|
267
316
|
'db-host': Flags.string({
|
|
268
317
|
description: 'Database host for the app',
|
|
269
318
|
}),
|
|
@@ -289,8 +338,8 @@ export default class Install extends Command {
|
|
|
289
338
|
static envPrompts = {
|
|
290
339
|
env: {
|
|
291
340
|
type: 'text',
|
|
292
|
-
message: '
|
|
293
|
-
placeholder:
|
|
341
|
+
message: installText('prompts.env.message'),
|
|
342
|
+
placeholder: installText('prompts.env.placeholder'),
|
|
294
343
|
required: true,
|
|
295
344
|
validate: validateEnvKey,
|
|
296
345
|
},
|
|
@@ -298,7 +347,7 @@ export default class Install extends Command {
|
|
|
298
347
|
static appPrompts = {
|
|
299
348
|
lang: {
|
|
300
349
|
type: 'select',
|
|
301
|
-
message: '
|
|
350
|
+
message: installText('prompts.lang.message'),
|
|
302
351
|
options: INSTALL_LANGUAGE_OPTIONS,
|
|
303
352
|
initialValue: DEFAULT_INSTALL_LANG,
|
|
304
353
|
yesInitialValue: DEFAULT_INSTALL_LANG,
|
|
@@ -311,39 +360,33 @@ export default class Install extends Command {
|
|
|
311
360
|
// },
|
|
312
361
|
appRootPath: {
|
|
313
362
|
type: 'text',
|
|
314
|
-
message: '
|
|
315
|
-
placeholder: '
|
|
363
|
+
message: installText('prompts.appRootPath.message'),
|
|
364
|
+
placeholder: installText('prompts.appRootPath.placeholder'),
|
|
316
365
|
initialValue: (values) => defaultInstallAppRootPath(values.env ?? values.appName),
|
|
317
366
|
},
|
|
318
367
|
appPort: {
|
|
319
368
|
type: 'text',
|
|
320
|
-
message: '
|
|
321
|
-
placeholder:
|
|
369
|
+
message: installText('prompts.appPort.message'),
|
|
370
|
+
placeholder: installText('prompts.appPort.placeholder'),
|
|
322
371
|
validate: validateAvailableTcpPort,
|
|
323
372
|
},
|
|
324
373
|
storagePath: {
|
|
325
374
|
type: 'text',
|
|
326
|
-
message: '
|
|
327
|
-
placeholder: '
|
|
375
|
+
message: installText('prompts.storagePath.message'),
|
|
376
|
+
placeholder: installText('prompts.storagePath.placeholder'),
|
|
328
377
|
initialValue: (values) => defaultInstallStoragePath(values.env ?? values.appName),
|
|
329
378
|
},
|
|
330
379
|
fetchSource: {
|
|
331
380
|
type: 'boolean',
|
|
332
|
-
message: '
|
|
381
|
+
message: installText('prompts.fetchSource.message'),
|
|
333
382
|
initialValue: true,
|
|
334
383
|
yesInitialValue: true,
|
|
335
384
|
},
|
|
336
385
|
};
|
|
337
386
|
static dbPrompts = {
|
|
338
|
-
builtinDb: {
|
|
339
|
-
type: 'boolean',
|
|
340
|
-
message: "Would you like to use the built-in database?",
|
|
341
|
-
initialValue: true,
|
|
342
|
-
yesInitialValue: true,
|
|
343
|
-
},
|
|
344
387
|
dbDialect: {
|
|
345
388
|
type: 'select',
|
|
346
|
-
message: '
|
|
389
|
+
message: installText('prompts.dbDialect.message'),
|
|
347
390
|
options: [
|
|
348
391
|
{ value: 'postgres', label: 'PostgreSQL' },
|
|
349
392
|
{ value: 'mysql', label: 'MySQL' },
|
|
@@ -354,10 +397,26 @@ export default class Install extends Command {
|
|
|
354
397
|
yesInitialValue: 'postgres',
|
|
355
398
|
required: true,
|
|
356
399
|
},
|
|
400
|
+
builtinDb: {
|
|
401
|
+
type: 'boolean',
|
|
402
|
+
message: installText('prompts.builtinDb.message'),
|
|
403
|
+
initialValue: true,
|
|
404
|
+
yesInitialValue: true,
|
|
405
|
+
validate: validateBuiltinDbEnabled,
|
|
406
|
+
},
|
|
407
|
+
builtinDbImage: {
|
|
408
|
+
type: 'text',
|
|
409
|
+
message: installText('prompts.builtinDbImage.message'),
|
|
410
|
+
placeholder: installText('prompts.builtinDbImage.placeholder'),
|
|
411
|
+
initialValue: (values) => defaultBuiltinDbImageForDialect(values.dbDialect),
|
|
412
|
+
hidden: (values) => !Boolean(values.builtinDb)
|
|
413
|
+
|| !supportsBuiltinDbDialect(values.dbDialect),
|
|
414
|
+
required: true,
|
|
415
|
+
},
|
|
357
416
|
dbHost: {
|
|
358
417
|
type: 'text',
|
|
359
|
-
message: '
|
|
360
|
-
placeholder:
|
|
418
|
+
message: installText('prompts.dbHost.message'),
|
|
419
|
+
placeholder: installText('prompts.dbHost.placeholder'),
|
|
361
420
|
initialValue: (values) => defaultDbHostForBuiltinDb(values),
|
|
362
421
|
yesInitialValue: DEFAULT_INSTALL_BUILTIN_DB_HOST,
|
|
363
422
|
required: true,
|
|
@@ -365,8 +424,8 @@ export default class Install extends Command {
|
|
|
365
424
|
},
|
|
366
425
|
dbPort: {
|
|
367
426
|
type: 'text',
|
|
368
|
-
message: '
|
|
369
|
-
placeholder:
|
|
427
|
+
message: installText('prompts.dbPort.message'),
|
|
428
|
+
placeholder: installText('prompts.dbPort.placeholder'),
|
|
370
429
|
initialValue: (values) => defaultDbPortForDialect(values.dbDialect),
|
|
371
430
|
required: true,
|
|
372
431
|
validate: validateTcpPort,
|
|
@@ -375,21 +434,20 @@ export default class Install extends Command {
|
|
|
375
434
|
},
|
|
376
435
|
dbDatabase: {
|
|
377
436
|
type: 'text',
|
|
378
|
-
message: '
|
|
379
|
-
initialValue:
|
|
380
|
-
yesInitialValue: DEFAULT_INSTALL_DB_DATABASE,
|
|
437
|
+
message: installText('prompts.dbDatabase.message'),
|
|
438
|
+
initialValue: (values) => defaultDbDatabaseForDialect(values.dbDialect),
|
|
381
439
|
required: true,
|
|
382
440
|
},
|
|
383
441
|
dbUser: {
|
|
384
442
|
type: 'text',
|
|
385
|
-
message: '
|
|
443
|
+
message: installText('prompts.dbUser.message'),
|
|
386
444
|
initialValue: DEFAULT_INSTALL_DB_USER,
|
|
387
445
|
yesInitialValue: DEFAULT_INSTALL_DB_USER,
|
|
388
446
|
required: true,
|
|
389
447
|
},
|
|
390
448
|
dbPassword: {
|
|
391
449
|
type: 'password',
|
|
392
|
-
message: '
|
|
450
|
+
message: installText('prompts.dbPassword.message'),
|
|
393
451
|
initialValue: DEFAULT_INSTALL_DB_PASSWORD,
|
|
394
452
|
yesInitialValue: DEFAULT_INSTALL_DB_PASSWORD,
|
|
395
453
|
required: true,
|
|
@@ -398,30 +456,30 @@ export default class Install extends Command {
|
|
|
398
456
|
static rootUserPrompts = {
|
|
399
457
|
rootUsername: {
|
|
400
458
|
type: 'text',
|
|
401
|
-
message: '
|
|
402
|
-
placeholder:
|
|
403
|
-
initialValue: DEFAULT_INSTALL_ROOT_USERNAME,
|
|
459
|
+
message: installText('prompts.rootUsername.message'),
|
|
460
|
+
placeholder: installText('prompts.rootUsername.placeholder'),
|
|
404
461
|
yesInitialValue: DEFAULT_INSTALL_ROOT_USERNAME,
|
|
462
|
+
required: true,
|
|
405
463
|
},
|
|
406
464
|
rootEmail: {
|
|
407
465
|
type: 'text',
|
|
408
|
-
message: '
|
|
409
|
-
placeholder:
|
|
410
|
-
initialValue: DEFAULT_INSTALL_ROOT_EMAIL,
|
|
466
|
+
message: installText('prompts.rootEmail.message'),
|
|
467
|
+
placeholder: installText('prompts.rootEmail.placeholder'),
|
|
411
468
|
yesInitialValue: DEFAULT_INSTALL_ROOT_EMAIL,
|
|
469
|
+
required: true,
|
|
412
470
|
},
|
|
413
471
|
rootPassword: {
|
|
414
472
|
type: 'password',
|
|
415
|
-
message: '
|
|
416
|
-
initialValue: DEFAULT_INSTALL_ROOT_PASSWORD,
|
|
473
|
+
message: installText('prompts.rootPassword.message'),
|
|
417
474
|
yesInitialValue: DEFAULT_INSTALL_ROOT_PASSWORD,
|
|
475
|
+
required: true,
|
|
418
476
|
},
|
|
419
477
|
rootNickname: {
|
|
420
478
|
type: 'text',
|
|
421
|
-
message: '
|
|
422
|
-
placeholder:
|
|
423
|
-
initialValue: DEFAULT_INSTALL_ROOT_NICKNAME,
|
|
479
|
+
message: installText('prompts.rootNickname.message'),
|
|
480
|
+
placeholder: installText('prompts.rootNickname.placeholder'),
|
|
424
481
|
yesInitialValue: DEFAULT_INSTALL_ROOT_NICKNAME,
|
|
482
|
+
required: true,
|
|
425
483
|
},
|
|
426
484
|
};
|
|
427
485
|
/**
|
|
@@ -520,6 +578,12 @@ export default class Install extends Command {
|
|
|
520
578
|
preset.dbDialect = t;
|
|
521
579
|
}
|
|
522
580
|
}
|
|
581
|
+
if (flags['builtin-db-image'] !== undefined) {
|
|
582
|
+
const v = String(flags['builtin-db-image'] ?? '').trim();
|
|
583
|
+
if (v) {
|
|
584
|
+
preset.builtinDbImage = v;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
523
587
|
if (flags['db-host'] !== undefined) {
|
|
524
588
|
const v = String(flags['db-host'] ?? '').trim();
|
|
525
589
|
if (v) {
|
|
@@ -563,6 +627,7 @@ export default class Install extends Command {
|
|
|
563
627
|
return pickPresetKeys(Install.buildPresetValuesFromFlags(flags), [
|
|
564
628
|
'builtinDb',
|
|
565
629
|
'dbDialect',
|
|
630
|
+
'builtinDbImage',
|
|
566
631
|
'dbHost',
|
|
567
632
|
'dbPort',
|
|
568
633
|
'dbDatabase',
|
|
@@ -603,6 +668,7 @@ export default class Install extends Command {
|
|
|
603
668
|
const dbDatabase = Install.toOptionalPromptString(config.dbDatabase);
|
|
604
669
|
const dbUser = Install.toOptionalPromptString(config.dbUser);
|
|
605
670
|
const dbPassword = Install.toOptionalPromptString(config.dbPassword);
|
|
671
|
+
const builtinDbImage = Install.toOptionalPromptString(config.builtinDbImage);
|
|
606
672
|
const auth = config.auth;
|
|
607
673
|
const appPreset = {
|
|
608
674
|
...(appRootPath ? { appRootPath } : {}),
|
|
@@ -630,6 +696,7 @@ export default class Install extends Command {
|
|
|
630
696
|
const dbPreset = {
|
|
631
697
|
...(typeof config.builtinDb === 'boolean' ? { builtinDb: config.builtinDb } : {}),
|
|
632
698
|
...(dbDialect ? { dbDialect } : {}),
|
|
699
|
+
...(builtinDbImage ? { builtinDbImage } : {}),
|
|
633
700
|
...(dbHost ? { dbHost } : {}),
|
|
634
701
|
...(dbPort ? { dbPort } : {}),
|
|
635
702
|
...(dbDatabase ? { dbDatabase } : {}),
|
|
@@ -719,7 +786,7 @@ export default class Install extends Command {
|
|
|
719
786
|
if (params.flags['app-port'] === undefined) {
|
|
720
787
|
initialValues.appPort = await Install.resolveAvailableDefaultPort(DEFAULT_INSTALL_APP_PORT, {
|
|
721
788
|
label: 'Default app port',
|
|
722
|
-
warn: true,
|
|
789
|
+
warn: params.warnOnPortFallback ?? true,
|
|
723
790
|
});
|
|
724
791
|
}
|
|
725
792
|
return initialValues;
|
|
@@ -745,20 +812,20 @@ export default class Install extends Command {
|
|
|
745
812
|
return {
|
|
746
813
|
dbPort: await Install.resolveAvailableDefaultPort(defaultPort, {
|
|
747
814
|
label: `Default ${dialect} port`,
|
|
748
|
-
warn: true,
|
|
815
|
+
warn: params.warnOnPortFallback ?? true,
|
|
749
816
|
}),
|
|
750
817
|
};
|
|
751
818
|
}
|
|
752
819
|
/**
|
|
753
|
-
* When install runs {@link Download.prompts} after app prompts, align
|
|
754
|
-
* output directory
|
|
820
|
+
* When install runs {@link Download.prompts} after app prompts, align the download
|
|
821
|
+
* output directory with app settings, while Docker registry defaults follow the CLI locale.
|
|
755
822
|
*/
|
|
756
823
|
static buildDownloadPromptOptionsForInstall(appResults, envName) {
|
|
757
824
|
const appRoot = String(appResults.appRootPath ?? '').trim() || defaultInstallAppRootPath(envName);
|
|
758
825
|
const lang = String(appResults.lang ?? DEFAULT_INSTALL_LANG).trim() || DEFAULT_INSTALL_LANG;
|
|
759
826
|
const initialValues = {
|
|
760
827
|
lang,
|
|
761
|
-
dockerRegistry: defaultDockerRegistryForLang(
|
|
828
|
+
dockerRegistry: defaultDockerRegistryForLang(process.env.NB_LOCALE),
|
|
762
829
|
outputDir: appRoot,
|
|
763
830
|
};
|
|
764
831
|
const values = {
|
|
@@ -900,6 +967,7 @@ export default class Install extends Command {
|
|
|
900
967
|
const dbDialect = String(params.dbDialect ?? 'postgres').trim() || 'postgres';
|
|
901
968
|
const dbPort = String(params.dbPort ?? defaultDbPortForDialect(dbDialect)).trim()
|
|
902
969
|
|| defaultDbPortForDialect(dbDialect);
|
|
970
|
+
const defaultDbDatabase = defaultDbDatabaseForDialect(dbDialect);
|
|
903
971
|
const networkName = Install.buildBuiltinDbNetworkName(params.envName, params.workspaceName);
|
|
904
972
|
const containerName = Install.buildBuiltinDbContainerName(params.envName, dbDialect, params.workspaceName);
|
|
905
973
|
const dbHostInput = String(params.dbHost ?? '').trim();
|
|
@@ -915,6 +983,7 @@ export default class Install extends Command {
|
|
|
915
983
|
? dbHostInput
|
|
916
984
|
: containerName);
|
|
917
985
|
if (dbDialect === 'postgres') {
|
|
986
|
+
const image = String(params.builtinDbImage ?? '').trim() || defaultBuiltinDbImageForDialect(dbDialect);
|
|
918
987
|
const dataDir = path.resolve(params.storagePath, 'db', 'postgres');
|
|
919
988
|
const args = [
|
|
920
989
|
'run',
|
|
@@ -937,14 +1006,14 @@ export default class Install extends Command {
|
|
|
937
1006
|
if (Install.shouldPublishBuiltinDbPort(params.source)) {
|
|
938
1007
|
args.push('-p', `${dbPort}:5432`);
|
|
939
1008
|
}
|
|
940
|
-
args.push(
|
|
1009
|
+
args.push(image, 'postgres', '-c', 'wal_level=logical');
|
|
941
1010
|
return {
|
|
942
1011
|
source: String(params.source ?? '').trim() || undefined,
|
|
943
1012
|
dbDialect,
|
|
944
1013
|
dbHost,
|
|
945
1014
|
dbPort,
|
|
946
|
-
dbDatabase: String(params.dbDatabase ??
|
|
947
|
-
||
|
|
1015
|
+
dbDatabase: String(params.dbDatabase ?? defaultDbDatabase).trim()
|
|
1016
|
+
|| defaultDbDatabase,
|
|
948
1017
|
dbUser: String(params.dbUser ?? DEFAULT_INSTALL_DB_USER).trim()
|
|
949
1018
|
|| DEFAULT_INSTALL_DB_USER,
|
|
950
1019
|
dbPassword: String(params.dbPassword ?? DEFAULT_INSTALL_DB_PASSWORD)
|
|
@@ -952,14 +1021,16 @@ export default class Install extends Command {
|
|
|
952
1021
|
networkName,
|
|
953
1022
|
containerName,
|
|
954
1023
|
dataDir,
|
|
955
|
-
|
|
1024
|
+
builtinDbImage: image,
|
|
1025
|
+
image,
|
|
956
1026
|
args,
|
|
957
1027
|
};
|
|
958
1028
|
}
|
|
959
1029
|
if (dbDialect === 'mysql') {
|
|
1030
|
+
const image = String(params.builtinDbImage ?? '').trim() || defaultBuiltinDbImageForDialect(dbDialect);
|
|
960
1031
|
const dataDir = path.resolve(params.storagePath, 'db', 'mysql');
|
|
961
1032
|
const dbUser = String(params.dbUser ?? DEFAULT_INSTALL_DB_USER).trim() || DEFAULT_INSTALL_DB_USER;
|
|
962
|
-
const dbDatabase = String(params.dbDatabase ??
|
|
1033
|
+
const dbDatabase = String(params.dbDatabase ?? defaultDbDatabase).trim() || defaultDbDatabase;
|
|
963
1034
|
const dbPassword = String(params.dbPassword ?? DEFAULT_INSTALL_DB_PASSWORD) || DEFAULT_INSTALL_DB_PASSWORD;
|
|
964
1035
|
const args = [
|
|
965
1036
|
'run',
|
|
@@ -984,7 +1055,7 @@ export default class Install extends Command {
|
|
|
984
1055
|
if (Install.shouldPublishBuiltinDbPort(params.source)) {
|
|
985
1056
|
args.push('-p', `${dbPort}:3306`);
|
|
986
1057
|
}
|
|
987
|
-
args.push(
|
|
1058
|
+
args.push(image);
|
|
988
1059
|
return {
|
|
989
1060
|
source: String(params.source ?? '').trim() || undefined,
|
|
990
1061
|
dbDialect,
|
|
@@ -996,14 +1067,16 @@ export default class Install extends Command {
|
|
|
996
1067
|
networkName,
|
|
997
1068
|
containerName,
|
|
998
1069
|
dataDir,
|
|
999
|
-
|
|
1070
|
+
builtinDbImage: image,
|
|
1071
|
+
image,
|
|
1000
1072
|
args,
|
|
1001
1073
|
};
|
|
1002
1074
|
}
|
|
1003
1075
|
if (dbDialect === 'mariadb') {
|
|
1076
|
+
const image = String(params.builtinDbImage ?? '').trim() || defaultBuiltinDbImageForDialect(dbDialect);
|
|
1004
1077
|
const dataDir = path.resolve(params.storagePath, 'db', 'mariadb');
|
|
1005
1078
|
const dbUser = String(params.dbUser ?? DEFAULT_INSTALL_DB_USER).trim() || DEFAULT_INSTALL_DB_USER;
|
|
1006
|
-
const dbDatabase = String(params.dbDatabase ??
|
|
1079
|
+
const dbDatabase = String(params.dbDatabase ?? defaultDbDatabase).trim() || defaultDbDatabase;
|
|
1007
1080
|
const dbPassword = String(params.dbPassword ?? DEFAULT_INSTALL_DB_PASSWORD) || DEFAULT_INSTALL_DB_PASSWORD;
|
|
1008
1081
|
const args = [
|
|
1009
1082
|
'run',
|
|
@@ -1028,7 +1101,58 @@ export default class Install extends Command {
|
|
|
1028
1101
|
if (Install.shouldPublishBuiltinDbPort(params.source)) {
|
|
1029
1102
|
args.push('-p', `${dbPort}:3306`);
|
|
1030
1103
|
}
|
|
1031
|
-
args.push(
|
|
1104
|
+
args.push(image);
|
|
1105
|
+
return {
|
|
1106
|
+
source: String(params.source ?? '').trim() || undefined,
|
|
1107
|
+
dbDialect,
|
|
1108
|
+
dbHost,
|
|
1109
|
+
dbPort,
|
|
1110
|
+
dbDatabase,
|
|
1111
|
+
dbUser,
|
|
1112
|
+
dbPassword,
|
|
1113
|
+
networkName,
|
|
1114
|
+
containerName,
|
|
1115
|
+
dataDir,
|
|
1116
|
+
builtinDbImage: image,
|
|
1117
|
+
image,
|
|
1118
|
+
args,
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
if (dbDialect === 'kingbase') {
|
|
1122
|
+
const image = String(params.builtinDbImage ?? '').trim() || defaultBuiltinDbImageForDialect(dbDialect);
|
|
1123
|
+
const dataDir = path.resolve(params.storagePath, 'db', 'kingbase');
|
|
1124
|
+
const dbUser = String(params.dbUser ?? DEFAULT_INSTALL_DB_USER).trim() || DEFAULT_INSTALL_DB_USER;
|
|
1125
|
+
const dbDatabase = String(params.dbDatabase ?? defaultDbDatabase).trim() || defaultDbDatabase;
|
|
1126
|
+
const dbPassword = String(params.dbPassword ?? DEFAULT_INSTALL_DB_PASSWORD) || DEFAULT_INSTALL_DB_PASSWORD;
|
|
1127
|
+
const args = [
|
|
1128
|
+
'run',
|
|
1129
|
+
'-d',
|
|
1130
|
+
'--name',
|
|
1131
|
+
containerName,
|
|
1132
|
+
'--restart',
|
|
1133
|
+
'always',
|
|
1134
|
+
'--network',
|
|
1135
|
+
networkName,
|
|
1136
|
+
'--platform',
|
|
1137
|
+
'linux/amd64',
|
|
1138
|
+
'--privileged',
|
|
1139
|
+
'-e',
|
|
1140
|
+
'ENABLE_CI=no',
|
|
1141
|
+
'-e',
|
|
1142
|
+
`DB_USER=${dbUser}`,
|
|
1143
|
+
'-e',
|
|
1144
|
+
`DB_PASSWORD=${dbPassword}`,
|
|
1145
|
+
'-e',
|
|
1146
|
+
'DB_MODE=pg',
|
|
1147
|
+
'-e',
|
|
1148
|
+
'NEED_START=yes',
|
|
1149
|
+
'-v',
|
|
1150
|
+
`${dataDir}:/home/kingbase/userdata`,
|
|
1151
|
+
];
|
|
1152
|
+
if (Install.shouldPublishBuiltinDbPort(params.source)) {
|
|
1153
|
+
args.push('-p', `${dbPort}:54321`);
|
|
1154
|
+
}
|
|
1155
|
+
args.push(image, '/usr/sbin/init');
|
|
1032
1156
|
return {
|
|
1033
1157
|
source: String(params.source ?? '').trim() || undefined,
|
|
1034
1158
|
dbDialect,
|
|
@@ -1040,11 +1164,12 @@ export default class Install extends Command {
|
|
|
1040
1164
|
networkName,
|
|
1041
1165
|
containerName,
|
|
1042
1166
|
dataDir,
|
|
1043
|
-
|
|
1167
|
+
builtinDbImage: image,
|
|
1168
|
+
image,
|
|
1044
1169
|
args,
|
|
1045
1170
|
};
|
|
1046
1171
|
}
|
|
1047
|
-
throw new Error(`Built-in database does not support "${dbDialect}" yet. Please choose PostgreSQL, MySQL, or
|
|
1172
|
+
throw new Error(`Built-in database does not support "${dbDialect}" yet. Please choose PostgreSQL, MySQL, MariaDB, or KingbaseES.`);
|
|
1048
1173
|
}
|
|
1049
1174
|
async ensureDockerNetwork(name) {
|
|
1050
1175
|
p.log.step(`Checking Docker network: ${name}`);
|
|
@@ -1138,6 +1263,7 @@ export default class Install extends Command {
|
|
|
1138
1263
|
dbDatabase: params.dbResults.dbDatabase,
|
|
1139
1264
|
dbUser: params.dbResults.dbUser,
|
|
1140
1265
|
dbPassword: params.dbResults.dbPassword,
|
|
1266
|
+
builtinDbImage: params.dbResults.builtinDbImage,
|
|
1141
1267
|
});
|
|
1142
1268
|
p.log.step(`Preparing built-in ${plan.dbDialect} database`);
|
|
1143
1269
|
await this.ensureDockerNetwork(plan.networkName);
|
|
@@ -1158,7 +1284,7 @@ export default class Install extends Command {
|
|
|
1158
1284
|
}
|
|
1159
1285
|
static buildDockerAppPlan(params) {
|
|
1160
1286
|
const dockerRegistry = String(downloadResultsValue(params.downloadResults, 'dockerRegistry') ?? '').trim()
|
|
1161
|
-
|| defaultDockerRegistryForLang(
|
|
1287
|
+
|| defaultDockerRegistryForLang(process.env.NB_LOCALE);
|
|
1162
1288
|
const version = String(downloadResultsValue(params.downloadResults, 'version') ?? '').trim() || 'latest';
|
|
1163
1289
|
const appPort = String(params.appResults.appPort ?? DEFAULT_INSTALL_APP_PORT).trim() || DEFAULT_INSTALL_APP_PORT;
|
|
1164
1290
|
const storagePath = path.resolve(String(params.appResults.storagePath ?? '').trim()
|
|
@@ -1252,8 +1378,11 @@ export default class Install extends Command {
|
|
|
1252
1378
|
argv.push(flag, text);
|
|
1253
1379
|
}
|
|
1254
1380
|
}
|
|
1255
|
-
static buildDownloadArgvFromResults(results) {
|
|
1381
|
+
static buildDownloadArgvFromResults(results, options) {
|
|
1256
1382
|
const argv = ['-y', '--no-intro'];
|
|
1383
|
+
if (options?.verbose) {
|
|
1384
|
+
argv.push('--verbose');
|
|
1385
|
+
}
|
|
1257
1386
|
Install.pushDownloadArgIfValue(argv, '--source', results.source);
|
|
1258
1387
|
Install.pushDownloadArgIfValue(argv, '--version', results.version);
|
|
1259
1388
|
Install.pushDownloadArgIfValue(argv, '--output-dir', results.outputDir);
|
|
@@ -1289,7 +1418,9 @@ export default class Install extends Command {
|
|
|
1289
1418
|
return path.resolve(process.cwd(), outputDir);
|
|
1290
1419
|
}
|
|
1291
1420
|
async downloadLocalApp(params) {
|
|
1292
|
-
const argv = Install.buildDownloadArgvFromResults(params.downloadResults
|
|
1421
|
+
const argv = Install.buildDownloadArgvFromResults(params.downloadResults, {
|
|
1422
|
+
verbose: params.verbose,
|
|
1423
|
+
});
|
|
1293
1424
|
p.log.step('Downloading local NocoBase app files');
|
|
1294
1425
|
const result = await this.config.runCommand('download', argv);
|
|
1295
1426
|
const projectRoot = Install.resolveLocalProjectRoot({
|
|
@@ -1519,6 +1650,7 @@ export default class Install extends Command {
|
|
|
1519
1650
|
Install.pushArgIfValue(argv, '--timezone', params.appResults.timeZone);
|
|
1520
1651
|
Install.pushBooleanArgIfSet(argv, '--builtin-db', params.dbResults.builtinDb);
|
|
1521
1652
|
Install.pushArgIfValue(argv, '--db-dialect', params.dbResults.dbDialect);
|
|
1653
|
+
Install.pushArgIfValue(argv, '--builtin-db-image', params.dbResults.builtinDbImage);
|
|
1522
1654
|
Install.pushArgIfValue(argv, '--db-host', params.dbResults.dbHost);
|
|
1523
1655
|
Install.pushArgIfValue(argv, '--db-port', params.dbResults.dbPort);
|
|
1524
1656
|
Install.pushArgIfValue(argv, '--db-database', params.dbResults.dbDatabase);
|
|
@@ -1624,6 +1756,7 @@ export default class Install extends Command {
|
|
|
1624
1756
|
}
|
|
1625
1757
|
async run() {
|
|
1626
1758
|
const parsedResult = await this.parse(Install);
|
|
1759
|
+
applyCliLocale(parsedResult.flags.locale);
|
|
1627
1760
|
const flags = parsedResult.flags;
|
|
1628
1761
|
const parsed = {
|
|
1629
1762
|
...flags,
|
|
@@ -1684,6 +1817,7 @@ export default class Install extends Command {
|
|
|
1684
1817
|
envName,
|
|
1685
1818
|
appResults,
|
|
1686
1819
|
downloadResults,
|
|
1820
|
+
verbose: parsed.verbose,
|
|
1687
1821
|
});
|
|
1688
1822
|
localAppPlan = await this.startLocalApp({
|
|
1689
1823
|
envName,
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { Args, Command, Flags } from '@oclif/core';
|
|
10
10
|
import { runPromptCatalog, } from "../lib/prompt-catalog.js";
|
|
11
|
+
import { applyCliLocale, CLI_LOCALE_FLAG_DESCRIPTION, CLI_LOCALE_FLAG_OPTIONS, } from "../lib/cli-locale.js";
|
|
11
12
|
import { runPromptCatalogWebUI } from "../lib/prompt-web-ui.js";
|
|
12
13
|
import PromptsTest from "./prompts-test.js";
|
|
13
14
|
function buildWebUiStagesFromTestPrompts(c) {
|
|
@@ -67,6 +68,10 @@ export default class PromptsStages extends Command {
|
|
|
67
68
|
description: 'Accept defaults only in the terminal (no Clack after submit); same semantics as `prompts-test` when used with the submitted or default preset.',
|
|
68
69
|
default: false,
|
|
69
70
|
}),
|
|
71
|
+
locale: Flags.string({
|
|
72
|
+
description: CLI_LOCALE_FLAG_DESCRIPTION,
|
|
73
|
+
options: CLI_LOCALE_FLAG_OPTIONS,
|
|
74
|
+
}),
|
|
70
75
|
file: Flags.string({
|
|
71
76
|
char: 'f',
|
|
72
77
|
description: 'Merged into initialValues.file (default for the text prompt when set)',
|
|
@@ -96,6 +101,7 @@ export default class PromptsStages extends Command {
|
|
|
96
101
|
};
|
|
97
102
|
async run() {
|
|
98
103
|
const { args, flags } = await this.parse(PromptsStages);
|
|
104
|
+
applyCliLocale(flags.locale);
|
|
99
105
|
let presetValues = this.buildPresetValuesFromParsed(args, flags);
|
|
100
106
|
if (flags.ui) {
|
|
101
107
|
presetValues = await runPromptCatalogWebUI({
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import * as p from '@clack/prompts';
|
|
10
10
|
import { Args, Command, Flags } from '@oclif/core';
|
|
11
11
|
import { runPromptCatalog, } from "../lib/prompt-catalog.js";
|
|
12
|
+
import { applyCliLocale, CLI_LOCALE_FLAG_DESCRIPTION, CLI_LOCALE_FLAG_OPTIONS, } from "../lib/cli-locale.js";
|
|
12
13
|
import { runPromptCatalogWebUI, } from "../lib/prompt-web-ui.js";
|
|
13
14
|
export default class PromptsTest extends Command {
|
|
14
15
|
static hidden = true;
|
|
@@ -33,6 +34,10 @@ export default class PromptsTest extends Command {
|
|
|
33
34
|
description: 'Accept defaults only (no prompts); uses `yesInitialValues` merged over `initialValues`, then per-block `yesInitialValue`. Same as non-TTY.',
|
|
34
35
|
default: false,
|
|
35
36
|
}),
|
|
37
|
+
locale: Flags.string({
|
|
38
|
+
description: CLI_LOCALE_FLAG_DESCRIPTION,
|
|
39
|
+
options: CLI_LOCALE_FLAG_OPTIONS,
|
|
40
|
+
}),
|
|
36
41
|
file: Flags.string({
|
|
37
42
|
char: 'f',
|
|
38
43
|
description: 'Merged into initialValues.file (default for the text prompt when set)',
|
|
@@ -127,6 +132,7 @@ export default class PromptsTest extends Command {
|
|
|
127
132
|
};
|
|
128
133
|
async run() {
|
|
129
134
|
const { args, flags } = await this.parse(PromptsTest);
|
|
135
|
+
applyCliLocale(flags.locale);
|
|
130
136
|
let presetValues = this.buildPresetValuesFromParsed(args, flags);
|
|
131
137
|
if (flags.ui) {
|
|
132
138
|
presetValues = await runPromptCatalogWebUI(PromptsTest.prompts, {
|