@nocobase/cli 2.1.0-beta.20 → 2.1.0-beta.22

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 (74) hide show
  1. package/README.md +32 -50
  2. package/README.zh-CN.md +29 -46
  3. package/bin/run.js +15 -0
  4. package/dist/commands/app/down.js +260 -0
  5. package/dist/commands/app/info.js +140 -0
  6. package/dist/commands/app/logs.js +98 -0
  7. package/dist/commands/app/ps.js +60 -0
  8. package/dist/commands/app/restart.js +75 -0
  9. package/dist/commands/app/shared.js +95 -0
  10. package/dist/commands/app/start.js +252 -0
  11. package/dist/commands/app/stop.js +98 -0
  12. package/dist/commands/app/upgrade.js +595 -0
  13. package/dist/commands/build.js +3 -48
  14. package/dist/commands/db/shared.js +19 -5
  15. package/dist/commands/dev.js +3 -140
  16. package/dist/commands/down.js +3 -184
  17. package/dist/commands/download.js +4 -856
  18. package/dist/commands/env/add.js +33 -48
  19. package/dist/commands/env/auth.js +6 -13
  20. package/dist/commands/env/list.js +10 -15
  21. package/dist/commands/env/remove.js +4 -10
  22. package/dist/commands/env/update.js +7 -13
  23. package/dist/commands/env/use.js +5 -13
  24. package/dist/commands/{prompts-stages.js → examples/prompts-stages.js} +3 -3
  25. package/dist/commands/{prompts-test.js → examples/prompts-test.js} +3 -3
  26. package/dist/commands/init.js +262 -63
  27. package/dist/commands/install.js +352 -86
  28. package/dist/commands/logs.js +3 -81
  29. package/dist/commands/plugin/disable.js +64 -0
  30. package/dist/commands/plugin/enable.js +64 -0
  31. package/dist/commands/plugin/list.js +62 -0
  32. package/dist/commands/pm/disable.js +3 -54
  33. package/dist/commands/pm/enable.js +3 -54
  34. package/dist/commands/pm/list.js +3 -45
  35. package/dist/commands/ps.js +3 -107
  36. package/dist/commands/restart.js +3 -65
  37. package/dist/commands/scaffold/migration.js +1 -1
  38. package/dist/commands/scaffold/plugin.js +1 -1
  39. package/dist/commands/self/check.js +1 -1
  40. package/dist/commands/self/update.js +13 -3
  41. package/dist/commands/skills/check.js +11 -5
  42. package/dist/commands/skills/index.js +1 -1
  43. package/dist/commands/skills/install.js +20 -7
  44. package/dist/commands/skills/remove.js +71 -0
  45. package/dist/commands/skills/update.js +27 -7
  46. package/dist/commands/source/build.js +58 -0
  47. package/dist/commands/source/dev.js +157 -0
  48. package/dist/commands/source/download.js +866 -0
  49. package/dist/commands/source/test.js +467 -0
  50. package/dist/commands/start.js +3 -202
  51. package/dist/commands/stop.js +3 -81
  52. package/dist/commands/test.js +3 -457
  53. package/dist/commands/upgrade.js +3 -574
  54. package/dist/help/runtime-help.js +3 -0
  55. package/dist/lib/api-client.js +3 -2
  56. package/dist/lib/app-health.js +126 -0
  57. package/dist/lib/app-managed-resources.js +264 -0
  58. package/dist/lib/app-runtime.js +16 -5
  59. package/dist/lib/auth-store.js +162 -43
  60. package/dist/lib/bootstrap.js +13 -12
  61. package/dist/lib/cli-home.js +38 -6
  62. package/dist/lib/cli-locale.js +15 -1
  63. package/dist/lib/env-auth.js +3 -3
  64. package/dist/lib/env-config.js +80 -0
  65. package/dist/lib/generated-command.js +10 -2
  66. package/dist/lib/http-request.js +49 -0
  67. package/dist/lib/resource-command.js +10 -2
  68. package/dist/lib/runtime-generator.js +1 -1
  69. package/dist/lib/self-manager.js +1 -1
  70. package/dist/lib/skills-manager.js +173 -79
  71. package/dist/lib/startup-update.js +203 -0
  72. package/dist/locale/en-US.json +4 -1
  73. package/dist/locale/zh-CN.json +4 -1
  74. package/package.json +26 -3
