@nocobase/cli 2.1.0-beta.2 → 2.1.0-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +107 -0
- package/README.md +367 -19
- package/README.zh-CN.md +336 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +131 -0
- package/dist/commands/api/resource/create.js +15 -0
- package/dist/commands/api/resource/destroy.js +15 -0
- package/dist/commands/api/resource/get.js +15 -0
- package/dist/commands/api/resource/index.js +20 -0
- package/dist/commands/api/resource/list.js +16 -0
- package/dist/commands/api/resource/query.js +15 -0
- package/dist/commands/api/resource/update.js +15 -0
- package/dist/commands/build.js +57 -0
- package/dist/commands/db/logs.js +85 -0
- package/dist/commands/db/ps.js +60 -0
- package/dist/commands/db/shared.js +95 -0
- package/dist/commands/db/start.js +70 -0
- package/dist/commands/db/stop.js +70 -0
- package/dist/commands/dev.js +156 -0
- package/dist/commands/down.js +197 -0
- package/dist/commands/download.js +865 -0
- package/dist/commands/env/add.js +307 -0
- package/dist/commands/env/auth.js +55 -0
- package/dist/commands/env/list.js +36 -0
- package/dist/commands/env/remove.js +59 -0
- package/dist/commands/env/update.js +67 -0
- package/dist/commands/env/use.js +28 -0
- package/dist/commands/init.js +950 -0
- package/dist/commands/install.js +1927 -0
- package/dist/commands/logs.js +97 -0
- package/dist/commands/pm/disable.js +63 -0
- package/dist/commands/pm/enable.js +63 -0
- package/dist/commands/pm/list.js +61 -0
- package/dist/commands/prompts-stages.js +150 -0
- package/dist/commands/prompts-test.js +181 -0
- package/dist/commands/ps.js +119 -0
- package/dist/commands/restart.js +74 -0
- package/dist/commands/scaffold/migration.js +38 -0
- package/dist/commands/scaffold/plugin.js +37 -0
- package/dist/commands/self/check.js +71 -0
- package/dist/commands/self/index.js +20 -0
- package/dist/commands/self/update.js +86 -0
- package/dist/commands/skills/check.js +69 -0
- package/dist/commands/skills/index.js +20 -0
- package/dist/commands/skills/install.js +71 -0
- package/dist/commands/skills/update.js +71 -0
- package/dist/commands/start.js +218 -0
- package/dist/commands/stop.js +97 -0
- package/dist/commands/test.js +466 -0
- package/dist/commands/upgrade.js +594 -0
- package/dist/generated/command-registry.js +133 -0
- package/dist/help/runtime-help.js +20 -0
- package/dist/lib/api-client.js +244 -0
- package/dist/lib/app-runtime.js +153 -0
- package/dist/lib/auth-store.js +357 -0
- package/dist/lib/bootstrap.js +388 -0
- package/dist/lib/build-config.js +10 -0
- package/dist/lib/cli-home.js +61 -0
- package/dist/lib/cli-locale.js +115 -0
- package/dist/lib/command-discovery.js +39 -0
- package/dist/lib/env-auth.js +872 -0
- package/dist/lib/generated-command.js +150 -0
- package/dist/lib/http-request.js +49 -0
- package/dist/lib/naming.js +70 -0
- package/dist/lib/openapi.js +62 -0
- package/dist/lib/post-processors.js +23 -0
- package/dist/lib/prompt-catalog.js +581 -0
- package/dist/lib/prompt-validators.js +185 -0
- package/dist/lib/prompt-web-ui.js +2096 -0
- package/dist/lib/resource-command.js +343 -0
- package/dist/lib/resource-request.js +104 -0
- package/dist/lib/run-npm.js +197 -0
- package/dist/lib/runtime-generator.js +419 -0
- package/dist/lib/runtime-store.js +56 -0
- package/dist/lib/self-manager.js +246 -0
- package/dist/lib/skills-manager.js +269 -0
- package/dist/lib/startup-update.js +203 -0
- package/dist/lib/ui.js +175 -0
- package/dist/locale/en-US.json +336 -0
- package/dist/locale/zh-CN.json +336 -0
- package/dist/post-processors/data-modeling.js +66 -0
- package/dist/post-processors/data-source-manager.js +114 -0
- package/dist/post-processors/index.js +19 -0
- package/nocobase-ctl.config.json +287 -0
- package/package.json +60 -26
- package/LICENSE +0 -661
- package/bin/index.js +0 -39
- package/nocobase.conf.tpl +0 -95
- package/src/cli.js +0 -19
- package/src/commands/benchmark.js +0 -73
- package/src/commands/build.js +0 -49
- package/src/commands/clean.js +0 -30
- package/src/commands/client.js +0 -166
- package/src/commands/create-nginx-conf.js +0 -37
- package/src/commands/create-plugin.js +0 -33
- package/src/commands/dev.js +0 -200
- package/src/commands/doc.js +0 -76
- package/src/commands/e2e.js +0 -265
- package/src/commands/global.js +0 -43
- package/src/commands/index.js +0 -45
- package/src/commands/instance-id.js +0 -47
- package/src/commands/locale/cronstrue.js +0 -122
- package/src/commands/locale/react-js-cron/en-US.json +0 -75
- package/src/commands/locale/react-js-cron/index.js +0 -17
- package/src/commands/locale/react-js-cron/zh-CN.json +0 -33
- package/src/commands/locale/react-js-cron/zh-TW.json +0 -33
- package/src/commands/locale.js +0 -81
- package/src/commands/p-test.js +0 -88
- package/src/commands/perf.js +0 -63
- package/src/commands/pkg.js +0 -321
- package/src/commands/pm2.js +0 -37
- package/src/commands/postinstall.js +0 -88
- package/src/commands/start.js +0 -148
- package/src/commands/tar.js +0 -36
- package/src/commands/test-coverage.js +0 -55
- package/src/commands/test.js +0 -107
- package/src/commands/umi.js +0 -33
- package/src/commands/update-deps.js +0 -72
- package/src/commands/upgrade.js +0 -47
- package/src/commands/view-license-key.js +0 -44
- package/src/index.js +0 -14
- package/src/license.js +0 -76
- package/src/logger.js +0 -75
- package/src/plugin-generator.js +0 -80
- package/src/util.js +0 -517
- package/templates/bundle-status.html +0 -338
- package/templates/create-app-package.json +0 -39
- package/templates/plugin/.npmignore.tpl +0 -2
- package/templates/plugin/README.md.tpl +0 -1
- package/templates/plugin/client.d.ts +0 -2
- package/templates/plugin/client.js +0 -1
- package/templates/plugin/package.json.tpl +0 -11
- package/templates/plugin/server.d.ts +0 -2
- package/templates/plugin/server.js +0 -1
- package/templates/plugin/src/client/client.d.ts +0 -249
- package/templates/plugin/src/client/index.tsx.tpl +0 -1
- package/templates/plugin/src/client/locale.ts +0 -21
- package/templates/plugin/src/client/models/index.ts +0 -12
- package/templates/plugin/src/client/plugin.tsx.tpl +0 -10
- package/templates/plugin/src/index.ts +0 -2
- package/templates/plugin/src/locale/en-US.json +0 -1
- package/templates/plugin/src/locale/zh-CN.json +0 -1
- package/templates/plugin/src/server/collections/.gitkeep +0 -0
- package/templates/plugin/src/server/index.ts.tpl +0 -1
- package/templates/plugin/src/server/plugin.ts.tpl +0 -19
|
@@ -0,0 +1,203 @@
|
|
|
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 fs from 'node:fs/promises';
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
import * as p from '@clack/prompts';
|
|
12
|
+
import { inspectSelfStatus, } from './self-manager.js';
|
|
13
|
+
import { inspectSkillsStatus } from './skills-manager.js';
|
|
14
|
+
import { resolveCliHomeDir } from './cli-home.js';
|
|
15
|
+
import { isInteractiveTerminal, printWarning } from './ui.js';
|
|
16
|
+
import { run } from './run-npm.js';
|
|
17
|
+
const STARTUP_UPDATE_STATE_FILE = 'startup-update.json';
|
|
18
|
+
const NB_SKIP_STARTUP_UPDATE_ENV = 'NB_SKIP_STARTUP_UPDATE';
|
|
19
|
+
function getStateFile() {
|
|
20
|
+
return path.join(resolveCliHomeDir('global'), STARTUP_UPDATE_STATE_FILE);
|
|
21
|
+
}
|
|
22
|
+
function todayStamp(now = new Date()) {
|
|
23
|
+
return now.toISOString().slice(0, 10);
|
|
24
|
+
}
|
|
25
|
+
function shouldSkipByArgv(argv) {
|
|
26
|
+
const tokens = argv.filter((token) => token && !token.startsWith('-'));
|
|
27
|
+
if (tokens.length === 0) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
if (tokens[0] === 'self' || tokens[0] === 'skills') {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
async function readState() {
|
|
36
|
+
try {
|
|
37
|
+
const raw = await fs.readFile(getStateFile(), 'utf8');
|
|
38
|
+
return JSON.parse(raw);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function writeState(state) {
|
|
45
|
+
const filePath = getStateFile();
|
|
46
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
47
|
+
await fs.writeFile(filePath, JSON.stringify(state, null, 2));
|
|
48
|
+
}
|
|
49
|
+
async function markChecked(now = new Date()) {
|
|
50
|
+
await writeState({ lastCheckedDate: todayStamp(now) });
|
|
51
|
+
}
|
|
52
|
+
export async function shouldRunStartupUpdateCheck(argv, now = new Date()) {
|
|
53
|
+
if (process.env[NB_SKIP_STARTUP_UPDATE_ENV] === '1') {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
if (shouldSkipByArgv(argv)) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
const state = await readState();
|
|
60
|
+
return state.lastCheckedDate !== todayStamp(now);
|
|
61
|
+
}
|
|
62
|
+
export function shouldEnableStartupUpdateForInstallMethod(installMethod) {
|
|
63
|
+
return installMethod === 'npm-global';
|
|
64
|
+
}
|
|
65
|
+
function hasPendingUpdates(selfStatus, skillsStatus) {
|
|
66
|
+
return Boolean(selfStatus.updateAvailable || skillsStatus.updateAvailable === true);
|
|
67
|
+
}
|
|
68
|
+
function describeCliUpdate(selfStatus) {
|
|
69
|
+
return selfStatus.latestVersion
|
|
70
|
+
? `NocoBase CLI: ${selfStatus.currentVersion} -> ${selfStatus.latestVersion}`
|
|
71
|
+
: `NocoBase CLI: update available from ${selfStatus.currentVersion}`;
|
|
72
|
+
}
|
|
73
|
+
function describeSkillsUpdate() {
|
|
74
|
+
return 'NocoBase AI skills: update available';
|
|
75
|
+
}
|
|
76
|
+
function describeSkillsUpdateWithVersion(skillsStatus) {
|
|
77
|
+
if (skillsStatus.installedVersion && skillsStatus.latestVersion) {
|
|
78
|
+
return `NocoBase AI skills: ${skillsStatus.installedVersion} -> ${skillsStatus.latestVersion}`;
|
|
79
|
+
}
|
|
80
|
+
if (skillsStatus.latestVersion) {
|
|
81
|
+
return `NocoBase AI skills: latest ${skillsStatus.latestVersion} available`;
|
|
82
|
+
}
|
|
83
|
+
return describeSkillsUpdate();
|
|
84
|
+
}
|
|
85
|
+
function buildPromptMessage(selfStatus, skillsStatus) {
|
|
86
|
+
const lines = [];
|
|
87
|
+
const hasCliUpdate = selfStatus.updateAvailable;
|
|
88
|
+
const hasSkillsUpdate = skillsStatus.updateAvailable === true;
|
|
89
|
+
if (hasCliUpdate && hasSkillsUpdate) {
|
|
90
|
+
lines.push('Updates are available for your NocoBase CLI and AI skills.');
|
|
91
|
+
}
|
|
92
|
+
else if (hasCliUpdate) {
|
|
93
|
+
lines.push('An update is available for your NocoBase CLI.');
|
|
94
|
+
}
|
|
95
|
+
else if (hasSkillsUpdate) {
|
|
96
|
+
lines.push('An update is available for your NocoBase AI skills.');
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
lines.push('A NocoBase CLI or skills update is available.');
|
|
100
|
+
}
|
|
101
|
+
if (hasCliUpdate) {
|
|
102
|
+
lines.push(`- ${describeCliUpdate(selfStatus)}`);
|
|
103
|
+
}
|
|
104
|
+
if (hasSkillsUpdate) {
|
|
105
|
+
lines.push(`- ${describeSkillsUpdateWithVersion(skillsStatus)}`);
|
|
106
|
+
}
|
|
107
|
+
lines.push('Update now?');
|
|
108
|
+
return lines.join('\n');
|
|
109
|
+
}
|
|
110
|
+
function buildUpdateCommands(selfStatus, skillsStatus) {
|
|
111
|
+
const commands = [];
|
|
112
|
+
if (selfStatus.updateAvailable && selfStatus.updatable) {
|
|
113
|
+
commands.push('nb self update --yes');
|
|
114
|
+
}
|
|
115
|
+
if (skillsStatus.updateAvailable === true) {
|
|
116
|
+
commands.push('nb skills update --yes');
|
|
117
|
+
}
|
|
118
|
+
return commands;
|
|
119
|
+
}
|
|
120
|
+
function buildNonInteractiveWarning(selfStatus, skillsStatus) {
|
|
121
|
+
const commands = buildUpdateCommands(selfStatus, skillsStatus);
|
|
122
|
+
const details = [];
|
|
123
|
+
if (selfStatus.updateAvailable) {
|
|
124
|
+
details.push(describeCliUpdate(selfStatus));
|
|
125
|
+
}
|
|
126
|
+
if (skillsStatus.updateAvailable === true) {
|
|
127
|
+
details.push(describeSkillsUpdateWithVersion(skillsStatus));
|
|
128
|
+
}
|
|
129
|
+
return [
|
|
130
|
+
`Updates available${details.length ? `: ${details.join(', ')}` : '.'}`,
|
|
131
|
+
'Non-interactive session, skipped auto-update.',
|
|
132
|
+
commands.length
|
|
133
|
+
? `Run: ${commands.join(' && ')}`
|
|
134
|
+
: 'Check with: `nb self check` and `nb skills check`.',
|
|
135
|
+
'You may run into compatibility issues until you update.',
|
|
136
|
+
].join(' ');
|
|
137
|
+
}
|
|
138
|
+
function buildDeclinedWarning(selfStatus, skillsStatus) {
|
|
139
|
+
const commands = buildUpdateCommands(selfStatus, skillsStatus);
|
|
140
|
+
const details = [];
|
|
141
|
+
if (selfStatus.updateAvailable) {
|
|
142
|
+
details.push(describeCliUpdate(selfStatus));
|
|
143
|
+
}
|
|
144
|
+
if (skillsStatus.updateAvailable === true) {
|
|
145
|
+
details.push(describeSkillsUpdateWithVersion(skillsStatus));
|
|
146
|
+
}
|
|
147
|
+
return [
|
|
148
|
+
`Skipped updates${details.length ? `: ${details.join(', ')}` : '.'}`,
|
|
149
|
+
commands.length
|
|
150
|
+
? `Run: ${commands.join(' && ')}`
|
|
151
|
+
: 'Check with: `nb self check` and `nb skills check`.',
|
|
152
|
+
'You may run into compatibility issues until you update.',
|
|
153
|
+
].join(' ');
|
|
154
|
+
}
|
|
155
|
+
async function runStartupUpdates() {
|
|
156
|
+
await run('nb', ['self', 'update', '--yes'], {
|
|
157
|
+
stdio: 'inherit',
|
|
158
|
+
env: {
|
|
159
|
+
[NB_SKIP_STARTUP_UPDATE_ENV]: '1',
|
|
160
|
+
},
|
|
161
|
+
errorName: 'nb self update',
|
|
162
|
+
});
|
|
163
|
+
await run('nb', ['skills', 'update', '--yes'], {
|
|
164
|
+
stdio: 'inherit',
|
|
165
|
+
env: {
|
|
166
|
+
[NB_SKIP_STARTUP_UPDATE_ENV]: '1',
|
|
167
|
+
},
|
|
168
|
+
errorName: 'nb skills update',
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
export async function maybeRunStartupUpdatePrompt(argv) {
|
|
172
|
+
if (!(await shouldRunStartupUpdateCheck(argv))) {
|
|
173
|
+
return { kind: 'skipped' };
|
|
174
|
+
}
|
|
175
|
+
const selfStatus = await inspectSelfStatus();
|
|
176
|
+
if (!shouldEnableStartupUpdateForInstallMethod(selfStatus.installMethod)) {
|
|
177
|
+
return { kind: 'skipped' };
|
|
178
|
+
}
|
|
179
|
+
const skillsStatus = await inspectSkillsStatus();
|
|
180
|
+
if (!hasPendingUpdates(selfStatus, skillsStatus)) {
|
|
181
|
+
await markChecked();
|
|
182
|
+
return { kind: 'no-update' };
|
|
183
|
+
}
|
|
184
|
+
if (!isInteractiveTerminal()) {
|
|
185
|
+
printWarning(buildNonInteractiveWarning(selfStatus, skillsStatus));
|
|
186
|
+
await markChecked();
|
|
187
|
+
return { kind: 'warned' };
|
|
188
|
+
}
|
|
189
|
+
const answer = await p.confirm({
|
|
190
|
+
message: buildPromptMessage(selfStatus, skillsStatus),
|
|
191
|
+
active: 'Yes',
|
|
192
|
+
inactive: 'No',
|
|
193
|
+
initialValue: true,
|
|
194
|
+
});
|
|
195
|
+
if (p.isCancel(answer) || !answer) {
|
|
196
|
+
printWarning(buildDeclinedWarning(selfStatus, skillsStatus));
|
|
197
|
+
await markChecked();
|
|
198
|
+
return { kind: 'declined' };
|
|
199
|
+
}
|
|
200
|
+
await runStartupUpdates();
|
|
201
|
+
await markChecked();
|
|
202
|
+
return { kind: 'updated' };
|
|
203
|
+
}
|
package/dist/lib/ui.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
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 readline from 'node:readline/promises';
|
|
10
|
+
import { stdin as input, stdout as output } from 'node:process';
|
|
11
|
+
import ora from 'ora';
|
|
12
|
+
import pc from 'picocolors';
|
|
13
|
+
let activeSpinner;
|
|
14
|
+
let verboseMode = false;
|
|
15
|
+
function stringWidth(value) {
|
|
16
|
+
return Array.from(value).length;
|
|
17
|
+
}
|
|
18
|
+
function pad(value, width) {
|
|
19
|
+
const padding = Math.max(0, width - stringWidth(value));
|
|
20
|
+
return `${value}${' '.repeat(padding)}`;
|
|
21
|
+
}
|
|
22
|
+
export function isInteractiveTerminal() {
|
|
23
|
+
return Boolean(input.isTTY && output.isTTY);
|
|
24
|
+
}
|
|
25
|
+
export function setVerboseMode(value) {
|
|
26
|
+
verboseMode = value;
|
|
27
|
+
}
|
|
28
|
+
export function isVerboseMode() {
|
|
29
|
+
return verboseMode;
|
|
30
|
+
}
|
|
31
|
+
export async function promptText(message, options) {
|
|
32
|
+
if (!isInteractiveTerminal()) {
|
|
33
|
+
return options?.defaultValue ?? '';
|
|
34
|
+
}
|
|
35
|
+
const rl = readline.createInterface({
|
|
36
|
+
input,
|
|
37
|
+
output,
|
|
38
|
+
terminal: true,
|
|
39
|
+
});
|
|
40
|
+
try {
|
|
41
|
+
const suffix = options?.defaultValue ? ` (${options.defaultValue})` : '';
|
|
42
|
+
const hint = options?.secret ? ' [input visible]' : '';
|
|
43
|
+
const prompt = `${message}${suffix}${hint}: `;
|
|
44
|
+
const answer = await rl.question(prompt);
|
|
45
|
+
return answer.trim() || options?.defaultValue || '';
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
rl.close();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export async function confirmAction(message, options) {
|
|
52
|
+
if (!isInteractiveTerminal()) {
|
|
53
|
+
return Boolean(options?.defaultValue);
|
|
54
|
+
}
|
|
55
|
+
stopTask();
|
|
56
|
+
const rl = readline.createInterface({
|
|
57
|
+
input,
|
|
58
|
+
output,
|
|
59
|
+
terminal: true,
|
|
60
|
+
});
|
|
61
|
+
try {
|
|
62
|
+
const suffix = options?.defaultValue ? pc.dim('[Y/n]') : pc.dim('[y/N]');
|
|
63
|
+
const prompt = `${pc.yellow('?')} ${pc.bold(message)} ${suffix} `;
|
|
64
|
+
const answer = await rl.question(prompt);
|
|
65
|
+
const normalized = answer.trim().toLowerCase();
|
|
66
|
+
if (!normalized) {
|
|
67
|
+
return Boolean(options?.defaultValue);
|
|
68
|
+
}
|
|
69
|
+
return normalized === 'y' || normalized === 'yes';
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
rl.close();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
export function printSection(title) {
|
|
76
|
+
console.log(pc.bold(title));
|
|
77
|
+
}
|
|
78
|
+
export function printInfo(message) {
|
|
79
|
+
if (activeSpinner) {
|
|
80
|
+
if (!isInteractiveTerminal()) {
|
|
81
|
+
activeSpinner = undefined;
|
|
82
|
+
console.log(pc.cyan(message));
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
activeSpinner.info(pc.cyan(message));
|
|
86
|
+
activeSpinner = undefined;
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
console.log(pc.cyan(message));
|
|
90
|
+
}
|
|
91
|
+
export function printVerbose(message) {
|
|
92
|
+
if (!verboseMode) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
printInfo(message);
|
|
96
|
+
}
|
|
97
|
+
export function printSuccess(message) {
|
|
98
|
+
if (activeSpinner) {
|
|
99
|
+
if (!isInteractiveTerminal()) {
|
|
100
|
+
activeSpinner = undefined;
|
|
101
|
+
console.log(pc.green(message));
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
activeSpinner.succeed(pc.green(message));
|
|
105
|
+
activeSpinner = undefined;
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
console.log(pc.green(message));
|
|
109
|
+
}
|
|
110
|
+
function clearActiveSpinner() {
|
|
111
|
+
if (activeSpinner) {
|
|
112
|
+
activeSpinner.stop();
|
|
113
|
+
activeSpinner = undefined;
|
|
114
|
+
}
|
|
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`));
|
|
123
|
+
}
|
|
124
|
+
export function printVerboseWarning(message) {
|
|
125
|
+
if (!verboseMode) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
printWarning(message);
|
|
129
|
+
}
|
|
130
|
+
export function startTask(message) {
|
|
131
|
+
if (activeSpinner) {
|
|
132
|
+
activeSpinner.stop();
|
|
133
|
+
}
|
|
134
|
+
activeSpinner = ora({
|
|
135
|
+
text: pc.cyan(message),
|
|
136
|
+
isSilent: !isInteractiveTerminal(),
|
|
137
|
+
}).start();
|
|
138
|
+
if (!isInteractiveTerminal()) {
|
|
139
|
+
console.log(pc.cyan(message));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
export function updateTask(message) {
|
|
143
|
+
if (!activeSpinner) {
|
|
144
|
+
startTask(message);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
activeSpinner.text = pc.cyan(message);
|
|
148
|
+
}
|
|
149
|
+
export function succeedTask(message) {
|
|
150
|
+
if (activeSpinner) {
|
|
151
|
+
activeSpinner.succeed(pc.green(message));
|
|
152
|
+
activeSpinner = undefined;
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
console.log(pc.green(message));
|
|
156
|
+
}
|
|
157
|
+
export function failTask(message) {
|
|
158
|
+
if (activeSpinner) {
|
|
159
|
+
activeSpinner.fail(pc.red(message));
|
|
160
|
+
activeSpinner = undefined;
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
console.error(pc.red(message));
|
|
164
|
+
}
|
|
165
|
+
export function stopTask() {
|
|
166
|
+
clearActiveSpinner();
|
|
167
|
+
}
|
|
168
|
+
export function renderTable(headers, rows) {
|
|
169
|
+
const widths = headers.map((header, index) => {
|
|
170
|
+
return rows.reduce((max, row) => Math.max(max, stringWidth(row[index] ?? '')), stringWidth(header));
|
|
171
|
+
});
|
|
172
|
+
const renderRow = (row) => row.map((cell, index) => pad(cell ?? '', widths[index])).join(' ').trimEnd();
|
|
173
|
+
const divider = widths.map((width) => '-'.repeat(width)).join(' ');
|
|
174
|
+
return [renderRow(headers), divider, ...rows.map(renderRow)].join('\n');
|
|
175
|
+
}
|