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

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 (42) hide show
  1. package/README.md +4 -4
  2. package/README.zh-CN.md +2 -2
  3. package/bin/run.js +15 -0
  4. package/dist/commands/db/shared.js +19 -5
  5. package/dist/commands/dev.js +8 -1
  6. package/dist/commands/down.js +10 -6
  7. package/dist/commands/env/add.js +14 -34
  8. package/dist/commands/env/auth.js +6 -13
  9. package/dist/commands/env/list.js +10 -15
  10. package/dist/commands/env/remove.js +4 -10
  11. package/dist/commands/env/update.js +7 -13
  12. package/dist/commands/env/use.js +5 -13
  13. package/dist/commands/init.js +190 -62
  14. package/dist/commands/install.js +65 -26
  15. package/dist/commands/logs.js +8 -1
  16. package/dist/commands/pm/list.js +8 -1
  17. package/dist/commands/ps.js +18 -15
  18. package/dist/commands/self/check.js +1 -1
  19. package/dist/commands/self/update.js +13 -3
  20. package/dist/commands/skills/check.js +11 -5
  21. package/dist/commands/skills/index.js +1 -1
  22. package/dist/commands/skills/install.js +20 -7
  23. package/dist/commands/skills/update.js +20 -7
  24. package/dist/commands/start.js +8 -1
  25. package/dist/commands/stop.js +8 -1
  26. package/dist/commands/upgrade.js +12 -1
  27. package/dist/lib/api-client.js +3 -2
  28. package/dist/lib/app-runtime.js +16 -5
  29. package/dist/lib/auth-store.js +159 -43
  30. package/dist/lib/bootstrap.js +13 -12
  31. package/dist/lib/cli-home.js +33 -2
  32. package/dist/lib/env-auth.js +3 -3
  33. package/dist/lib/generated-command.js +10 -2
  34. package/dist/lib/http-request.js +49 -0
  35. package/dist/lib/resource-command.js +10 -2
  36. package/dist/lib/runtime-generator.js +1 -1
  37. package/dist/lib/self-manager.js +1 -1
  38. package/dist/lib/skills-manager.js +140 -73
  39. package/dist/lib/startup-update.js +203 -0
  40. package/dist/locale/en-US.json +4 -1
  41. package/dist/locale/zh-CN.json +4 -1
  42. package/package.json +2 -2
package/README.md CHANGED
@@ -58,7 +58,7 @@ nb init --ui
58
58
 
59
59
  `nb init` can either connect to an existing NocoBase app or install a new one.
60
60
  When creating a new app, it can also install NocoBase AI coding skills
61
- (`nocobase/skills`) for the current workspace.
61
+ (`nocobase/skills`) globally.
62
62
 
63
63
  ### Non-Interactive Setup
64
64
 
@@ -149,7 +149,7 @@ In non-interactive mode, pass these setup-only flags again because they are not
149
149
  | `nb api` | Call NocoBase API resources from the CLI. |
150
150
  | `nb pm` | Manage plugins for the selected NocoBase env. |
151
151
  | `nb self` | Check or update the installed NocoBase CLI. |
152
- | `nb skills` | Check, install, or update NocoBase AI coding skills for the current workspace. |
152
+ | `nb skills` | Check, install, or update global NocoBase AI coding skills. |
153
153
 
154
154
  Recommended style: use `--env` explicitly for app/runtime commands. `-e` is the short form:
155
155
 
@@ -186,7 +186,7 @@ Update the CLI when it is installed globally with npm:
186
186
  nb self update
187
187
  ```
188
188
 
189
- Check whether the current workspace already has the NocoBase AI coding skills:
189
+ Check whether the global NocoBase AI coding skills are installed:
190
190
 
191
191
  ```bash
192
192
  nb skills check
@@ -240,7 +240,7 @@ To connect an existing app, use `nb init` and choose the existing-app setup
240
240
  path, or add the env directly:
241
241
 