@@ -15,9 +15,10 @@ import { stdin as stdinStream, stdout as stdoutStream } from 'node:process';
15
15
  import { getEnv, upsertEnv } from "../lib/auth-store.js";
16
16
  import { runPromptCatalog, } from "../lib/prompt-catalog.js";
17
17
  import { applyCliLocale, localeText, translateCli } from "../lib/cli-locale.js";
18
+ import { resolveDefaultConfigScope } from '../lib/cli-home.js';
18
19
  import { runPromptCatalogWebUI, } from "../lib/prompt-web-ui.js";
19
20
  import { validateApiBaseUrl, validateEnvKey } from "../lib/prompt-validators.js";
20
- import { installNocoBaseSkills } from '../lib/skills-manager.js';
21
+ import { inspectSkillsStatus, installNocoBaseSkills, updateNocoBaseSkills, } from '../lib/skills-manager.js';
21
22
  import Download from "./download.js";
22
23
  import EnvAdd from "./env/add.js";
23
24
  import Install, { defaultDbPortForDialect } from "./install.js";
@@ -25,7 +26,14 @@ import _ from 'lodash';
25
26
  const DEFAULT_INIT_API_BASE_URL = 'http://localhost:13000/api';
26
27
  const DEFAULT_INIT_APP_NAME = 'local';
27
28
  const DOWNLOAD_OUTPUT_DIR_PROMPT = Download.prompts.outputDir;
28
- const CONFIG_SCOPE = 'project';
29
+ const INIT_ENV_ADD_FLAG_NAMES = [
30
+ 'locale',
31
+ 'default-api-base-url',
32
+ 'api-base-url',
33
+ 'auth-type',
34
+ 'access-token',
35
+ 'token',
36
+ ];
29
37
  const initText = (key, values) => localeText(`commands.init.${key}`, values);
