@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.
Files changed (39) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/bin/run.js +3 -2
  4. package/dist/commands/app/upgrade.js +38 -16
  5. package/dist/commands/backup/create.js +147 -0
  6. package/dist/commands/backup/index.js +20 -0
  7. package/dist/commands/backup/restore.js +105 -0
  8. package/dist/commands/config/delete.js +4 -0
  9. package/dist/commands/config/get.js +4 -0
  10. package/dist/commands/config/set.js +5 -1
  11. package/dist/commands/env/add.js +129 -15
  12. package/dist/commands/env/auth.js +145 -12
  13. package/dist/commands/env/info.js +52 -8
  14. package/dist/commands/env/list.js +2 -2
  15. package/dist/commands/env/shared.js +41 -3
  16. package/dist/commands/init.js +254 -136
  17. package/dist/commands/install.js +447 -272
  18. package/dist/commands/license/activate.js +6 -4
  19. package/dist/commands/source/publish.js +17 -0
  20. package/dist/commands/v1.js +210 -0
  21. package/dist/lib/app-managed-resources.js +20 -1
  22. package/dist/lib/app-runtime.js +13 -4
  23. package/dist/lib/auth-store.js +69 -18
  24. package/dist/lib/backup.js +171 -0
  25. package/dist/lib/bootstrap.js +23 -13
  26. package/dist/lib/cli-config.js +99 -4
  27. package/dist/lib/cli-locale.js +19 -7
  28. package/dist/lib/db-connection-check.js +61 -0
  29. package/dist/lib/env-auth.js +79 -0
  30. package/dist/lib/env-config.js +8 -1
  31. package/dist/lib/prompt-validators.js +23 -5
  32. package/dist/lib/prompt-web-ui.js +143 -19
  33. package/dist/lib/run-npm.js +166 -30
  34. package/dist/lib/skills-manager.js +74 -4
  35. package/dist/lib/source-publish.js +20 -1
  36. package/dist/lib/source-registry.js +2 -2
  37. package/dist/locale/en-US.json +36 -5
  38. package/dist/locale/zh-CN.json +36 -5
  39. package/package.json +6 -3
@@ -15,9 +15,9 @@ import { getEnv, upsertEnv } from "../lib/auth-store.js";
15
15
  import { runPromptCatalog, } from "../lib/prompt-catalog.js";
16
16
  import { applyCliLocale, localeText, translateCli } from "../lib/cli-locale.js";
17
17
  import { resolveDefaultConfigScope } from '../lib/cli-home.js';
18
- import { runPromptCatalogWebUI, } from "../lib/prompt-web-ui.js";
18
+ import { runPromptCatalogWebUI } from "../lib/prompt-web-ui.js";
19
19
  import { validateApiBaseUrl, validateEnvKey } from "../lib/prompt-validators.js";
20
- import { inspectSkillsStatus, installNocoBaseSkills, updateNocoBaseSkills, } from '../lib/skills-manager.js';
20
+ import { installNocoBaseSkills, isNpmRegistryUnavailable } from '../lib/skills-manager.js';
21
21
  import { omitKeys, pickKeys } from "../lib/object-utils.js";
22
22
  import { printInfo, printStage, printVerbose, printWarning } from '../lib/ui.js';
23
23
  import Download from "./download.js";
@@ -33,6 +33,9 @@ const INIT_ENV_ADD_FLAG_NAMES = [
33
33
  'auth-type',
34
34
  'access-token',
35
35
  'token',
36
+ 'username',
37
+ 'password',
38
+ 'skip-auth',
36
39
  ];
37
40
  const initText = (key, values) => localeText(`commands.init.${key}`, values);