242
242
  ```bash
243
- nb env add app1 --base-url http://localhost:13000/api
243
+ nb env add app1 --api-base-url http://localhost:13000/api
244
244
  ```
245
245
 
246
246
  `nb env add` will start the authentication flow automatically when needed.
package/README.zh-CN.md CHANGED
@@ -53,7 +53,7 @@ nb init
53
53
  nb init --ui
54
54
  ```
55
55
 
56
- `nb init` 可以连接已有的 NocoBase 应用,也可以安装一个新的 NocoBase 应用。创建新应用时,还可以为当前工作区安装 NocoBase AI coding skills (`nocobase/skills`)。
56
+ `nb init` 可以连接已有的 NocoBase 应用,也可以安装一个新的 NocoBase 应用。创建新应用时,还可以全局安装 NocoBase AI coding skills (`nocobase/skills`)。
57
57
 
58
58
  ### 非交互式初始化
59
59
 
@@ -202,7 +202,7 @@ nb dev --env app1
202
202
  如果要连接已有应用,可以运行 `nb init` 并选择已有应用流程,也可以直接添加 env:
203
203
 
204
204
  ```bash
205
- nb env add app1 --base-url http://localhost:13000/api
205
+ nb env add app1 --api-base-url http://localhost:13000/api
206
206
  ```
207
207
 
208
208
  `nb env add` 会在需要时自动进入认证流程。
package/bin/run.js CHANGED
@@ -61,6 +61,10 @@ if (isDev && !process.env._NOCO_CLI_TSX_CHILD) {
61
61
 
62
62
  const bootstrapPath = isDev ? path.join(root, 'src/lib/bootstrap.ts') : path.join(root, 'dist/lib/bootstrap.js');
63
63
  const { ensureRuntimeFromArgv } = await import(pathToFileURL(bootstrapPath).href);
64
+ const startupUpdatePath = isDev
65
+ ? path.join(root, 'src/lib/startup-update.ts')
66
+ : path.join(root, 'dist/lib/startup-update.js');
67
+ const { maybeRunStartupUpdatePrompt } = await import(pathToFileURL(startupUpdatePath).href);
64
68
  const { flush, run, settings } = await import('@oclif/core');
65
69
 
66
70
  if (isDev) {
@@ -102,6 +106,17 @@ function formatCliEntryError(error, argv) {
102
106
 
103
107
  try {
104
108
  const argv = process.argv.slice(2);
109
+ const startupUpdate = await maybeRunStartupUpdatePrompt(argv);
110
+ if (startupUpdate.kind === 'updated') {
111
+ const result = spawnSync(process.execPath, process.argv.slice(1), {
112
+ stdio: 'inherit',
113
+ env: {
114
+ ...process.env,
115
+ NB_SKIP_STARTUP_UPDATE: '1',
116
+ },
117
+ });
118
+ process.exit(result.status === null ? 1 : result.status);
119
+ }
105
120
  if (argv[0] === 'api') {
106
121
  await ensureRuntimeFromArgv(argv, {
107
122
  configFile: path.join(root, 'nocobase-ctl.config.json'),
@@ -20,9 +20,9 @@ export async function resolveDbRuntime(envName) {
20
20
  if (!runtime) {
21
21
  return undefined;
22
22
  }
23
- const source = runtime.kind === 'remote' ? 'remote' : runtime.source;
23
+ const source = runtime.kind === 'http' || runtime.kind === 'ssh' ? runtime.kind : runtime.source;
24
24
  const dbDialect = String(runtime.env.config.dbDialect ?? 'postgres').trim() || 'postgres';
25
- if (runtime.kind !== 'remote' && runtime.env.config.builtinDb) {
25
+ if ((runtime.kind === 'local' || runtime.kind === 'docker') && runtime.env.config.builtinDb) {
26
26
  const containerName = buildDockerDbContainerName(runtime.envName, dbDialect, runtime.workspaceName);
27
27
  return {
28
28
  kind: 'builtin',
@@ -40,7 +40,7 @@ export async function resolveDbRuntime(envName) {
40
40
  source,
41
41
  dbDialect,
42
42
  address: formatAddress(runtime.env.config.dbHost, runtime.env.config.dbPort),
43
- status: runtime.kind === 'remote' ? 'remote' : 'external',
43
+ status: runtime.kind === 'http' || runtime.kind === 'ssh' ? runtime.kind : 'external',
44
44
  appRuntime: runtime,
45
45
  };
46
46
  }
@@ -52,13 +52,20 @@ export async function builtinDbStatus(containerName) {
52
52
  }
53
53
  export function formatUnmanagedDbMessage(action, runtime) {
54
54
  const verb = action === 'start' ? 'start' : 'stop';
55
- if (runtime.appRuntime.kind === 'remote') {
55
+ if (runtime.appRuntime.kind === 'http') {
56
56
  return [
57
57
  `Can't ${verb} the database for "${runtime.envName}" from this machine.`,