30
38
  function withExtraHidden(def, extraHidden) {
31
39
  if (def.type === 'run') {
@@ -55,6 +63,27 @@ function resolveInitDownloadVersion(results) {
55
63
  }
56
64
  return preset;
57
65
  }
66
+ function initVersionPromptValue(version) {
67
+ return version === 'latest' || version === 'beta' || version === 'alpha'
68
+ ? version
69
+ : 'other';
70
+ }
71
+ function yesInitialValue(def, fallback) {
72
+ if ('yesInitialValue' in def && def.yesInitialValue !== undefined) {
73
+ return String(def.yesInitialValue);
74
+ }
75
+ return fallback;
76
+ }
77
+ function hasDownloadOverride(flags) {
78
+ return Boolean(String(flags.source ?? '').trim()
79
+ || String(flags.version ?? '').trim());
80
+ }
81
+ function explicitApiBaseUrlFlag(flags) {
82
+ return String(flags['api-base-url'] ?? '').trim();
83
+ }
84
+ function explicitDbHostFlag(flags) {
85
+ return String(flags['db-host'] ?? '').trim();
86
+ }
58
87
  function shouldAllowExistingInitEnv() {
59
88
  return argvHasToken(process.argv.slice(2), ['--force', '-f']);
60
89
  }
@@ -67,7 +96,7 @@ async function validateInitAppName(value) {
67
96
  if (!envName) {
68
97
  return undefined;
69
98
  }
70
- const existingEnv = await getEnv(envName, { scope: 'project' });
99
+ const existingEnv = await getEnv(envName, { scope: resolveDefaultConfigScope() });
71
100
  if (existingEnv) {
72
101
  if (shouldAllowExistingInitEnv()) {
73
102
  return undefined;
@@ -94,6 +123,11 @@ function formatSkippedAppNameRequiredMessage() {
94
123
  translateCli('commands.init.messages.appNameEnvHelp'),
95
124
  ].join('\n');
96
125
  }
126
+ function shellQuoteArg(value) {
127
+ return /^[A-Za-z0-9_@%+=:,./-]+$/.test(value)
128
+ ? value
129
+ : `'${value.replace(/'/g, `'\\''`)}'`;
130
+ }
97
131
  function initTitle() {
98
132
  return translateCli('commands.init.messages.title');
99
133
  }
@@ -137,6 +171,26 @@ Prompt modes:
137
171
  '<%= config.bin %> <%= command.id %> --ui --ui-port 3000',
138
172
  ];
139
173
  static prompts = {
174
+ seedResume: {
175
+ type: 'run',
176
+ run: (values, command) => {
177
+ const record = values;
178
+ if (record.resume === undefined) {
179
+ const flags = command?.parsedFlagsForPromptSeeds;
180
+ record.resume = Boolean(flags?.resume);
181
+ }
182
+ },
183
+ },
184
+ seedEnvName: {
185
+ type: 'run',
186
+ run: (values) => {
187
+ const record = values;
188
+ const appName = String(record.appName ?? '').trim();
189
+ if (appName && record.env === undefined) {
190
+ record.env = appName;
191
+ }
192
+ },
193
+ },
140
194
  appName: {
141
195
  type: 'text',
142
196
  message: initText('prompts.appName.message'),
@@ -162,12 +216,6 @@ Prompt modes:
162
216
  yesInitialValue: 'no',
163
217
  required: true,
164
218
  },
165
- installSkills: {
166
- type: 'boolean',
167
- message: initText('prompts.installSkills.message'),
168
- initialValue: true,
169
- yesInitialValue: true,
170
- },
171
219
  apiBaseUrl: existingAppOnly({
172
220
  type: 'text',
173
221
  message: initText('prompts.apiBaseUrl.message'),
@@ -228,6 +276,7 @@ Prompt modes:
228
276
  rootPassword: newInstallOnly(Install.rootUserPrompts.rootPassword),
229
277
  rootNickname: newInstallOnly(Install.rootUserPrompts.rootNickname),
230
278
  };
279
+ parsedFlagsForPromptSeeds;
231
280
  static flags = {
232
281
  yes: Flags.boolean({
233
282
  char: 'y',
@@ -238,10 +287,6 @@ Prompt modes:
238
287
  char: 'e',
239
288
  description: 'Env name for this setup. Required with --yes and --resume',
240
289
  }),
241
- 'install-skills': Flags.boolean({
242
- description: 'Install NocoBase AI coding skills (`nocobase/skills`) for this workspace',
243
- default: false,
244
- }),
245
290
  ui: Flags.boolean({
246
291
  description: 'Open the guided setup flow in a local browser form (not valid with --yes)',
247
292
  default: false,
@@ -250,6 +295,11 @@ Prompt modes:
250
295
  description: 'Show detailed command output',
251
296
  default: false,
252
297
  }),
298
+ 'skip-skills': Flags.boolean({
299
+ description: 'Skip installing or updating NocoBase AI coding skills during init',
300
+ hidden: true,
301
+ default: false,
302
+ }),
253
303
  'ui-host': Flags.string({
254
304
  description: 'Host for the local --ui setup server (default: 127.0.0.1)',
255
305
  }),
@@ -258,6 +308,7 @@ Prompt modes:
258
308
  min: 0,
259
309
  max: 65535,
260
310
  }),
311
+ ..._.pick(EnvAdd.flags, INIT_ENV_ADD_FLAG_NAMES),
261
312
  ..._.omit(Install.flags, ['yes', 'env']),
262
313
  };
263
314
  async run() {
@@ -265,6 +316,9 @@ Prompt modes:
265
316
  applyCliLocale(parsedResult.flags.locale);
266
317
  const flags = parsedResult.flags;
267
318
  const normalizedFlags = { ...flags };
319
+ this.parsedFlagsForPromptSeeds = {
320
+ resume: Boolean(normalizedFlags.resume),
321
+ };
268
322
  if (normalizedFlags.ui && normalizedFlags.yes) {
269
323
  this.error('--ui cannot be used with --yes.');
270
324
  }
@@ -282,24 +336,14 @@ Prompt modes:
282
336
  this.exit(1);
283
337
  }
284
338
  p.intro(initTitle());
285
- if (Boolean(normalizedFlags['install-skills'])) {
286
- try {
287
- p.log.step('Installing NocoBase agent skills (nb skills install)');
288
- await installNocoBaseSkills();
289
- }
290
- catch (error) {
291
- const message = error instanceof Error ? error.message : String(error);
292
- p.outro(pc.red(`Skills install failed: ${message}`));
293
- this.error(message);
294
- }
295
- }
339
+ await this.syncNocoBaseSkills({
340
+ skip: Boolean(normalizedFlags['skip-skills']),
341
+ });
296
342
  try {
297
- p.log.step(`Resuming setup for env "${envName}" from the saved workspace config`);
298
343
  await this.config.runCommand('install', this.buildResumeInstallArgv(normalizedFlags));
299
344
  }
300
345
  catch (error) {
301
346
  const message = error instanceof Error ? error.message : String(error);
302
- p.outro(pc.red(message));
303
347
  this.error(message);
304
348
  }
305
349
  p.outro('Workspace init finished.');
@@ -308,6 +352,24 @@ Prompt modes:
308
352
  const interactive = Boolean(stdinStream.isTTY && stdoutStream.isTTY);
309
353
  const useBrowserUi = Boolean(normalizedFlags.ui);
310
354
  let presetValues = this.buildPresetValuesFromFlags(normalizedFlags);
355
+ if (normalizedFlags.resume) {
356
+ const resumeEnvName = String(normalizedFlags.env ?? '').trim();
357
+ if (resumeEnvName) {
358
+ const resumeEnv = await getEnv(resumeEnvName, {
359
+ scope: resolveDefaultConfigScope(),
360
+ });
361
+ if (resumeEnv) {
362
+ const savedAppPort = String(resumeEnv.config.appPort ?? '').trim();
363
+ const savedDbPort = String(resumeEnv.config.dbPort ?? '').trim();
364
+ if (savedAppPort) {
365
+ presetValues.resumeSavedAppPort = savedAppPort;
366
+ }
367
+ if (savedDbPort) {
368
+ presetValues.resumeSavedDbPort = savedDbPort;
369
+ }
370
+ }
371
+ }
372
+ }
311
373
  if (normalizedFlags.yes && !String(presetValues.appName ?? '').trim()) {
312
374
  const formatted = formatSkippedAppNameRequiredMessage();
313
375
  p.log.error(highlightInitValidationMessage(formatted));
@@ -365,28 +427,17 @@ Prompt modes:
365
427
  },
366
428
  command: this,
367
429
  });
368
- const installSkills = Boolean(results.installSkills);
369
430
  const hasNocobase = results.hasNocobase === 'yes';
370
431
  const existingEnv = !hasNocobase
371
- ? await getEnv(String(results.appName ?? '').trim(), { scope: 'project' })
432
+ ? await getEnv(String(results.appName ?? '').trim(), { scope: resolveDefaultConfigScope() })
372
433
  : undefined;
373
434
  if (existingEnv && Boolean(normalizedFlags.force)) {
374
- p.log.warn(`Reconfiguring existing env ${pc.cyan(pc.bold(`"${existingEnv.name}"`))} in this workspace because ${pc.bold('--force')} was set. The env config will be updated before install starts, then refreshed again after install succeeds.`);
375
- }
376
- if (installSkills) {
377
- try {
378
- p.log.step('Installing NocoBase agent skills (nb skills install)');
379
- await installNocoBaseSkills();
380
- }
381
- catch (error) {
382
- const message = error instanceof Error ? error.message : String(error);
383
- p.outro(pc.red(`Skills install failed: ${message}`));
384
- this.error(message);
385
- }
386
- }
387
- else {
388
- p.log.info('Skipped NocoBase agent skills install.');
435
+ p.log.warn(`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.`);
389
436
  }
437
+ await this.syncNocoBaseSkills({
438
+ skip: Boolean(normalizedFlags['skip-skills']),
439
+ });
440
+ let managedInstallResults;
390
441
  try {
391
442
  // oclif explicit registry keys use `:` (e.g. `env:add`); users still type `nb env add`.
392
443
  if (hasNocobase) {
@@ -395,15 +446,19 @@ Prompt modes:
395
446
  }
396
447
  else {
397
448
  p.log.step('Saving the local env config');
398
- await this.persistManagedEnvConfig(results);
399
- p.log.step('Running nb install');
449
+ await this.persistManagedEnvConfig(results, normalizedFlags);
450
+ managedInstallResults = results;
451
+ p.log.step('Running nb init');
400
452
  await this.config.runCommand('install', this.buildInstallArgv(results, normalizedFlags));
401
453
  }
402
454
  }
403
455
  catch (error) {
404
456
  const message = error instanceof Error ? error.message : String(error);
405
- p.outro(pc.red(message));
406
- this.error(message);
457
+ const formatted = managedInstallResults
458
+ ? this.formatManagedInstallFailureMessage(message, managedInstallResults, normalizedFlags)
459
+ : message;
460
+ p.outro(pc.red(formatted));
461
+ this.exit(1);
407
462
  }
408
463
  p.outro('Workspace init finished.');
409
464
  }
@@ -451,7 +506,6 @@ Prompt modes:
451
506
  catalog: {
452
507
  appName: c.appName,
453
508
  hasNocobase: c.hasNocobase,
454
- installSkills: c.installSkills,
455
509
  },
456
510
  },
457
511
  {
@@ -525,6 +579,22 @@ Prompt modes:
525
579
  if (flags.env !== undefined && String(flags.env).trim() !== '') {
526
580
  preset.appName = String(flags.env).trim();
527
581
  }
582
+ const apiBaseUrl = explicitApiBaseUrlFlag(flags);
583
+ if (apiBaseUrl) {
584
+ preset.hasNocobase = 'yes';
585
+ preset.apiBaseUrl = apiBaseUrl;
586
+ }
587
+ else if (flags['default-api-base-url'] !== undefined
588
+ && String(flags['default-api-base-url']).trim() !== '') {
589
+ preset.apiBaseUrl = String(flags['default-api-base-url']).trim();
590
+ }
591
+ if (flags['auth-type'] !== undefined && String(flags['auth-type']).trim() !== '') {
592
+ preset.authType = String(flags['auth-type']).trim();
593
+ }
594
+ const accessToken = String(flags['access-token'] ?? flags.token ?? '');
595
+ if (flags['access-token'] !== undefined || flags.token !== undefined) {
596
+ preset.accessToken = accessToken;
597
+ }
528
598
  if (flags.lang !== undefined && String(flags.lang).trim() !== '') {
529
599
  preset.lang = String(flags.lang).trim();
530
600
  }
@@ -557,6 +627,7 @@ Prompt modes:
557
627
  }
558
628
  if (flags['db-host'] !== undefined && String(flags['db-host']).trim() !== '') {
559
629
  preset.dbHost = String(flags['db-host']).trim();
630
+ preset.builtinDb = false;
560
631
  }
561
632
  if (flags['db-port'] !== undefined && String(flags['db-port']).trim() !== '') {
562
633
  preset.dbPort = String(flags['db-port']).trim();
@@ -577,7 +648,11 @@ Prompt modes:
577
648
  preset.source = String(flags.source).trim();
578
649
  }
579
650
  if (flags.version !== undefined) {
580
- preset.version = String(flags.version).trim() || 'latest';
651
+ const version = String(flags.version).trim() || 'latest';
652
+ preset.version = initVersionPromptValue(version);
653
+ if (preset.version === 'other') {
654
+ preset.otherVersion = version;
655
+ }
581
656
  }
582
657
  if (flags['docker-registry'] !== undefined && String(flags['docker-registry']).trim() !== '') {
583
658
  preset.dockerRegistry = String(flags['docker-registry']).trim();
@@ -609,21 +684,42 @@ Prompt modes:
609
684
  if (argvHasToken(argv, ['--build-dts', '--no-build-dts'])) {
610
685
  preset.buildDts = Boolean(flags['build-dts']);
611
686
  }
612
- if (argvHasToken(argv, ['--builtin-db'])) {
687
+ if (argvHasToken(argv, ['--builtin-db', '--no-builtin-db'])) {
613
688
  preset.builtinDb = Boolean(flags['builtin-db']);
614
689
  }
615
- if (argvHasToken(argv, ['--install-skills'])) {
616
- preset.installSkills = Boolean(flags['install-skills']);
690
+ if (explicitDbHostFlag(flags)) {
691
+ preset.builtinDb = false;
617
692
  }
618
- else if (this.hasAgentsDirInCwd()) {
619
- preset.installSkills = false;
693
+ if (!preset.hasNocobase && hasDownloadOverride(flags)) {
694
+ preset.hasNocobase = 'no';
620
695
  }
621
696
  return preset;
622
697
  }
623
698
  hasAgentsDirInCwd() {
624
699
  return existsSync(path.resolve(process.cwd(), '.agents'));
625
700
  }
626
- async persistManagedEnvConfig(results) {
701
+ async syncNocoBaseSkills(options) {
702
+ if (options?.skip) {
703
+ p.log.step('Skipped NocoBase agent skills sync.');
704
+ return;
705
+ }
706
+ try {
707
+ const status = await inspectSkillsStatus();
708
+ if (!status.installed) {
709
+ p.log.step('Installing NocoBase agent skills (nb skills install)');
710
+ await installNocoBaseSkills();
711
+ return;
712
+ }
713
+ p.log.step('Updating NocoBase agent skills (nb skills update)');
714
+ await updateNocoBaseSkills();
715
+ }
716
+ catch (error) {
717
+ const message = error instanceof Error ? error.message : String(error);
718
+ p.outro(pc.red(`Skills sync failed: ${message}`));
719
+ this.exit(1);
720
+ }
721
+ }
722
+ async persistManagedEnvConfig(results, flags = {}) {
627
723
  const envName = String(results.appName ?? DEFAULT_INIT_APP_NAME).trim() || DEFAULT_INIT_APP_NAME;
628
724
  const appPort = String(results.appPort ?? '').trim();
629
725
  const source = String(results.source ?? '').trim();
@@ -641,8 +737,24 @@ Prompt modes:
641
737
  const dbDatabase = String(results.dbDatabase ?? '').trim();
642
738
  const dbUser = String(results.dbUser ?? '').trim();
643
739
  const dbPassword = String(results.dbPassword ?? '');
740
+ const apiBaseUrl = String(results.apiBaseUrl ?? '').trim();
741
+ const authType = String(results.authType ?? '').trim() || 'oauth';
742
+ const accessToken = String(results.accessToken ?? '');
743
+ const builtinDb = explicitDbHostFlag(flags)
744
+ ? false
745
+ : results.builtinDb === undefined
746
+ ? undefined
747
+ : Boolean(results.builtinDb);
644
748
  await upsertEnv(envName, {
645
- ...(appPort ? { baseUrl: `http://127.0.0.1:${appPort}/api` } : {}),
749
+ ...(source === 'docker'
750
+ ? { kind: 'docker' }
751
+ : source || appRootPath
752
+ ? { kind: 'local' }
753
+ : appPort
754
+ ? { kind: 'http' }
755
+ : {}),
756
+ ...(apiBaseUrl ? { apiBaseUrl } : appPort ? { apiBaseUrl: `http://127.0.0.1:${appPort}/api` } : {}),
757
+ ...(authType === 'token' && accessToken ? { accessToken } : {}),
646
758
  ...(source ? { source } : {}),
647
759
  ...(version ? { downloadVersion: version } : {}),
648
760
  ...(dockerRegistry ? { dockerRegistry } : {}),
@@ -655,20 +767,19 @@ Prompt modes:
655
767
  ...(results.devDependencies !== undefined ? { devDependencies: Boolean(results.devDependencies) } : {}),
656
768
  ...(results.build !== undefined ? { build: Boolean(results.build) } : {}),
657
769
  ...(results.buildDts !== undefined ? { buildDts: Boolean(results.buildDts) } : {}),
658
- ...(results.builtinDb !== undefined ? { builtinDb: Boolean(results.builtinDb) } : {}),
770
+ ...(builtinDb !== undefined ? { builtinDb } : {}),
659
771
  ...(dbDialect ? { dbDialect } : {}),
660
- ...(builtinDbImage || results.builtinDb === false ? { builtinDbImage: builtinDbImage || undefined } : {}),
772
+ ...(builtinDbImage || builtinDb === false ? { builtinDbImage: builtinDbImage || undefined } : {}),
661
773
  ...(dbHost ? { dbHost } : {}),
662
774
  ...(dbPort ? { dbPort } : {}),
663
775
  ...(dbDatabase ? { dbDatabase } : {}),
664
776
  ...(dbUser ? { dbUser } : {}),
665
777
  ...(dbPassword ? { dbPassword } : {}),
666
- }, { scope: CONFIG_SCOPE });
778
+ }, { scope: resolveDefaultConfigScope() });
667
779
  }