38
41
  function withExtraHidden(def, extraHidden) {
@@ -50,8 +53,8 @@ function existingAppOnly(def) {
50
53
  function newInstallOnly(def) {
51
54
  return withExtraHidden(def, (values) => values.hasNocobase !== 'no');
52
55
  }
53
- function downloadInNewInstallOnly(def) {
54
- return withExtraHidden(def, (values) => values.hasNocobase !== 'no' || values.fetchSource !== true);
56
+ function newInstallDownloadExecutionOnly(def) {
57
+ return withExtraHidden(def, (values) => values.hasNocobase !== 'no' || values.skipDownload === true);
55
58
  }
56
59
  function argvHasToken(argv, tokens) {
57
60
  return tokens.some((token) => argv.includes(token));
@@ -64,9 +67,7 @@ function resolveInitDownloadVersion(results) {
64
67
  return preset;
65
68
  }
66
69
  function initVersionPromptValue(version) {
67
- return version === 'latest' || version === 'beta' || version === 'alpha'
68
- ? version
69
- : 'other';
70
+ return version === 'latest' || version === 'beta' || version === 'alpha' ? version : 'other';
70
71
  }
71
72
  function yesInitialValue(def, fallback) {
72
73
  if ('yesInitialValue' in def && def.yesInitialValue !== undefined) {
@@ -75,8 +76,7 @@ function yesInitialValue(def, fallback) {
75
76
  return fallback;
76
77
  }
77
78
  function hasDownloadOverride(flags) {
78
- return Boolean(String(flags.source ?? '').trim()
79
- || String(flags.version ?? '').trim());
79
+ return Boolean(String(flags.source ?? '').trim() || String(flags.version ?? '').trim());
80
80
  }
81
81
  function explicitApiBaseUrlFlag(flags) {
82
82
  return String(flags['api-base-url'] ?? '').trim();
@@ -124,9 +124,7 @@ function formatSkippedAppNameRequiredMessage() {
124
124
  ].join('\n');
125
125
  }
126
126
  function shellQuoteArg(value) {
127
- return /^[A-Za-z0-9_@%+=:,./-]+$/.test(value)
128
- ? value
129
- : `'${value.replace(/'/g, `'\\''`)}'`;
127
+ return /^[A-Za-z0-9_@%+=:,./-]+$/.test(value) ? value : `'${value.replace(/'/g, `'\\''`)}'`;
130
128
  }
131
129
  function initTitle() {
132
130
  return 'Set up NocoBase';
@@ -233,20 +231,27 @@ Prompt modes:
233
231
  validate: validateApiBaseUrl,
234
232
  }),
235
233
  authType: existingAppOnly(EnvAdd.prompts.authType),
234
+ username: existingAppOnly(EnvAdd.prompts.username),
235
+ password: existingAppOnly(EnvAdd.prompts.password),
236
236
  accessToken: existingAppOnly(EnvAdd.prompts.accessToken),
237
237
  lang: newInstallOnly(Install.appPrompts.lang),
238
238
  appRootPath: newInstallOnly(Install.appPrompts.appRootPath),
239
239
  appPort: newInstallOnly(Install.appPrompts.appPort),
240
240
  storagePath: newInstallOnly(Install.appPrompts.storagePath),
241
- fetchSource: newInstallOnly(Install.appPrompts.fetchSource),
242
- source: downloadInNewInstallOnly(Download.prompts.source),
243
- version: downloadInNewInstallOnly(Download.prompts.version),
244
- otherVersion: downloadInNewInstallOnly(Download.prompts.otherVersion),
245
- dockerRegistry: downloadInNewInstallOnly(Download.prompts.dockerRegistry),
246
- dockerPlatform: downloadInNewInstallOnly(Download.prompts.dockerPlatform),
247
- dockerSave: downloadInNewInstallOnly(Download.prompts.dockerSave),
248
- gitUrl: downloadInNewInstallOnly(Download.prompts.gitUrl),
249
- outputDir: downloadInNewInstallOnly({
241
+ skipDownload: newInstallOnly({
242
+ type: 'boolean',
243
+ message: initText('prompts.skipDownload.message'),
244
+ initialValue: false,
245
+ yesInitialValue: false,
246
+ }),
247
+ source: newInstallOnly(Download.prompts.source),
248
+ version: newInstallOnly(Download.prompts.version),
249
+ otherVersion: newInstallOnly(Download.prompts.otherVersion),
250
+ dockerRegistry: newInstallOnly(Download.prompts.dockerRegistry),
251
+ dockerPlatform: newInstallOnly(Download.prompts.dockerPlatform),
252
+ dockerSave: newInstallDownloadExecutionOnly(Download.prompts.dockerSave),
253
+ gitUrl: newInstallOnly(Download.prompts.gitUrl),
254
+ outputDir: newInstallDownloadExecutionOnly({
250
255
  ...DOWNLOAD_OUTPUT_DIR_PROMPT,
251
256
  hidden: (values) => {
252
257
  const source = String(values.source ?? '').trim();
@@ -267,11 +272,11 @@ Prompt modes:
267
272
  return typeof initialValue === 'function' ? initialValue(values) : String(initialValue ?? '');
268
273
  },
269
274
  }),
270
- npmRegistry: downloadInNewInstallOnly(Download.prompts.npmRegistry),
271
- replace: downloadInNewInstallOnly(Download.prompts.replace),
272
- devDependencies: downloadInNewInstallOnly(Download.prompts.devDependencies),
273
- build: downloadInNewInstallOnly(Download.prompts.build),
274
- buildDts: downloadInNewInstallOnly(Download.prompts.buildDts),
275
+ npmRegistry: newInstallOnly(Download.prompts.npmRegistry),
276
+ replace: newInstallDownloadExecutionOnly(Download.prompts.replace),
277
+ devDependencies: newInstallDownloadExecutionOnly(Download.prompts.devDependencies),
278
+ build: newInstallDownloadExecutionOnly(Download.prompts.build),
279
+ buildDts: newInstallDownloadExecutionOnly(Download.prompts.buildDts),
275
280
  dbDialect: newInstallOnly(Install.dbPrompts.dbDialect),
276
281
  builtinDb: newInstallOnly(Install.dbPrompts.builtinDb),
277
282
  builtinDbImage: newInstallOnly(Install.dbPrompts.builtinDbImage),
@@ -280,11 +285,37 @@ Prompt modes:
280
285
  dbDatabase: newInstallOnly(Install.dbPrompts.dbDatabase),
281
286
  dbUser: newInstallOnly(Install.dbPrompts.dbUser),
282
287
  dbPassword: newInstallOnly(Install.dbPrompts.dbPassword),
288
+ dbSchema: newInstallOnly(Install.dbPrompts.dbSchema),
289
+ dbTablePrefix: newInstallOnly(Install.dbPrompts.dbTablePrefix),
290
+ dbUnderscored: newInstallOnly(Install.dbPrompts.dbUnderscored),
283
291
  rootUsername: newInstallOnly(Install.rootUserPrompts.rootUsername),
284
292
  rootEmail: newInstallOnly(Install.rootUserPrompts.rootEmail),
285
293
  rootPassword: newInstallOnly(Install.rootUserPrompts.rootPassword),
286
294
  rootNickname: newInstallOnly(Install.rootUserPrompts.rootNickname),
287
295
  };
296
+ buildPromptCatalog(flags) {
297
+ const prompts = {
298
+ ...Init.prompts,
299
+ };
300
+ if (flags['skip-auth']) {
301
+ const accessTokenPrompt = {
302
+ ...EnvAdd.prompts.accessToken,
303
+ hidden: () => true,
304
+ };
305
+ const usernamePrompt = {
306
+ ...EnvAdd.prompts.username,
307
+ hidden: () => true,
308
+ };
309
+ const passwordPrompt = {
310
+ ...EnvAdd.prompts.password,
311
+ hidden: () => true,
312
+ };
313
+ prompts.username = existingAppOnly(usernamePrompt);
314
+ prompts.password = existingAppOnly(passwordPrompt);
315
+ prompts.accessToken = existingAppOnly(accessTokenPrompt);
316
+ }
317
+ return prompts;
318
+ }
288
319
  parsedFlagsForPromptSeeds;
289
320
  static flags = {
290
321
  yes: Flags.boolean({
@@ -305,7 +336,7 @@ Prompt modes:
305
336
  default: false,
306
337
  }),
307
338
  'skip-skills': Flags.boolean({
308
- description: 'Skip installing or updating NocoBase AI coding skills during init',
339
+ description: 'Skip installing NocoBase AI coding skills during init',
309
340
  default: false,
310
341
  }),
311
342
  'ui-host': Flags.string({
@@ -330,11 +361,14 @@ Prompt modes:
330
361
  if (normalizedFlags.ui && normalizedFlags.yes) {
331
362
  this.error('--ui cannot be used with --yes.');
332
363
  }
364
+ if (normalizedFlags['skip-auth'] &&
365
+ (normalizedFlags['access-token'] !== undefined || normalizedFlags.token !== undefined)) {
366
+ this.error('--skip-auth cannot be used with --access-token or --token.');
367
+ }
333
368
  if (normalizedFlags.ui && normalizedFlags.resume) {
334
369
  this.error('--ui cannot be used with --resume.');
335
370
  }
336
- if (!normalizedFlags.ui &&
337
- (normalizedFlags['ui-host'] !== undefined || normalizedFlags['ui-port'] !== undefined)) {
371
+ if (!normalizedFlags.ui && (normalizedFlags['ui-host'] !== undefined || normalizedFlags['ui-port'] !== undefined)) {
338
372
  this.error('--ui-host and --ui-port require --ui.');
339
373
  }
340
374
  if (normalizedFlags.resume) {
@@ -397,9 +431,10 @@ Prompt modes:
397
431
  }
398
432
  }
399
433
  const dynamicInitialValues = await Init.buildDynamicInitialValuesForInstall(normalizedFlags, presetValues);
434
+ const promptCatalog = this.buildPromptCatalog(normalizedFlags);
400
435
  if (useBrowserUi) {
401
436
  presetValues = await runPromptCatalogWebUI({
402
- stages: Init.buildWebUiStages(),
437
+ stages: Init.buildWebUiStages(promptCatalog),
403
438
  values: {
404
439
  ...dynamicInitialValues,
405
440
  ...presetValues,
@@ -418,7 +453,7 @@ Prompt modes:
418
453
  },
419
454
  });
420
455
  }
421
- const results = await runPromptCatalog(Init.prompts, {
456
+ const results = await runPromptCatalog(promptCatalog, {
422
457
  initialValues: dynamicInitialValues,
423
458
  values: presetValues,
424
459
  yes: normalizedFlags.yes || useBrowserUi || !interactive,
@@ -434,9 +469,22 @@ Prompt modes:
434
469
  },
435
470
  command: this,
436
471
  });
437
- const hasNocobase = results.hasNocobase === 'yes';
472
+ const normalizedResults = {
473
+ ...pickKeys(presetValues, [
474
+ 'authType',
475
+ 'accessToken',
476
+ 'dbSchema',
477
+ 'dbTablePrefix',
478
+ 'dbUnderscored',
479
+ 'skipAuth',
480
+ 'username',
481
+ 'password',
482
+ ]),
483
+ ...results,
484
+ };
485
+ const hasNocobase = normalizedResults.hasNocobase === 'yes';
438
486
  const existingEnv = !hasNocobase
439
- ? await getEnv(String(results.appName ?? '').trim(), { scope: resolveDefaultConfigScope() })
487
+ ? await getEnv(String(normalizedResults.appName ?? '').trim(), { scope: resolveDefaultConfigScope() })
440
488
  : undefined;
441
489
  if (existingEnv && Boolean(normalizedFlags.force)) {
442
490
  printWarning(`Reconfiguring existing env ${pc.cyan(pc.bold(`"${existingEnv.name}"`))} from the global config because ${pc.bold('--force')} was set. The env config will be updated before install starts, then refreshed again after install succeeds.`);
@@ -450,15 +498,15 @@ Prompt modes:
450
498
  if (hasNocobase) {
451
499
  logInitStage('Connecting to the env');
452
500
  printVerbose('Running nb env add');
453
- await this.config.runCommand('env:add', this.buildEnvAddArgv(results));
501
+ await this.config.runCommand('env:add', this.buildEnvAddArgv(normalizedResults));
454
502
  }
455
503
  else {
456
504
  logInitStage('Saving env config');
457
- await this.persistManagedEnvConfig(results, normalizedFlags);
458
- managedInstallResults = results;
459
- printInfo(`Saved env config for "${String(results.appName ?? DEFAULT_INIT_APP_NAME).trim() || DEFAULT_INIT_APP_NAME}".`);
505
+ await this.persistManagedEnvConfig(normalizedResults, normalizedFlags);
506
+ managedInstallResults = normalizedResults;
507
+ printInfo(`Saved env config for "${String(normalizedResults.appName ?? DEFAULT_INIT_APP_NAME).trim() || DEFAULT_INIT_APP_NAME}".`);
460
508
  printVerbose('Running nb init');
461
- await this.config.runCommand('install', this.buildInstallArgv(results, normalizedFlags));
509
+ await this.config.runCommand('install', this.buildInstallArgv(normalizedResults, normalizedFlags));
462
510
  }
463
511
  }
464
512
  catch (error) {
@@ -487,9 +535,7 @@ Prompt modes:
487
535
  }
488
536
  }
489
537
  const downloadSeed = { ...presetValues };
490
- if (flags.yes
491
- && !Object.prototype.hasOwnProperty.call(downloadSeed, 'source')
492
- && downloadSeed.fetchSource !== false) {
538
+ if (flags.yes && !Object.prototype.hasOwnProperty.call(downloadSeed, 'source')) {
493
539
  downloadSeed.source = 'docker';
494
540
  }
495
541
  const dbInitial = await Install.buildDbPromptInitialValues({
@@ -505,8 +551,7 @@ Prompt modes:
505
551
  }
506
552
  return out;
507
553
  }
508
- static buildWebUiStages() {
509
- const c = Init.prompts;
554
+ static buildWebUiStages(c = Init.prompts) {
510
555
  return [
511
556
  {
512
557
  sectionTitle: initText('webUi.gettingStarted.title'),
@@ -522,6 +567,8 @@ Prompt modes:
522
567
  catalog: {
523
568
  apiBaseUrl: c.apiBaseUrl,
524
569
  authType: c.authType,
570
+ username: c.username,
571
+ password: c.password,
525
572
  accessToken: c.accessToken,
526
573
  },
527
574
  },
@@ -533,7 +580,7 @@ Prompt modes:
533
580
  appRootPath: c.appRootPath,
534
581
  appPort: c.appPort,
535
582
  storagePath: c.storagePath,
536
- fetchSource: c.fetchSource,
583
+ skipDownload: c.skipDownload,
537
584
  },
538
585
  },
539
586
  {
@@ -567,6 +614,9 @@ Prompt modes:
567
614
  dbDatabase: c.dbDatabase,
568
615
  dbUser: c.dbUser,
569
616
  dbPassword: c.dbPassword,
617
+ dbSchema: c.dbSchema,
618
+ dbTablePrefix: c.dbTablePrefix,
619
+ dbUnderscored: c.dbUnderscored,
570
620
  },
571
621
  },
572
622
  {
@@ -592,17 +642,25 @@ Prompt modes:
592
642
  preset.hasNocobase = 'yes';
593
643
  preset.apiBaseUrl = apiBaseUrl;
594
644
  }
595
- else if (flags['default-api-base-url'] !== undefined
596
- && String(flags['default-api-base-url']).trim() !== '') {
645
+ else if (flags['default-api-base-url'] !== undefined && String(flags['default-api-base-url']).trim() !== '') {
597
646
  preset.apiBaseUrl = String(flags['default-api-base-url']).trim();
598
647
  }
599
648
  if (flags['auth-type'] !== undefined && String(flags['auth-type']).trim() !== '') {
600
649
  preset.authType = String(flags['auth-type']).trim();
601
650
  }
651
+ if (flags['skip-auth']) {
652
+ preset.skipAuth = true;
653
+ }
602
654
  const accessToken = String(flags['access-token'] ?? flags.token ?? '');
603
655
  if (flags['access-token'] !== undefined || flags.token !== undefined) {
604
656
  preset.accessToken = accessToken;
605
657
  }
658
+ if (flags.username !== undefined) {
659
+ preset.username = String(flags.username ?? '').trim();
660
+ }
661
+ if (flags.password !== undefined) {
662
+ preset.password = String(flags.password ?? '');
663
+ }
606
664
  if (flags.lang !== undefined && String(flags.lang).trim() !== '') {
607
665
  preset.lang = String(flags.lang).trim();
608
666
  }
@@ -649,8 +707,24 @@ Prompt modes:
649
707
  if (flags['db-password'] !== undefined) {
650
708
  preset.dbPassword = String(flags['db-password'] ?? '');
651
709
  }
652
- if (argvHasToken(argv, ['--fetch-source'])) {
653
- preset.fetchSource = Boolean(flags['fetch-source']);
710
+ if (flags['db-schema'] !== undefined && String(flags['db-schema']).trim() !== '') {
711
+ preset.dbSchema = String(flags['db-schema']).trim();
712
+ }
713
+ if (flags['db-table-prefix'] !== undefined && String(flags['db-table-prefix']).trim() !== '') {
714
+ preset.dbTablePrefix = String(flags['db-table-prefix']).trim();
715
+ }
716
+ if (argvHasToken(argv, ['--db-underscored', '--no-db-underscored'])) {
717
+ preset.dbUnderscored = Boolean(flags['db-underscored']);
718
+ }
719
+ if (argvHasToken(argv, ['--skip-download'])) {
720
+ preset.skipDownload = Boolean(flags['skip-download']);
721
+ if (preset.skipDownload) {
722
+ preset.dockerSave = false;
723
+ preset.replace = false;
724
+ preset.devDependencies = false;
725
+ preset.build = false;
726
+ preset.buildDts = false;
727
+ }
654
728
  }
655
729
  if (flags.source !== undefined && String(flags.source).trim() !== '') {
656
730
  preset.source = String(flags.source).trim();
@@ -713,19 +787,16 @@ Prompt modes:
713
787
  }
714
788
  try {
715
789
  logInitStage('Syncing agent skills');
716
- const status = await inspectSkillsStatus();
717
- if (!status.installed) {
718
- printVerbose('Installing NocoBase agent skills (nb skills install)');
719
- await installNocoBaseSkills();
720
- printInfo('Agent skills ready.');
721
- return;
722
- }
723
- printVerbose('Updating NocoBase agent skills (nb skills update)');
724
- await updateNocoBaseSkills();
790
+ await installNocoBaseSkills();
725
791
  printInfo('Agent skills ready.');
726
792
  }
727
793
  catch (error) {
728
794
  const message = error instanceof Error ? error.message : String(error);
795
+ if (isNpmRegistryUnavailable(error)) {
796
+ printWarning(translateCli('commands.init.messages.skillsSyncRegistryUnavailable'));
797
+ printVerbose(`Skipped agent skills sync because the npm registry was unavailable: ${message}`);
798
+ return;
799
+ }
729
800
  this.error(pc.red(`Skills sync failed: ${message}`));
730
801
  this.exit(1);
731
802
  }
@@ -748,9 +819,13 @@ Prompt modes:
748
819
  const dbDatabase = String(results.dbDatabase ?? '').trim();
749
820
  const dbUser = String(results.dbUser ?? '').trim();
750
821
  const dbPassword = String(results.dbPassword ?? '');
822
+ const dbSchema = String(results.dbSchema ?? '').trim();
823
+ const dbTablePrefix = String(results.dbTablePrefix ?? '').trim();
751
824
  const apiBaseUrl = String(results.apiBaseUrl ?? '').trim();
752
825
  const authType = String(results.authType ?? '').trim() || 'oauth';
826
+ const authUsername = authType === 'basic' ? String(results.username ?? results.rootUsername ?? '').trim() : '';
753
827
  const accessToken = String(results.accessToken ?? '');
828
+ const skipDownload = results.skipDownload === true;
754
829
  const builtinDb = explicitDbHostFlag(flags)
755
830
  ? false
756
831
  : results.builtinDb === undefined
@@ -765,7 +840,9 @@ Prompt modes:
765
840
  ? { kind: 'http' }
766
841
  : {}),
767
842
  ...(apiBaseUrl ? { apiBaseUrl } : appPort ? { apiBaseUrl: `http://127.0.0.1:${appPort}/api` } : {}),
768
- ...(authType === 'token' && accessToken ? { accessToken } : {}),
843
+ ...(authType ? { authType } : {}),
844
+ ...(authUsername ? { authUsername } : {}),
845
+ ...((authType === 'token' || authType === 'basic') && accessToken ? { accessToken } : {}),
769
846
  ...(source ? { source } : {}),
770
847
  ...(version ? { downloadVersion: version } : {}),
771
848
  ...(dockerRegistry ? { dockerRegistry } : {}),
@@ -775,9 +852,11 @@ Prompt modes:
775
852
  ...(appRootPath ? { appRootPath } : {}),
776
853
  ...(storagePath ? { storagePath } : {}),
777
854
  ...(appPort ? { appPort } : {}),
778
- ...(results.devDependencies !== undefined ? { devDependencies: Boolean(results.devDependencies) } : {}),
779
- ...(results.build !== undefined ? { build: Boolean(results.build) } : {}),
780
- ...(results.buildDts !== undefined ? { buildDts: Boolean(results.buildDts) } : {}),
855
+ ...(!skipDownload && results.devDependencies !== undefined
856
+ ? { devDependencies: Boolean(results.devDependencies) }
857
+ : {}),
858
+ ...(!skipDownload && results.build !== undefined ? { build: Boolean(results.build) } : {}),
859
+ ...(!skipDownload && results.buildDts !== undefined ? { buildDts: Boolean(results.buildDts) } : {}),
781
860
  ...(builtinDb !== undefined ? { builtinDb } : {}),
782
861
  ...(dbDialect ? { dbDialect } : {}),
783
862
  ...(builtinDbImage || builtinDb === false ? { builtinDbImage: builtinDbImage || undefined } : {}),
@@ -786,6 +865,9 @@ Prompt modes:
786
865
  ...(dbDatabase ? { dbDatabase } : {}),
787
866
  ...(dbUser ? { dbUser } : {}),
788
867
  ...(dbPassword ? { dbPassword } : {}),
868
+ ...(dbSchema ? { dbSchema } : {}),
869
+ ...(dbTablePrefix ? { dbTablePrefix } : {}),
870
+ ...(results.dbUnderscored !== undefined ? { dbUnderscored: Boolean(results.dbUnderscored) } : {}),
789
871
  }, { scope: resolveDefaultConfigScope() });
790
872
  }
791
873
  buildEnvAddArgv(results) {
@@ -793,8 +875,20 @@ Prompt modes:
793
875
  argv.push('--no-intro');
794
876
  argv.push('--api-base-url', String(results.apiBaseUrl ?? DEFAULT_INIT_API_BASE_URL));
795
877
  argv.push('--auth-type', String(results.authType ?? 'oauth'));
796
- if (results.authType === 'token') {
797
- argv.push('--access-token', String(results.accessToken ?? ''));
878
+ const accessToken = String(results.accessToken ?? '');
879
+ const username = String(results.username ?? '').trim();
880
+ const password = String(results.password ?? '');
881
+ if (results.skipAuth === true) {
882
+ argv.push('--skip-auth');
883
+ }
884
+ else if (results.authType === 'token' && accessToken) {
885
+ argv.push('--access-token', accessToken);
886
+ }
887
+ if (results.authType === 'basic' && username) {
888
+ argv.push('--username', username);
889
+ }
890
+ if (results.authType === 'basic' && results.skipAuth !== true && password) {
891
+ argv.push('--password', password);
798
892
  }
799
893
  return argv;
800
894
  }
@@ -807,15 +901,18 @@ Prompt modes:
807
901
  const processArgv = process.argv.slice(2);
808
902
  const envName = String(results.appName ?? DEFAULT_INIT_APP_NAME).trim() || DEFAULT_INIT_APP_NAME;
809
903
  const source = String(results.source ?? '').trim();
904
+ const skipDownload = Boolean(flags['skip-download']) || results.skipDownload === true;
810
905
  const hasNocobase = String(results.hasNocobase ?? '').trim() === 'yes';
811
906
  const apiBaseUrl = String(results.apiBaseUrl ?? '').trim();
812
907
  const authType = String(results.authType ?? '').trim();
813
908
  const accessToken = String(results.accessToken ?? '');
909
+ const username = String(results.username ?? flags.username ?? '').trim();
910
+ const password = String(results.password ?? flags.password ?? '');
814
911
  argv.push('--env', envName);
815
912
  if (options?.resume) {
816
913
  argv.push('--resume');
817
914
  }
818
- if (Boolean(flags.verbose)) {
915
+ if (flags.verbose) {
819
916
  argv.push('--verbose');
820
917
  }
821
918
  if (hasNocobase && apiBaseUrl) {
@@ -824,9 +921,18 @@ Prompt modes:
824
921
  if (authType) {
825
922
  argv.push('--auth-type', authType);
826
923
  }
924
+ if (Boolean(flags['skip-auth']) || results.skipAuth === true) {
925
+ argv.push('--skip-auth');
926
+ }
827
927
  if (authType === 'token' && accessToken) {
828
928
  argv.push('--access-token', accessToken);
829
929
  }
930
+ if (authType === 'basic' && username) {
931
+ argv.push('--username', username);
932
+ }
933
+ if (authType === 'basic' && password) {
934
+ argv.push('--password', password);
935
+ }
830
936
  const lang = String(results.lang ?? '').trim();
831
937
  if (lang) {
832
938
  argv.push('--lang', lang);
@@ -843,54 +949,56 @@ Prompt modes:
843
949
  if (storagePath) {
844
950
  argv.push('--storage-path', storagePath);
845
951
  }
846
- if (Boolean(flags.force)) {
952
+ if (flags.force) {
847
953
  argv.push('--force');
848
954
  }
849
- if (Boolean(results.fetchSource)) {
850
- argv.push('--fetch-source');
851
- if (source) {
852
- argv.push('--source', source);
853
- }
854
- const version = resolveInitDownloadVersion(results);
855
- if (version) {
856
- argv.push('--version', version);
857
- }
955
+ if (source) {
956
+ argv.push('--source', source);
957
+ }
958
+ const version = resolveInitDownloadVersion(results);
959
+ if (version) {
960
+ argv.push('--version', version);
961
+ }
962
+ const gitUrl = String(results.gitUrl ?? '').trim();
963
+ if (gitUrl) {
964
+ argv.push('--git-url', gitUrl);
965
+ }
966
+ const dockerRegistry = String(results.dockerRegistry ?? '').trim();
967
+ if (dockerRegistry) {
968
+ argv.push('--docker-registry', dockerRegistry);
969
+ }
970
+ const dockerPlatform = String(results.dockerPlatform ?? '').trim();
971
+ if (dockerPlatform) {
972
+ argv.push('--docker-platform', dockerPlatform);
973
+ }
974
+ const npmRegistry = String(results.npmRegistry ?? '').trim();
975
+ if (npmRegistry) {
976
+ argv.push('--npm-registry', npmRegistry);
977
+ }
978
+ if (skipDownload) {
979
+ argv.push('--skip-download');
980
+ }
981
+ else {
858
982
  const outputDir = String(results.outputDir ?? '').trim();
859
983
  if (outputDir) {
860
984
  argv.push('--output-dir', outputDir);
861
985
  }
862
- const gitUrl = String(results.gitUrl ?? '').trim();
863
- if (gitUrl) {
864
- argv.push('--git-url', gitUrl);
865
- }
866
- const dockerRegistry = String(results.dockerRegistry ?? '').trim();
867
- if (dockerRegistry) {
868
- argv.push('--docker-registry', dockerRegistry);
869
- }
870
- const dockerPlatform = String(results.dockerPlatform ?? '').trim();
871
- if (dockerPlatform) {
872
- argv.push('--docker-platform', dockerPlatform);
873
- }
874
- const npmRegistry = String(results.npmRegistry ?? '').trim();
875
- if (npmRegistry) {
876
- argv.push('--npm-registry', npmRegistry);
877
- }
878
- if (Boolean(results.replace)) {
986
+ if (results.replace) {
879
987
  argv.push('--replace');
880
988
  }
881
- if (Boolean(results.devDependencies)) {
989
+ if (results.devDependencies) {
882
990
  argv.push('--dev-dependencies');
883
991
  }
884
- if (Boolean(results.dockerSave)) {
992
+ if (results.dockerSave) {
885
993
  argv.push('--docker-save');
886
994
  }
887
- if (results.build !== undefined && !Boolean(results.build)) {
995
+ if (results.build !== undefined && !results.build) {
888
996
  argv.push('--no-build');
889
997
  }
890
998
  else if (argvHasToken(processArgv, ['--build', '--no-build']) && flags.build === false) {
891
999
  argv.push('--no-build');
892
1000
  }
893
- if (Boolean(results.buildDts)) {
1001
+ if (results.buildDts) {
894
1002
  argv.push('--build-dts');
895
1003
  }
896
1004
  }
@@ -918,9 +1026,9 @@ Prompt modes:
918
1026
  const dbPortWasProvided = argvHasToken(processArgv, ['--db-port']);
919
1027
  const dockerBuiltinDbPortIsHidden = builtinDb && source === 'docker';
920
1028
  const dbDefaultPort = defaultDbPortForDialect(dbDialect);
921
- if (dbPort
922
- && (!dockerBuiltinDbPortIsHidden || dbPortWasProvided)
923
- && (!flags.yes || dbPortWasProvided || dbPort !== dbDefaultPort)) {
1029
+ if (dbPort &&
1030
+ (!dockerBuiltinDbPortIsHidden || dbPortWasProvided) &&
1031
+ (!flags.yes || dbPortWasProvided || dbPort !== dbDefaultPort)) {
924
1032
  argv.push('--db-port', dbPort);
925
1033
  }
926
1034
  const dbDatabase = String(results.dbDatabase ?? '').trim();
@@ -935,6 +1043,17 @@ Prompt modes:
935
1043
  if (dbPassword) {
936
1044
  argv.push('--db-password', dbPassword);
937
1045
  }
1046
+ const dbSchema = String(results.dbSchema ?? '').trim();
1047
+ if (dbSchema) {
1048
+ argv.push('--db-schema', dbSchema);
1049
+ }
1050
+ const dbTablePrefix = String(results.dbTablePrefix ?? '').trim();
1051
+ if (dbTablePrefix) {
1052
+ argv.push('--db-table-prefix', dbTablePrefix);
1053
+ }
1054
+ if (results.dbUnderscored !== undefined) {
1055
+ argv.push(results.dbUnderscored ? '--db-underscored' : '--no-db-underscored');
1056
+ }
938
1057
  const rootUsername = String(results.rootUsername ?? '').trim();
939
1058
  if (rootUsername) {
940
1059
  argv.push('--root-username', rootUsername);
@@ -955,50 +1074,54 @@ Prompt modes:
955
1074
  }
956
1075
  buildManagedInstallResumeCommand(results, flags) {
957
1076
  const argv = ['nb', 'init'];
958
- if (Boolean(flags.yes)) {
1077
+ if (flags.yes) {
959
1078
  argv.push('--yes');
960
1079
  }
961
1080
  const envName = String(results.appName ?? DEFAULT_INIT_APP_NAME).trim() || DEFAULT_INIT_APP_NAME;
962
1081
  argv.push('--env', envName);
963
- if (Boolean(results.fetchSource)) {
964
- const source = String(results.source ?? '').trim();
965
- if (source) {
966
- argv.push('--source', source);
967
- }
968
- const version = resolveInitDownloadVersion(results);
969
- if (version) {
970
- argv.push('--version', version);
971
- }
1082
+ const source = String(results.source ?? '').trim();
1083
+ const skipDownload = Boolean(flags['skip-download']) || results.skipDownload === true;
1084
+ if (source) {
1085
+ argv.push('--source', source);
1086
+ }
1087
+ const version = resolveInitDownloadVersion(results);
1088
+ if (version) {
1089
+ argv.push('--version', version);
1090
+ }
1091
+ const gitUrl = String(results.gitUrl ?? '').trim();
1092
+ if (gitUrl) {
1093
+ argv.push('--git-url', gitUrl);
1094
+ }
1095
+ const dockerRegistry = String(results.dockerRegistry ?? '').trim();
1096
+ if (dockerRegistry) {
1097
+ argv.push('--docker-registry', dockerRegistry);
1098
+ }
1099
+ const dockerPlatform = String(results.dockerPlatform ?? '').trim();
1100
+ if (dockerPlatform) {
1101
+ argv.push('--docker-platform', dockerPlatform);
1102
+ }
1103
+ const npmRegistry = String(results.npmRegistry ?? '').trim();
1104
+ if (npmRegistry) {
1105
+ argv.push('--npm-registry', npmRegistry);
1106
+ }
1107
+ if (skipDownload) {
1108
+ argv.push('--skip-download');
1109
+ }
1110
+ else {
972
1111
  const outputDir = String(results.outputDir ?? '').trim();
973
1112
  if (outputDir && outputDir !== String(results.appRootPath ?? '').trim()) {
974
1113
  argv.push('--output-dir', outputDir);
975
1114
  }
976
- const gitUrl = String(results.gitUrl ?? '').trim();
977
- if (gitUrl) {
978
- argv.push('--git-url', gitUrl);
979
- }
980
- const dockerRegistry = String(results.dockerRegistry ?? '').trim();
981
- if (dockerRegistry) {
982
- argv.push('--docker-registry', dockerRegistry);
983
- }
984
- const dockerPlatform = String(results.dockerPlatform ?? '').trim();
985
- if (dockerPlatform) {
986
- argv.push('--docker-platform', dockerPlatform);
987
- }
988
- const npmRegistry = String(results.npmRegistry ?? '').trim();
989
- if (npmRegistry) {
990
- argv.push('--npm-registry', npmRegistry);
991
- }
992
- if (Boolean(results.devDependencies)) {
1115
+ if (results.devDependencies) {
993
1116
  argv.push('--dev-dependencies');
994
1117
  }
995
- if (Boolean(results.dockerSave)) {
1118
+ if (results.dockerSave) {
996
1119
  argv.push('--docker-save');
997
1120
  }
998
- if (results.build !== undefined && !Boolean(results.build)) {
1121
+ if (results.build !== undefined && !results.build) {
999
1122
  argv.push('--no-build');
1000
1123
  }
1001
- if (Boolean(results.buildDts)) {
1124
+ if (results.buildDts) {
1002
1125
  argv.push('--build-dts');
1003
1126
  }
1004
1127
  }
@@ -1007,11 +1130,7 @@ Prompt modes:
1007
1130
  }
1008
1131
  formatManagedInstallFailureMessage(message, results, flags) {
1009
1132
  const command = this.buildManagedInstallResumeCommand(results, flags);
1010
- return [
1011
- message,
1012
- '',
1013
- translateCli('commands.init.messages.resumeAfterInstallFailure', { command }),
1014
- ].join('\n');
1133
+ return [message, '', translateCli('commands.init.messages.resumeAfterInstallFailure', { command })].join('\n');
1015
1134
  }
1016
1135
  buildResumeInstallArgv(flags) {
1017
1136
  const preset = this.buildPresetValuesFromFlags(flags);
@@ -1022,10 +1141,9 @@ Prompt modes:
1022
1141
  preset.rootPassword ??= yesInitialValue(Install.rootUserPrompts.rootPassword, 'admin123');
1023
1142
  preset.rootNickname ??= yesInitialValue(Install.rootUserPrompts.rootNickname, 'Super Admin');
1024
1143
  }
1025
- if (hasDownloadOverride(flags)) {
1026
- preset.fetchSource ??= true;
1144
+ if (!flags['skip-download']) {
1145
+ preset.replace ??= true;
1027
1146
  }
1028
- preset.replace ??= true;
1029
1147
  return this.buildInstallArgv(preset, flags, {
1030
1148
  nonInteractive: Boolean(flags.yes),
1031
1149
  resume: true,