@nocobase/cli 2.1.0-alpha.20 → 2.1.0-alpha.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +256 -89
- package/README.zh-CN.md +332 -0
- package/bin/run.js +21 -2
- package/dist/commands/build.js +7 -1
- package/dist/commands/db/logs.js +85 -0
- package/dist/commands/db/ps.js +60 -0
- package/dist/commands/db/shared.js +81 -0
- package/dist/commands/db/start.js +55 -7
- package/dist/commands/db/stop.js +70 -0
- package/dist/commands/dev.js +112 -21
- package/dist/commands/down.js +193 -0
- package/dist/commands/download.js +622 -183
- package/dist/commands/env/add.js +233 -131
- package/dist/commands/env/auth.js +9 -8
- package/dist/commands/init.js +696 -103
- package/dist/commands/install.js +1588 -566
- package/dist/commands/logs.js +90 -0
- package/dist/commands/pm/disable.js +35 -3
- package/dist/commands/pm/enable.js +35 -3
- package/dist/commands/pm/list.js +37 -4
- package/dist/commands/prompts-stages.js +144 -0
- package/dist/commands/prompts-test.js +175 -0
- package/dist/commands/ps.js +116 -0
- package/dist/commands/start.js +171 -15
- package/dist/commands/stop.js +90 -0
- package/dist/commands/upgrade.js +559 -11
- package/dist/lib/app-runtime.js +142 -0
- package/dist/lib/auth-store.js +44 -3
- package/dist/lib/bootstrap.js +7 -3
- package/dist/lib/env-auth.js +427 -82
- package/dist/lib/prompt-catalog.js +552 -0
- package/dist/lib/prompt-validators.js +184 -0
- package/dist/lib/prompt-web-ui.js +2027 -0
- package/dist/lib/run-npm.js +71 -7
- package/package.json +3 -3
- package/dist/commands/restart.js +0 -32
- package/dist/lib/init-browser-wizard.js +0 -431
|
@@ -11,279 +11,718 @@ import { Command, Flags } from '@oclif/core';
|
|
|
11
11
|
import * as p from '@clack/prompts';
|
|
12
12
|
import path from 'node:path';
|
|
13
13
|
import { stdin as stdinStream, stdout as stdoutStream } from 'node:process';
|
|
14
|
+
import { runPromptCatalog, } from "../lib/prompt-catalog.js";
|
|
14
15
|
import { run } from "../lib/run-npm.js";
|
|
16
|
+
import { printVerbose, setVerboseMode, startTask, stopTask, updateTask } from '../lib/ui.js';
|
|
17
|
+
const DEFAULT_DOCKER_REGISTRY = 'nocobase/nocobase';
|
|
18
|
+
const DEFAULT_DOCKER_REGISTRY_ZH_CN = 'registry.cn-shanghai.aliyuncs.com/nocobase/nocobase';
|
|
19
|
+
const DEFAULT_DOCKER_PLATFORM = 'auto';
|
|
20
|
+
function defaultOutputDirForVersion(versionTag) {
|
|
21
|
+
const safe = versionTag.replace(/[/\\]/g, '-');
|
|
22
|
+
return `./nocobase-${safe}`;
|
|
23
|
+
}
|
|
24
|
+
async function pathExists(target) {
|
|
25
|
+
try {
|
|
26
|
+
await fsp.access(target);
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function defaultDockerRegistryForLang(lang) {
|
|
34
|
+
return String(lang ?? '').trim() === 'zh-CN'
|
|
35
|
+
? DEFAULT_DOCKER_REGISTRY_ZH_CN
|
|
36
|
+
: DEFAULT_DOCKER_REGISTRY;
|
|
37
|
+
}
|
|
38
|
+
function argvHasToken(argv, tokens) {
|
|
39
|
+
return tokens.some((t) => argv.includes(t));
|
|
40
|
+
}
|
|
41
|
+
function gitRefForVersion(versionSpec) {
|
|
42
|
+
const versionToRef = {
|
|
43
|
+
latest: 'main',
|
|
44
|
+
beta: 'next',
|
|
45
|
+
alpha: 'develop',
|
|
46
|
+
};
|
|
47
|
+
return versionToRef[versionSpec] || versionSpec;
|
|
48
|
+
}
|
|
49
|
+
/** `build-dts` only applies when `build` is true and source is npm/git. */
|
|
50
|
+
function normalizeBuildDts(source, build, wantDts) {
|
|
51
|
+
if (source !== 'npm' && source !== 'git') {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
return Boolean(build && wantDts);
|
|
55
|
+
}
|
|
56
|
+
function downloadSourceLabel(source) {
|
|
57
|
+
switch (source) {
|
|
58
|
+
case 'docker':
|
|
59
|
+
return 'Docker image';
|
|
60
|
+
case 'npm':
|
|
61
|
+
return 'npm package';
|
|
62
|
+
case 'git':
|
|
63
|
+
return 'Git repository';
|
|
64
|
+
default:
|
|
65
|
+
return source;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function normalizeDockerPlatform(value) {
|
|
69
|
+
const text = String(value ?? '').trim();
|
|
70
|
+
if (text === 'linux/amd64' || text === 'linux/arm64') {
|
|
71
|
+
return text;
|
|
72
|
+
}
|
|
73
|
+
return DEFAULT_DOCKER_PLATFORM;
|
|
74
|
+
}
|
|
75
|
+
function dockerPlatformArg(value) {
|
|
76
|
+
const platform = normalizeDockerPlatform(value);
|
|
77
|
+
if (platform === 'auto') {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
return platform;
|
|
81
|
+
}
|
|
82
|
+
const EXTERNAL_COMMAND_LOADING_DELAY_MS = 8_000;
|
|
83
|
+
const EXTERNAL_COMMAND_LOADING_UPDATE_MS = 15_000;
|
|
15
84
|
export default class Download extends Command {
|
|
16
|
-
|
|
85
|
+
_flags;
|
|
86
|
+
preparationTaskActive = false;
|
|
87
|
+
static description = 'Scaffold or fetch NocoBase from npm, Docker, or Git. `--version` is the shared version input: package version for npm, image tag for Docker, and git ref for Git.';
|
|
17
88
|
static examples = [
|
|
18
89
|
'<%= config.bin %> <%= command.id %>',
|
|
19
|
-
'<%= config.bin %> <%= command.id %> -y --source npm --version
|
|
20
|
-
'<%= config.bin %> <%= command.id %> --source npm --version
|
|
21
|
-
'<%= config.bin %> <%= command.id %> --source npm --version
|
|
22
|
-
'<%= config.bin %> <%= command.id %> --source
|
|
23
|
-
'<%= config.bin %> <%= command.id %> --source
|
|
90
|
+
'<%= config.bin %> <%= command.id %> -y --source npm --version alpha',
|
|
91
|
+
'<%= config.bin %> <%= command.id %> -y --source npm --version alpha --no-build',
|
|
92
|
+
'<%= config.bin %> <%= command.id %> --source npm --version alpha',
|
|
93
|
+
'<%= config.bin %> <%= command.id %> --source npm --version alpha --output-dir=./app',
|
|
94
|
+
'<%= config.bin %> <%= command.id %> --source docker --version alpha --docker-registry=nocobase/nocobase --docker-platform=linux/arm64',
|
|
95
|
+
'<%= config.bin %> <%= command.id %> -y --source docker --version alpha --docker-save -o ./docker-images',
|
|
96
|
+
'<%= config.bin %> <%= command.id %> --source git --version alpha --git-url=git@github.com:nocobase/nocobase.git',
|
|
97
|
+
'<%= config.bin %> <%= command.id %> --source git --version fix/cli-v2',
|
|
98
|
+
'<%= config.bin %> <%= command.id %> -y --source git --version fix/cli-v2 --no-build',
|
|
99
|
+
'<%= config.bin %> <%= command.id %> -y --source npm --version alpha --build-dts',
|
|
100
|
+
'<%= config.bin %> <%= command.id %> -y --source npm --version alpha --npm-registry=https://registry.npmmirror.com',
|
|
24
101
|
];
|
|
25
102
|
static flags = {
|
|
26
103
|
yes: Flags.boolean({
|
|
27
104
|
char: 'y',
|
|
28
|
-
description: '
|
|
105
|
+
description: 'Use defaults and skip interactive prompts.',
|
|
106
|
+
default: false,
|
|
107
|
+
}),
|
|
108
|
+
verbose: Flags.boolean({
|
|
109
|
+
description: 'Show detailed command output',
|
|
110
|
+
default: false,
|
|
111
|
+
}),
|
|
112
|
+
'no-intro': Flags.boolean({
|
|
113
|
+
hidden: true,
|
|
114
|
+
description: 'Skip command intro when invoked by another CLI command',
|
|
29
115
|
default: false,
|
|
30
116
|
}),
|
|
31
117
|
source: Flags.string({
|
|
32
118
|
char: 's',
|
|
33
|
-
description: '
|
|
119
|
+
description: 'How to get NocoBase: Docker image, npm package, or Git repository.',
|
|
34
120
|
options: ['docker', 'npm', 'git'],
|
|
35
121
|
required: false,
|
|
36
122
|
}),
|
|
37
123
|
version: Flags.string({
|
|
38
124
|
char: 'v',
|
|
39
|
-
description: 'npm
|
|
125
|
+
description: 'Shared version input. For npm this is the package version, for Docker the image tag, and for Git a git ref such as a branch name (for example: alpha, beta, latest, fix/cli-v2).',
|
|
40
126
|
}),
|
|
41
127
|
replace: Flags.boolean({
|
|
42
128
|
char: 'r',
|
|
43
|
-
description: '
|
|
129
|
+
description: 'Replace the target directory if it already exists.',
|
|
44
130
|
default: false,
|
|
45
131
|
}),
|
|
46
|
-
'dev': Flags.boolean({
|
|
47
|
-
|
|
132
|
+
'dev-dependencies': Flags.boolean({
|
|
133
|
+
char: 'D',
|
|
134
|
+
allowNo: true,
|
|
135
|
+
description: 'Install development dependencies for npm/git source installs.',
|
|
48
136
|
default: false,
|
|
49
137
|
}),
|
|
50
138
|
'output-dir': Flags.string({
|
|
51
139
|
char: 'o',
|
|
52
|
-
description: '
|
|
140
|
+
description: 'Download target directory, or Docker tarball directory when --docker-save is enabled.',
|
|
53
141
|
}),
|
|
54
142
|
'git-url': Flags.string({
|
|
55
|
-
description: '
|
|
143
|
+
description: 'Git repository URL to clone when --source git is used.',
|
|
56
144
|
}),
|
|
57
145
|
'docker-registry': Flags.string({
|
|
58
|
-
description: '
|
|
146
|
+
description: 'Docker image repository to pull when --source docker is used.',
|
|
147
|
+
}),
|
|
148
|
+
'docker-platform': Flags.string({
|
|
149
|
+
description: 'Docker image platform to pull; use auto to let Docker choose.',
|
|
150
|
+
options: ['auto', 'linux/amd64', 'linux/arm64'],
|
|
151
|
+
}),
|
|
152
|
+
'docker-save': Flags.boolean({
|
|
153
|
+
allowNo: true,
|
|
154
|
+
description: 'Also save the pulled Docker image as a tarball.',
|
|
155
|
+
default: false,
|
|
156
|
+
}),
|
|
157
|
+
'npm-registry': Flags.string({
|
|
158
|
+
description: 'npm registry for npm/git downloads and dependency installation.',
|
|
159
|
+
}),
|
|
160
|
+
'build': Flags.boolean({
|
|
161
|
+
allowNo: true,
|
|
162
|
+
description: 'Build npm/git source after dependencies are installed.',
|
|
163
|
+
default: true,
|
|
59
164
|
}),
|
|
165
|
+
'build-dts': Flags.boolean({
|
|
166
|
+
description: 'Generate TypeScript declaration files during the npm/git build.',
|
|
167
|
+
default: false,
|
|
168
|
+
}),
|
|
169
|
+
};
|
|
170
|
+
static prompts = {
|
|
171
|
+
source: {
|
|
172
|
+
type: 'select',
|
|
173
|
+
message: 'How would you like to get NocoBase?',
|
|
174
|
+
options: [
|
|
175
|
+
{ value: 'npm', label: 'NPM package' },
|
|
176
|
+
{ value: 'git', label: 'Git repository' },
|
|
177
|
+
{ value: 'docker', label: 'Docker image' },
|
|
178
|
+
],
|
|
179
|
+
yesInitialValue: 'docker',
|
|
180
|
+
initialValue: 'docker',
|
|
181
|
+
required: true,
|
|
182
|
+
},
|
|
183
|
+
version: {
|
|
184
|
+
type: 'text',
|
|
185
|
+
message: 'Which version would you like to use? You can enter a package version, Docker image tag, or Git ref such as a branch name.',
|
|
186
|
+
placeholder: 'alpha',
|
|
187
|
+
initialValue: 'alpha',
|
|
188
|
+
yesInitialValue: 'alpha',
|
|
189
|
+
required: true,
|
|
190
|
+
},
|
|
191
|
+
dockerRegistry: {
|
|
192
|
+
type: 'text',
|
|
193
|
+
message: 'Which Docker image would you like to use?',
|
|
194
|
+
placeholder: DEFAULT_DOCKER_REGISTRY,
|
|
195
|
+
initialValue: (values) => defaultDockerRegistryForLang(values.lang),
|
|
196
|
+
yesInitialValue: DEFAULT_DOCKER_REGISTRY,
|
|
197
|
+
required: true,
|
|
198
|
+
hidden: (values) => values.source !== 'docker',
|
|
199
|
+
},
|
|
200
|
+
dockerPlatform: {
|
|
201
|
+
type: 'select',
|
|
202
|
+
message: 'Which Docker image platform should be used?',
|
|
203
|
+
options: [
|
|
204
|
+
{ value: 'auto', label: 'Auto', hint: 'Use Docker default for this machine' },
|
|
205
|
+
{ value: 'linux/amd64', label: 'linux/amd64' },
|
|
206
|
+
{ value: 'linux/arm64', label: 'linux/arm64' },
|
|
207
|
+
],
|
|
208
|
+
initialValue: DEFAULT_DOCKER_PLATFORM,
|
|
209
|
+
yesInitialValue: DEFAULT_DOCKER_PLATFORM,
|
|
210
|
+
required: true,
|
|
211
|
+
hidden: (values) => values.source !== 'docker',
|
|
212
|
+
},
|
|
213
|
+
dockerSave: {
|
|
214
|
+
type: 'boolean',
|
|
215
|
+
message: 'Save the Docker image as a tar file',
|
|
216
|
+
initialValue: false,
|
|
217
|
+
hidden: (values) => values.source !== 'docker',
|
|
218
|
+
},
|
|
219
|
+
gitUrl: {
|
|
220
|
+
type: 'text',
|
|
221
|
+
message: 'Git repository URL',
|
|
222
|
+
placeholder: 'https://github.com/nocobase/nocobase.git',
|
|
223
|
+
initialValue: 'https://github.com/nocobase/nocobase.git',
|
|
224
|
+
yesInitialValue: 'https://github.com/nocobase/nocobase.git',
|
|
225
|
+
required: true,
|
|
226
|
+
hidden: (values) => values.source !== 'git',
|
|
227
|
+
},
|
|
228
|
+
outputDir: {
|
|
229
|
+
type: 'text',
|
|
230
|
+
message: 'Download location',
|
|
231
|
+
placeholder: 'e.g. ./nocobase-latest',
|
|
232
|
+
initialValue: (values) => defaultOutputDirForVersion(String(values.version ?? 'latest').trim() || 'latest'),
|
|
233
|
+
required: true,
|
|
234
|
+
hidden: (values) => {
|
|
235
|
+
const s = values.source;
|
|
236
|
+
if (s === 'npm' || s === 'git') {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
if (s === 'docker') {
|
|
240
|
+
return !values.dockerSave;
|
|
241
|
+
}
|
|
242
|
+
return true;
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
npmRegistry: {
|
|
246
|
+
type: 'text',
|
|
247
|
+
message: 'NPM registry URL (optional)',
|
|
248
|
+
placeholder: 'Leave empty to use the default registry',
|
|
249
|
+
initialValue: '',
|
|
250
|
+
hidden: (values) => values.source !== 'npm' && values.source !== 'git',
|
|
251
|
+
},
|
|
252
|
+
replace: {
|
|
253
|
+
type: 'boolean',
|
|
254
|
+
message: 'Clear the app directory if it already contains files',
|
|
255
|
+
initialValue: false,
|
|
256
|
+
hidden: (values) => Download.hideOutputDirAndReplaceSteps(values),
|
|
257
|
+
},
|
|
258
|
+
devDependencies: {
|
|
259
|
+
type: 'boolean',
|
|
260
|
+
message: 'Install development dependencies (npm only)',
|
|
261
|
+
initialValue: false,
|
|
262
|
+
hidden: (values) => values.source !== 'npm',
|
|
263
|
+
},
|
|
264
|
+
build: {
|
|
265
|
+
type: 'boolean',
|
|
266
|
+
message: 'Build the app after download',
|
|
267
|
+
initialValue: true,
|
|
268
|
+
yesInitialValue: true,
|
|
269
|
+
hidden: () => true,
|
|
270
|
+
},
|
|
271
|
+
buildDts: {
|
|
272
|
+
type: 'boolean',
|
|
273
|
+
message: 'Generate TypeScript declaration files',
|
|
274
|
+
initialValue: false,
|
|
275
|
+
hidden: (values) => values.source !== 'git',
|
|
276
|
+
},
|
|
60
277
|
};
|
|
278
|
+
/** When true, `outputDir` / `replace` prompts are skipped (same condition for both). */
|
|
279
|
+
static hideOutputDirAndReplaceSteps(values) {
|
|
280
|
+
const s = values.source;
|
|
281
|
+
if (s === 'npm' || s === 'git') {
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
if (s === 'docker') {
|
|
285
|
+
return !values.dockerSave;
|
|
286
|
+
}
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
61
289
|
resolveOutputDir(flags) {
|
|
62
290
|
const explicit = flags['output-dir'];
|
|
63
291
|
if (explicit) {
|
|
64
292
|
return explicit;
|
|
65
293
|
}
|
|
66
|
-
|
|
67
|
-
const safe = tag.replace(/[/\\]/g, '-');
|
|
68
|
-
return `./nocobase-${safe}`;
|
|
294
|
+
return defaultOutputDirForVersion(flags.version || 'latest');
|
|
69
295
|
}
|
|
70
|
-
|
|
71
|
-
const
|
|
72
|
-
|
|
296
|
+
async ensureOutputDirAvailable(outputDir, replace) {
|
|
297
|
+
const outputAbs = path.resolve(process.cwd(), outputDir);
|
|
298
|
+
if (replace) {
|
|
299
|
+
await fsp.rm(outputAbs, { recursive: true, force: true });
|
|
300
|
+
return outputAbs;
|
|
301
|
+
}
|
|
302
|
+
if (await pathExists(outputAbs)) {
|
|
303
|
+
this.error(`Download target already exists: ${outputDir}. Use --replace to remove it before continuing.`);
|
|
304
|
+
}
|
|
305
|
+
return outputAbs;
|
|
306
|
+
}
|
|
307
|
+
dockerTarPath(flags, outputAbs) {
|
|
308
|
+
const image = flags['docker-registry'] ?? DEFAULT_DOCKER_REGISTRY;
|
|
309
|
+
const tag = flags.version ?? 'latest';
|
|
310
|
+
const safeBase = `${image.replace(/[/:]/g, '-')}-${tag.replace(/[/\\]/g, '-')}`;
|
|
311
|
+
return path.join(outputAbs, `${safeBase}.tar`);
|
|
73
312
|
}
|
|
74
313
|
/**
|
|
75
|
-
*
|
|
314
|
+
* Defaults for prompts only. Keys present in **`preset`** are omitted so `runPromptCatalog` uses
|
|
315
|
+
* **`values`** (preset) alone for those steps — no duplicate prefill for skipped prompts.
|
|
76
316
|
*/
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
if (source
|
|
81
|
-
source =
|
|
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;
|
|
317
|
+
buildInitialValuesFromParsed(flags, preset) {
|
|
318
|
+
const initialValues = {};
|
|
319
|
+
const source = flags.source?.trim();
|
|
320
|
+
if (source) {
|
|
321
|
+
initialValues.source = source;
|
|
129
322
|
}
|
|
130
|
-
if (version
|
|
131
|
-
|
|
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
|
-
}
|
|
323
|
+
if (flags.version !== undefined) {
|
|
324
|
+
initialValues.version = flags.version.trim() || 'latest';
|
|
156
325
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
326
|
+
initialValues.replace = flags.replace;
|
|
327
|
+
initialValues.devDependencies = flags['dev-dependencies'];
|
|
328
|
+
initialValues.build = flags.build;
|
|
329
|
+
initialValues.buildDts = flags['build-dts'];
|
|
330
|
+
if (flags['output-dir'] !== undefined) {
|
|
331
|
+
initialValues.outputDir = flags['output-dir']?.trim() ?? '';
|
|
332
|
+
}
|
|
333
|
+
if (flags['git-url'] !== undefined) {
|
|
334
|
+
initialValues.gitUrl = flags['git-url']?.trim() ?? '';
|
|
335
|
+
}
|
|
336
|
+
if (flags['docker-registry'] !== undefined) {
|
|
337
|
+
initialValues.dockerRegistry = String(flags['docker-registry'] ?? '').trim();
|
|
338
|
+
}
|
|
339
|
+
initialValues.dockerPlatform = normalizeDockerPlatform(flags['docker-platform']);
|
|
340
|
+
initialValues.dockerSave = flags['docker-save'];
|
|
341
|
+
if (flags['npm-registry'] !== undefined) {
|
|
342
|
+
initialValues.npmRegistry =
|
|
343
|
+
typeof flags['npm-registry'] === 'string' ? flags['npm-registry'] : '';
|
|
344
|
+
}
|
|
345
|
+
for (const key of Object.keys(preset)) {
|
|
346
|
+
if (Object.prototype.hasOwnProperty.call(initialValues, key)) {
|
|
347
|
+
delete initialValues[key];
|
|
169
348
|
}
|
|
170
349
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
350
|
+
return initialValues;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Preset `values` for `runPromptCatalog`: any key here skips that prompt and fixes the result.
|
|
354
|
+
* Keys not listed are resolved interactively (TTY) or from catalog defaults / `initialValues` (non-TTY / `-y`).
|
|
355
|
+
*/
|
|
356
|
+
buildPresetValuesFromFlags(flags) {
|
|
357
|
+
const preset = {};
|
|
358
|
+
const argv = process.argv.slice(2);
|
|
359
|
+
if (flags.source !== undefined && String(flags.source).trim() !== '') {
|
|
360
|
+
preset.source = String(flags.source).trim();
|
|
361
|
+
}
|
|
362
|
+
if (flags.version !== undefined) {
|
|
363
|
+
preset.version = String(flags.version).trim() || 'latest';
|
|
364
|
+
}
|
|
365
|
+
if (flags['docker-registry'] !== undefined) {
|
|
366
|
+
const v = String(flags['docker-registry'] ?? '').trim();
|
|
367
|
+
if (v) {
|
|
368
|
+
preset.dockerRegistry = v;
|
|
184
369
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
370
|
+
}
|
|
371
|
+
if (argvHasToken(argv, ['--docker-platform'])) {
|
|
372
|
+
preset.dockerPlatform = normalizeDockerPlatform(flags['docker-platform']);
|
|
373
|
+
}
|
|
374
|
+
if (flags['output-dir'] !== undefined) {
|
|
375
|
+
const v = flags['output-dir']?.trim();
|
|
376
|
+
if (v) {
|
|
377
|
+
preset.outputDir = v;
|
|
192
378
|
}
|
|
193
|
-
replace = replaceAns;
|
|
194
379
|
}
|
|
195
|
-
if (
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
});
|
|
200
|
-
if (p.isCancel(devAns)) {
|
|
201
|
-
p.cancel('Download cancelled.');
|
|
202
|
-
this.exit(0);
|
|
380
|
+
if (flags['git-url'] !== undefined) {
|
|
381
|
+
const v = flags['git-url']?.trim();
|
|
382
|
+
if (v) {
|
|
383
|
+
preset.gitUrl = v;
|
|
203
384
|
}
|
|
204
|
-
dev = devAns;
|
|
205
385
|
}
|
|
386
|
+
if (flags['npm-registry'] !== undefined) {
|
|
387
|
+
preset.npmRegistry = typeof flags['npm-registry'] === 'string' ? flags['npm-registry'] : '';
|
|
388
|
+
}
|
|
389
|
+
if (argvHasToken(argv, ['--replace', '-r'])) {
|
|
390
|
+
preset.replace = flags.replace;
|
|
391
|
+
}
|
|
392
|
+
if (argvHasToken(argv, ['--dev-dependencies', '--no-dev-dependencies', '-D'])) {
|
|
393
|
+
preset.devDependencies = flags['dev-dependencies'];
|
|
394
|
+
}
|
|
395
|
+
if (argvHasToken(argv, ['--docker-save', '--no-docker-save'])) {
|
|
396
|
+
preset.dockerSave = flags['docker-save'];
|
|
397
|
+
}
|
|
398
|
+
if (argvHasToken(argv, ['--build', '--no-build'])) {
|
|
399
|
+
preset.build = flags.build;
|
|
400
|
+
}
|
|
401
|
+
if (argvHasToken(argv, ['--build-dts', '--no-build-dts'])) {
|
|
402
|
+
preset.buildDts = flags['build-dts'];
|
|
403
|
+
}
|
|
404
|
+
return preset;
|
|
405
|
+
}
|
|
406
|
+
resolveEffectiveBuild(source, results, flags) {
|
|
407
|
+
if (source === 'npm' && !Boolean(results.devDependencies)) {
|
|
408
|
+
return false;
|
|
409
|
+
}
|
|
410
|
+
if (source === 'npm' || source === 'git') {
|
|
411
|
+
return results.build !== undefined ? Boolean(results.build) : flags.build;
|
|
412
|
+
}
|
|
413
|
+
return flags.build;
|
|
414
|
+
}
|
|
415
|
+
mapCatalogResultsToResolved(results, flags) {
|
|
416
|
+
const source = String(results.source);
|
|
417
|
+
const version = String(results.version ?? '').trim() || 'latest';
|
|
418
|
+
const devDependencies = source === 'npm' ? Boolean(results.devDependencies) : undefined;
|
|
419
|
+
const effectiveBuild = this.resolveEffectiveBuild(source, results, flags);
|
|
420
|
+
const buildDtsWant = results.buildDts !== undefined ? Boolean(results.buildDts) : flags['build-dts'];
|
|
421
|
+
const outputDir = results.outputDir !== undefined
|
|
422
|
+
? String(results.outputDir).trim() || undefined
|
|
423
|
+
: flags['output-dir']?.trim() || undefined;
|
|
424
|
+
const replace = results.replace !== undefined ? Boolean(results.replace) : flags.replace;
|
|
425
|
+
const gitUrl = results.gitUrl !== undefined
|
|
426
|
+
? String(results.gitUrl).trim() || undefined
|
|
427
|
+
: flags['git-url']?.trim() || undefined;
|
|
428
|
+
const dockerRegistry = results.dockerRegistry !== undefined
|
|
429
|
+
? String(results.dockerRegistry).trim() || undefined
|
|
430
|
+
: flags['docker-registry']?.trim() || undefined;
|
|
431
|
+
const dockerPlatform = source === 'docker'
|
|
432
|
+
? normalizeDockerPlatform(results.dockerPlatform !== undefined
|
|
433
|
+
? results.dockerPlatform
|
|
434
|
+
: flags['docker-platform'])
|
|
435
|
+
: undefined;
|
|
436
|
+
const dockerSave = source === 'docker'
|
|
437
|
+
? results.dockerSave !== undefined
|
|
438
|
+
? Boolean(results.dockerSave)
|
|
439
|
+
: flags['docker-save']
|
|
440
|
+
: false;
|
|
441
|
+
const npmRegistryRaw = results.npmRegistry !== undefined
|
|
442
|
+
? String(results.npmRegistry)
|
|
443
|
+
: flags['npm-registry'] ?? '';
|
|
444
|
+
const npmRegistry = npmRegistryRaw.trim() || undefined;
|
|
206
445
|
return {
|
|
207
446
|
source,
|
|
208
|
-
version
|
|
447
|
+
version,
|
|
209
448
|
replace,
|
|
210
|
-
'dev':
|
|
449
|
+
...(source === 'npm' ? { 'dev-dependencies': devDependencies } : {}),
|
|
450
|
+
'build': effectiveBuild,
|
|
451
|
+
'build-dts': normalizeBuildDts(source, effectiveBuild, buildDtsWant),
|
|
211
452
|
'output-dir': outputDir,
|
|
212
453
|
'git-url': gitUrl,
|
|
213
454
|
'docker-registry': dockerRegistry,
|
|
455
|
+
...(source === 'docker' ? { 'docker-platform': dockerPlatform } : {}),
|
|
456
|
+
...(source === 'docker' ? { 'docker-save': dockerSave } : {}),
|
|
457
|
+
...(npmRegistry ? { 'npm-registry': npmRegistry } : {}),
|
|
214
458
|
};
|
|
215
459
|
}
|
|
460
|
+
async resolveDownloadFlags(flags) {
|
|
461
|
+
const nonInteractive = !stdinStream.isTTY || !stdoutStream.isTTY || flags.yes;
|
|
462
|
+
if (nonInteractive && !flags.source?.trim()) {
|
|
463
|
+
this.error('Download source is required in non-interactive mode. Use --source npm, --source git, or --source docker.');
|
|
464
|
+
}
|
|
465
|
+
const presetValues = this.buildPresetValuesFromFlags(flags);
|
|
466
|
+
const initialValues = this.buildInitialValuesFromParsed(flags, presetValues);
|
|
467
|
+
const results = await runPromptCatalog(Download.prompts, {
|
|
468
|
+
initialValues,
|
|
469
|
+
values: presetValues,
|
|
470
|
+
yes: flags.yes,
|
|
471
|
+
command: this,
|
|
472
|
+
hooks: {
|
|
473
|
+
onCancel: () => {
|
|
474
|
+
p.cancel('Download cancelled.');
|
|
475
|
+
this.exit(0);
|
|
476
|
+
},
|
|
477
|
+
onMissingNonInteractive: (message) => {
|
|
478
|
+
this.error(message);
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
});
|
|
482
|
+
const source = String(results.source ?? '').trim();
|
|
483
|
+
if (!source || !['docker', 'npm', 'git'].includes(source)) {
|
|
484
|
+
this.error('Download source is required. Choose npm, git, or docker.');
|
|
485
|
+
}
|
|
486
|
+
if (flags['docker-save'] && source !== 'docker') {
|
|
487
|
+
this.error('--docker-save is only available when --source docker is selected.');
|
|
488
|
+
}
|
|
489
|
+
return this.mapCatalogResultsToResolved(results, flags);
|
|
490
|
+
}
|
|
491
|
+
npmRegistryUrl(flags) {
|
|
492
|
+
const url = flags['npm-registry']?.trim();
|
|
493
|
+
return url || undefined;
|
|
494
|
+
}
|
|
495
|
+
npmRegistryEnv(flags) {
|
|
496
|
+
const url = this.npmRegistryUrl(flags);
|
|
497
|
+
if (!url) {
|
|
498
|
+
return undefined;
|
|
499
|
+
}
|
|
500
|
+
return { npm_config_registry: url };
|
|
501
|
+
}
|
|
502
|
+
isVerbose() {
|
|
503
|
+
const flags = this._flags;
|
|
504
|
+
return Boolean(flags?.verbose);
|
|
505
|
+
}
|
|
506
|
+
commandStdio() {
|
|
507
|
+
return this.isVerbose() ? 'inherit' : 'ignore';
|
|
508
|
+
}
|
|
509
|
+
formatCommandForLog(name, args, cwd) {
|
|
510
|
+
const quotedArgs = args.map((arg) => (/\s/.test(arg) ? JSON.stringify(arg) : arg));
|
|
511
|
+
const commandLine = [name, ...quotedArgs].join(' ');
|
|
512
|
+
return cwd ? `${commandLine} (cwd: ${cwd})` : commandLine;
|
|
513
|
+
}
|
|
514
|
+
async runExternalCommand(name, args, options) {
|
|
515
|
+
const cwd = options?.cwd;
|
|
516
|
+
printVerbose(`Running command: ${this.formatCommandForLog(name, args, cwd)}`);
|
|
517
|
+
let loadingStarted = false;
|
|
518
|
+
let loadingTimer;
|
|
519
|
+
let updateTimer;
|
|
520
|
+
let elapsedSeconds = 0;
|
|
521
|
+
if (!this.isVerbose() && options?.loadingMessage) {
|
|
522
|
+
loadingTimer = setTimeout(() => {
|
|
523
|
+
loadingStarted = true;
|
|
524
|
+
elapsedSeconds = Math.floor(EXTERNAL_COMMAND_LOADING_DELAY_MS / 1000);
|
|
525
|
+
startTask(`${options.loadingMessage}. Please wait...`);
|
|
526
|
+
updateTimer = setInterval(() => {
|
|
527
|
+
elapsedSeconds += Math.floor(EXTERNAL_COMMAND_LOADING_UPDATE_MS / 1000);
|
|
528
|
+
updateTask(`${options.loadingMessage}. Still working... (${elapsedSeconds}s elapsed)`);
|
|
529
|
+
}, EXTERNAL_COMMAND_LOADING_UPDATE_MS);
|
|
530
|
+
}, EXTERNAL_COMMAND_LOADING_DELAY_MS);
|
|
531
|
+
}
|
|
532
|
+
try {
|
|
533
|
+
await run(name, args, {
|
|
534
|
+
...options,
|
|
535
|
+
stdio: this.commandStdio(),
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
finally {
|
|
539
|
+
if (loadingTimer) {
|
|
540
|
+
clearTimeout(loadingTimer);
|
|
541
|
+
}
|
|
542
|
+
if (updateTimer) {
|
|
543
|
+
clearInterval(updateTimer);
|
|
544
|
+
}
|
|
545
|
+
if (loadingStarted) {
|
|
546
|
+
stopTask();
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
startPreparationTask(message) {
|
|
551
|
+
if (this.isVerbose()) {
|
|
552
|
+
p.log.step(message);
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
this.preparationTaskActive = true;
|
|
556
|
+
startTask(message);
|
|
557
|
+
}
|
|
558
|
+
finishPreparationTask() {
|
|
559
|
+
if (!this.preparationTaskActive) {
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
this.preparationTaskActive = false;
|
|
563
|
+
stopTask();
|
|
564
|
+
}
|
|
565
|
+
runOptionsWithCwd(cwd, registryEnv) {
|
|
566
|
+
if (registryEnv) {
|
|
567
|
+
return { cwd, env: registryEnv };
|
|
568
|
+
}
|
|
569
|
+
return { cwd };
|
|
570
|
+
}
|
|
571
|
+
buildCommandArgv(projectRoot, flags) {
|
|
572
|
+
const argv = ['--cwd', projectRoot];
|
|
573
|
+
if (!flags['build-dts']) {
|
|
574
|
+
argv.push('--no-dts');
|
|
575
|
+
}
|
|
576
|
+
return argv;
|
|
577
|
+
}
|
|
216
578
|
async downloadFromDocker(flags) {
|
|
217
|
-
const image = flags['docker-registry'] ??
|
|
579
|
+
const image = flags['docker-registry'] ?? DEFAULT_DOCKER_REGISTRY;
|
|
218
580
|
const tag = flags.version ?? 'latest';
|
|
219
|
-
|
|
581
|
+
const imageRef = `${image}:${tag}`;
|
|
582
|
+
const platform = dockerPlatformArg(flags['docker-platform']);
|
|
583
|
+
const pullArgs = ['pull'];
|
|
584
|
+
if (platform) {
|
|
585
|
+
pullArgs.push('--platform', platform);
|
|
586
|
+
}
|
|
587
|
+
pullArgs.push(imageRef);
|
|
588
|
+
this.finishPreparationTask();
|
|
589
|
+
p.log.step(`Pulling Docker image ${imageRef}`);
|
|
590
|
+
await this.runExternalCommand('docker', pullArgs, {
|
|
591
|
+
errorName: 'docker pull',
|
|
592
|
+
loadingMessage: 'Pulling the Docker image',
|
|
593
|
+
});
|
|
594
|
+
p.log.info(`Docker image is ready: ${imageRef}`);
|
|
595
|
+
if (!flags['docker-save']) {
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
const outputDir = this.resolveOutputDir(flags);
|
|
599
|
+
const outAbs = flags.replace
|
|
600
|
+
? path.resolve(process.cwd(), outputDir)
|
|
601
|
+
: await this.ensureOutputDirAvailable(outputDir, false);
|
|
602
|
+
if (flags.replace) {
|
|
603
|
+
await fsp.rm(outAbs, { recursive: true, force: true });
|
|
604
|
+
}
|
|
605
|
+
await fsp.mkdir(outAbs, { recursive: true });
|
|
606
|
+
const tarPath = this.dockerTarPath(flags, outAbs);
|
|
607
|
+
p.log.step(`Saving Docker image tarball to ${tarPath}`);
|
|
608
|
+
await this.runExternalCommand('docker', ['save', '-o', tarPath, imageRef], {
|
|
609
|
+
errorName: 'docker save',
|
|
610
|
+
loadingMessage: 'Saving the Docker image tarball',
|
|
611
|
+
});
|
|
612
|
+
p.log.info(`Docker image tarball saved: ${tarPath}`);
|
|
220
613
|
}
|
|
221
614
|
async downloadFromNpm(flags) {
|
|
222
615
|
const versionSpec = flags.version || 'latest';
|
|
223
616
|
const outputDir = this.resolveOutputDir(flags);
|
|
224
617
|
const projectRoot = path.resolve(process.cwd(), outputDir);
|
|
225
|
-
|
|
226
|
-
|
|
618
|
+
await this.ensureOutputDirAvailable(outputDir, flags.replace);
|
|
619
|
+
const parentDir = path.dirname(projectRoot);
|
|
620
|
+
const appName = path.basename(projectRoot);
|
|
621
|
+
const npxArgs = ['-y', `create-nocobase-app@${versionSpec}`, appName];
|
|
622
|
+
if (!flags['dev-dependencies']) {
|
|
227
623
|
npxArgs.push('--skip-dev-dependencies');
|
|
228
624
|
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
625
|
+
await fsp.mkdir(parentDir, { recursive: true });
|
|
626
|
+
const registryEnv = this.npmRegistryEnv(flags);
|
|
627
|
+
this.finishPreparationTask();
|
|
628
|
+
p.log.step(`Creating NocoBase app "${appName}" from npm`);
|
|
629
|
+
await this.runExternalCommand('npx', npxArgs, {
|
|
630
|
+
...this.runOptionsWithCwd(parentDir, registryEnv),
|
|
631
|
+
errorName: 'npx create-nocobase-app',
|
|
632
|
+
loadingMessage: 'Creating the app scaffold',
|
|
633
|
+
});
|
|
233
634
|
const installArgs = ['install'];
|
|
234
|
-
if (!flags['dev']) {
|
|
635
|
+
if (!flags['dev-dependencies']) {
|
|
235
636
|
installArgs.push('--production');
|
|
236
637
|
}
|
|
237
|
-
|
|
638
|
+
p.log.step(`Installing dependencies in ${projectRoot}`);
|
|
639
|
+
await this.runExternalCommand('yarn', installArgs, {
|
|
640
|
+
...this.runOptionsWithCwd(projectRoot, registryEnv),
|
|
641
|
+
errorName: 'yarn install',
|
|
642
|
+
loadingMessage: 'Installing dependencies',
|
|
643
|
+
});
|
|
644
|
+
if (flags.build && flags['dev-dependencies']) {
|
|
645
|
+
p.log.step(`Building app in ${projectRoot}`);
|
|
646
|
+
await this.config.runCommand('build', [
|
|
647
|
+
...this.buildCommandArgv(projectRoot, flags),
|
|
648
|
+
...(this.isVerbose() ? ['--verbose'] : []),
|
|
649
|
+
]);
|
|
650
|
+
}
|
|
651
|
+
p.log.info(`NocoBase app is ready at ${projectRoot}`);
|
|
238
652
|
return projectRoot;
|
|
239
653
|
}
|
|
240
654
|
async downloadFromGit(flags) {
|
|
241
655
|
const repoUrl = flags['git-url'] ?? 'https://github.com/nocobase/nocobase.git';
|
|
242
656
|
const versionSpec = flags.version || 'latest';
|
|
243
657
|
const outputDir = this.resolveOutputDir(flags);
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
'beta': 'next',
|
|
247
|
-
'alpha': 'develop',
|
|
248
|
-
};
|
|
249
|
-
if (flags.replace) {
|
|
250
|
-
await fsp.rm(path.resolve(process.cwd(), outputDir), { recursive: true, force: true });
|
|
251
|
-
}
|
|
252
|
-
const branch = versionToRef[versionSpec] || versionSpec;
|
|
658
|
+
await this.ensureOutputDirAvailable(outputDir, flags.replace);
|
|
659
|
+
const branch = gitRefForVersion(versionSpec);
|
|
253
660
|
const gitArgs = ['clone'];
|
|
254
661
|
gitArgs.push('--branch', branch);
|
|
255
662
|
gitArgs.push('--depth', '1', repoUrl, outputDir);
|
|
256
|
-
|
|
663
|
+
this.finishPreparationTask();
|
|
664
|
+
p.log.step(branch === versionSpec
|
|
665
|
+
? `Cloning NocoBase from ${repoUrl} (${branch})`
|
|
666
|
+
: `Cloning NocoBase from ${repoUrl} (${branch}, resolved from ${versionSpec})`);
|
|
667
|
+
await this.runExternalCommand('git', gitArgs, {
|
|
668
|
+
errorName: 'git clone',
|
|
669
|
+
loadingMessage: 'Cloning the repository',
|
|
670
|
+
});
|
|
257
671
|
const projectRoot = path.resolve(process.cwd(), outputDir);
|
|
258
|
-
|
|
672
|
+
const registryEnv = this.npmRegistryEnv(flags);
|
|
673
|
+
p.log.step(`Installing dependencies in ${projectRoot}`);
|
|
674
|
+
await this.runExternalCommand('yarn', ['install'], {
|
|
675
|
+
...this.runOptionsWithCwd(projectRoot, registryEnv),
|
|
676
|
+
errorName: 'yarn install',
|
|
677
|
+
loadingMessage: 'Installing dependencies',
|
|
678
|
+
});
|
|
679
|
+
if (flags.build) {
|
|
680
|
+
p.log.step(`Building app in ${projectRoot}`);
|
|
681
|
+
await this.config.runCommand('build', [
|
|
682
|
+
...this.buildCommandArgv(projectRoot, flags),
|
|
683
|
+
...(this.isVerbose() ? ['--verbose'] : []),
|
|
684
|
+
]);
|
|
685
|
+
}
|
|
686
|
+
p.log.info(`NocoBase app is ready at ${projectRoot}`);
|
|
259
687
|
return projectRoot;
|
|
260
688
|
}
|
|
261
|
-
/**
|
|
262
|
-
* @returns Final resolved flags and, for npm/git, the absolute project directory.
|
|
263
|
-
*/
|
|
264
689
|
async download() {
|
|
265
690
|
const { flags } = await this.parse(Download);
|
|
691
|
+
this._flags = flags;
|
|
692
|
+
setVerboseMode(Boolean(flags.verbose));
|
|
693
|
+
if (!flags['no-intro']) {
|
|
694
|
+
p.intro('Get NocoBase');
|
|
695
|
+
}
|
|
266
696
|
const resolved = await this.resolveDownloadFlags(flags);
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
697
|
+
const source = resolved.source;
|
|
698
|
+
this.startPreparationTask(`Preparing download from ${downloadSourceLabel(source)}`);
|
|
699
|
+
try {
|
|
700
|
+
switch (source) {
|
|
701
|
+
case 'npm': {
|
|
702
|
+
const projectRoot = await this.downloadFromNpm(resolved);
|
|
703
|
+
return { resolved, projectRoot };
|
|
704
|
+
}
|
|
705
|
+
case 'docker': {
|
|
706
|
+
await this.downloadFromDocker(resolved);
|
|
707
|
+
return { resolved, projectRoot: undefined };
|
|
708
|
+
}
|
|
709
|
+
case 'git': {
|
|
710
|
+
const projectRoot = await this.downloadFromGit(resolved);
|
|
711
|
+
return { resolved, projectRoot };
|
|
712
|
+
}
|
|
713
|
+
default:
|
|
714
|
+
this.error(`Unsupported download source: ${resolved.source}`);
|
|
279
715
|
}
|
|
280
|
-
|
|
281
|
-
|
|
716
|
+
}
|
|
717
|
+
finally {
|
|
718
|
+
this.finishPreparationTask();
|
|
282
719
|
}
|
|
283
720
|
}
|
|
284
721
|
async run() {
|
|
285
722
|
try {
|
|
286
|
-
|
|
723
|
+
const result = await this.download();
|
|
724
|
+
p.outro(`Download completed via ${downloadSourceLabel(result.resolved.source)}.`);
|
|
725
|
+
return result;
|
|
287
726
|
}
|
|
288
727
|
catch (error) {
|
|
289
728
|
const message = error instanceof Error ? error.message : String(error);
|