668
780
  buildEnvAddArgv(results) {
669
781
  const argv = [String(results.appName ?? DEFAULT_INIT_APP_NAME)];
670
782
  argv.push('--no-intro');
671
- argv.push('--scope', CONFIG_SCOPE);
672
783
  argv.push('--api-base-url', String(results.apiBaseUrl ?? DEFAULT_INIT_API_BASE_URL));
673
784
  argv.push('--auth-type', String(results.authType ?? 'oauth'));
674
785
  if (results.authType === 'token') {
@@ -684,6 +795,9 @@ Prompt modes:
684
795
  const processArgv = process.argv.slice(2);
685
796
  const envName = String(results.appName ?? DEFAULT_INIT_APP_NAME).trim() || DEFAULT_INIT_APP_NAME;
686
797
  const source = String(results.source ?? '').trim();
798
+ const apiBaseUrl = String(results.apiBaseUrl ?? '').trim();
799
+ const authType = String(results.authType ?? '').trim();
800
+ const accessToken = String(results.accessToken ?? '');
687
801
  argv.push('--env', envName);
688
802
  if (options?.resume) {
689
803
  argv.push('--resume');
@@ -691,6 +805,15 @@ Prompt modes:
691
805
  if (Boolean(flags.verbose)) {
692
806
  argv.push('--verbose');
693
807
  }
808
+ if (apiBaseUrl) {
809
+ argv.push('--api-base-url', apiBaseUrl);
810
+ }
811
+ if (authType) {
812
+ argv.push('--auth-type', authType);
813
+ }
814
+ if (authType === 'token' && accessToken) {
815
+ argv.push('--access-token', accessToken);
816
+ }
694
817
  const lang = String(results.lang ?? '').trim();
695
818
  if (lang) {
696
819
  argv.push('--lang', lang);
@@ -758,10 +881,15 @@ Prompt modes:
758
881
  argv.push('--build-dts');
759
882
  }
760
883
  }
761
- const builtinDb = Boolean(results.builtinDb);
884
+ const explicitDbHost = explicitDbHostFlag(flags);
885
+ const dbHost = explicitDbHost || String(results.dbHost ?? '').trim();
886
+ const builtinDb = explicitDbHost ? false : Boolean(results.builtinDb);
762
887
  if (builtinDb) {
763
888
  argv.push('--builtin-db');
764
889
  }
890
+ else if (explicitDbHost || results.builtinDb !== undefined) {
891
+ argv.push('--no-builtin-db');
892
+ }
765
893
  const dbDialect = String(results.dbDialect ?? '').trim();
766
894
  if (dbDialect) {
767
895
  argv.push('--db-dialect', dbDialect);
@@ -770,7 +898,6 @@ Prompt modes:
770
898
  if (builtinDb && builtinDbImage) {
771
899
  argv.push('--builtin-db-image', builtinDbImage);
772
900
  }
773
- const dbHost = String(results.dbHost ?? '').trim();
774
901
  if (dbHost) {
775
902
  argv.push('--db-host', dbHost);
776
903
  }
@@ -813,8 +940,80 @@ Prompt modes:
813
940
  }
814
941
  return argv;
815
942
  }
943
+ buildManagedInstallResumeCommand(results, flags) {
944
+ const argv = ['nb', 'init'];
945
+ if (Boolean(flags.yes)) {
946
+ argv.push('--yes');
947
+ }
948
+ const envName = String(results.appName ?? DEFAULT_INIT_APP_NAME).trim() || DEFAULT_INIT_APP_NAME;
949
+ argv.push('--env', envName);
950
+ if (Boolean(results.fetchSource)) {
951
+ const source = String(results.source ?? '').trim();
952
+ if (source) {
953
+ argv.push('--source', source);
954
+ }
955
+ const version = resolveInitDownloadVersion(results);
956
+ if (version) {
957
+ argv.push('--version', version);
958
+ }
959
+ const outputDir = String(results.outputDir ?? '').trim();
960
+ if (outputDir && outputDir !== String(results.appRootPath ?? '').trim()) {
961
+ argv.push('--output-dir', outputDir);
962
+ }
963
+ const gitUrl = String(results.gitUrl ?? '').trim();
964
+ if (gitUrl) {
965
+ argv.push('--git-url', gitUrl);
966
+ }
967
+ const dockerRegistry = String(results.dockerRegistry ?? '').trim();
968
+ if (dockerRegistry) {
969
+ argv.push('--docker-registry', dockerRegistry);
970
+ }
971
+ const dockerPlatform = String(results.dockerPlatform ?? '').trim();
972
+ if (dockerPlatform) {
973
+ argv.push('--docker-platform', dockerPlatform);
974
+ }
975
+ const npmRegistry = String(results.npmRegistry ?? '').trim();
976
+ if (npmRegistry) {
977
+ argv.push('--npm-registry', npmRegistry);
978
+ }
979
+ if (Boolean(results.devDependencies)) {
980
+ argv.push('--dev-dependencies');
981
+ }
982
+ if (Boolean(results.dockerSave)) {
983
+ argv.push('--docker-save');
984
+ }
985
+ if (results.build !== undefined && !Boolean(results.build)) {
986
+ argv.push('--no-build');
987
+ }
988
+ if (Boolean(results.buildDts)) {
989
+ argv.push('--build-dts');
990
+ }
991
+ }
992
+ argv.push('--resume', '--verbose');
993
+ return argv.map(shellQuoteArg).join(' ');
994
+ }
995
+ formatManagedInstallFailureMessage(message, results, flags) {
996
+ const command = this.buildManagedInstallResumeCommand(results, flags);
997
+ return [
998
+ message,
999
+ '',
1000
+ translateCli('commands.init.messages.resumeAfterInstallFailure', { command }),
1001
+ ].join('\n');
1002
+ }
816
1003
  buildResumeInstallArgv(flags) {
817
- return this.buildInstallArgv(this.buildPresetValuesFromFlags(flags), flags, {
1004
+ const preset = this.buildPresetValuesFromFlags(flags);
1005
+ if (flags.yes) {
1006
+ preset.lang ??= yesInitialValue(Install.appPrompts.lang, 'en-US');
1007
+ preset.rootUsername ??= yesInitialValue(Install.rootUserPrompts.rootUsername, 'nocobase');
1008
+ preset.rootEmail ??= yesInitialValue(Install.rootUserPrompts.rootEmail, 'admin@nocobase.com');
1009
+ preset.rootPassword ??= yesInitialValue(Install.rootUserPrompts.rootPassword, 'admin123');
1010
+ preset.rootNickname ??= yesInitialValue(Install.rootUserPrompts.rootNickname, 'Super Admin');
1011
+ }
1012
+ if (hasDownloadOverride(flags)) {
1013
+ preset.fetchSource ??= true;
1014
+ }
1015
+ preset.replace ??= true;
1016
+ return this.buildInstallArgv(preset, flags, {
818
1017
  nonInteractive: Boolean(flags.yes),
819
1018
  resume: true,
820
1019
  });