@nocobase/cli 2.1.0-alpha.18 → 2.1.0-alpha.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/run.js +7 -5
- package/dist/commands/{resource → api/resource}/create.js +1 -1
- package/dist/commands/{resource → api/resource}/destroy.js +1 -1
- package/dist/commands/{resource → api/resource}/get.js +1 -1
- package/dist/commands/{resource → api/resource}/list.js +1 -1
- package/dist/commands/{resource → api/resource}/query.js +1 -1
- package/dist/commands/{resource → api/resource}/update.js +1 -1
- package/dist/commands/build.js +51 -0
- package/dist/commands/dev.js +58 -0
- package/dist/commands/download.js +121 -0
- package/dist/commands/install.js +55 -0
- package/dist/commands/pm/disable.js +32 -0
- package/dist/commands/pm/enable.js +32 -0
- package/dist/commands/pm/list.js +32 -0
- package/dist/commands/restart.js +32 -0
- package/dist/commands/scaffold/migration.js +38 -0
- package/dist/commands/scaffold/plugin.js +37 -0
- package/dist/commands/self-update.js +46 -0
- package/dist/commands/start.js +55 -0
- package/dist/commands/upgrade.js +35 -0
- package/dist/generated/command-registry.js +25 -26
- package/dist/lib/bootstrap.js +67 -38
- package/dist/lib/command-discovery.js +39 -0
- package/dist/lib/env-auth.js +48 -6
- package/dist/lib/run-npm.js +74 -0
- package/dist/lib/ui.js +19 -13
- package/package.json +2 -2
- package/dist/commands/api/index.js +0 -8
- package/dist/commands/env/index.js +0 -27
- package/dist/commands/resource/index.js +0 -7
package/bin/run.js
CHANGED
|
@@ -9,6 +9,10 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
9
9
|
const root = path.resolve(__dirname, '..');
|
|
10
10
|
const realRoot = fs.realpathSync(root);
|
|
11
11
|
const isSourcePackage = realRoot.split(path.sep).join('/').endsWith('/packages/core/cli');
|
|
12
|
+
let isDev = isSourcePackage;
|
|
13
|
+
if (process.env.NODE_ENV === 'production') {
|
|
14
|
+
isDev = false;
|
|
15
|
+
}
|
|
12
16
|
|
|
13
17
|
/**
|
|
14
18
|
* In the monorepo, plain `node` cannot load `.ts`. Re-exec once with `--import tsx`
|
|
@@ -30,17 +34,15 @@ function reexecWithTsx() {
|
|
|
30
34
|
process.exit(result.status === null ? 1 : result.status);
|
|
31
35
|
}
|
|
32
36
|
|
|
33
|
-
if (
|
|
37
|
+
if (isDev && !process.env._NOCO_CLI_TSX_CHILD) {
|
|
34
38
|
reexecWithTsx();
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
const bootstrapPath =
|
|
38
|
-
? path.join(root, 'src/lib/bootstrap.ts')
|
|
39
|
-
: path.join(root, 'dist/lib/bootstrap.js');
|
|
41
|
+
const bootstrapPath = isDev ? path.join(root, 'src/lib/bootstrap.ts') : path.join(root, 'dist/lib/bootstrap.js');
|
|
40
42
|
const { ensureRuntimeFromArgv } = await import(pathToFileURL(bootstrapPath).href);
|
|
41
43
|
const { flush, run, settings } = await import('@oclif/core');
|
|
42
44
|
|
|
43
|
-
if (
|
|
45
|
+
if (isDev) {
|
|
44
46
|
settings.debug = true;
|
|
45
47
|
}
|
|
46
48
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
-
import { buildCreateArgs, createFlags, runResourceCommand } from '
|
|
2
|
+
import { buildCreateArgs, createFlags, runResourceCommand } from '../../../lib/resource-command.js';
|
|
3
3
|
export default class ResourceCreate extends Command {
|
|
4
4
|
static summary = 'Create a record in a resource';
|
|
5
5
|
static description = 'Create a record in a generic resource. Pass record content through --values as a JSON object.';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
-
import { buildDestroyArgs, destroyFlags, runResourceCommand } from '
|
|
2
|
+
import { buildDestroyArgs, destroyFlags, runResourceCommand } from '../../../lib/resource-command.js';
|
|
3
3
|
export default class ResourceDestroy extends Command {
|
|
4
4
|
static summary = 'Delete records from a resource';
|
|
5
5
|
static description = 'Delete records from a generic resource. Target records with --filter-by-tk or --filter.';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
-
import { buildGetArgs, getFlags, runResourceCommand } from '
|
|
2
|
+
import { buildGetArgs, getFlags, runResourceCommand } from '../../../lib/resource-command.js';
|
|
3
3
|
export default class ResourceGet extends Command {
|
|
4
4
|
static summary = 'Get a record from a resource';
|
|
5
5
|
static description = 'Get a record from a generic resource. Use --filter-by-tk for the primary key and association resource names with --source-id when needed.';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
-
import { buildListArgs, listFlags, runResourceCommand } from '
|
|
2
|
+
import { buildListArgs, listFlags, runResourceCommand } from '../../../lib/resource-command.js';
|
|
3
3
|
export default class ResourceList extends Command {
|
|
4
4
|
static summary = 'List records from a resource';
|
|
5
5
|
static description = 'List records from a generic resource. Use association resource names like posts.comments with --source-id when needed.';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
-
import { buildQueryArgs, queryFlags, runResourceCommand } from '
|
|
2
|
+
import { buildQueryArgs, queryFlags, runResourceCommand } from '../../../lib/resource-command.js';
|
|
3
3
|
export default class ResourceQuery extends Command {
|
|
4
4
|
static summary = 'Run an aggregate query on a resource';
|
|
5
5
|
static description = 'Run an aggregate query on a generic resource. Pass measures, dimensions, and orders as JSON arrays.';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
-
import { buildUpdateArgs, runResourceCommand, updateFlags } from '
|
|
2
|
+
import { buildUpdateArgs, runResourceCommand, updateFlags } from '../../../lib/resource-command.js';
|
|
3
3
|
export default class ResourceUpdate extends Command {
|
|
4
4
|
static summary = 'Update records in a resource';
|
|
5
5
|
static description = 'Update records in a generic resource. Target records with --filter-by-tk or --filter, and pass updated values through --values.';
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
10
|
+
import { runNocoBaseCommand } from "../lib/run-npm.js";
|
|
11
|
+
export default class Build extends Command {
|
|
12
|
+
static args = {
|
|
13
|
+
/** Matches `nb build @nocobase/acl @nocobase/actions` — zero or more package names. */
|
|
14
|
+
packages: Args.string({
|
|
15
|
+
description: 'package names to build',
|
|
16
|
+
multiple: true,
|
|
17
|
+
required: false,
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
static description = 'Run the legacy NocoBase build (forwards to `npm run build` in the repo root)';
|
|
21
|
+
static examples = [
|
|
22
|
+
'<%= config.bin %> <%= command.id %>',
|
|
23
|
+
'<%= config.bin %> <%= command.id %> --no-dts',
|
|
24
|
+
'<%= config.bin %> <%= command.id %> --sourcemap',
|
|
25
|
+
'<%= config.bin %> <%= command.id %> @nocobase/acl',
|
|
26
|
+
'<%= config.bin %> <%= command.id %> @nocobase/acl @nocobase/actions',
|
|
27
|
+
];
|
|
28
|
+
static flags = {
|
|
29
|
+
env: Flags.string({ description: 'Environment', char: 'e', required: false }),
|
|
30
|
+
'no-dts': Flags.boolean({ description: 'not generate dts' }),
|
|
31
|
+
sourcemap: Flags.boolean({ description: 'generate sourcemap' }),
|
|
32
|
+
};
|
|
33
|
+
async run() {
|
|
34
|
+
const { args, flags } = await this.parse(Build);
|
|
35
|
+
const packages = args.packages ?? [];
|
|
36
|
+
const npmArgs = ['build', ...packages];
|
|
37
|
+
if (flags['no-dts']) {
|
|
38
|
+
npmArgs.push('--no-dts');
|
|
39
|
+
}
|
|
40
|
+
if (flags.sourcemap) {
|
|
41
|
+
npmArgs.push('--sourcemap');
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
await runNocoBaseCommand(npmArgs, process.cwd());
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
48
|
+
this.error(message);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
10
|
+
import { runNocoBaseCommand } from "../lib/run-npm.js";
|
|
11
|
+
export default class Dev extends Command {
|
|
12
|
+
static args = {
|
|
13
|
+
file: Args.string({ description: 'file to read' }),
|
|
14
|
+
};
|
|
15
|
+
static description = 'describe the command here';
|
|
16
|
+
static examples = [
|
|
17
|
+
'<%= config.bin %> <%= command.id %>',
|
|
18
|
+
'<%= config.bin %> <%= command.id %> --db-sync',
|
|
19
|
+
'<%= config.bin %> <%= command.id %> --port 12000',
|
|
20
|
+
'<%= config.bin %> <%= command.id %> --client',
|
|
21
|
+
'<%= config.bin %> <%= command.id %> --server',
|
|
22
|
+
'<%= config.bin %> <%= command.id %> --inspect 9229',
|
|
23
|
+
];
|
|
24
|
+
static flags = {
|
|
25
|
+
env: Flags.string({ description: 'Environment', char: 'e', required: false }),
|
|
26
|
+
'db-sync': Flags.boolean({ description: 'Sync the database', required: false }),
|
|
27
|
+
port: Flags.string({ description: 'Port', char: 'p', required: false }),
|
|
28
|
+
client: Flags.boolean({ description: 'Client', char: 'c', required: false }),
|
|
29
|
+
server: Flags.boolean({ description: 'Server', char: 's', required: false }),
|
|
30
|
+
inspect: Flags.string({ description: 'Inspect port', char: 'i', required: false }),
|
|
31
|
+
};
|
|
32
|
+
async run() {
|
|
33
|
+
const { flags } = await this.parse(Dev);
|
|
34
|
+
const npmArgs = ['dev', '--rsbuild'];
|
|
35
|
+
if (flags['db-sync']) {
|
|
36
|
+
npmArgs.push('--db-sync');
|
|
37
|
+
}
|
|
38
|
+
if (flags.port) {
|
|
39
|
+
npmArgs.push('--port', flags.port);
|
|
40
|
+
}
|
|
41
|
+
if (flags.client) {
|
|
42
|
+
npmArgs.push('--client');
|
|
43
|
+
}
|
|
44
|
+
if (flags.server) {
|
|
45
|
+
npmArgs.push('--server');
|
|
46
|
+
}
|
|
47
|
+
if (flags.inspect) {
|
|
48
|
+
npmArgs.push('--inspect', flags.inspect);
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
await runNocoBaseCommand(npmArgs, process.cwd());
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
55
|
+
this.error(message);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import fsp from 'node:fs/promises';
|
|
10
|
+
import { Command, Flags } from '@oclif/core';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
import { run } from "../lib/run-npm.js";
|
|
13
|
+
export default class Download extends Command {
|
|
14
|
+
static description = 'Download a NocoBase app from npm (create-nocobase-app), Docker Hub, or git.';
|
|
15
|
+
static examples = [
|
|
16
|
+
'<%= config.bin %> <%= command.id %> -s npm -v latest --app-root-path=./app --env-file=.env',
|
|
17
|
+
'<%= config.bin %> <%= command.id %> -s docker -v latest --docker-registry=nocobase/nocobase',
|
|
18
|
+
'<%= config.bin %> <%= command.id %> -s git -v main --git-url=https://github.com/nocobase/nocobase.git --app-root-path=./my-nocobase-app',
|
|
19
|
+
];
|
|
20
|
+
static flags = {
|
|
21
|
+
source: Flags.string({
|
|
22
|
+
char: 's',
|
|
23
|
+
description: 'Where to download from',
|
|
24
|
+
options: ['docker', 'npm', 'git'],
|
|
25
|
+
required: true,
|
|
26
|
+
}),
|
|
27
|
+
version: Flags.string({
|
|
28
|
+
char: 'v',
|
|
29
|
+
default: 'latest',
|
|
30
|
+
description: 'Version or tag: npm package dist-tag/version, Docker image tag, or git branch/tag',
|
|
31
|
+
}),
|
|
32
|
+
'force-overwrite': Flags.boolean({
|
|
33
|
+
char: 'f',
|
|
34
|
+
description: 'Pass --force to create-nocobase-app (npm) or overwrite when supported',
|
|
35
|
+
default: false,
|
|
36
|
+
}),
|
|
37
|
+
'dev': Flags.boolean({
|
|
38
|
+
description: 'Include dev dependencies in the app directory',
|
|
39
|
+
default: false,
|
|
40
|
+
}),
|
|
41
|
+
'env-file': Flags.string({
|
|
42
|
+
description: 'Dotenv file whose variables are passed to create-nocobase-app as -e KEY=value (npm only)',
|
|
43
|
+
}),
|
|
44
|
+
'app-root-path': Flags.string({
|
|
45
|
+
description: 'Project directory name or path for the new app (default: my-nocobase-app)',
|
|
46
|
+
default: 'my-nocobase-app',
|
|
47
|
+
}),
|
|
48
|
+
'db-password': Flags.string({ description: 'DB password (npm: DB_PASSWORD)' }),
|
|
49
|
+
'git-url': Flags.string({
|
|
50
|
+
description: 'Git remote URL to clone (git source)',
|
|
51
|
+
}),
|
|
52
|
+
'docker-registry': Flags.string({
|
|
53
|
+
description: 'Docker image repository without tag (default: nocobase/nocobase). Example: ghcr.io/nocobase/nocobase',
|
|
54
|
+
}),
|
|
55
|
+
};
|
|
56
|
+
async downloadFromDocker(flags) {
|
|
57
|
+
const image = flags['docker-registry'] ?? 'nocobase/nocobase';
|
|
58
|
+
const tag = flags.version ?? 'latest';
|
|
59
|
+
await run('docker', ['pull', `${image}:${tag}`], process.cwd());
|
|
60
|
+
}
|
|
61
|
+
async downloadFromNpm(flags) {
|
|
62
|
+
const appRoot = flags['app-root-path'] ?? 'my-nocobase-app';
|
|
63
|
+
const versionSpec = flags.version || 'latest';
|
|
64
|
+
const npxArgs = ['-y', `create-nocobase-app@${versionSpec}`, appRoot];
|
|
65
|
+
if (!flags['--dev']) {
|
|
66
|
+
npxArgs.push('--skip-dev-dependencies');
|
|
67
|
+
}
|
|
68
|
+
if (flags['force-overwrite']) {
|
|
69
|
+
await fsp.rm(path.resolve(process.cwd(), appRoot), { recursive: true, force: true });
|
|
70
|
+
}
|
|
71
|
+
await run('npx', npxArgs, process.cwd());
|
|
72
|
+
const installArgs = ['install'];
|
|
73
|
+
if (!flags['--dev']) {
|
|
74
|
+
installArgs.push('--production');
|
|
75
|
+
}
|
|
76
|
+
await run('yarn', installArgs, path.resolve(process.cwd(), appRoot));
|
|
77
|
+
}
|
|
78
|
+
async downloadFromGit(flags) {
|
|
79
|
+
const repoUrl = flags['git-url'] ?? 'https://github.com/nocobase/nocobase.git';
|
|
80
|
+
const appRoot = flags['app-root-path'] ?? 'my-nocobase-app';
|
|
81
|
+
const versionToRef = {
|
|
82
|
+
'latest': 'main',
|
|
83
|
+
'beta': 'next',
|
|
84
|
+
'alpha': 'develop',
|
|
85
|
+
};
|
|
86
|
+
if (flags['force-overwrite']) {
|
|
87
|
+
await fsp.rm(path.resolve(process.cwd(), appRoot), { recursive: true, force: true });
|
|
88
|
+
}
|
|
89
|
+
const branch = versionToRef[flags.version || 'latest'] || flags.version || 'latest';
|
|
90
|
+
const gitArgs = ['clone'];
|
|
91
|
+
gitArgs.push('--branch', branch);
|
|
92
|
+
gitArgs.push('--depth', '1', repoUrl, appRoot);
|
|
93
|
+
await run('git', gitArgs, process.cwd());
|
|
94
|
+
await run('yarn', ['install'], path.resolve(process.cwd(), appRoot));
|
|
95
|
+
}
|
|
96
|
+
async download() {
|
|
97
|
+
const { flags } = await this.parse(Download);
|
|
98
|
+
switch (flags.source) {
|
|
99
|
+
case 'npm':
|
|
100
|
+
await this.downloadFromNpm(flags);
|
|
101
|
+
break;
|
|
102
|
+
case 'docker':
|
|
103
|
+
await this.downloadFromDocker(flags);
|
|
104
|
+
break;
|
|
105
|
+
case 'git':
|
|
106
|
+
await this.downloadFromGit(flags);
|
|
107
|
+
break;
|
|
108
|
+
default:
|
|
109
|
+
this.error(`Invalid source: ${flags.source}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async run() {
|
|
113
|
+
try {
|
|
114
|
+
await this.download();
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
118
|
+
this.error(message);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Command, Flags } from '@oclif/core';
|
|
10
|
+
import { runNocoBaseCommand } from "../lib/run-npm.js";
|
|
11
|
+
export default class Install extends Command {
|
|
12
|
+
static description = 'Run the legacy NocoBase install (forwards to `npm run install` in the repo root)';
|
|
13
|
+
static examples = [
|
|
14
|
+
'<%= config.bin %> <%= command.id %>',
|
|
15
|
+
'<%= config.bin %> <%= command.id %> -f',
|
|
16
|
+
'<%= config.bin %> <%= command.id %> -l zh-CN',
|
|
17
|
+
'<%= config.bin %> <%= command.id %> -m demo@nocobase.com',
|
|
18
|
+
'<%= config.bin %> <%= command.id %> -p admin123',
|
|
19
|
+
'<%= config.bin %> <%= command.id %> -n "Super Admin"',
|
|
20
|
+
];
|
|
21
|
+
static flags = {
|
|
22
|
+
env: Flags.string({ description: 'Environment', char: 'e', required: false }),
|
|
23
|
+
force: Flags.boolean({ description: 'Reinstall the application by clearing the database', char: 'f', required: false }),
|
|
24
|
+
lang: Flags.string({ description: 'Language during installation', char: 'l', required: false }),
|
|
25
|
+
rootEmail: Flags.string({ description: 'Root user email', char: 'm', required: false }),
|
|
26
|
+
rootPassword: Flags.string({ description: 'Root user password', char: 'p', required: false }),
|
|
27
|
+
rootNickname: Flags.string({ description: 'Root user nickname', char: 'n', required: false }),
|
|
28
|
+
};
|
|
29
|
+
async run() {
|
|
30
|
+
const { flags } = await this.parse(Install);
|
|
31
|
+
const npmArgs = ['install'];
|
|
32
|
+
if (flags.force) {
|
|
33
|
+
npmArgs.push('--force');
|
|
34
|
+
}
|
|
35
|
+
if (flags.lang !== undefined) {
|
|
36
|
+
npmArgs.push('--lang', flags.lang);
|
|
37
|
+
}
|
|
38
|
+
if (flags.rootEmail !== undefined) {
|
|
39
|
+
npmArgs.push('--root-email', flags.rootEmail);
|
|
40
|
+
}
|
|
41
|
+
if (flags.rootPassword !== undefined) {
|
|
42
|
+
npmArgs.push('--root-password', flags.rootPassword);
|
|
43
|
+
}
|
|
44
|
+
if (flags.rootNickname !== undefined) {
|
|
45
|
+
npmArgs.push('--root-nickname', flags.rootNickname);
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
await runNocoBaseCommand(npmArgs, process.cwd());
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
52
|
+
this.error(message);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
10
|
+
export default class PmDisable extends Command {
|
|
11
|
+
static args = {
|
|
12
|
+
file: Args.string({ description: 'file to read' }),
|
|
13
|
+
};
|
|
14
|
+
static description = 'describe the command here';
|
|
15
|
+
static examples = [
|
|
16
|
+
'<%= config.bin %> <%= command.id %>',
|
|
17
|
+
];
|
|
18
|
+
static flags = {
|
|
19
|
+
// flag with no value (-f, --force)
|
|
20
|
+
force: Flags.boolean({ char: 'f' }),
|
|
21
|
+
// flag with a value (-n, --name=VALUE)
|
|
22
|
+
name: Flags.string({ char: 'n', description: 'name to print' }),
|
|
23
|
+
};
|
|
24
|
+
async run() {
|
|
25
|
+
const { args, flags } = await this.parse(PmDisable);
|
|
26
|
+
const name = flags.name ?? 'world';
|
|
27
|
+
this.log(`hello ${name} from packages/core/cli/src/commands/pm/disable.ts`);
|
|
28
|
+
if (args.file && flags.force) {
|
|
29
|
+
this.log(`you input --force and --file: ${args.file}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
10
|
+
export default class PmEnable extends Command {
|
|
11
|
+
static args = {
|
|
12
|
+
file: Args.string({ description: 'file to read' }),
|
|
13
|
+
};
|
|
14
|
+
static description = 'describe the command here';
|
|
15
|
+
static examples = [
|
|
16
|
+
'<%= config.bin %> <%= command.id %>',
|
|
17
|
+
];
|
|
18
|
+
static flags = {
|
|
19
|
+
// flag with no value (-f, --force)
|
|
20
|
+
force: Flags.boolean({ char: 'f' }),
|
|
21
|
+
// flag with a value (-n, --name=VALUE)
|
|
22
|
+
name: Flags.string({ char: 'n', description: 'name to print' }),
|
|
23
|
+
};
|
|
24
|
+
async run() {
|
|
25
|
+
const { args, flags } = await this.parse(PmEnable);
|
|
26
|
+
const name = flags.name ?? 'world';
|
|
27
|
+
this.log(`hello ${name} from packages/core/cli/src/commands/pm/enable.ts`);
|
|
28
|
+
if (args.file && flags.force) {
|
|
29
|
+
this.log(`you input --force and --file: ${args.file}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
10
|
+
export default class PmList extends Command {
|
|
11
|
+
static args = {
|
|
12
|
+
file: Args.string({ description: 'file to read' }),
|
|
13
|
+
};
|
|
14
|
+
static description = 'describe the command here';
|
|
15
|
+
static examples = [
|
|
16
|
+
'<%= config.bin %> <%= command.id %>',
|
|
17
|
+
];
|
|
18
|
+
static flags = {
|
|
19
|
+
// flag with no value (-f, --force)
|
|
20
|
+
force: Flags.boolean({ char: 'f' }),
|
|
21
|
+
// flag with a value (-n, --name=VALUE)
|
|
22
|
+
name: Flags.string({ char: 'n', description: 'name to print' }),
|
|
23
|
+
};
|
|
24
|
+
async run() {
|
|
25
|
+
const { args, flags } = await this.parse(PmList);
|
|
26
|
+
const name = flags.name ?? 'world';
|
|
27
|
+
this.log(`hello ${name} from packages/core/cli/src/commands/pm/list.ts`);
|
|
28
|
+
if (args.file && flags.force) {
|
|
29
|
+
this.log(`you input --force and --file: ${args.file}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
10
|
+
export default class Restart extends Command {
|
|
11
|
+
static args = {
|
|
12
|
+
file: Args.string({ description: 'file to read' }),
|
|
13
|
+
};
|
|
14
|
+
static description = 'describe the command here';
|
|
15
|
+
static examples = [
|
|
16
|
+
'<%= config.bin %> <%= command.id %>',
|
|
17
|
+
];
|
|
18
|
+
static flags = {
|
|
19
|
+
// flag with no value (-f, --force)
|
|
20
|
+
force: Flags.boolean({ char: 'f' }),
|
|
21
|
+
// flag with a value (-n, --name=VALUE)
|
|
22
|
+
name: Flags.string({ char: 'n', description: 'name to print' }),
|
|
23
|
+
};
|
|
24
|
+
async run() {
|
|
25
|
+
const { args, flags } = await this.parse(Restart);
|
|
26
|
+
const name = flags.name ?? 'world';
|
|
27
|
+
this.log(`hello ${name} from packages/core/cli/src/commands/restart.ts`);
|
|
28
|
+
if (args.file && flags.force) {
|
|
29
|
+
this.log(`you input --force and --file: ${args.file}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
10
|
+
import { runNocoBaseCommand } from "../../lib/run-npm.js";
|
|
11
|
+
export default class ScaffoldMigration extends Command {
|
|
12
|
+
static args = {
|
|
13
|
+
name: Args.string({ description: 'migration name', required: true }),
|
|
14
|
+
};
|
|
15
|
+
static description = 'Run the legacy NocoBase scaffold migration (forwards to `npm run scaffold:migration` in the repo root)';
|
|
16
|
+
static examples = [
|
|
17
|
+
'<%= config.bin %> <%= command.id %> migration-name --pkg @nocobase/plugin-acl',
|
|
18
|
+
'<%= config.bin %> <%= command.id %> migration-name --pkg @nocobase/plugin-acl --on afterLoad',
|
|
19
|
+
];
|
|
20
|
+
static flags = {
|
|
21
|
+
pkg: Flags.string({ description: 'plugin package name', required: true }),
|
|
22
|
+
on: Flags.string({ description: 'on', required: false, options: ['beforeLoad', 'afterSync', 'afterLoad'] }),
|
|
23
|
+
};
|
|
24
|
+
async run() {
|
|
25
|
+
const { args, flags } = await this.parse(ScaffoldMigration);
|
|
26
|
+
const npmArgs = ['create-migration', args.name, '--pkg', flags.pkg];
|
|
27
|
+
if (flags.on) {
|
|
28
|
+
npmArgs.push('--on', flags.on);
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
await runNocoBaseCommand(npmArgs, process.cwd(), { env: { LOGGER_SILENT: 'true' } });
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
35
|
+
this.error(message);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
10
|
+
import { runNocoBaseCommand } from "../../lib/run-npm.js";
|
|
11
|
+
export default class ScaffoldPlugin extends Command {
|
|
12
|
+
static args = {
|
|
13
|
+
pkg: Args.string({ description: 'plugin package name', required: true }),
|
|
14
|
+
};
|
|
15
|
+
static description = 'Run the legacy NocoBase scaffold plugin (forwards to `npm run scaffold:plugin` in the repo root)';
|
|
16
|
+
static examples = [
|
|
17
|
+
'<%= config.bin %> <%= command.id %> @nocobase-example/plugin-hello',
|
|
18
|
+
'<%= config.bin %> <%= command.id %> @nocobase-example/plugin-hello --force-recreate',
|
|
19
|
+
];
|
|
20
|
+
static flags = {
|
|
21
|
+
'force-recreate': Flags.boolean({ description: 'Force recreate the plugin', char: 'f', required: false }),
|
|
22
|
+
};
|
|
23
|
+
async run() {
|
|
24
|
+
const { args, flags } = await this.parse(ScaffoldPlugin);
|
|
25
|
+
const npmArgs = ['pm', 'create', args.pkg];
|
|
26
|
+
if (flags['force-recreate']) {
|
|
27
|
+
npmArgs.push('--force-recreate');
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
await runNocoBaseCommand(npmArgs, process.cwd(), { env: { LOGGER_SILENT: 'true' } });
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
34
|
+
this.error(message);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Command } from '@oclif/core';
|
|
10
|
+
import { spawn } from 'node:child_process';
|
|
11
|
+
function runNpmInstallGlobal(args) {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
const child = spawn('npm', ['install', '-g', ...args], {
|
|
14
|
+
stdio: 'inherit',
|
|
15
|
+
shell: true,
|
|
16
|
+
env: process.env,
|
|
17
|
+
});
|
|
18
|
+
child.once('error', reject);
|
|
19
|
+
child.once('close', (code) => {
|
|
20
|
+
if (code === 0) {
|
|
21
|
+
resolve();
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
reject(new Error(`npm exited with code ${code}`));
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
export default class SelfUpdate extends Command {
|
|
29
|
+
static description = 'Update the NocoBase CLI to the latest version';
|
|
30
|
+
static examples = ['<%= config.bin %> <%= command.id %>'];
|
|
31
|
+
async run() {
|
|
32
|
+
this.log('Updating NocoBase CLI to the latest version...');
|
|
33
|
+
try {
|
|
34
|
+
await runNpmInstallGlobal(['@nocobase/cli']);
|
|
35
|
+
this.log('Update finished.');
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
39
|
+
this.error([
|
|
40
|
+
'Failed to update the CLI.',
|
|
41
|
+
'Try running manually: npm install -g @nocobase/cli',
|
|
42
|
+
message,
|
|
43
|
+
].join('\n'), { exit: 1 });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Command, Flags } from '@oclif/core';
|
|
10
|
+
import { runNocoBaseCommand } from "../lib/run-npm.js";
|
|
11
|
+
export default class Start extends Command {
|
|
12
|
+
static description = 'Run the legacy NocoBase start (forwards to `npm run start` in the repo root)';
|
|
13
|
+
static examples = [
|
|
14
|
+
'<%= config.bin %> <%= command.id %>',
|
|
15
|
+
'<%= config.bin %> <%= command.id %> --quickstart',
|
|
16
|
+
'<%= config.bin %> <%= command.id %> --port 12000',
|
|
17
|
+
'<%= config.bin %> <%= command.id %> --daemon',
|
|
18
|
+
'<%= config.bin %> <%= command.id %> --instances 2',
|
|
19
|
+
'<%= config.bin %> <%= command.id %> --launch-mode pm2',
|
|
20
|
+
];
|
|
21
|
+
static flags = {
|
|
22
|
+
env: Flags.string({ description: 'Environment', char: 'e', required: false }),
|
|
23
|
+
quickstart: Flags.boolean({ description: 'Quickstart the application', required: false }),
|
|
24
|
+
port: Flags.string({ description: 'Port', char: 'p', required: false }),
|
|
25
|
+
daemon: Flags.boolean({ description: 'Run the application as a daemon', char: 'd', required: false }),
|
|
26
|
+
instances: Flags.integer({ description: 'Number of instances to run', char: 'i', required: false }),
|
|
27
|
+
'launch-mode': Flags.string({ description: 'Launch Mode', required: false, options: ['pm2', 'node'] }),
|
|
28
|
+
};
|
|
29
|
+
async run() {
|
|
30
|
+
const { flags } = await this.parse(Start);
|
|
31
|
+
const npmArgs = ['start'];
|
|
32
|
+
if (flags.quickstart) {
|
|
33
|
+
npmArgs.push('--quickstart');
|
|
34
|
+
}
|
|
35
|
+
if (flags.port) {
|
|
36
|
+
npmArgs.push('--port', flags.port);
|
|
37
|
+
}
|
|
38
|
+
if (flags.daemon) {
|
|
39
|
+
npmArgs.push('--daemon');
|
|
40
|
+
}
|
|
41
|
+
if (flags.instances) {
|
|
42
|
+
npmArgs.push('--instances', flags.instances.toString());
|
|
43
|
+
}
|
|
44
|
+
if (flags['launch-mode']) {
|
|
45
|
+
npmArgs.push('--launch-mode', flags['launch-mode']);
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
await runNocoBaseCommand(npmArgs, process.cwd());
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
52
|
+
this.error(message);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Command, Flags } from '@oclif/core';
|
|
10
|
+
import { runNocoBaseCommand } from "../lib/run-npm.js";
|
|
11
|
+
export default class Upgrade extends Command {
|
|
12
|
+
static description = 'Run the legacy NocoBase upgrade (forwards to `npm run upgrade` in the repo root)';
|
|
13
|
+
static examples = [
|
|
14
|
+
'<%= config.bin %> <%= command.id %>',
|
|
15
|
+
'<%= config.bin %> <%= command.id %> --skip-code-update',
|
|
16
|
+
];
|
|
17
|
+
static flags = {
|
|
18
|
+
env: Flags.string({ description: 'Environment', char: 'e', required: false }),
|
|
19
|
+
'skip-code-update': Flags.boolean({ description: 'Skip code update', char: 'S', required: false }),
|
|
20
|
+
};
|
|
21
|
+
async run() {
|
|
22
|
+
const { flags } = await this.parse(Upgrade);
|
|
23
|
+
const npmArgs = ['upgrade'];
|
|
24
|
+
if (flags['skip-code-update']) {
|
|
25
|
+
npmArgs.push('--skip-code-update');
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
await runNocoBaseCommand(npmArgs, process.cwd());
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
32
|
+
this.error(message);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -6,22 +6,34 @@
|
|
|
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
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
10
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
11
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
12
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
return path;
|
|
16
|
+
};
|
|
9
17
|
import { Command } from '@oclif/core';
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import EnvRemove from "../commands/env/remove.js";
|
|
14
|
-
import EnvUpdate from "../commands/env/update.js";
|
|
15
|
-
import EnvUse from "../commands/env/use.js";
|
|
16
|
-
import ResourceCreate from "../commands/resource/create.js";
|
|
17
|
-
import ResourceDestroy from "../commands/resource/destroy.js";
|
|
18
|
-
import ResourceGet from "../commands/resource/get.js";
|
|
19
|
-
import ResourceList from "../commands/resource/list.js";
|
|
20
|
-
import ResourceQuery from "../commands/resource/query.js";
|
|
21
|
-
import ResourceUpdate from "../commands/resource/update.js";
|
|
18
|
+
import { dirname, join, relative } from 'node:path';
|
|
19
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
20
|
+
import { collectCommandModulePaths, commandRelativePathToRegistryKey, } from "../lib/command-discovery.js";
|
|
22
21
|
import { getCurrentEnvName, getEnv } from "../lib/auth-store.js";
|
|
23
22
|
import { createGeneratedFlags, GeneratedApiCommand } from "../lib/generated-command.js";
|
|
24
23
|
import { loadRuntimeSync } from "../lib/runtime-store.js";
|
|
24
|
+
const registryFilePath = fileURLToPath(import.meta.url);
|
|
25
|
+
const commandsRoot = join(dirname(registryFilePath), '../commands');
|
|
26
|
+
const commandModuleExtension = registryFilePath.endsWith('.ts') ? '.ts' : '.js';
|
|
27
|
+
async function loadCommandsFromDirectory() {
|
|
28
|
+
const absolutePaths = await collectCommandModulePaths(commandsRoot, commandModuleExtension);
|
|
29
|
+
const entries = await Promise.all(absolutePaths.map(async (absolutePath) => {
|
|
30
|
+
const rel = relative(commandsRoot, absolutePath).replace(/\\/g, '/');
|
|
31
|
+
const key = commandRelativePathToRegistryKey(rel);
|
|
32
|
+
const mod = await import(__rewriteRelativeImportExtension(pathToFileURL(absolutePath).href));
|
|
33
|
+
return [key, mod.default];
|
|
34
|
+
}));
|
|
35
|
+
return Object.fromEntries(entries);
|
|
36
|
+
}
|
|
25
37
|
function readEnvName(argv) {
|
|
26
38
|
for (let index = 0; index < argv.length; index += 1) {
|
|
27
39
|
const token = argv[index];
|
|
@@ -56,20 +68,7 @@ function createRuntimeIndexCommand(commandId, operation) {
|
|
|
56
68
|
};
|
|
57
69
|
}
|
|
58
70
|
const registry = {
|
|
59
|
-
|
|
60
|
-
'env:add': EnvAdd,
|
|
61
|
-
'env:auth': EnvAuth,
|
|
62
|
-
'env:list': EnvList,
|
|
63
|
-
'env:remove': EnvRemove,
|
|
64
|
-
'env:update': EnvUpdate,
|
|
65
|
-
'env:use': EnvUse,
|
|
66
|
-
// 'api:resource': Resource,
|
|
67
|
-
'api:resource:create': ResourceCreate,
|
|
68
|
-
'api:resource:destroy': ResourceDestroy,
|
|
69
|
-
'api:resource:get': ResourceGet,
|
|
70
|
-
'api:resource:list': ResourceList,
|
|
71
|
-
'api:resource:query': ResourceQuery,
|
|
72
|
-
'api:resource:update': ResourceUpdate,
|
|
71
|
+
...(await loadCommandsFromDirectory()),
|
|
73
72
|
};
|
|
74
73
|
const envName = readEnvName(process.argv.slice(2)) ?? (await getCurrentEnvName());
|
|
75
74
|
const env = await getEnv(envName);
|
package/dist/lib/bootstrap.js
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
1
9
|
import { getCurrentEnvName, getEnv, setEnvRuntime, updateEnvConnection } from './auth-store.js';
|
|
2
10
|
import { resolveAccessToken } from './env-auth.js';
|
|
3
11
|
import { generateRuntime } from './runtime-generator.js';
|
|
4
12
|
import { hasRuntimeSync, saveRuntime } from './runtime-store.js';
|
|
5
|
-
import { confirmAction, printInfo, printVerbose,
|
|
13
|
+
import { confirmAction, printInfo, printVerbose, printWarningBlock, setVerboseMode, stopTask, updateTask } from './ui.js';
|
|
6
14
|
const APP_RETRY_INTERVAL = 2000;
|
|
7
15
|
const APP_RETRY_TIMEOUT = 120000;
|
|
8
16
|
function readFlag(argv, name) {
|
|
@@ -66,6 +74,9 @@ function isBuiltinCommand(argv) {
|
|
|
66
74
|
export function shouldSkipRuntimeBootstrap(argv) {
|
|
67
75
|
return hasVersionFlag(argv) || isBuiltinCommand(argv);
|
|
68
76
|
}
|
|
77
|
+
function shouldIgnoreBootstrapFailure(argv, commandToken) {
|
|
78
|
+
return !commandToken || hasHelpFlag(argv) || (commandToken === 'api' && argv.length === 1);
|
|
79
|
+
}
|
|
69
80
|
async function requestJson(url, options) {
|
|
70
81
|
const headers = new Headers();
|
|
71
82
|
if (options.token) {
|
|
@@ -215,6 +226,9 @@ function collectErrorEntries(data) {
|
|
|
215
226
|
function hasInvalidTokenError(data) {
|
|
216
227
|
return collectErrorEntries(data).some((entry) => entry?.code === 'INVALID_TOKEN');
|
|
217
228
|
}
|
|
229
|
+
function isNetworkFetchFailure(response) {
|
|
230
|
+
return response.status === 0;
|
|
231
|
+
}
|
|
218
232
|
export function formatSwaggerSchemaError(response, context) {
|
|
219
233
|
if (hasInvalidTokenError(response.data)) {
|
|
220
234
|
const entries = collectErrorEntries(response.data);
|
|
@@ -236,6 +250,17 @@ export function formatSwaggerSchemaError(response, context) {
|
|
|
236
250
|
commandHint,
|
|
237
251
|
].join('\n');
|
|
238
252
|
}
|
|
253
|
+
if (isNetworkFetchFailure(response)) {
|
|
254
|
+
const rawMessage = response.data?.error?.message || 'fetch failed';
|
|
255
|
+
return [
|
|
256
|
+
'Failed to reach the NocoBase server while loading the command runtime from `swagger:get`.',
|
|
257
|
+
`Base URL: ${context.baseUrl}`,
|
|
258
|
+
`Network error: ${rawMessage}`,
|
|
259
|
+
'Check that the NocoBase app is running, the base URL is correct, and the server is reachable from this machine.',
|
|
260
|
+
'If you recently changed the server address, update it with `nb env add --name <name> --base-url <url>` and retry `nb env update`.',
|
|
261
|
+
'Use `nb env list` to inspect the current env configuration.',
|
|
262
|
+
].join('\n');
|
|
263
|
+
}
|
|
239
264
|
return `Failed to load swagger schema from \`swagger:get\`.\n${JSON.stringify(response.data, null, 2)}`;
|
|
240
265
|
}
|
|
241
266
|
export function formatMissingRuntimeEnvError(commandToken) {
|
|
@@ -256,55 +281,59 @@ export function formatMissingRuntimeEnvError(commandToken) {
|
|
|
256
281
|
export async function ensureRuntimeFromArgv(argv, options) {
|
|
257
282
|
const commandToken = getCommandToken(argv);
|
|
258
283
|
const isRootInvocation = !commandToken;
|
|
284
|
+
const canContinueWithoutRuntime = shouldIgnoreBootstrapFailure(argv, commandToken);
|
|
259
285
|
setVerboseMode(hasBooleanFlag(argv, 'verbose'));
|
|
260
286
|
if (shouldSkipRuntimeBootstrap(argv)) {
|
|
261
287
|
return;
|
|
262
288
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}
|
|
276
|
-
if (!baseUrl) {
|
|
277
|
-
if (isRootInvocation) {
|
|
289
|
+
try {
|
|
290
|
+
const envName = readFlag(argv, 'env') ?? (await getCurrentEnvName());
|
|
291
|
+
const env = await getEnv(envName);
|
|
292
|
+
const baseUrl = readFlag(argv, 'base-url') ?? env?.baseUrl;
|
|
293
|
+
const role = readFlag(argv, 'role');
|
|
294
|
+
const token = await resolveAccessToken({
|
|
295
|
+
envName,
|
|
296
|
+
baseUrl,
|
|
297
|
+
token: readFlag(argv, 'token'),
|
|
298
|
+
});
|
|
299
|
+
const runtimeVersion = env?.runtime?.version;
|
|
300
|
+
if (runtimeVersion && hasRuntimeSync(runtimeVersion)) {
|
|
278
301
|
return;
|
|
279
302
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
try {
|
|
284
|
-
printVerbose(`Runtime source: ${baseUrl}`);
|
|
285
|
-
const document = await fetchSwaggerSchema(baseUrl, token, role, { envName, commandToken }, isRootInvocation
|
|
286
|
-
? {
|
|
287
|
-
allowEnableApiDoc: false,
|
|
288
|
-
retryAppAvailability: false,
|
|
303
|
+
if (!baseUrl) {
|
|
304
|
+
if (isRootInvocation) {
|
|
305
|
+
return;
|
|
289
306
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
307
|
+
throw new Error(formatMissingRuntimeEnvError(commandToken));
|
|
308
|
+
}
|
|
309
|
+
updateTask('Loading command runtime...');
|
|
310
|
+
try {
|
|
311
|
+
printVerbose(`Runtime source: ${baseUrl}`);
|
|
312
|
+
const document = await fetchSwaggerSchema(baseUrl, token, role, { envName, commandToken }, isRootInvocation
|
|
313
|
+
? {
|
|
314
|
+
allowEnableApiDoc: false,
|
|
315
|
+
retryAppAvailability: false,
|
|
316
|
+
}
|
|
317
|
+
: undefined);
|
|
318
|
+
const runtime = await generateRuntime(document, options.configFile, baseUrl);
|
|
319
|
+
await saveRuntime(runtime);
|
|
320
|
+
await setEnvRuntime(envName, {
|
|
321
|
+
version: runtime.version,
|
|
322
|
+
schemaHash: runtime.schemaHash,
|
|
323
|
+
generatedAt: runtime.generatedAt,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
finally {
|
|
327
|
+
stopTask();
|
|
328
|
+
}
|
|
298
329
|
}
|
|
299
330
|
catch (error) {
|
|
300
|
-
if (!
|
|
331
|
+
if (!canContinueWithoutRuntime) {
|
|
301
332
|
throw error;
|
|
302
333
|
}
|
|
303
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
304
|
-
printWarning(`${message}\nContinuing with built-in help because runtime commands could not be loaded.`);
|
|
305
|
-
}
|
|
306
|
-
finally {
|
|
307
334
|
stopTask();
|
|
335
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
336
|
+
printWarningBlock(`Unable to load runtime commands. Showing built-in help instead.\n\n${message}`);
|
|
308
337
|
}
|
|
309
338
|
}
|
|
310
339
|
export async function updateEnvRuntime(options) {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { readdir } from 'node:fs/promises';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
/**
|
|
12
|
+
* Recursively collect command module paths under `commandsRoot` (e.g. `dist/commands` → `.js`, `src/commands` → `.ts`).
|
|
13
|
+
*/
|
|
14
|
+
export async function collectCommandModulePaths(commandsRoot, extension) {
|
|
15
|
+
const entries = await readdir(commandsRoot, { withFileTypes: true });
|
|
16
|
+
const files = [];
|
|
17
|
+
for (const ent of entries) {
|
|
18
|
+
const full = join(commandsRoot, ent.name);
|
|
19
|
+
if (ent.isDirectory()) {
|
|
20
|
+
files.push(...(await collectCommandModulePaths(full, extension)));
|
|
21
|
+
}
|
|
22
|
+
else if (ent.isFile() && ent.name.endsWith(extension)) {
|
|
23
|
+
files.push(full);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return files.sort();
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Map a path relative to `commands/` with `.js` / `.ts` to an oclif explicit-registry key.
|
|
30
|
+
* `resource/foo.js` → `api:resource:foo` (topic `api resource …`); other paths use `:` between segments.
|
|
31
|
+
*/
|
|
32
|
+
export function commandRelativePathToRegistryKey(relativePath) {
|
|
33
|
+
const normalized = relativePath.replace(/\\/g, '/').replace(/\.(js|ts)$/i, '');
|
|
34
|
+
const segments = normalized.split('/').filter(Boolean);
|
|
35
|
+
// if (segments[0] === 'resource' && segments.length >= 2) {
|
|
36
|
+
// return ['api', 'resource', ...segments.slice(1)].join(':');
|
|
37
|
+
// }
|
|
38
|
+
return segments.join(':');
|
|
39
|
+
}
|
package/dist/lib/env-auth.js
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
1
9
|
import crypto from 'node:crypto';
|
|
2
10
|
import { createServer } from 'node:http';
|
|
3
11
|
import { spawn } from 'node:child_process';
|
|
4
12
|
import { URL } from 'node:url';
|
|
5
13
|
import { getCurrentEnvName, getEnv, setEnvOauthSession, } from './auth-store.js';
|
|
6
|
-
import { printInfo, printVerbose, printWarning, updateTask } from './ui.js';
|
|
14
|
+
import { printInfo, printVerbose, printWarning, printWarningBlock, updateTask } from './ui.js';
|
|
7
15
|
const ACCESS_TOKEN_REFRESH_WINDOW_MS = 60_000;
|
|
8
16
|
const LOOPBACK_HOST = '127.0.0.1';
|
|
9
17
|
const OAUTH_LOGIN_TIMEOUT_MS = 5 * 60 * 1000;
|
|
@@ -62,9 +70,36 @@ function formatOauthError(prefix, data, fallbackStatus) {
|
|
|
62
70
|
}
|
|
63
71
|
return prefix;
|
|
64
72
|
}
|
|
65
|
-
|
|
73
|
+
function formatOauthFetchFailure(prefix, options) {
|
|
74
|
+
return [
|
|
75
|
+
prefix,
|
|
76
|
+
options.envName ? `Env: ${options.envName}` : undefined,
|
|
77
|
+
options.baseUrl ? `Base URL: ${options.baseUrl}` : undefined,
|
|
78
|
+
`Request URL: ${options.url}`,
|
|
79
|
+
`Network error: ${options.rawMessage || 'fetch failed'}`,
|
|
80
|
+
'Check that the NocoBase app is running, the base URL is correct, and the server is reachable from this machine.',
|
|
81
|
+
options.envName
|
|
82
|
+
? `If the saved login is stale, run \`nb env auth -e ${options.envName}\` again after connectivity is restored.`
|
|
83
|
+
: 'If the saved login is stale, run `nb env auth -e <name>` again after connectivity is restored.',
|
|
84
|
+
'Use `nb env list` to inspect the current env configuration.',
|
|
85
|
+
]
|
|
86
|
+
.filter(Boolean)
|
|
87
|
+
.join('\n');
|
|
88
|
+
}
|
|
89
|
+
async function fetchOauthServerMetadata(baseUrl, options = {}) {
|
|
66
90
|
const metadataUrl = getOauthMetadataUrl(baseUrl);
|
|
67
|
-
|
|
91
|
+
let response;
|
|
92
|
+
try {
|
|
93
|
+
response = await fetch(metadataUrl);
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
throw new Error(formatOauthFetchFailure('Failed to load OAuth metadata.', {
|
|
97
|
+
envName: options.envName,
|
|
98
|
+
baseUrl,
|
|
99
|
+
url: metadataUrl,
|
|
100
|
+
rawMessage: error?.message,
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
68
103
|
const data = await parseJsonResponse(response);
|
|
69
104
|
if (!response.ok) {
|
|
70
105
|
throw new Error(formatOauthError(`Failed to load OAuth metadata from ${metadataUrl}`, data, response.status));
|
|
@@ -246,7 +281,7 @@ async function refreshOauthAccessToken(options) {
|
|
|
246
281
|
if (!options.auth.refreshToken || !options.auth.clientId) {
|
|
247
282
|
throw new Error(`OAuth session for env "${options.envName}" cannot be refreshed. Run \`nb env auth -e ${options.envName}\`.`);
|
|
248
283
|
}
|
|
249
|
-
const metadata = await fetchOauthServerMetadata(options.baseUrl);
|
|
284
|
+
const metadata = await fetchOauthServerMetadata(options.baseUrl, { envName: options.envName });
|
|
250
285
|
const resource = options.auth.resource || getOauthResource(metadata.issuer);
|
|
251
286
|
const body = new URLSearchParams({
|
|
252
287
|
grant_type: 'refresh_token',
|
|
@@ -261,6 +296,13 @@ async function refreshOauthAccessToken(options) {
|
|
|
261
296
|
'content-type': 'application/x-www-form-urlencoded',
|
|
262
297
|
},
|
|
263
298
|
body,
|
|
299
|
+
}).catch((error) => {
|
|
300
|
+
throw new Error(formatOauthFetchFailure(`Failed to refresh OAuth session for env "${options.envName}".`, {
|
|
301
|
+
envName: options.envName,
|
|
302
|
+
baseUrl: options.baseUrl,
|
|
303
|
+
url: metadata.token_endpoint,
|
|
304
|
+
rawMessage: error?.message,
|
|
305
|
+
}));
|
|
264
306
|
});
|
|
265
307
|
const data = await parseJsonResponse(response);
|
|
266
308
|
if (!response.ok) {
|
|
@@ -338,7 +380,7 @@ export async function authenticateEnvWithOauth(options) {
|
|
|
338
380
|
].join('\n'));
|
|
339
381
|
}
|
|
340
382
|
updateTask(`Loading OAuth metadata for env "${envName}"...`);
|
|
341
|
-
const metadata = await fetchOauthServerMetadata(baseUrl);
|
|
383
|
+
const metadata = await fetchOauthServerMetadata(baseUrl, { envName });
|
|
342
384
|
const state = encodeBase64Url(crypto.randomBytes(16));
|
|
343
385
|
const { codeVerifier, codeChallenge } = buildPkcePair();
|
|
344
386
|
const callback = await createLoopbackServer(state);
|
|
@@ -359,7 +401,7 @@ export async function authenticateEnvWithOauth(options) {
|
|
|
359
401
|
updateTask(`Waiting for OAuth login for env "${envName}"...`);
|
|
360
402
|
const opened = maybeOpenBrowser(authorizationUrl.toString());
|
|
361
403
|
if (!opened) {
|
|
362
|
-
|
|
404
|
+
printWarningBlock('Unable to open the browser automatically. Open this URL manually:');
|
|
363
405
|
}
|
|
364
406
|
else {
|
|
365
407
|
printInfo('Complete the OAuth login in your browser.');
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { spawn } from 'node:child_process';
|
|
10
|
+
export function run(name, args, cwd, options) {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
const child = spawn(name, [...args], {
|
|
13
|
+
stdio: 'inherit',
|
|
14
|
+
shell: true,
|
|
15
|
+
cwd,
|
|
16
|
+
env: {
|
|
17
|
+
...options?.env,
|
|
18
|
+
...process.env,
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
child.once('error', reject);
|
|
22
|
+
child.once('close', (code) => {
|
|
23
|
+
if (code === 0) {
|
|
24
|
+
resolve();
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
reject(new Error(`${name} exited with code ${code}`));
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/** Run `npm` with the given argument list in `cwd`, inheriting stdio. */
|
|
32
|
+
export function runNpm(args, cwd) {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
const child = spawn('yarn', [...args], {
|
|
35
|
+
stdio: 'inherit',
|
|
36
|
+
shell: true,
|
|
37
|
+
cwd,
|
|
38
|
+
env: process.env,
|
|
39
|
+
});
|
|
40
|
+
child.once('error', reject);
|
|
41
|
+
child.once('close', (code, signal) => {
|
|
42
|
+
if (code === 0) {
|
|
43
|
+
resolve();
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (signal) {
|
|
47
|
+
reject(new Error(`npm exited due to signal ${signal}`));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
reject(new Error(`npm exited with code ${code}`));
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
export async function runNocoBaseCommand(args, cwd, options) {
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
const child = spawn('node', ['./node_modules/.bin/nocobase-v1', ...args], {
|
|
57
|
+
stdio: 'inherit',
|
|
58
|
+
shell: true,
|
|
59
|
+
cwd,
|
|
60
|
+
env: {
|
|
61
|
+
...options?.env,
|
|
62
|
+
...process.env,
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
child.once('error', reject);
|
|
66
|
+
child.once('close', (code) => {
|
|
67
|
+
if (code === 0) {
|
|
68
|
+
resolve();
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
reject(new Error(`nocobase command exited with code ${code}`));
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
package/dist/lib/ui.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
1
9
|
import readline from 'node:readline/promises';
|
|
2
10
|
import { stdin as input, stdout as output } from 'node:process';
|
|
3
11
|
import ora from 'ora';
|
|
@@ -99,18 +107,19 @@ export function printSuccess(message) {
|
|
|
99
107
|
}
|
|
100
108
|
console.log(pc.green(message));
|
|
101
109
|
}
|
|
102
|
-
|
|
110
|
+
function clearActiveSpinner() {
|
|
103
111
|
if (activeSpinner) {
|
|
104
|
-
|
|
105
|
-
activeSpinner = undefined;
|
|
106
|
-
console.log(pc.yellow(message));
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
activeSpinner.warn(pc.yellow(message));
|
|
112
|
+
activeSpinner.stop();
|
|
110
113
|
activeSpinner = undefined;
|
|
111
|
-
return;
|
|
112
114
|
}
|
|
113
|
-
|
|
115
|
+
}
|
|
116
|
+
export function printWarning(message) {
|
|
117
|
+
clearActiveSpinner();
|
|
118
|
+
console.log(pc.yellow(`⚠ Warning: ${message}`));
|
|
119
|
+
}
|
|
120
|
+
export function printWarningBlock(message) {
|
|
121
|
+
clearActiveSpinner();
|
|
122
|
+
console.log(pc.yellow(`⚠ Warning\n${message}\n`));
|
|
114
123
|
}
|
|
115
124
|
export function printVerboseWarning(message) {
|
|
116
125
|
if (!verboseMode) {
|
|
@@ -154,10 +163,7 @@ export function failTask(message) {
|
|
|
154
163
|
console.error(pc.red(message));
|
|
155
164
|
}
|
|
156
165
|
export function stopTask() {
|
|
157
|
-
|
|
158
|
-
activeSpinner.stop();
|
|
159
|
-
activeSpinner = undefined;
|
|
160
|
-
}
|
|
166
|
+
clearActiveSpinner();
|
|
161
167
|
}
|
|
162
168
|
export function renderTable(headers, rows) {
|
|
163
169
|
const widths = headers.map((header, index) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/cli",
|
|
3
|
-
"version": "2.1.0-alpha.
|
|
3
|
+
"version": "2.1.0-alpha.19",
|
|
4
4
|
"description": "NocoBase Command Line Tool",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/generated/command-registry.js",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"type": "git",
|
|
60
60
|
"url": "git+https://github.com/nocobase/nocobase.git"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "3d13700360eac1c0f9dbf6a5f167ed396a294a3c"
|
|
63
63
|
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { Command } from '@oclif/core';
|
|
2
|
-
export default class Api extends Command {
|
|
3
|
-
static summary = 'Work with NocoBase APIs, environments, resources, and runtime commands';
|
|
4
|
-
static id = 'api';
|
|
5
|
-
async run() {
|
|
6
|
-
this.log('Use `nb api --help` to view available subcommands.');
|
|
7
|
-
}
|
|
8
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { Command, Flags } from '@oclif/core';
|
|
2
|
-
import { getCurrentEnvName, getEnv } from '../../lib/auth-store.js';
|
|
3
|
-
import { formatCliHomeScope } from '../../lib/cli-home.js';
|
|
4
|
-
import { renderTable } from '../../lib/ui.js';
|
|
5
|
-
export default class Env extends Command {
|
|
6
|
-
static summary = 'Show the current environment';
|
|
7
|
-
static id = 'env';
|
|
8
|
-
static flags = {
|
|
9
|
-
scope: Flags.string({
|
|
10
|
-
char: 's',
|
|
11
|
-
description: 'Config scope',
|
|
12
|
-
options: ['project', 'global'],
|
|
13
|
-
}),
|
|
14
|
-
};
|
|
15
|
-
async run() {
|
|
16
|
-
const { flags } = await this.parse(Env);
|
|
17
|
-
const scope = flags.scope;
|
|
18
|
-
const envName = await getCurrentEnvName({ scope });
|
|
19
|
-
const env = await getEnv(envName, { scope });
|
|
20
|
-
if (!env?.baseUrl) {
|
|
21
|
-
this.log(`No current env is configured${scope ? ` in ${formatCliHomeScope(scope)} scope` : ''}.`);
|
|
22
|
-
this.log('Run `nb env add --name <name> --base-url <url>` to add one.');
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
this.log(renderTable(['Name', 'Base URL', 'Auth', 'Runtime'], [[envName, env?.baseUrl ?? '', env?.auth?.type ?? '', env?.runtime?.version ?? '']]));
|
|
26
|
-
}
|
|
27
|
-
}
|