58
58
  'This env only has an API connection, so there is no CLI-managed database container here.',
59
59
  'If you need CLI-managed database start and stop, create a local env with the built-in database option enabled.',
60
60
  ].join('\n');
61
61
  }
62
+ if (runtime.appRuntime.kind === 'ssh') {
63
+ return [
64
+ `Can't ${verb} the database for "${runtime.envName}" yet.`,
65
+ 'SSH env support is reserved but not implemented yet.',
66
+ 'Use a local env with the built-in database option enabled if you need CLI-managed database operations right now.',
67
+ ].join('\n');
68
+ }
62
69
  return [
63
70
  `Can't ${verb} the database for "${runtime.envName}" from this machine.`,
64
71
  'This env does not use a CLI-managed built-in database, so there is no saved database container to manage here.',
@@ -66,13 +73,20 @@ export function formatUnmanagedDbMessage(action, runtime) {
66
73
  ].join('\n');
67
74
  }
68
75
  export function formatUnmanagedDbLogsMessage(runtime) {
69
- if (runtime.appRuntime.kind === 'remote') {
76
+ if (runtime.appRuntime.kind === 'http') {
70
77
  return [
71
78
  `Can't show database logs for "${runtime.envName}" from this machine.`,
72
79
  'This env only has an API connection, so there is no CLI-managed database container here.',
73
80
  'If you need CLI-managed database logs, create a local env with the built-in database option enabled.',
74
81
  ].join('\n');
75
82
  }
83
+ if (runtime.appRuntime.kind === 'ssh') {
84
+ return [
85
+ `Can't show database logs for "${runtime.envName}" yet.`,
86
+ 'SSH env support is reserved but not implemented yet.',
87
+ 'Use a local env with the built-in database option enabled if you need CLI-managed database logs right now.',
88
+ ].join('\n');
89
+ }
76
90
  return [
77
91
  `Can't show database logs for "${runtime.envName}" from this machine.`,
78
92
  'This env does not use a CLI-managed built-in database, so there is no saved database container to read logs from here.',
@@ -17,6 +17,13 @@ function formatUnsupportedRuntimeMessage(kind, envName) {
17
17
  `Use \`nb logs --env ${envName}\` to inspect the Docker app, or create a source-based env with \`nb init --env ${envName} --source git\`.`,
18
18
  ].join('\n');
19
19
  }
20
+ if (kind === 'ssh') {
21
+ return [
22
+ `Can't run dev mode for "${envName}" yet.`,
23
+ 'SSH env support is reserved but not implemented yet.',
24
+ `Create a source-based env with \`nb init --env ${envName} --source git\` if you want local development mode right now.`,
25
+ ].join('\n');
26
+ }
20
27
  return [
21
28
  `Can't run dev mode for "${envName}".`,
22
29
  'This env only has an API connection, but `nb dev` requires a local npm or Git source directory.',
@@ -99,7 +106,7 @@ export default class Dev extends Command {
99
106
  if (!runtime) {
100
107
  this.error(formatMissingManagedAppEnvMessage(requestedEnv));
101
108
  }
102
- if (runtime.kind === 'docker' || runtime.kind === 'remote') {
109
+ if (runtime.kind === 'docker' || runtime.kind === 'http' || runtime.kind === 'ssh') {
103
110
  this.error(formatUnsupportedRuntimeMessage(runtime.kind, runtime.envName));
104
111
  }
105
112
  const devPort = flags.port
@@ -12,14 +12,11 @@ import os from 'node:os';
12
12
  import path from 'node:path';
13
13
  import { buildDockerDbContainerName, formatMissingManagedAppEnvMessage, resolveManagedAppRuntime, runLocalNocoBaseCommand, } from '../lib/app-runtime.js';
14
14
  import { removeEnv } from '../lib/auth-store.js';
15
+ import { resolveConfiguredEnvPath } from '../lib/cli-home.js';
15
16
  import { commandSucceeds, run } from '../lib/run-npm.js';
16
17
  import { confirmAction, failTask, isInteractiveTerminal, printInfo, startTask, succeedTask, } from '../lib/ui.js';
17
18
  function resolveConfiguredPath(value) {
18
- const text = String(value ?? '').trim();
19
- if (!text) {
20
- return undefined;
21
- }
22
- return path.isAbsolute(text) ? text : path.resolve(process.cwd(), text);
19
+ return resolveConfiguredEnvPath(value);
23
20
  }
24
21
  function assertSafeRemovalPath(target, label) {
25
22
  const resolved = path.resolve(target);
@@ -113,13 +110,20 @@ export default class Down extends Command {
113
110
  if (!runtime) {
114
111
  this.error(formatMissingManagedAppEnvMessage(requestedEnv));
115
112
  }
116
- if (runtime.kind === 'remote') {
113
+ if (runtime.kind === 'http') {
117
114
  this.error([
118
115
  `Can't bring down "${runtime.envName}" from this machine.`,
119
116
  'This env only has an API connection, so there is no saved local app, Docker app, or managed database to remove here.',
120
117
  'Use `nb env remove` if you only want to remove the CLI connection config.',
121
118
  ].join('\n'));
122
119
  }
120
+ if (runtime.kind === 'ssh') {
121
+ this.error([
122
+ `Can't bring down "${runtime.envName}" yet.`,
123
+ 'SSH env support is reserved but not implemented yet.',
124
+ 'Use `nb env remove` if you only want to remove the saved CLI config for now.',
125
+ ].join('\n'));
126
+ }
123
127
  if (flags['remove-data']) {
124
128
  let confirmed = false;
125
129
  try {
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import { Args, Command, Flags } from '@oclif/core';
10
10
  import { upsertEnv } from '../../lib/auth-store.js';
11
+ import { resolveDefaultConfigScope } from '../../lib/cli-home.js';
11
12
  import { runPromptCatalog, } from '../../lib/prompt-catalog.js';
12
13
  import { applyCliLocale, CLI_LOCALE_FLAG_DESCRIPTION, CLI_LOCALE_FLAG_OPTIONS, localeText, } from '../../lib/cli-locale.js';
13
14
  import { validateApiBaseUrl } from '../../lib/prompt-validators.js';
@@ -45,7 +46,7 @@ export default class EnvAdd extends Command {
45
46
  static examples = [
46
47
  '<%= config.bin %> <%= command.id %>',
47
48
  '<%= config.bin %> <%= command.id %> local',
48
- '<%= config.bin %> <%= command.id %> local --scope project --api-base-url http://localhost:13000/api --auth-type oauth',
49
+ '<%= config.bin %> <%= command.id %> local --api-base-url http://localhost:13000/api --auth-type oauth',
49
50
  ];
50
51
  static args = {
51
52
  name: Args.string({
@@ -73,12 +74,6 @@ export default class EnvAdd extends Command {
73
74
  description: 'Skip command intro when invoked by another CLI command',
74
75
  default: false,
75
76
  }),
76
- scope: Flags.string({
77
- char: 's',
78
- description: 'Where to store env config: project (.nocobase in the repo) or global (user-level); prompted in a TTY when omitted',
79
- options: ['project', 'global'],
80
- default: 'project',
81
- }),
82
77
  'default-api-base-url': Flags.string({
83
78
  char: 'd',
84
79
  hidden: true,
@@ -86,7 +81,6 @@ export default class EnvAdd extends Command {
86
81
  }),
87
82
  'api-base-url': Flags.string({
88
83
  char: 'u',
89
- aliases: ['base-url'],
90
84
  description: 'Root URL for HTTP API calls, including the /api prefix (e.g. http://localhost:13000/api); prompted in a TTY when omitted',
91
85
  }),
92
86
  'auth-type': Flags.string({
@@ -199,24 +193,6 @@ export default class EnvAdd extends Command {
199
193
  placeholder: envAddText('prompts.name.placeholder'),
200
194
  required: true,
201
195
  },
202
- scope: {
203
- type: 'select',
204
- message: envAddText('prompts.scope.message'),
205
- options: [
206
- {
207
- value: 'project',
208
- label: envAddText('prompts.scope.projectLabel'),
209
- hint: envAddText('prompts.scope.projectHint'),
210
- },
211
- {
212
- value: 'global',
213
- label: envAddText('prompts.scope.globalLabel'),
214
- hint: envAddText('prompts.scope.globalHint'),
215
- },
216
- ],
217
- initialValue: 'project',
218
- required: true,
219
- },
220
196
  apiBaseUrl: {
221
197
  type: 'text',
222
198
  message: envAddText('prompts.apiBaseUrl.message'),
@@ -252,10 +228,7 @@ export default class EnvAdd extends Command {
252
228
  if (name) {
253
229
  values.name = name;
254
230
  }
255
- if (flags.scope) {
256
- values.scope = flags.scope;
257
- }
258
- const apiFromFlag = flags['api-base-url'] ?? flags['base-url'];
231
+ const apiFromFlag = flags['api-base-url'];
259
232
  if (typeof apiFromFlag === 'string' && apiFromFlag.trim() !== '') {
260
233
  values.apiBaseUrl = apiFromFlag.trim();
261
234
  }
@@ -277,8 +250,16 @@ export default class EnvAdd extends Command {
277
250
  return initialValues;
278
251
  }
279
252
  buildEnvConfig(results, flags) {
253
+ const source = String(flags.source ?? '').trim();
254
+ const appRootPath = String(flags['app-root-path'] ?? '').trim();
255
+ const kind = source === 'docker'
256
+ ? 'docker'
257
+ : source === 'npm' || source === 'git' || source === 'local' || appRootPath
258
+ ? 'local'
259
+ : 'http';
280
260
  const envConfig = {
281
- baseUrl: String(results.apiBaseUrl ?? ''),
261
+ kind,
262
+ apiBaseUrl: String(results.apiBaseUrl ?? ''),
282
263
  };
283
264
  for (const [flagName, configKey] of Object.entries(ENV_RUNTIME_FLAG_MAP)) {
284
265
  const value = flags[flagName];
@@ -314,10 +295,9 @@ export default class EnvAdd extends Command {
314
295
  command: this,
315
296
  });
316
297
  const envName = String(results.name);
317
- const scope = results.scope;
318
298
  const envConfig = this.buildEnvConfig(results, parsedFlags);
319
- printVerbose(`Saving env "${envName}" with scope "${scope}".`);
320
- await upsertEnv(envName, envConfig, { scope });
299
+ printVerbose(`Saving env "${envName}" globally.`);
300
+ await upsertEnv(envName, envConfig, { scope: resolveDefaultConfigScope() });
321
301
  if (results.authType === 'oauth') {
322
302
  await this.config.runCommand('env:auth', [envName]);
323
303
  }
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import { Args, Command, Flags } from '@oclif/core';
10
10
  import { getCurrentEnvName } from '../../lib/auth-store.js';
11
- import { formatCliHomeScope } from '../../lib/cli-home.js';
11
+ import { resolveDefaultConfigScope } from '../../lib/cli-home.js';
12
12
  import { authenticateEnvWithOauth } from '../../lib/env-auth.js';
13
13
  import { failTask, startTask, succeedTask } from '../../lib/ui.js';
14
14
  export default class EnvAuth extends Command {
@@ -16,7 +16,6 @@ export default class EnvAuth extends Command {
16
16
  static examples = [
17
17
  '<%= config.bin %> <%= command.id %>',
18
18
  '<%= config.bin %> <%= command.id %> prod',
19
- '<%= config.bin %> <%= command.id %> --scope global',
20
19
  ];
21
20
  static args = {
22
21
  name: Args.string({
@@ -31,31 +30,25 @@ export default class EnvAuth extends Command {
31
30
  deprecated: true,
32
31
  description: 'Environment name (same as the optional positional argument; for compatibility with -e/--env on other commands)',
33
32
  }),
34
- scope: Flags.string({
35
- char: 's',
36
- description: 'Config scope',
37
- options: ['project', 'global'],
38
- }),
39
33
  };
40
34
  async run() {
41
35
  const { args, flags } = await this.parse(EnvAuth);
42
- const scope = flags.scope;
43
36
  const nameArg = args.name?.trim();
44
37
  const nameFlag = flags.env?.trim() || undefined;
45
38
  if (nameArg && nameFlag && nameArg !== nameFlag) {
46
39
  this.error(`Environment name was provided both as the argument ("${nameArg}") and as --env ("${nameFlag}"). Please use only one.`);
47
40
  }
48
- const envName = nameArg || nameFlag || (await getCurrentEnvName({ scope }));
49
- startTask(`Starting browser sign-in for "${envName}"${scope ? ` (${formatCliHomeScope(scope)} scope)` : ''}...`);
41
+ const envName = nameArg || nameFlag || (await getCurrentEnvName({ scope: resolveDefaultConfigScope() }));
42
+ startTask(`Starting browser sign-in for "${envName}"...`);
50
43
  try {
51
44
  await authenticateEnvWithOauth({
52
45
  envName,
53
- scope,
46
+ scope: resolveDefaultConfigScope(),
54
47
  });
55
- succeedTask(`Signed in to "${envName}"${scope ? ` in ${formatCliHomeScope(scope)} scope` : ''}.`);
48
+ succeedTask(`Signed in to "${envName}".`);
56
49
  }
57
50
  catch (error) {
58
- failTask(`Sign-in failed for "${envName}"${scope ? ` in ${formatCliHomeScope(scope)} scope` : ''}.`);
51
+ failTask(`Sign-in failed for "${envName}".`);
59
52
  throw error;
60
53
  }
61
54
  }
@@ -6,35 +6,30 @@
6
6
  * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
- import { Command, Flags } from '@oclif/core';
9
+ import { Command } from '@oclif/core';
10
10
  import { listEnvs } from '../../lib/auth-store.js';
11
- import { formatCliHomeScope } from '../../lib/cli-home.js';
11
+ import { resolveDefaultConfigScope } from '../../lib/cli-home.js';
12
12
  import { renderTable } from '../../lib/ui.js';
13
+ function resolveApiBaseUrl(config) {
14
+ return String(config.apiBaseUrl ?? config.baseUrl ?? config.apibaseUrl ?? '').trim();
15
+ }
13
16
  export default class EnvList extends Command {
14
17
  static summary = 'List configured environments';
15
18
  static examples = [
16
19
  '<%= config.bin %> <%= command.id %>',
17
20
  ];
18
- static flags = {
19
- scope: Flags.string({
20
- char: 's',
21
- description: 'Config scope',
22
- options: ['project', 'global'],
23
- }),
24
- };
25
21
  async run() {
26
- const { flags } = await this.parse(EnvList);
27
- const scope = flags.scope;
28
- const { currentEnv, envs } = await listEnvs({ scope });
22
+ await this.parse(EnvList);
23
+ const { currentEnv, envs } = await listEnvs({ scope: resolveDefaultConfigScope() });
29
24
  const names = Object.keys(envs).sort();
30
25
  if (!names.length) {
31
- this.log(`No envs configured${scope ? ` in ${formatCliHomeScope(scope)} scope` : ''}.`);
32
- this.log('Run `nb env add <name> --base-url <url>` to add one.');
26
+ this.log('No envs configured.');
27
+ this.log('Run `nb env add <name> --api-base-url <url>` to add one.');
33
28
  return;
34
29
  }
35
30
  const rows = names.map((name) => {
36
31
  const env = envs[name];
37
- return [name === currentEnv ? '*' : '', name, env.baseUrl ?? '', env.auth?.type ?? '', env.runtime?.version ?? ''];
32
+ return [name === currentEnv ? '*' : '', name, resolveApiBaseUrl(env), env.auth?.type ?? '', env.runtime?.version ?? ''];
38
33
  });
39
34
  this.log(renderTable(['Current', 'Name', 'Base URL', 'Auth', 'Runtime'], rows));
40
35
  }
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import { Args, Command, Flags } from '@oclif/core';
10
10
  import { getCurrentEnvName, removeEnv } from '../../lib/auth-store.js';
11
- import { formatCliHomeScope } from '../../lib/cli-home.js';
11
+ import { resolveDefaultConfigScope } from '../../lib/cli-home.js';
12
12
  import { confirmAction, isInteractiveTerminal, printVerbose, setVerboseMode } from '../../lib/ui.js';
13
13
  export default class EnvRemove extends Command {
14
14
  static summary = 'Remove a configured environment';
@@ -26,11 +26,6 @@ export default class EnvRemove extends Command {
26
26
  description: 'Show detailed progress output',
27
27
  default: false,
28
28
  }),
29
- scope: Flags.string({
30
- char: 's',
31
- description: 'Config scope',
32
- options: ['project', 'global'],
33
- }),
34
29
  };
35
30
  static args = {
36
31
  name: Args.string({
@@ -41,8 +36,7 @@ export default class EnvRemove extends Command {
41
36
  async run() {
42
37
  const { args, flags } = await this.parse(EnvRemove);
43
38
  setVerboseMode(flags.verbose);
44
- const scope = flags.scope;
45
- const currentEnv = await getCurrentEnvName({ scope });
39
+ const currentEnv = await getCurrentEnvName({ scope: resolveDefaultConfigScope() });
46
40
  if (args.name === currentEnv && !flags.force) {
47
41
  if (!isInteractiveTerminal()) {
48
42
  this.error('Refusing to remove the current env without confirmation. Re-run with `--force`.');
@@ -54,8 +48,8 @@ export default class EnvRemove extends Command {
54
48
  }
55
49
  }
56
50
  printVerbose(`Removing env "${args.name}"`);
57
- const result = await removeEnv(args.name, { scope });
58
- this.log(`Removed env "${result.removed}"${scope ? ` from ${formatCliHomeScope(scope)} scope` : ''}.`);
51
+ const result = await removeEnv(args.name, { scope: resolveDefaultConfigScope() });
52
+ this.log(`Removed env "${result.removed}".`);
59
53
  if (result.hasEnvs) {
60
54
  this.log(`Current env: ${result.currentEnv}`);
61
55
  return;
@@ -11,7 +11,7 @@ import { fileURLToPath } from 'node:url';
11
11
  import { Args, Command, Flags } from '@oclif/core';
12
12
  import { getCurrentEnvName } from '../../lib/auth-store.js';
13
13
  import { updateEnvRuntime } from '../../lib/bootstrap.js';
14
- import { formatCliHomeScope } from '../../lib/cli-home.js';
14
+ import { resolveDefaultConfigScope } from '../../lib/cli-home.js';
15
15
  import { failTask, startTask, succeedTask } from '../../lib/ui.js';
16
16
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
17
17
  export default class EnvUpdate extends Command {
@@ -31,12 +31,7 @@ export default class EnvUpdate extends Command {
31
31
  description: 'Show detailed progress output',
32
32
  default: false,
33
33
  }),
34
- scope: Flags.string({
35
- char: 's',
36
- description: 'Config scope',
37
- options: ['project', 'global'],
38
- }),
39
- 'base-url': Flags.string({
34
+ 'api-base-url': Flags.string({
40
35
  description: 'NocoBase API base URL override. When provided, persist it to the target env before saving the refreshed runtime.',
41
36
  }),
42
37
  role: Flags.string({
@@ -49,21 +44,20 @@ export default class EnvUpdate extends Command {
49
44
  };
50
45
  async run() {
51
46
  const { args, flags } = await this.parse(EnvUpdate);
52
- const scope = flags.scope;
53
47
  const envName = args.name;
54
- const envLabel = envName ?? (await getCurrentEnvName({ scope }));
55
- startTask(`Updating env runtime: ${envLabel}${scope ? ` (${formatCliHomeScope(scope)})` : ''}`);
48
+ const envLabel = envName ?? (await getCurrentEnvName({ scope: resolveDefaultConfigScope() }));
49
+ startTask(`Updating env runtime: ${envLabel}`);
56
50
  try {
57
51
  const runtime = await updateEnvRuntime({
58
52
  envName,
59
- scope,
60
- baseUrl: flags['base-url'],
53
+ scope: resolveDefaultConfigScope(),
54
+ baseUrl: flags['api-base-url'],
61
55
  role: flags.role,
62
56
  token: flags.token,
63
57
  configFile: path.join(path.dirname(path.dirname(path.dirname(__dirname))), 'nocobase-ctl.config.json'),
64
58
  verbose: flags.verbose,
65
59
  });
66
- succeedTask(`Updated env "${envLabel}" to runtime "${runtime.version}"${scope ? ` in ${formatCliHomeScope(scope)} scope` : ''}.`);
60
+ succeedTask(`Updated env "${envLabel}" to runtime "${runtime.version}".`);
67
61
  }
68
62
  catch (error) {
69
63
  failTask(`Failed to update env "${envLabel}".`);
@@ -6,21 +6,14 @@
6
6
  * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
- import { Args, Command, Flags } from '@oclif/core';
9
+ import { Args, Command } from '@oclif/core';
10
10
  import { setCurrentEnv } from '../../lib/auth-store.js';
11
- import { formatCliHomeScope } from '../../lib/cli-home.js';
11
+ import { resolveDefaultConfigScope } from '../../lib/cli-home.js';
12
12
  export default class EnvUse extends Command {
13
13
  static summary = 'Switch the current environment';
14
14
  static examples = [
15
15
  '<%= config.bin %> <%= command.id %> local',
16
16
  ];
17
- static flags = {
18
- scope: Flags.string({
19
- char: 's',
20
- description: 'Config scope',
21
- options: ['project', 'global'],
22
- }),
23
- };
24
17
  static args = {
25
18
  name: Args.string({
26
19
  description: 'Configured environment name',
@@ -28,9 +21,8 @@ export default class EnvUse extends Command {
28
21
  }),
29
22
  };
30
23
  async run() {
31
- const { args, flags } = await this.parse(EnvUse);
32
- const scope = flags.scope;
33
- await setCurrentEnv(args.name, { scope });
34
- this.log(`Current env: ${args.name}${scope ? ` (${formatCliHomeScope(scope)} scope)` : ''}`);
24
+ const { args } = await this.parse(EnvUse);
25
+ await setCurrentEnv(args.name, { scope: resolveDefaultConfigScope() });
26
+ this.log(`Current env: ${args.name}`);
35
27
  }
36
28
  }