@nocobase/cli 2.1.0-alpha.19 → 2.1.0-alpha.20
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/README.md +15 -9
- package/bin/run.js +9 -3
- package/dist/commands/api/resource/index.js +20 -0
- package/dist/commands/build.js +2 -2
- package/dist/commands/db/start.js +22 -0
- package/dist/commands/dev.js +1 -1
- package/dist/commands/download.js +221 -49
- package/dist/commands/env/add.js +179 -34
- package/dist/commands/env/auth.js +31 -6
- package/dist/commands/env/list.js +12 -2
- package/dist/commands/env/remove.js +12 -1
- package/dist/commands/env/update.js +24 -9
- package/dist/commands/env/use.js +11 -1
- package/dist/commands/init.js +186 -0
- package/dist/commands/install.js +660 -12
- package/dist/commands/pm/disable.js +14 -15
- package/dist/commands/pm/enable.js +14 -15
- package/dist/commands/pm/list.js +5 -16
- package/dist/commands/scaffold/migration.js +1 -1
- package/dist/commands/scaffold/plugin.js +1 -1
- package/dist/commands/start.js +1 -1
- package/dist/commands/upgrade.js +1 -1
- package/dist/generated/command-registry.js +57 -11
- package/dist/help/runtime-help.js +20 -0
- package/dist/lib/auth-store.js +48 -3
- package/dist/lib/bootstrap.js +14 -9
- package/dist/lib/command-discovery.js +4 -4
- package/dist/lib/env-auth.js +95 -15
- package/dist/lib/init-browser-wizard.js +431 -0
- package/dist/lib/openapi.js +8 -200
- package/dist/lib/run-npm.js +27 -42
- package/nocobase-ctl.config.json +28 -68
- package/package.json +7 -6
- package/dist/commands/self-update.js +0 -46
package/README.md
CHANGED
|
@@ -35,19 +35,19 @@ npm install -g @nocobase/ctl@latest
|
|
|
35
35
|
Add an environment:
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
nb env add
|
|
38
|
+
nb env add local --base-url http://localhost:13000/api
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
Add an environment with an API key:
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
|
-
nb env add
|
|
44
|
+
nb env add local --base-url http://localhost:13000/api --auth-type token --token <api-key>
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
Authenticate an environment with OAuth:
|
|
48
48
|
|
|
49
49
|
```bash
|
|
50
|
-
nb env auth
|
|
50
|
+
nb env auth local
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
Show the current environment:
|
|
@@ -72,7 +72,7 @@ Update the runtime command cache from `swagger:get`:
|
|
|
72
72
|
|
|
73
73
|
```bash
|
|
74
74
|
nb env update
|
|
75
|
-
nb env update
|
|
75
|
+
nb env update local
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
Use the generic resource commands:
|
|
@@ -96,10 +96,16 @@ If the `API documentation plugin` is disabled, the CLI will prompt to enable it.
|
|
|
96
96
|
|
|
97
97
|
## Environment Selection
|
|
98
98
|
|
|
99
|
-
|
|
99
|
+
`nb env update` and `nb env auth` take an optional environment name as the first argument (omit it to use the current env):
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
nb env update prod
|
|
103
|
+
nb env auth prod
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Use `-e, --env` on **runtime / API** commands to temporarily select an environment:
|
|
100
107
|
|
|
101
108
|
```bash
|
|
102
|
-
nb env update -e prod
|
|
103
109
|
nb api resource list --resource users -e prod
|
|
104
110
|
```
|
|
105
111
|
|
|
@@ -120,8 +126,8 @@ Use `-s, --scope` to select one explicitly:
|
|
|
120
126
|
|
|
121
127
|
```bash
|
|
122
128
|
nb env list -s project
|
|
123
|
-
nb env add -s global --
|
|
124
|
-
nb env auth
|
|
129
|
+
nb env add prod -s global --base-url http://example.com/api --auth-type token --token <api-key>
|
|
130
|
+
nb env auth prod -s global
|
|
125
131
|
nb env use local -s project
|
|
126
132
|
```
|
|
127
133
|
|
|
@@ -157,7 +163,7 @@ nb api resource --help
|
|
|
157
163
|
Example:
|
|
158
164
|
|
|
159
165
|
```bash
|
|
160
|
-
nb env update
|
|
166
|
+
nb env update prod -s global
|
|
161
167
|
nb api resource list --resource users -e prod -j
|
|
162
168
|
nb api resource list --resource users -e prod --role admin
|
|
163
169
|
```
|
package/bin/run.js
CHANGED
|
@@ -10,7 +10,7 @@ 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
12
|
let isDev = isSourcePackage;
|
|
13
|
-
if (process.env.
|
|
13
|
+
if (process.env.NB_CLI_USE_DIST === '1') {
|
|
14
14
|
isDev = false;
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -47,15 +47,21 @@ if (isDev) {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
function getCommandToken(argv) {
|
|
50
|
+
const tokens = [];
|
|
51
|
+
|
|
50
52
|
for (const token of argv) {
|
|
51
53
|
if (!token || token.startsWith('-')) {
|
|
52
54
|
continue;
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
|
|
57
|
+
tokens.push(token);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (tokens[0] === 'api') {
|
|
61
|
+
return tokens[1] ?? tokens[0];
|
|
56
62
|
}
|
|
57
63
|
|
|
58
|
-
return
|
|
64
|
+
return tokens[0];
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
function formatCliEntryError(error, argv) {
|
|
@@ -0,0 +1,20 @@
|
|
|
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, loadHelpClass } from '@oclif/core';
|
|
10
|
+
export default class Resource extends Command {
|
|
11
|
+
static summary = 'Work with generic collection resources';
|
|
12
|
+
async run() {
|
|
13
|
+
await this.parse(Resource);
|
|
14
|
+
const Help = await loadHelpClass(this.config);
|
|
15
|
+
await new Help(this.config, this.config.pjson.oclif.helpOptions ?? this.config.pjson.helpOptions).showHelp([
|
|
16
|
+
this.id ?? 'api:resource',
|
|
17
|
+
...this.argv,
|
|
18
|
+
]);
|
|
19
|
+
}
|
|
20
|
+
}
|
package/dist/commands/build.js
CHANGED
|
@@ -26,7 +26,7 @@ export default class Build extends Command {
|
|
|
26
26
|
'<%= config.bin %> <%= command.id %> @nocobase/acl @nocobase/actions',
|
|
27
27
|
];
|
|
28
28
|
static flags = {
|
|
29
|
-
|
|
29
|
+
'cwd': Flags.string({ description: 'Current working directory', char: 'c', required: false }),
|
|
30
30
|
'no-dts': Flags.boolean({ description: 'not generate dts' }),
|
|
31
31
|
sourcemap: Flags.boolean({ description: 'generate sourcemap' }),
|
|
32
32
|
};
|
|
@@ -41,7 +41,7 @@ export default class Build extends Command {
|
|
|
41
41
|
npmArgs.push('--sourcemap');
|
|
42
42
|
}
|
|
43
43
|
try {
|
|
44
|
-
await runNocoBaseCommand(npmArgs,
|
|
44
|
+
await runNocoBaseCommand(npmArgs, { cwd: flags['cwd'] });
|
|
45
45
|
}
|
|
46
46
|
catch (error) {
|
|
47
47
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -0,0 +1,22 @@
|
|
|
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 } from '@oclif/core';
|
|
10
|
+
export default class DbStart 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
|
+
async run() {
|
|
20
|
+
const { args, flags } = await this.parse(DbStart);
|
|
21
|
+
}
|
|
22
|
+
}
|
package/dist/commands/dev.js
CHANGED
|
@@ -48,7 +48,7 @@ export default class Dev extends Command {
|
|
|
48
48
|
npmArgs.push('--inspect', flags.inspect);
|
|
49
49
|
}
|
|
50
50
|
try {
|
|
51
|
-
await runNocoBaseCommand(npmArgs
|
|
51
|
+
await runNocoBaseCommand(npmArgs);
|
|
52
52
|
}
|
|
53
53
|
catch (error) {
|
|
54
54
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -8,110 +8,282 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import fsp from 'node:fs/promises';
|
|
10
10
|
import { Command, Flags } from '@oclif/core';
|
|
11
|
+
import * as p from '@clack/prompts';
|
|
11
12
|
import path from 'node:path';
|
|
13
|
+
import { stdin as stdinStream, stdout as stdoutStream } from 'node:process';
|
|
12
14
|
import { run } from "../lib/run-npm.js";
|
|
13
15
|
export default class Download extends Command {
|
|
14
|
-
static description = '
|
|
16
|
+
static description = 'Scaffold or fetch NocoBase: npm (create-nocobase-app), docker (image pull), or git (shallow clone).';
|
|
15
17
|
static examples = [
|
|
16
|
-
'<%= config.bin %> <%= command.id %>
|
|
17
|
-
'<%= config.bin %> <%= command.id %> -
|
|
18
|
-
'<%= config.bin %> <%= command.id %>
|
|
18
|
+
'<%= config.bin %> <%= command.id %>',
|
|
19
|
+
'<%= config.bin %> <%= command.id %> -y --source npm --version latest',
|
|
20
|
+
'<%= config.bin %> <%= command.id %> --source npm --version latest',
|
|
21
|
+
'<%= config.bin %> <%= command.id %> --source npm --version latest --output-dir=./app',
|
|
22
|
+
'<%= config.bin %> <%= command.id %> --source docker --version latest --docker-registry=nocobase/nocobase',
|
|
23
|
+
'<%= config.bin %> <%= command.id %> --source git --version latest --git-url=https://github.com/nocobase/nocobase.git',
|
|
19
24
|
];
|
|
20
25
|
static flags = {
|
|
26
|
+
yes: Flags.boolean({
|
|
27
|
+
char: 'y',
|
|
28
|
+
description: 'Skip interactive prompts; use flags only (non-TTY implies -y)',
|
|
29
|
+
default: false,
|
|
30
|
+
}),
|
|
21
31
|
source: Flags.string({
|
|
22
32
|
char: 's',
|
|
23
|
-
description: '
|
|
33
|
+
description: 'Distribution: npm runs create-nocobase-app, docker runs docker pull, git clones the repository',
|
|
24
34
|
options: ['docker', 'npm', 'git'],
|
|
25
|
-
required:
|
|
35
|
+
required: false,
|
|
26
36
|
}),
|
|
27
37
|
version: Flags.string({
|
|
28
38
|
char: 'v',
|
|
29
|
-
|
|
30
|
-
description: 'Version or tag: npm package dist-tag/version, Docker image tag, or git branch/tag',
|
|
39
|
+
description: 'npm: dist-tag or version for create-nocobase-app; docker: image tag; git: branch or tag (latest→main, beta→next, alpha→develop); default: latest',
|
|
31
40
|
}),
|
|
32
|
-
|
|
33
|
-
char: '
|
|
34
|
-
description: '
|
|
41
|
+
replace: Flags.boolean({
|
|
42
|
+
char: 'r',
|
|
43
|
+
description: 'npm/git: delete the target project directory if it exists, then scaffold or clone again; docker: ignored',
|
|
35
44
|
default: false,
|
|
36
45
|
}),
|
|
37
46
|
'dev': Flags.boolean({
|
|
38
|
-
description: '
|
|
47
|
+
description: 'npm: install devDependencies in create-nocobase-app and run a non-production yarn install; git/docker: ignored',
|
|
39
48
|
default: false,
|
|
40
49
|
}),
|
|
41
|
-
'
|
|
42
|
-
|
|
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',
|
|
50
|
+
'output-dir': Flags.string({
|
|
51
|
+
char: 'o',
|
|
52
|
+
description: 'npm/git: output directory (relative to cwd); default ./nocobase-<version> using the same value as --version; docker: ignored',
|
|
47
53
|
}),
|
|
48
|
-
'db-password': Flags.string({ description: 'DB password (npm: DB_PASSWORD)' }),
|
|
49
54
|
'git-url': Flags.string({
|
|
50
|
-
description: '
|
|
55
|
+
description: 'git: remote URL to clone (default: https://github.com/nocobase/nocobase.git)',
|
|
51
56
|
}),
|
|
52
57
|
'docker-registry': Flags.string({
|
|
53
|
-
description: '
|
|
58
|
+
description: 'docker: image reference without tag (default: nocobase/nocobase); use -v for the tag, e.g. ghcr.io/nocobase/nocobase',
|
|
54
59
|
}),
|
|
55
60
|
};
|
|
61
|
+
resolveOutputDir(flags) {
|
|
62
|
+
const explicit = flags['output-dir'];
|
|
63
|
+
if (explicit) {
|
|
64
|
+
return explicit;
|
|
65
|
+
}
|
|
66
|
+
const tag = flags.version || 'latest';
|
|
67
|
+
const safe = tag.replace(/[/\\]/g, '-');
|
|
68
|
+
return `./nocobase-${safe}`;
|
|
69
|
+
}
|
|
70
|
+
defaultOutputDir(versionTag) {
|
|
71
|
+
const safe = versionTag.replace(/[/\\]/g, '-');
|
|
72
|
+
return `./nocobase-${safe}`;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* When stdin/stdout are TTY and not `-y`, prompt for any missing download options.
|
|
76
|
+
*/
|
|
77
|
+
async resolveDownloadFlags(flags) {
|
|
78
|
+
const interactive = Boolean(stdinStream.isTTY && stdoutStream.isTTY && !flags.yes);
|
|
79
|
+
let source = flags.source?.trim();
|
|
80
|
+
if (source === '') {
|
|
81
|
+
source = undefined;
|
|
82
|
+
}
|
|
83
|
+
let version = flags.version?.trim() || undefined;
|
|
84
|
+
let replace = flags.replace;
|
|
85
|
+
let dev = flags['dev'];
|
|
86
|
+
let outputDir = flags['output-dir']?.trim() || undefined;
|
|
87
|
+
if (outputDir === '') {
|
|
88
|
+
outputDir = undefined;
|
|
89
|
+
}
|
|
90
|
+
let gitUrl = flags['git-url']?.trim() || undefined;
|
|
91
|
+
if (gitUrl === '') {
|
|
92
|
+
gitUrl = undefined;
|
|
93
|
+
}
|
|
94
|
+
let dockerRegistry = flags['docker-registry']?.trim() || undefined;
|
|
95
|
+
if (dockerRegistry === '') {
|
|
96
|
+
dockerRegistry = undefined;
|
|
97
|
+
}
|
|
98
|
+
if (!interactive) {
|
|
99
|
+
if (!source) {
|
|
100
|
+
this.error('Distribution is required (--source npm|git|docker). Use a terminal for interactive setup, or pass -s/--source.');
|
|
101
|
+
}
|
|
102
|
+
const v = version || 'latest';
|
|
103
|
+
return {
|
|
104
|
+
source,
|
|
105
|
+
version: v,
|
|
106
|
+
replace,
|
|
107
|
+
'dev': dev,
|
|
108
|
+
'output-dir': outputDir,
|
|
109
|
+
'git-url': gitUrl,
|
|
110
|
+
'docker-registry': dockerRegistry,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
p.intro('nb download');
|
|
114
|
+
if (!source) {
|
|
115
|
+
const src = await p.select({
|
|
116
|
+
message: 'How do you want to get NocoBase?',
|
|
117
|
+
options: [
|
|
118
|
+
{ value: 'npm', label: 'npm — create-nocobase-app' },
|
|
119
|
+
{ value: 'git', label: 'git — shallow clone' },
|
|
120
|
+
{ value: 'docker', label: 'docker — pull image' },
|
|
121
|
+
],
|
|
122
|
+
initialValue: 'npm',
|
|
123
|
+
});
|
|
124
|
+
if (p.isCancel(src)) {
|
|
125
|
+
p.cancel('Download cancelled.');
|
|
126
|
+
this.exit(0);
|
|
127
|
+
}
|
|
128
|
+
source = src;
|
|
129
|
+
}
|
|
130
|
+
if (version === undefined) {
|
|
131
|
+
const verAns = await p.text({
|
|
132
|
+
message: 'Version / dist-tag / image tag / branch alias (-v)',
|
|
133
|
+
placeholder: 'latest',
|
|
134
|
+
initialValue: 'latest',
|
|
135
|
+
});
|
|
136
|
+
if (p.isCancel(verAns)) {
|
|
137
|
+
p.cancel('Download cancelled.');
|
|
138
|
+
this.exit(0);
|
|
139
|
+
}
|
|
140
|
+
version = verAns.trim() || 'latest';
|
|
141
|
+
}
|
|
142
|
+
const versionResolved = version || 'latest';
|
|
143
|
+
if (source === 'docker') {
|
|
144
|
+
if (dockerRegistry === undefined) {
|
|
145
|
+
const reg = await p.text({
|
|
146
|
+
message: 'Docker image without tag (--docker-registry)',
|
|
147
|
+
placeholder: 'nocobase/nocobase',
|
|
148
|
+
initialValue: 'nocobase/nocobase',
|
|
149
|
+
});
|
|
150
|
+
if (p.isCancel(reg)) {
|
|
151
|
+
p.cancel('Download cancelled.');
|
|
152
|
+
this.exit(0);
|
|
153
|
+
}
|
|
154
|
+
dockerRegistry = reg.trim() || 'nocobase/nocobase';
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (source === 'git') {
|
|
158
|
+
if (gitUrl === undefined) {
|
|
159
|
+
const urlAns = await p.text({
|
|
160
|
+
message: 'Git remote URL (--git-url)',
|
|
161
|
+
placeholder: 'https://github.com/nocobase/nocobase.git',
|
|
162
|
+
initialValue: 'https://github.com/nocobase/nocobase.git',
|
|
163
|
+
});
|
|
164
|
+
if (p.isCancel(urlAns)) {
|
|
165
|
+
p.cancel('Download cancelled.');
|
|
166
|
+
this.exit(0);
|
|
167
|
+
}
|
|
168
|
+
gitUrl = urlAns.trim() || 'https://github.com/nocobase/nocobase.git';
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (source === 'npm' || source === 'git') {
|
|
172
|
+
if (outputDir === undefined) {
|
|
173
|
+
const initialOut = this.defaultOutputDir(versionResolved);
|
|
174
|
+
const outAns = await p.text({
|
|
175
|
+
message: 'Output directory relative to cwd (-o)',
|
|
176
|
+
placeholder: initialOut,
|
|
177
|
+
initialValue: initialOut,
|
|
178
|
+
});
|
|
179
|
+
if (p.isCancel(outAns)) {
|
|
180
|
+
p.cancel('Download cancelled.');
|
|
181
|
+
this.exit(0);
|
|
182
|
+
}
|
|
183
|
+
outputDir = outAns.trim() || initialOut;
|
|
184
|
+
}
|
|
185
|
+
const replaceAns = await p.confirm({
|
|
186
|
+
message: 'Delete existing output directory if present, then retry? (--replace)',
|
|
187
|
+
initialValue: replace,
|
|
188
|
+
});
|
|
189
|
+
if (p.isCancel(replaceAns)) {
|
|
190
|
+
p.cancel('Download cancelled.');
|
|
191
|
+
this.exit(0);
|
|
192
|
+
}
|
|
193
|
+
replace = replaceAns;
|
|
194
|
+
}
|
|
195
|
+
if (source === 'npm') {
|
|
196
|
+
const devAns = await p.confirm({
|
|
197
|
+
message: 'Install devDependencies and run a non-production yarn install? (--dev)',
|
|
198
|
+
initialValue: dev,
|
|
199
|
+
});
|
|
200
|
+
if (p.isCancel(devAns)) {
|
|
201
|
+
p.cancel('Download cancelled.');
|
|
202
|
+
this.exit(0);
|
|
203
|
+
}
|
|
204
|
+
dev = devAns;
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
source,
|
|
208
|
+
version: versionResolved,
|
|
209
|
+
replace,
|
|
210
|
+
'dev': dev,
|
|
211
|
+
'output-dir': outputDir,
|
|
212
|
+
'git-url': gitUrl,
|
|
213
|
+
'docker-registry': dockerRegistry,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
56
216
|
async downloadFromDocker(flags) {
|
|
57
217
|
const image = flags['docker-registry'] ?? 'nocobase/nocobase';
|
|
58
218
|
const tag = flags.version ?? 'latest';
|
|
59
|
-
await run('docker', ['pull', `${image}:${tag}`]
|
|
219
|
+
await run('docker', ['pull', `${image}:${tag}`]);
|
|
60
220
|
}
|
|
61
221
|
async downloadFromNpm(flags) {
|
|
62
|
-
const appRoot = flags['app-root-path'] ?? 'my-nocobase-app';
|
|
63
222
|
const versionSpec = flags.version || 'latest';
|
|
64
|
-
const
|
|
65
|
-
|
|
223
|
+
const outputDir = this.resolveOutputDir(flags);
|
|
224
|
+
const projectRoot = path.resolve(process.cwd(), outputDir);
|
|
225
|
+
const npxArgs = ['-y', `create-nocobase-app@${versionSpec}`, outputDir];
|
|
226
|
+
if (!flags['dev']) {
|
|
66
227
|
npxArgs.push('--skip-dev-dependencies');
|
|
67
228
|
}
|
|
68
|
-
if (flags
|
|
69
|
-
await fsp.rm(
|
|
229
|
+
if (flags.replace) {
|
|
230
|
+
await fsp.rm(projectRoot, { recursive: true, force: true });
|
|
70
231
|
}
|
|
71
|
-
await run('npx', npxArgs
|
|
232
|
+
await run('npx', npxArgs);
|
|
72
233
|
const installArgs = ['install'];
|
|
73
|
-
if (!flags['
|
|
234
|
+
if (!flags['dev']) {
|
|
74
235
|
installArgs.push('--production');
|
|
75
236
|
}
|
|
76
|
-
await run('yarn', installArgs,
|
|
237
|
+
await run('yarn', installArgs, { cwd: projectRoot });
|
|
238
|
+
return projectRoot;
|
|
77
239
|
}
|
|
78
240
|
async downloadFromGit(flags) {
|
|
79
241
|
const repoUrl = flags['git-url'] ?? 'https://github.com/nocobase/nocobase.git';
|
|
80
|
-
const
|
|
242
|
+
const versionSpec = flags.version || 'latest';
|
|
243
|
+
const outputDir = this.resolveOutputDir(flags);
|
|
81
244
|
const versionToRef = {
|
|
82
245
|
'latest': 'main',
|
|
83
246
|
'beta': 'next',
|
|
84
247
|
'alpha': 'develop',
|
|
85
248
|
};
|
|
86
|
-
if (flags
|
|
87
|
-
await fsp.rm(path.resolve(process.cwd(),
|
|
249
|
+
if (flags.replace) {
|
|
250
|
+
await fsp.rm(path.resolve(process.cwd(), outputDir), { recursive: true, force: true });
|
|
88
251
|
}
|
|
89
|
-
const branch = versionToRef[
|
|
252
|
+
const branch = versionToRef[versionSpec] || versionSpec;
|
|
90
253
|
const gitArgs = ['clone'];
|
|
91
254
|
gitArgs.push('--branch', branch);
|
|
92
|
-
gitArgs.push('--depth', '1', repoUrl,
|
|
93
|
-
await run('git', gitArgs
|
|
94
|
-
|
|
255
|
+
gitArgs.push('--depth', '1', repoUrl, outputDir);
|
|
256
|
+
await run('git', gitArgs);
|
|
257
|
+
const projectRoot = path.resolve(process.cwd(), outputDir);
|
|
258
|
+
await run('yarn', ['install'], { cwd: projectRoot });
|
|
259
|
+
return projectRoot;
|
|
95
260
|
}
|
|
261
|
+
/**
|
|
262
|
+
* @returns Final resolved flags and, for npm/git, the absolute project directory.
|
|
263
|
+
*/
|
|
96
264
|
async download() {
|
|
97
265
|
const { flags } = await this.parse(Download);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
266
|
+
const resolved = await this.resolveDownloadFlags(flags);
|
|
267
|
+
switch (resolved.source) {
|
|
268
|
+
case 'npm': {
|
|
269
|
+
const projectRoot = await this.downloadFromNpm(resolved);
|
|
270
|
+
return { resolved, projectRoot };
|
|
271
|
+
}
|
|
272
|
+
case 'docker': {
|
|
273
|
+
await this.downloadFromDocker(resolved);
|
|
274
|
+
return { resolved, projectRoot: undefined };
|
|
275
|
+
}
|
|
276
|
+
case 'git': {
|
|
277
|
+
const projectRoot = await this.downloadFromGit(resolved);
|
|
278
|
+
return { resolved, projectRoot };
|
|
279
|
+
}
|
|
108
280
|
default:
|
|
109
|
-
this.error(`Invalid source: ${
|
|
281
|
+
this.error(`Invalid --source: ${resolved.source}`);
|
|
110
282
|
}
|
|
111
283
|
}
|
|
112
284
|
async run() {
|
|
113
285
|
try {
|
|
114
|
-
await this.download();
|
|
286
|
+
return await this.download();
|
|
115
287
|
}
|
|
116
288
|
catch (error) {
|
|
117
289
|
const message = error instanceof Error ? error.message : String(error);
|