@nocobase/cli 2.1.0-alpha.28 → 2.1.0-alpha.29

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.
@@ -97,15 +97,21 @@ function builtinDbContainerName(runtime) {
97
97
  function managedDockerNetworkName(runtime) {
98
98
  return runtime.dockerNetworkName?.trim() || runtime.workspaceName?.trim() || undefined;
99
99
  }
100
- async function confirmDownAll(envName, yes) {
100
+ async function confirmDownAll(envName, yes, options) {
101
101
  if (yes) {
102
102
  return true;
103
103
  }
104
+ const usedCurrentEnv = options?.explicitEnv === false;
104
105
  if (!isInteractiveTerminal()) {
106
+ if (usedCurrentEnv) {
107
+ throw new Error(`\`nb app down --all\` is using the current env "${envName}". Re-run with --env ${envName} --yes to delete everything for that env in non-interactive mode.`);
108
+ }
105
109
  throw new Error(`\`nb app down --all\` needs confirmation. Re-run with --yes to delete everything for "${envName}" in non-interactive mode.`);
106
110
  }
107
111
  const answer = await p.confirm({
108
- message: `Delete everything for "${envName}"? This removes the app, managed containers, storage data, and the saved CLI env config.`,
112
+ message: usedCurrentEnv
113
+ ? `Delete everything for current env "${envName}"? This removes the app, managed containers, storage data, and the saved CLI env config.`
114
+ : `Delete everything for "${envName}"? This removes the app, managed containers, storage data, and the saved CLI env config.`,
109
115
  active: 'yes',
110
116
  inactive: 'no',
111
117
  initialValue: false,
@@ -152,6 +158,7 @@ export default class AppDown extends Command {
152
158
  async run() {
153
159
  const { flags } = await this.parse(AppDown);
154
160
  const requestedEnv = flags.env?.trim() || undefined;
161
+ const explicitEnv = Boolean(requestedEnv);
155
162
  const removeData = Boolean(flags.all);
156
163
  const removeEnvConfig = Boolean(flags.all);
157
164
  const runtime = await resolveManagedAppRuntime(requestedEnv);
@@ -175,7 +182,7 @@ export default class AppDown extends Command {
175
182
  if (flags.all) {
176
183
  let confirmed = false;
177
184
  try {
178
- confirmed = await confirmDownAll(runtime.envName, flags.yes);
185
+ confirmed = await confirmDownAll(runtime.envName, flags.yes, { explicitEnv });
179
186
  }
180
187
  catch (error) {
181
188
  this.error(error instanceof Error ? error.message : String(error));
@@ -10,7 +10,7 @@ import { Command, Flags } from '@oclif/core';
10
10
  import { formatMissingManagedAppEnvMessage, resolveManagedAppRuntime, runLocalNocoBaseCommand, startDockerContainer, } from '../../lib/app-runtime.js';
11
11
  import { AppHealthCheckError, formatAppUrl, isAppReady, resolveManagedAppApiBaseUrl, waitForAppReady, } from '../../lib/app-health.js';
12
12
  import { ensureBuiltinDbReady, ensureSavedLocalSource, recreateSavedDockerApp, } from '../../lib/app-managed-resources.js';
13
- import { failTask, printInfo, startTask, succeedTask } from '../../lib/ui.js';
13
+ import { announceTargetEnv, failTask, printInfo, startTask, succeedTask } from '../../lib/ui.js';
14
14
  function argvHasToken(argv, tokens) {
15
15
  return tokens.some((token) => argv.includes(token));
16
16
  }
@@ -107,6 +107,7 @@ export default class AppStart extends Command {
107
107
  'Use a local or Docker env if you need CLI-managed start and stop right now.',
108
108
  ].join('\n'));
109
109
  }
110
+ announceTargetEnv(runtime.envName);
110
111
  if (runtime.kind === 'docker') {
111
112
  const unsupportedFlags = [
112
113
  flags.quickstart ? '--quickstart' : undefined,
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import { Command, Flags } from '@oclif/core';
10
10
  import { formatMissingManagedAppEnvMessage, resolveManagedAppRuntime, runLocalNocoBaseCommand, stopDockerContainer, } from '../../lib/app-runtime.js';
11
- import { failTask, startTask, succeedTask } from '../../lib/ui.js';
11
+ import { announceTargetEnv, failTask, startTask, succeedTask } from '../../lib/ui.js';
12
12
  function formatStopFailure(envName, message) {
13
13
  if (/does not exist/i.test(message)) {
14
14
  return [
@@ -65,6 +65,7 @@ export default class AppStop extends Command {
65
65
  'Use a local or Docker env if you need CLI-managed stop right now.',
66
66
  ].join('\n'));
67
67
  }
68
+ announceTargetEnv(runtime.envName);
68
69
  if (runtime.kind === 'docker') {
69
70
  startTask(`Stopping NocoBase for "${runtime.envName}"...`);
70
71
  try {
@@ -12,7 +12,7 @@ import { formatMissingManagedAppEnvMessage, resolveManagedAppRuntime, runLocalNo
12
12
  import { resolveConfiguredEnvPath } from '../../lib/cli-home.js';
13
13
  import { deriveBuiltinDbConnection } from '../../lib/builtin-db.js';
14
14
  import { commandSucceeds, run } from '../../lib/run-npm.js';
15
- import { failTask, printInfo, startTask, stopTask, succeedTask, updateTask } from '../../lib/ui.js';
15
+ import { announceTargetEnv, failTask, printInfo, startTask, stopTask, succeedTask, updateTask } from '../../lib/ui.js';
16
16
  const DEFAULT_DOCKER_REGISTRY = 'nocobase/nocobase';
17
17
  const DOCKER_APP_STORAGE_DESTINATION = '/app/nocobase/storage';
18
18
  const APP_HEALTH_CHECK_INTERVAL_MS = 2_000;
@@ -563,6 +563,7 @@ export default class AppUpgrade extends Command {
563
563
  'Use a local or Docker env if you need CLI-managed upgrades right now.',
564
564
  ].join('\n'));
565
565
  }
566
+ announceTargetEnv(runtime.envName);
566
567
  try {
567
568
  const resolvedVersion = AppUpgrade.resolveUpgradeVersion(runtime, parsed);
568
569
  const runCommand = this.config.runCommand.bind(this.config);
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import { Command, Flags } from '@oclif/core';
10
10
  import { formatMissingManagedAppEnvMessage, startDockerContainer, } from '../../lib/app-runtime.js';
11
- import { failTask, startTask, succeedTask } from '../../lib/ui.js';
11
+ import { announceTargetEnv, failTask, startTask, succeedTask } from '../../lib/ui.js';
12
12
  import { formatUnmanagedDbMessage, resolveDbRuntime } from './shared.js';
13
13
  function formatDbStartFailure(envName, message) {
14
14
  if (/does not exist/i.test(message)) {
@@ -52,6 +52,7 @@ export default class DbStart extends Command {
52
52
  if (runtime.kind !== 'builtin') {
53
53
  this.error(formatUnmanagedDbMessage('start', runtime));
54
54
  }
55
+ announceTargetEnv(runtime.envName);
55
56
  startTask(`Starting the built-in database for "${runtime.envName}"...`);
56
57
  try {
57
58
  const state = await startDockerContainer(runtime.containerName, {
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import { Command, Flags } from '@oclif/core';
10
10
  import { formatMissingManagedAppEnvMessage, stopDockerContainer, } from '../../lib/app-runtime.js';
11
- import { failTask, startTask, succeedTask } from '../../lib/ui.js';
11
+ import { announceTargetEnv, failTask, startTask, succeedTask } from '../../lib/ui.js';
12
12
  import { formatUnmanagedDbMessage, resolveDbRuntime } from './shared.js';
13
13
  function formatDbStopFailure(envName, message) {
14
14
  if (/does not exist/i.test(message)) {
@@ -52,6 +52,7 @@ export default class DbStop extends Command {
52
52
  if (runtime.kind !== 'builtin') {
53
53
  this.error(formatUnmanagedDbMessage('stop', runtime));
54
54
  }
55
+ announceTargetEnv(runtime.envName);
55
56
  startTask(`Stopping the built-in database for "${runtime.envName}"...`);
56
57
  try {
57
58
  const state = await stopDockerContainer(runtime.containerName, {
@@ -10,7 +10,7 @@ import * as p from '@clack/prompts';
10
10
  import { Command, Flags } from '@oclif/core';
11
11
  import { readFile } from 'node:fs/promises';
12
12
  import { ensureInstanceId, licenseEnvFlag, licenseJsonFlag, licensePkgUrlFlag, redactLicenseKey, requireLicenseRuntime, resolveLicenseKeyFile, resolveLicenseServiceUrl, saveLicenseKey, sanitizeLicenseOutput, validateLicenseKey, } from './shared.js';
13
- import { isInteractiveTerminal } from '../../lib/ui.js';
13
+ import { announceTargetEnv, isInteractiveTerminal } from '../../lib/ui.js';
14
14
  import { appUrl } from '../env/shared.js';
15
15
  function resolveOnlineInputValue(value) {
16
16
  return String(value ?? '').trim();
@@ -210,6 +210,9 @@ export default class LicenseActivate extends Command {
210
210
  async run() {
211
211
  const { flags } = await this.parse(LicenseActivate);
212
212
  const runtime = await requireLicenseRuntime(flags.env);
213
+ if (!flags.json) {
214
+ announceTargetEnv(runtime.envName);
215
+ }
213
216
  let key = String(flags.key ?? '').trim();
214
217
  let keyFile = String(flags['key-file'] ?? '').trim();
215
218
  let online = Boolean(flags.online);
@@ -21,6 +21,7 @@ function formatMissingFieldsMessage(missing) {
21
21
  ].join('\n');
22
22
  }
23
23
  export default class LicenseGenerateId extends Command {
24
+ static hidden = true;
24
25
  static summary = 'Generate a commercial license instance ID from explicit database settings';
25
26
  static description = 'Generate the commercial licensing instance ID from explicit `--db-*` flags. This command only prints the generated ID and does not save it.';
26
27
  static examples = [
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import { Command, Flags } from '@oclif/core';
10
10
  import { generateAndSaveInstanceId, licenseEnvFlag, licenseJsonFlag, readSavedInstanceId, requireLicenseRuntime, resolveInstanceIdFile, } from './shared.js';
11
+ import { announceTargetEnv } from '../../lib/ui.js';
11
12
  export default class LicenseId extends Command {
12
13
  static summary = 'Show the instance ID for the selected env';
13
14
  static description = 'Show the commercial licensing instance ID for the selected env, generating and saving it if needed.';
@@ -28,6 +29,9 @@ export default class LicenseId extends Command {
28
29
  async run() {
29
30
  const { flags } = await this.parse(LicenseId);
30
31
  const runtime = await requireLicenseRuntime(flags.env);
32
+ if (!flags.json) {
33
+ announceTargetEnv(runtime.envName);
34
+ }
31
35
  const savedBefore = await readSavedInstanceId(runtime);
32
36
  const shouldGenerate = Boolean(flags.force) || !savedBefore;
33
37
  const instanceId = shouldGenerate
@@ -11,6 +11,7 @@ import pc from 'picocolors';
11
11
  import { licenseEnvFlag, licenseJsonFlag, licensePkgUrlFlag, requireLicenseRuntime } from '../shared.js';
12
12
  import { cleanLicensedPlugins } from './shared.js';
13
13
  import { resolvePluginStoragePath } from '../../../lib/plugin-storage.js';
14
+ import { announceTargetEnv } from '../../../lib/ui.js';
14
15
  function formatActionLabel(action) {
15
16
  switch (action) {
16
17
  case 'removed':
@@ -38,7 +39,6 @@ export default class LicensePluginsClean extends Command {
38
39
  default: false,
39
40
  }),
40
41
  verbose: Flags.boolean({
41
- char: 'V',
42
42
  description: 'Show detailed per-plugin clean logs',
43
43
  default: false,
44
44
  }),
@@ -46,6 +46,9 @@ export default class LicensePluginsClean extends Command {
46
46
  async run() {
47
47
  const { flags } = await this.parse(LicensePluginsClean);
48
48
  const runtime = await requireLicenseRuntime(flags.env);
49
+ if (!flags.json) {
50
+ announceTargetEnv(runtime.envName);
51
+ }
49
52
  const shouldStreamLogs = !flags.json && Boolean(flags.verbose);
50
53
  const pluginStoragePath = resolvePluginStoragePath(runtime.env.storagePath);
51
54
  if (!flags.json) {
@@ -14,11 +14,10 @@ import { licenseEnvFlag, licenseJsonFlag, licensePkgUrlFlag, requireLicenseRunti
14
14
  import { syncLicensedPlugins } from './shared.js';
15
15
  import { resolvePluginStoragePath } from '../../../lib/plugin-storage.js';
16
16
  import { commandOutput } from '../../../lib/run-npm.js';
17
- import { startTask, stopTask, succeedTask, updateTask } from '../../../lib/ui.js';
17
+ import { announceTargetEnv, startTask, stopTask, succeedTask, updateTask } from '../../../lib/ui.js';
18
18
  const SYNC_LOADING_DELAY_MS = 1200;
19
19
  const SYNC_LOADING_UPDATE_MS = 5000;
20
- const LOCAL_CLI_PACKAGE_JSON_PATH = 'node_modules/@nocobase/cli/package.json';
21
- const DOCKER_CLI_PACKAGE_JSON_PATH = '/opt/nb/node_modules/@nocobase/cli/package.json';
20
+ const LOCAL_APP_PACKAGE_JSON_PATH = 'node_modules/@nocobase/app/package.json';
22
21
  const DEFAULT_DOCKER_REGISTRY = 'nocobase/nocobase';
23
22
  const DEFAULT_DOCKER_VERSION = 'alpha';
24
23
  function formatActionLabel(action) {
@@ -78,13 +77,13 @@ async function parseVersionFromPackageJson(content, sourceLabel) {
78
77
  return version;
79
78
  }
80
79
  async function resolveLocalAppVersion(runtime) {
81
- const packageJsonPath = path.join(runtime.projectRoot, LOCAL_CLI_PACKAGE_JSON_PATH);
80
+ const packageJsonPath = path.join(runtime.projectRoot, LOCAL_APP_PACKAGE_JSON_PATH);
82
81
  let content;
83
82
  try {
84
83
  content = await readFile(packageJsonPath, 'utf8');
85
84
  }
86
85
  catch {
87
- throw new Error(`Missing ${LOCAL_CLI_PACKAGE_JSON_PATH} for env "${runtime.envName}" at ${packageJsonPath}.`);
86
+ throw new Error(`Missing ${LOCAL_APP_PACKAGE_JSON_PATH} for env "${runtime.envName}" at ${packageJsonPath}.`);
88
87
  }
89
88
  return await parseVersionFromPackageJson(content, packageJsonPath);
90
89
  }
@@ -101,7 +100,7 @@ async function resolveDockerAppVersion(runtime) {
101
100
  if (dockerPlatform) {
102
101
  args.push('--platform', dockerPlatform);
103
102
  }
104
- args.push('--entrypoint', 'node', imageRef, '-p', `JSON.stringify(require(${JSON.stringify(DOCKER_CLI_PACKAGE_JSON_PATH)}).version)`);
103
+ args.push('--entrypoint', 'nb', imageRef, '--version');
105
104
  let output;
106
105
  try {
107
106
  output = await commandOutput('docker', args, {
@@ -110,11 +109,12 @@ async function resolveDockerAppVersion(runtime) {
110
109
  }
111
110
  catch (error) {
112
111
  const message = error instanceof Error ? error.message : String(error);
113
- throw new Error(`Missing ${DOCKER_CLI_PACKAGE_JSON_PATH} for env "${runtime.envName}" inside Docker image ${imageRef}. ${message}`);
112
+ throw new Error(`Failed to read app version for env "${runtime.envName}" from Docker image ${imageRef}. ${message}`);
114
113
  }
115
- const version = trimValue(output.replace(/^"+|"+$/g, ''));
114
+ const versionMatch = output.match(/@nocobase\/cli\/([^\s]+)/);
115
+ const version = trimValue(versionMatch?.[1] ?? output.replace(/^"+|"+$/g, ''));
116
116
  if (!version) {
117
- throw new Error(`Missing version in ${DOCKER_CLI_PACKAGE_JSON_PATH} for env "${runtime.envName}" inside Docker image ${imageRef}.`);
117
+ throw new Error(`Missing app version for env "${runtime.envName}" inside Docker image ${imageRef}.`);
118
118
  }
119
119
  return version;
120
120
  }
@@ -148,7 +148,6 @@ export default class LicensePluginsSync extends Command {
148
148
  description: 'Registry version or dist-tag to synchronize. Defaults to the current workspace version.',
149
149
  }),
150
150
  verbose: Flags.boolean({
151
- char: 'V',
152
151
  description: 'Show detailed per-plugin sync logs',
153
152
  default: false,
154
153
  }),
@@ -156,6 +155,9 @@ export default class LicensePluginsSync extends Command {
156
155
  async run() {
157
156
  const { flags } = await this.parse(LicensePluginsSync);
158
157
  const runtime = await requireLicenseRuntime(flags.env);
158
+ if (!flags.json) {
159
+ announceTargetEnv(runtime.envName);
160
+ }
159
161
  const version = trimValue(flags.version) || await resolveManagedAppVersion(runtime);
160
162
  const registryVersion = normalizePluginRegistryVersion(version);
161
163
  const shouldStreamLogs = !flags.json && Boolean(flags.verbose);
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import { Args, Command, Flags } from '@oclif/core';
10
10
  import { formatMissingManagedAppEnvMessage, resolveManagedAppRuntime, runDockerNocoBaseCommand, runLocalNocoBaseCommand, } from '../../lib/app-runtime.js';
11
+ import { announceTargetEnv } from '../../lib/ui.js';
11
12
  export default class PluginDisable extends Command {
12
13
  static hidden = false;
13
14
  static args = {
@@ -39,6 +40,7 @@ export default class PluginDisable extends Command {
39
40
  if (!runtime) {
40
41
  this.error(formatMissingManagedAppEnvMessage(flags.env));
41
42
  }
43
+ announceTargetEnv(runtime.envName);
42
44
  if (runtime.kind === 'local') {
43
45
  try {
44
46
  await runLocalNocoBaseCommand(runtime, ['pm', 'disable', ...packages]);
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import { Args, Command, Flags } from '@oclif/core';
10
10
  import { formatMissingManagedAppEnvMessage, resolveManagedAppRuntime, runDockerNocoBaseCommand, runLocalNocoBaseCommand, } from '../../lib/app-runtime.js';
11
+ import { announceTargetEnv } from '../../lib/ui.js';
11
12
  export default class PluginEnable extends Command {
12
13
  static hidden = false;
13
14
  static args = {
@@ -39,6 +40,7 @@ export default class PluginEnable extends Command {
39
40
  if (!runtime) {
40
41
  this.error(formatMissingManagedAppEnvMessage(flags.env));
41
42
  }
43
+ announceTargetEnv(runtime.envName);
42
44
  if (runtime.kind === 'local') {
43
45
  try {
44
46
  await runLocalNocoBaseCommand(runtime, ['pm', 'enable', ...packages]);
@@ -8,7 +8,7 @@
8
8
  */
9
9
  import { Command, Flags } from '@oclif/core';
10
10
  import { formatMissingManagedAppEnvMessage, resolveManagedAppRuntime, runLocalNocoBaseCommand, } from '../../lib/app-runtime.js';
11
- import { printInfo } from '../../lib/ui.js';
11
+ import { announceTargetEnv, printInfo } from '../../lib/ui.js';
12
12
  function formatUnsupportedRuntimeMessage(kind, envName) {
13
13
  if (kind === 'docker') {
14
14
  return [
@@ -110,6 +110,7 @@ export default class SourceDev extends Command {
110
110
  if (runtime.kind === 'docker' || runtime.kind === 'http' || runtime.kind === 'ssh') {
111
111
  this.error(formatUnsupportedRuntimeMessage(runtime.kind, runtime.envName));
112
112
  }
113
+ announceTargetEnv(runtime.envName);
113
114
  const devPort = flags.port
114
115
  || (runtime.env.appPort !== undefined && runtime.env.appPort !== null
115
116
  ? String(runtime.env.appPort).trim()
@@ -36,14 +36,10 @@ function hasBooleanFlag(argv, name) {
36
36
  const exact = `--${name}`;
37
37
  const negated = `--no-${name}`;
38
38
  const prefix = `--${name}=`;
39
- const alias = name === 'verbose' ? '-V' : undefined;
40
39
  for (const value of argv) {
41
40
  if (value === exact) {
42
41
  return true;
43
42
  }
44
- if (alias && value === alias) {
45
- return true;
46
- }
47
43
  if (value === negated) {
48
44
  return false;
49
45
  }
package/dist/lib/ui.js CHANGED
@@ -88,6 +88,9 @@ export function printInfo(message) {
88
88
  }
89
89
  console.log(pc.cyan(message));
90
90
  }
91
+ export function announceTargetEnv(envName) {
92
+ printInfo(`Target env: ${envName}`);
93
+ }
91
94
  export function printVerbose(message) {
92
95
  if (!verboseMode) {
93
96
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/cli",
3
- "version": "2.1.0-alpha.28",
3
+ "version": "2.1.0-alpha.29",
4
4
  "description": "NocoBase Command Line Tool",
5
5
  "type": "module",
6
6
  "main": "dist/generated/command-registry.js",
@@ -103,5 +103,5 @@
103
103
  "type": "git",
104
104
  "url": "git+https://github.com/nocobase/nocobase.git"
105
105
  },
106
- "gitHead": "e38293c4a1ce4d043d2b17a3067fd4f0341a7a2d"
106
+ "gitHead": "526e36e399a570755286f9a0d34fa202b4a58a03"
107
107
  }