pcu 0.5.6 → 0.6.3
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/pcu.js +1 -1
- package/dist/index.js +9559 -32
- package/dist/index.js.map +1 -1
- package/package.json +36 -84
- package/src/cli/commands/checkCommand.ts +227 -0
- package/src/cli/commands/initCommand.ts +394 -0
- package/src/cli/commands/securityCommand.ts +569 -0
- package/src/cli/commands/updateCommand.ts +245 -0
- package/src/cli/formatters/outputFormatter.ts +830 -0
- package/src/cli/formatters/progressBar.ts +700 -0
- package/src/cli/index.ts +565 -0
- package/src/cli/interactive/interactivePrompts.ts +517 -0
- package/src/cli/options/globalOptions.ts +380 -0
- package/src/cli/options/index.ts +5 -0
- package/src/cli/themes/colorTheme.ts +379 -0
- package/src/cli/validators/commandValidator.ts +395 -0
- package/src/cli/validators/index.ts +5 -0
- package/src/index.ts +4 -0
- package/README.ja.md +0 -582
- package/README.md +0 -690
- package/README.zh-CN.md +0 -630
- package/dist/application/services/CatalogUpdateService.d.ts +0 -209
- package/dist/application/services/CatalogUpdateService.d.ts.map +0 -1
- package/dist/application/services/CatalogUpdateService.js +0 -836
- package/dist/application/services/CatalogUpdateService.js.map +0 -1
- package/dist/application/services/WorkspaceService.d.ts +0 -139
- package/dist/application/services/WorkspaceService.d.ts.map +0 -1
- package/dist/application/services/WorkspaceService.js +0 -340
- package/dist/application/services/WorkspaceService.js.map +0 -1
- package/dist/cli/commands/CheckCommand.d.ts +0 -40
- package/dist/cli/commands/CheckCommand.d.ts.map +0 -1
- package/dist/cli/commands/CheckCommand.js +0 -177
- package/dist/cli/commands/CheckCommand.js.map +0 -1
- package/dist/cli/commands/InitCommand.d.ts +0 -53
- package/dist/cli/commands/InitCommand.d.ts.map +0 -1
- package/dist/cli/commands/InitCommand.js +0 -338
- package/dist/cli/commands/InitCommand.js.map +0 -1
- package/dist/cli/commands/SecurityCommand.d.ts +0 -113
- package/dist/cli/commands/SecurityCommand.d.ts.map +0 -1
- package/dist/cli/commands/SecurityCommand.js +0 -410
- package/dist/cli/commands/SecurityCommand.js.map +0 -1
- package/dist/cli/commands/UpdateCommand.d.ts +0 -44
- package/dist/cli/commands/UpdateCommand.d.ts.map +0 -1
- package/dist/cli/commands/UpdateCommand.js +0 -189
- package/dist/cli/commands/UpdateCommand.js.map +0 -1
- package/dist/cli/formatters/OutputFormatter.d.ts +0 -116
- package/dist/cli/formatters/OutputFormatter.d.ts.map +0 -1
- package/dist/cli/formatters/OutputFormatter.js +0 -664
- package/dist/cli/formatters/OutputFormatter.js.map +0 -1
- package/dist/cli/formatters/ProgressBar.d.ts +0 -195
- package/dist/cli/formatters/ProgressBar.d.ts.map +0 -1
- package/dist/cli/formatters/ProgressBar.js +0 -622
- package/dist/cli/formatters/ProgressBar.js.map +0 -1
- package/dist/cli/index.d.ts +0 -12
- package/dist/cli/index.d.ts.map +0 -1
- package/dist/cli/index.js +0 -492
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/interactive/InteractivePrompts.d.ts +0 -85
- package/dist/cli/interactive/InteractivePrompts.d.ts.map +0 -1
- package/dist/cli/interactive/InteractivePrompts.js +0 -434
- package/dist/cli/interactive/InteractivePrompts.js.map +0 -1
- package/dist/cli/options/GlobalOptions.d.ts +0 -117
- package/dist/cli/options/GlobalOptions.d.ts.map +0 -1
- package/dist/cli/options/GlobalOptions.js +0 -278
- package/dist/cli/options/GlobalOptions.js.map +0 -1
- package/dist/cli/options/index.d.ts +0 -5
- package/dist/cli/options/index.d.ts.map +0 -1
- package/dist/cli/options/index.js +0 -5
- package/dist/cli/options/index.js.map +0 -1
- package/dist/cli/themes/ColorTheme.d.ts +0 -211
- package/dist/cli/themes/ColorTheme.d.ts.map +0 -1
- package/dist/cli/themes/ColorTheme.js +0 -267
- package/dist/cli/themes/ColorTheme.js.map +0 -1
- package/dist/cli/validators/CommandValidator.d.ts +0 -60
- package/dist/cli/validators/CommandValidator.d.ts.map +0 -1
- package/dist/cli/validators/CommandValidator.js +0 -319
- package/dist/cli/validators/CommandValidator.js.map +0 -1
- package/dist/cli/validators/index.d.ts +0 -5
- package/dist/cli/validators/index.d.ts.map +0 -1
- package/dist/cli/validators/index.js +0 -5
- package/dist/cli/validators/index.js.map +0 -1
- package/dist/common/config/Config.d.ts +0 -142
- package/dist/common/config/Config.d.ts.map +0 -1
- package/dist/common/config/Config.js +0 -382
- package/dist/common/config/Config.js.map +0 -1
- package/dist/common/config/ConfigLoader.d.ts +0 -49
- package/dist/common/config/ConfigLoader.d.ts.map +0 -1
- package/dist/common/config/ConfigLoader.js +0 -180
- package/dist/common/config/ConfigLoader.js.map +0 -1
- package/dist/common/config/PackageFilterConfig.d.ts +0 -56
- package/dist/common/config/PackageFilterConfig.d.ts.map +0 -1
- package/dist/common/config/PackageFilterConfig.js +0 -94
- package/dist/common/config/PackageFilterConfig.js.map +0 -1
- package/dist/common/config/index.d.ts +0 -8
- package/dist/common/config/index.d.ts.map +0 -1
- package/dist/common/config/index.js +0 -8
- package/dist/common/config/index.js.map +0 -1
- package/dist/common/error-handling/ErrorTracker.d.ts +0 -48
- package/dist/common/error-handling/ErrorTracker.d.ts.map +0 -1
- package/dist/common/error-handling/ErrorTracker.js +0 -93
- package/dist/common/error-handling/ErrorTracker.js.map +0 -1
- package/dist/common/error-handling/UserFriendlyErrorHandler.d.ts +0 -74
- package/dist/common/error-handling/UserFriendlyErrorHandler.d.ts.map +0 -1
- package/dist/common/error-handling/UserFriendlyErrorHandler.js +0 -703
- package/dist/common/error-handling/UserFriendlyErrorHandler.js.map +0 -1
- package/dist/common/error-handling/index.d.ts +0 -11
- package/dist/common/error-handling/index.d.ts.map +0 -1
- package/dist/common/error-handling/index.js +0 -9
- package/dist/common/error-handling/index.js.map +0 -1
- package/dist/common/logger/Logger.d.ts +0 -110
- package/dist/common/logger/Logger.d.ts.map +0 -1
- package/dist/common/logger/Logger.js +0 -289
- package/dist/common/logger/Logger.js.map +0 -1
- package/dist/common/logger/index.d.ts +0 -6
- package/dist/common/logger/index.d.ts.map +0 -1
- package/dist/common/logger/index.js +0 -6
- package/dist/common/logger/index.js.map +0 -1
- package/dist/common/types/cli.d.ts +0 -265
- package/dist/common/types/cli.d.ts.map +0 -1
- package/dist/common/types/cli.js +0 -5
- package/dist/common/types/cli.js.map +0 -1
- package/dist/common/types/core.d.ts +0 -270
- package/dist/common/types/core.d.ts.map +0 -1
- package/dist/common/types/core.js +0 -32
- package/dist/common/types/core.js.map +0 -1
- package/dist/common/types/index.d.ts +0 -8
- package/dist/common/types/index.d.ts.map +0 -1
- package/dist/common/types/index.js +0 -8
- package/dist/common/types/index.js.map +0 -1
- package/dist/common/utils/VersionChecker.d.ts +0 -54
- package/dist/common/utils/VersionChecker.d.ts.map +0 -1
- package/dist/common/utils/VersionChecker.js +0 -180
- package/dist/common/utils/VersionChecker.js.map +0 -1
- package/dist/common/utils/async.d.ts +0 -74
- package/dist/common/utils/async.d.ts.map +0 -1
- package/dist/common/utils/async.js +0 -228
- package/dist/common/utils/async.js.map +0 -1
- package/dist/common/utils/format.d.ts +0 -32
- package/dist/common/utils/format.d.ts.map +0 -1
- package/dist/common/utils/format.js +0 -121
- package/dist/common/utils/format.js.map +0 -1
- package/dist/common/utils/git.d.ts +0 -44
- package/dist/common/utils/git.d.ts.map +0 -1
- package/dist/common/utils/git.js +0 -147
- package/dist/common/utils/git.js.map +0 -1
- package/dist/common/utils/index.d.ts +0 -12
- package/dist/common/utils/index.d.ts.map +0 -1
- package/dist/common/utils/index.js +0 -12
- package/dist/common/utils/index.js.map +0 -1
- package/dist/common/utils/string.d.ts +0 -56
- package/dist/common/utils/string.d.ts.map +0 -1
- package/dist/common/utils/string.js +0 -134
- package/dist/common/utils/string.js.map +0 -1
- package/dist/common/utils/validation.d.ts +0 -88
- package/dist/common/utils/validation.d.ts.map +0 -1
- package/dist/common/utils/validation.js +0 -308
- package/dist/common/utils/validation.js.map +0 -1
- package/dist/domain/entities/Catalog.d.ts +0 -117
- package/dist/domain/entities/Catalog.d.ts.map +0 -1
- package/dist/domain/entities/Catalog.js +0 -240
- package/dist/domain/entities/Catalog.js.map +0 -1
- package/dist/domain/entities/Package.d.ts +0 -143
- package/dist/domain/entities/Package.d.ts.map +0 -1
- package/dist/domain/entities/Package.js +0 -272
- package/dist/domain/entities/Package.js.map +0 -1
- package/dist/domain/entities/Workspace.d.ts +0 -95
- package/dist/domain/entities/Workspace.d.ts.map +0 -1
- package/dist/domain/entities/Workspace.js +0 -173
- package/dist/domain/entities/Workspace.js.map +0 -1
- package/dist/domain/repositories/WorkspaceRepository.d.ts +0 -41
- package/dist/domain/repositories/WorkspaceRepository.d.ts.map +0 -1
- package/dist/domain/repositories/WorkspaceRepository.js +0 -8
- package/dist/domain/repositories/WorkspaceRepository.js.map +0 -1
- package/dist/domain/value-objects/CatalogCollection.d.ts +0 -106
- package/dist/domain/value-objects/CatalogCollection.d.ts.map +0 -1
- package/dist/domain/value-objects/CatalogCollection.js +0 -230
- package/dist/domain/value-objects/CatalogCollection.js.map +0 -1
- package/dist/domain/value-objects/PackageCollection.d.ts +0 -122
- package/dist/domain/value-objects/PackageCollection.d.ts.map +0 -1
- package/dist/domain/value-objects/PackageCollection.js +0 -263
- package/dist/domain/value-objects/PackageCollection.js.map +0 -1
- package/dist/domain/value-objects/Version.d.ts +0 -141
- package/dist/domain/value-objects/Version.d.ts.map +0 -1
- package/dist/domain/value-objects/Version.js +0 -268
- package/dist/domain/value-objects/Version.js.map +0 -1
- package/dist/domain/value-objects/WorkspaceConfig.d.ts +0 -144
- package/dist/domain/value-objects/WorkspaceConfig.d.ts.map +0 -1
- package/dist/domain/value-objects/WorkspaceConfig.js +0 -357
- package/dist/domain/value-objects/WorkspaceConfig.js.map +0 -1
- package/dist/domain/value-objects/WorkspaceId.d.ts +0 -51
- package/dist/domain/value-objects/WorkspaceId.d.ts.map +0 -1
- package/dist/domain/value-objects/WorkspaceId.js +0 -104
- package/dist/domain/value-objects/WorkspaceId.js.map +0 -1
- package/dist/domain/value-objects/WorkspacePath.d.ts +0 -75
- package/dist/domain/value-objects/WorkspacePath.d.ts.map +0 -1
- package/dist/domain/value-objects/WorkspacePath.js +0 -128
- package/dist/domain/value-objects/WorkspacePath.js.map +0 -1
- package/dist/index.d.ts +0 -25
- package/dist/index.d.ts.map +0 -1
- package/dist/infrastructure/cache/Cache.d.ts +0 -161
- package/dist/infrastructure/cache/Cache.d.ts.map +0 -1
- package/dist/infrastructure/cache/Cache.js +0 -398
- package/dist/infrastructure/cache/Cache.js.map +0 -1
- package/dist/infrastructure/cache/index.d.ts +0 -6
- package/dist/infrastructure/cache/index.d.ts.map +0 -1
- package/dist/infrastructure/cache/index.js +0 -6
- package/dist/infrastructure/cache/index.js.map +0 -1
- package/dist/infrastructure/external-services/NpmRegistryService.d.ts +0 -145
- package/dist/infrastructure/external-services/NpmRegistryService.d.ts.map +0 -1
- package/dist/infrastructure/external-services/NpmRegistryService.js +0 -466
- package/dist/infrastructure/external-services/NpmRegistryService.js.map +0 -1
- package/dist/infrastructure/file-system/FileSystemService.d.ts +0 -120
- package/dist/infrastructure/file-system/FileSystemService.d.ts.map +0 -1
- package/dist/infrastructure/file-system/FileSystemService.js +0 -663
- package/dist/infrastructure/file-system/FileSystemService.js.map +0 -1
- package/dist/infrastructure/repositories/FileWorkspaceRepository.d.ts +0 -57
- package/dist/infrastructure/repositories/FileWorkspaceRepository.d.ts.map +0 -1
- package/dist/infrastructure/repositories/FileWorkspaceRepository.js +0 -179
- package/dist/infrastructure/repositories/FileWorkspaceRepository.js.map +0 -1
|
@@ -0,0 +1,700 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Progress Bar
|
|
3
|
+
*
|
|
4
|
+
* Provides beautiful progress indicators for CLI operations
|
|
5
|
+
* with multiple styles and themes.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
|
|
10
|
+
export interface ProgressBarOptions {
|
|
11
|
+
text?: string;
|
|
12
|
+
total?: number;
|
|
13
|
+
style?: 'default' | 'gradient' | 'fancy' | 'minimal' | 'rainbow' | 'neon';
|
|
14
|
+
showSpeed?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class ProgressBar {
|
|
18
|
+
private percentageBar: PercentageProgressBar | null = null;
|
|
19
|
+
private current = 0;
|
|
20
|
+
private total = 0;
|
|
21
|
+
private text = '';
|
|
22
|
+
private startTime: number = 0;
|
|
23
|
+
private style: string;
|
|
24
|
+
private showSpeed: boolean;
|
|
25
|
+
|
|
26
|
+
constructor(options: ProgressBarOptions = {}) {
|
|
27
|
+
this.text = options.text || 'Processing...';
|
|
28
|
+
this.total = options.total || 0;
|
|
29
|
+
this.style = options.style || 'default';
|
|
30
|
+
this.showSpeed = options.showSpeed ?? true;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Start the progress bar
|
|
35
|
+
*/
|
|
36
|
+
start(text?: string): void {
|
|
37
|
+
this.text = text || this.text;
|
|
38
|
+
this.startTime = Date.now();
|
|
39
|
+
|
|
40
|
+
// 在开始新进度条前,彻底清理可能的残留内容
|
|
41
|
+
this.clearPreviousOutput();
|
|
42
|
+
|
|
43
|
+
// 强制使用percentageBar,即使没有total也要创建
|
|
44
|
+
// 这样可以避免spinner导致的冲突问题
|
|
45
|
+
const effectiveTotal = this.total > 0 ? this.total : 1; // 如果没有total,设为1避免除零错误
|
|
46
|
+
|
|
47
|
+
this.percentageBar = new PercentageProgressBar(40, {
|
|
48
|
+
style: this.style,
|
|
49
|
+
showStats: this.showSpeed,
|
|
50
|
+
multiLine: true, // 使用多行模式减少闪烁
|
|
51
|
+
});
|
|
52
|
+
this.percentageBar.start(effectiveTotal, this.text);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Update progress with text
|
|
57
|
+
*/
|
|
58
|
+
update(text: string, current?: number, total?: number): void {
|
|
59
|
+
this.text = text;
|
|
60
|
+
if (current !== undefined) this.current = current;
|
|
61
|
+
if (total !== undefined) this.total = total;
|
|
62
|
+
|
|
63
|
+
// 只使用percentageBar,不使用spinner
|
|
64
|
+
if (this.percentageBar) {
|
|
65
|
+
this.percentageBar.update(this.current, text);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Increment progress
|
|
71
|
+
*/
|
|
72
|
+
increment(amount = 1, text?: string): void {
|
|
73
|
+
this.current += amount;
|
|
74
|
+
if (text) this.text = text;
|
|
75
|
+
|
|
76
|
+
// 只使用percentageBar,不使用spinner
|
|
77
|
+
if (this.percentageBar) {
|
|
78
|
+
this.percentageBar.update(this.current, text);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Mark as succeeded
|
|
84
|
+
*/
|
|
85
|
+
succeed(text?: string): void {
|
|
86
|
+
// 只使用percentageBar,不使用spinner
|
|
87
|
+
if (this.percentageBar) {
|
|
88
|
+
const successText = text || this.getCompletionText();
|
|
89
|
+
this.percentageBar.complete(successText);
|
|
90
|
+
console.log(this.getSuccessMessage(successText));
|
|
91
|
+
this.percentageBar = null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Mark as failed
|
|
97
|
+
*/
|
|
98
|
+
fail(text?: string): void {
|
|
99
|
+
// 只使用percentageBar,不使用spinner
|
|
100
|
+
if (this.percentageBar) {
|
|
101
|
+
const failText = text || this.getFailureText();
|
|
102
|
+
console.log(this.getFailureMessage(failText));
|
|
103
|
+
this.percentageBar = null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Get styled success message
|
|
109
|
+
*/
|
|
110
|
+
private getSuccessMessage(text: string): string {
|
|
111
|
+
const elapsed = this.getElapsedTime();
|
|
112
|
+
switch (this.style) {
|
|
113
|
+
case 'gradient':
|
|
114
|
+
return `${chalk.magenta.bold('✨')} ${chalk.green(text)} ${chalk.gray(elapsed)}`;
|
|
115
|
+
case 'fancy':
|
|
116
|
+
return `${chalk.cyan('🎉')} ${chalk.green.bold(text)} ${chalk.cyan('🎉')} ${chalk.gray(elapsed)}`;
|
|
117
|
+
case 'minimal':
|
|
118
|
+
return chalk.green(text);
|
|
119
|
+
case 'rainbow':
|
|
120
|
+
return `${chalk.magenta('🌈')} ${chalk.green(text)} ${chalk.gray(elapsed)}`;
|
|
121
|
+
case 'neon':
|
|
122
|
+
return `${chalk.green.bold('⚡ SUCCESS')} ${chalk.green(text)} ${chalk.gray(elapsed)}`;
|
|
123
|
+
default:
|
|
124
|
+
return `${chalk.green('✅')} ${chalk.green(text)} ${chalk.gray(elapsed)}`;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Get styled failure message
|
|
130
|
+
*/
|
|
131
|
+
private getFailureMessage(text: string): string {
|
|
132
|
+
const elapsed = this.getElapsedTime();
|
|
133
|
+
switch (this.style) {
|
|
134
|
+
case 'gradient':
|
|
135
|
+
return `${chalk.red.bold('💥')} ${chalk.red(text)} ${chalk.gray(elapsed)}`;
|
|
136
|
+
case 'fancy':
|
|
137
|
+
return `${chalk.red('💔')} ${chalk.red.bold(text)} ${chalk.red('💔')} ${chalk.gray(elapsed)}`;
|
|
138
|
+
case 'minimal':
|
|
139
|
+
return chalk.red(text);
|
|
140
|
+
case 'rainbow':
|
|
141
|
+
return `${chalk.red('⚠️')} ${chalk.red(text)} ${chalk.gray(elapsed)}`;
|
|
142
|
+
case 'neon':
|
|
143
|
+
return `${chalk.red.bold('⚡ ERROR')} ${chalk.red(text)} ${chalk.gray(elapsed)}`;
|
|
144
|
+
default:
|
|
145
|
+
return `${chalk.red('❌')} ${chalk.red(text)} ${chalk.gray(elapsed)}`;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Get completion text with stats
|
|
151
|
+
*/
|
|
152
|
+
private getCompletionText(): string {
|
|
153
|
+
const elapsed = this.getElapsedTime();
|
|
154
|
+
const speed = this.getAverageSpeed();
|
|
155
|
+
return `${this.text} completed ${speed} ${elapsed}`;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Get failure text
|
|
160
|
+
*/
|
|
161
|
+
private getFailureText(): string {
|
|
162
|
+
return `${this.text} failed`;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Get elapsed time formatted
|
|
167
|
+
*/
|
|
168
|
+
private getElapsedTime(): string {
|
|
169
|
+
const elapsed = Date.now() - this.startTime;
|
|
170
|
+
if (elapsed < 1000) return `(${elapsed}ms)`;
|
|
171
|
+
if (elapsed < 60000) return `(${(elapsed / 1000).toFixed(1)}s)`;
|
|
172
|
+
return `(${Math.floor(elapsed / 60000)}m ${Math.floor((elapsed % 60000) / 1000)}s)`;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Get average processing speed
|
|
177
|
+
*/
|
|
178
|
+
private getAverageSpeed(): string {
|
|
179
|
+
const elapsed = Date.now() - this.startTime;
|
|
180
|
+
if (elapsed === 0 || this.current === 0) return '';
|
|
181
|
+
const speed = Math.round((this.current / elapsed) * 1000);
|
|
182
|
+
return speed > 0 ? `(${speed}/s)` : '';
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Mark as warning
|
|
187
|
+
*/
|
|
188
|
+
warn(text?: string): void {
|
|
189
|
+
// 只使用percentageBar,不使用spinner
|
|
190
|
+
if (this.percentageBar) {
|
|
191
|
+
const warnText = text || this.text;
|
|
192
|
+
console.log(this.getWarningMessage(warnText));
|
|
193
|
+
this.percentageBar = null;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Mark as info
|
|
199
|
+
*/
|
|
200
|
+
info(text?: string): void {
|
|
201
|
+
// 只使用percentageBar,不使用spinner
|
|
202
|
+
if (this.percentageBar) {
|
|
203
|
+
const infoText = text || this.text;
|
|
204
|
+
console.log(this.getInfoMessage(infoText));
|
|
205
|
+
this.percentageBar = null;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Get styled warning message
|
|
211
|
+
*/
|
|
212
|
+
private getWarningMessage(text: string): string {
|
|
213
|
+
const elapsed = this.getElapsedTime();
|
|
214
|
+
switch (this.style) {
|
|
215
|
+
case 'gradient':
|
|
216
|
+
return `${chalk.yellow.bold('⚡')} ${chalk.yellow(text)} ${chalk.gray(elapsed)}`;
|
|
217
|
+
case 'fancy':
|
|
218
|
+
return `${chalk.yellow('⚠️')} ${chalk.yellow.bold(text)} ${chalk.yellow('⚠️')} ${chalk.gray(elapsed)}`;
|
|
219
|
+
case 'minimal':
|
|
220
|
+
return chalk.yellow(text);
|
|
221
|
+
case 'rainbow':
|
|
222
|
+
return `${chalk.yellow('⚠️')} ${chalk.yellow(text)} ${chalk.gray(elapsed)}`;
|
|
223
|
+
case 'neon':
|
|
224
|
+
return `${chalk.yellow.bold('⚡ WARNING')} ${chalk.yellow(text)} ${chalk.gray(elapsed)}`;
|
|
225
|
+
default:
|
|
226
|
+
return `${chalk.yellow('⚠️')} ${chalk.yellow(text)} ${chalk.gray(elapsed)}`;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Get styled info message
|
|
232
|
+
*/
|
|
233
|
+
private getInfoMessage(text: string): string {
|
|
234
|
+
const elapsed = this.getElapsedTime();
|
|
235
|
+
switch (this.style) {
|
|
236
|
+
case 'gradient':
|
|
237
|
+
return `${chalk.blue.bold('ℹ️')} ${chalk.blue(text)} ${chalk.gray(elapsed)}`;
|
|
238
|
+
case 'fancy':
|
|
239
|
+
return `${chalk.blue('💡')} ${chalk.blue.bold(text)} ${chalk.blue('💡')} ${chalk.gray(elapsed)}`;
|
|
240
|
+
case 'minimal':
|
|
241
|
+
return chalk.blue(text);
|
|
242
|
+
case 'rainbow':
|
|
243
|
+
return `${chalk.blue('ℹ️')} ${chalk.blue(text)} ${chalk.gray(elapsed)}`;
|
|
244
|
+
case 'neon':
|
|
245
|
+
return `${chalk.blue.bold('⚡ INFO')} ${chalk.blue(text)} ${chalk.gray(elapsed)}`;
|
|
246
|
+
default:
|
|
247
|
+
return `${chalk.blue('ℹ️')} ${chalk.blue(text)} ${chalk.gray(elapsed)}`;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Stop the progress bar
|
|
253
|
+
*/
|
|
254
|
+
stop(): void {
|
|
255
|
+
// 只使用percentageBar,不使用spinner
|
|
256
|
+
if (this.percentageBar) {
|
|
257
|
+
this.percentageBar = null;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Clear previous output to prevent residual progress bars
|
|
263
|
+
*/
|
|
264
|
+
private clearPreviousOutput(): void {
|
|
265
|
+
// 清理可能的残留进度条显示(最多清理5行,应该足够了)
|
|
266
|
+
for (let i = 0; i < 5; i++) {
|
|
267
|
+
process.stdout.write('\x1b[1A\r\x1b[K'); // 上移一行并清除
|
|
268
|
+
}
|
|
269
|
+
// 确保光标在正确位置
|
|
270
|
+
process.stdout.write('\r');
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Create a multi-step progress indicator
|
|
275
|
+
*/
|
|
276
|
+
static createMultiStep(steps: string[]): MultiStepProgress {
|
|
277
|
+
return new MultiStepProgress(steps);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Create a beautiful gradient progress bar
|
|
282
|
+
*/
|
|
283
|
+
static createGradient(options?: Partial<ProgressBarOptions>): ProgressBar {
|
|
284
|
+
return new ProgressBar({
|
|
285
|
+
style: 'gradient',
|
|
286
|
+
showSpeed: true,
|
|
287
|
+
...options,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Create a fancy progress bar with decorations
|
|
293
|
+
*/
|
|
294
|
+
static createFancy(options?: Partial<ProgressBarOptions>): ProgressBar {
|
|
295
|
+
return new ProgressBar({
|
|
296
|
+
style: 'fancy',
|
|
297
|
+
showSpeed: true,
|
|
298
|
+
...options,
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Create a minimal clean progress bar
|
|
304
|
+
*/
|
|
305
|
+
static createMinimal(options?: Partial<ProgressBarOptions>): ProgressBar {
|
|
306
|
+
return new ProgressBar({
|
|
307
|
+
style: 'minimal',
|
|
308
|
+
showSpeed: false,
|
|
309
|
+
...options,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Create a rainbow themed progress bar
|
|
315
|
+
*/
|
|
316
|
+
static createRainbow(options?: Partial<ProgressBarOptions>): ProgressBar {
|
|
317
|
+
return new ProgressBar({
|
|
318
|
+
style: 'rainbow',
|
|
319
|
+
showSpeed: true,
|
|
320
|
+
...options,
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Create a neon style progress bar
|
|
326
|
+
*/
|
|
327
|
+
static createNeon(options?: Partial<ProgressBarOptions>): ProgressBar {
|
|
328
|
+
return new ProgressBar({
|
|
329
|
+
style: 'neon',
|
|
330
|
+
showSpeed: true,
|
|
331
|
+
...options,
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Multi-step progress indicator
|
|
338
|
+
*/
|
|
339
|
+
export class MultiStepProgress {
|
|
340
|
+
private currentStep = 0;
|
|
341
|
+
private steps: string[] = [];
|
|
342
|
+
|
|
343
|
+
constructor(steps: string[]) {
|
|
344
|
+
this.steps = steps;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
start(): void {
|
|
348
|
+
console.log(chalk.bold('\n📋 Progress Steps:\n'));
|
|
349
|
+
this.renderSteps();
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
next(text?: string): void {
|
|
353
|
+
if (this.currentStep < this.steps.length) {
|
|
354
|
+
const stepText = text || this.steps[this.currentStep];
|
|
355
|
+
console.log(` ${chalk.green('✓')} ${stepText}`);
|
|
356
|
+
this.currentStep++;
|
|
357
|
+
|
|
358
|
+
if (this.currentStep < this.steps.length) {
|
|
359
|
+
console.log(` ${chalk.cyan('→')} ${this.steps[this.currentStep]}`);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
complete(): void {
|
|
365
|
+
console.log(chalk.green('\n🎉 All steps completed!\n'));
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
private renderSteps(): void {
|
|
369
|
+
this.steps.forEach((step, index) => {
|
|
370
|
+
const prefix = index === 0 ? chalk.cyan('→') : ' ';
|
|
371
|
+
const style = index < this.currentStep ? chalk.green : chalk.gray;
|
|
372
|
+
console.log(` ${prefix} ${style(step)}`);
|
|
373
|
+
});
|
|
374
|
+
console.log('');
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Progress bar with percentage and beautiful visual effects
|
|
380
|
+
*/
|
|
381
|
+
export class PercentageProgressBar {
|
|
382
|
+
private current = 0;
|
|
383
|
+
private total = 0;
|
|
384
|
+
private text = '';
|
|
385
|
+
private lastRender = '';
|
|
386
|
+
private startTime = 0;
|
|
387
|
+
private style: string;
|
|
388
|
+
private useMultiLine = true;
|
|
389
|
+
private isFirstRender = true;
|
|
390
|
+
|
|
391
|
+
constructor(
|
|
392
|
+
private readonly width = 40,
|
|
393
|
+
private readonly options: { style?: string; showStats?: boolean; multiLine?: boolean } = {}
|
|
394
|
+
) {
|
|
395
|
+
this.style = options.style || 'gradient';
|
|
396
|
+
this.useMultiLine = options.multiLine ?? true; // 默认使用多行模式来减少闪烁
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
start(total: number, text: string): void {
|
|
400
|
+
this.total = total;
|
|
401
|
+
this.current = 0;
|
|
402
|
+
this.text = text;
|
|
403
|
+
this.startTime = Date.now();
|
|
404
|
+
this.isFirstRender = true; // 重置首次渲染标记
|
|
405
|
+
|
|
406
|
+
// 清理可能的残留输出
|
|
407
|
+
this.clearPreviousLines();
|
|
408
|
+
|
|
409
|
+
this.render();
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* Clear any previous output lines to prevent conflicts
|
|
414
|
+
*/
|
|
415
|
+
private clearPreviousLines(): void {
|
|
416
|
+
// 更强力的清理:清理多行可能的残留内容
|
|
417
|
+
for (let i = 0; i < 6; i++) {
|
|
418
|
+
process.stdout.write('\x1b[1A\r\x1b[2K'); // 上移一行并完全清除该行
|
|
419
|
+
}
|
|
420
|
+
// 回到起始位置
|
|
421
|
+
process.stdout.write('\r');
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
update(current: number, text?: string): void {
|
|
425
|
+
this.current = current;
|
|
426
|
+
if (text) this.text = text;
|
|
427
|
+
this.render();
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
increment(amount = 1, text?: string): void {
|
|
431
|
+
this.current += amount;
|
|
432
|
+
if (text) this.text = text;
|
|
433
|
+
this.render();
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
complete(text?: string): void {
|
|
437
|
+
this.current = this.total;
|
|
438
|
+
if (text) this.text = text;
|
|
439
|
+
this.render();
|
|
440
|
+
console.log(''); // New line after completion
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
private render(): void {
|
|
444
|
+
const percentage = Math.round((this.current / this.total) * 100);
|
|
445
|
+
const filledWidth = Math.round((this.current / this.total) * this.width);
|
|
446
|
+
const emptyWidth = this.width - filledWidth;
|
|
447
|
+
|
|
448
|
+
if (this.useMultiLine) {
|
|
449
|
+
this.renderMultiLine(percentage, filledWidth, emptyWidth);
|
|
450
|
+
} else {
|
|
451
|
+
this.renderSingleLine(percentage, filledWidth, emptyWidth);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
private renderMultiLine(percentage: number, filledWidth: number, emptyWidth: number): void {
|
|
456
|
+
const currentText = `${this.getStyledPrefix()} ${this.text}`;
|
|
457
|
+
|
|
458
|
+
// 构建进度条
|
|
459
|
+
let bar: string;
|
|
460
|
+
switch (this.style) {
|
|
461
|
+
case 'gradient':
|
|
462
|
+
bar = this.renderGradientBar(filledWidth, emptyWidth);
|
|
463
|
+
break;
|
|
464
|
+
case 'fancy':
|
|
465
|
+
bar = this.renderFancyBar(filledWidth, emptyWidth);
|
|
466
|
+
break;
|
|
467
|
+
case 'minimal':
|
|
468
|
+
bar = this.renderMinimalBar(filledWidth, emptyWidth);
|
|
469
|
+
break;
|
|
470
|
+
case 'blocks':
|
|
471
|
+
bar = this.renderBlockBar(filledWidth, emptyWidth);
|
|
472
|
+
break;
|
|
473
|
+
default:
|
|
474
|
+
bar = this.renderDefaultBar(filledWidth, emptyWidth);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
let progressLine = `(${this.current}/${this.total}) [${bar}] ${this.getStyledPercentage(percentage)}`;
|
|
478
|
+
|
|
479
|
+
// Add stats if enabled
|
|
480
|
+
if (this.options.showStats && this.startTime > 0) {
|
|
481
|
+
const elapsed = Date.now() - this.startTime;
|
|
482
|
+
const speed = elapsed > 0 ? Math.round((this.current / elapsed) * 1000) : 0;
|
|
483
|
+
if (speed > 0) {
|
|
484
|
+
progressLine += ` ${chalk.gray(`${speed}/s`)}`;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
if (this.isFirstRender) {
|
|
489
|
+
// 第一次渲染:输出两行
|
|
490
|
+
console.log(currentText);
|
|
491
|
+
console.log(progressLine);
|
|
492
|
+
this.isFirstRender = false;
|
|
493
|
+
} else {
|
|
494
|
+
// 后续更新:回到两行前的位置,分别更新这两行
|
|
495
|
+
// 光标上移两行,清除文字行,输出新文字行
|
|
496
|
+
process.stdout.write('\x1b[2A\r\x1b[2K' + currentText + '\n');
|
|
497
|
+
// 清除进度条行,输出新进度条行
|
|
498
|
+
process.stdout.write('\r\x1b[2K' + progressLine);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
this.lastRender = progressLine;
|
|
502
|
+
|
|
503
|
+
if (this.current >= this.total) {
|
|
504
|
+
process.stdout.write('\n');
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
private renderSingleLine(percentage: number, filledWidth: number, emptyWidth: number): void {
|
|
509
|
+
let bar: string;
|
|
510
|
+
switch (this.style) {
|
|
511
|
+
case 'gradient':
|
|
512
|
+
bar = this.renderGradientBar(filledWidth, emptyWidth);
|
|
513
|
+
break;
|
|
514
|
+
case 'fancy':
|
|
515
|
+
bar = this.renderFancyBar(filledWidth, emptyWidth);
|
|
516
|
+
break;
|
|
517
|
+
case 'minimal':
|
|
518
|
+
bar = this.renderMinimalBar(filledWidth, emptyWidth);
|
|
519
|
+
break;
|
|
520
|
+
case 'blocks':
|
|
521
|
+
bar = this.renderBlockBar(filledWidth, emptyWidth);
|
|
522
|
+
break;
|
|
523
|
+
default:
|
|
524
|
+
bar = this.renderDefaultBar(filledWidth, emptyWidth);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
let progressText = `${this.getStyledPrefix()} ${this.text} (${this.current}/${this.total}) [${bar}] ${this.getStyledPercentage(percentage)}`;
|
|
528
|
+
|
|
529
|
+
// Add stats if enabled
|
|
530
|
+
if (this.options.showStats && this.startTime > 0) {
|
|
531
|
+
const elapsed = Date.now() - this.startTime;
|
|
532
|
+
const speed = elapsed > 0 ? Math.round((this.current / elapsed) * 1000) : 0;
|
|
533
|
+
if (speed > 0) {
|
|
534
|
+
progressText += ` ${chalk.gray(`${speed}/s`)}`;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// Clear previous line and render new one
|
|
539
|
+
if (this.lastRender) {
|
|
540
|
+
process.stdout.write('\r\x1b[K');
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
process.stdout.write(progressText);
|
|
544
|
+
this.lastRender = progressText;
|
|
545
|
+
|
|
546
|
+
if (this.current >= this.total) {
|
|
547
|
+
process.stdout.write('\n');
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
private renderGradientBar(filledWidth: number, emptyWidth: number): string {
|
|
552
|
+
const colors = [chalk.red, chalk.yellow, chalk.green, chalk.cyan, chalk.blue, chalk.magenta];
|
|
553
|
+
|
|
554
|
+
let filledBar = '';
|
|
555
|
+
for (let i = 0; i < filledWidth; i++) {
|
|
556
|
+
const colorIndex = Math.floor((i / this.width) * colors.length);
|
|
557
|
+
const colorFn = colors[Math.min(colorIndex, colors.length - 1)];
|
|
558
|
+
if (colorFn) {
|
|
559
|
+
filledBar += colorFn('█');
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
const emptyBar = chalk.gray('░'.repeat(emptyWidth));
|
|
564
|
+
return filledBar + emptyBar;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
private renderFancyBar(filledWidth: number, emptyWidth: number): string {
|
|
568
|
+
const filledBar = chalk.cyan('▓'.repeat(filledWidth));
|
|
569
|
+
const emptyBar = chalk.gray('░'.repeat(emptyWidth));
|
|
570
|
+
return filledBar + emptyBar;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
private renderMinimalBar(filledWidth: number, emptyWidth: number): string {
|
|
574
|
+
const filledBar = chalk.white('━'.repeat(filledWidth));
|
|
575
|
+
const emptyBar = chalk.gray('─'.repeat(emptyWidth));
|
|
576
|
+
return filledBar + emptyBar;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
private renderBlockBar(filledWidth: number, emptyWidth: number): string {
|
|
580
|
+
const filledBar = chalk.green('■'.repeat(filledWidth));
|
|
581
|
+
const emptyBar = chalk.gray('□'.repeat(emptyWidth));
|
|
582
|
+
return filledBar + emptyBar;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
private renderDefaultBar(filledWidth: number, emptyWidth: number): string {
|
|
586
|
+
const filledBar = chalk.green('█'.repeat(filledWidth));
|
|
587
|
+
const emptyBar = chalk.gray('░'.repeat(emptyWidth));
|
|
588
|
+
return filledBar + emptyBar;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
private getStyledPrefix(): string {
|
|
592
|
+
switch (this.style) {
|
|
593
|
+
case 'gradient':
|
|
594
|
+
return chalk.magenta('▶');
|
|
595
|
+
case 'fancy':
|
|
596
|
+
return chalk.cyan('★');
|
|
597
|
+
case 'minimal':
|
|
598
|
+
return chalk.gray('•');
|
|
599
|
+
case 'blocks':
|
|
600
|
+
return chalk.green('◆');
|
|
601
|
+
default:
|
|
602
|
+
return chalk.cyan('●');
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
private getStyledPercentage(percentage: number): string {
|
|
607
|
+
if (percentage < 25) return chalk.red.bold(`${percentage}%`);
|
|
608
|
+
if (percentage < 50) return chalk.yellow.bold(`${percentage}%`);
|
|
609
|
+
if (percentage < 75) return chalk.blue.bold(`${percentage}%`);
|
|
610
|
+
if (percentage < 100) return chalk.cyan.bold(`${percentage}%`);
|
|
611
|
+
return chalk.green.bold(`${percentage}%`);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Create a gradient percentage progress bar
|
|
616
|
+
*/
|
|
617
|
+
static createGradient(width = 40): PercentageProgressBar {
|
|
618
|
+
return new PercentageProgressBar(width, {
|
|
619
|
+
style: 'gradient',
|
|
620
|
+
showStats: true,
|
|
621
|
+
multiLine: true,
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
/**
|
|
626
|
+
* Create a fancy percentage progress bar
|
|
627
|
+
*/
|
|
628
|
+
static createFancy(width = 40): PercentageProgressBar {
|
|
629
|
+
return new PercentageProgressBar(width, { style: 'fancy', showStats: true, multiLine: true });
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Create a minimal percentage progress bar
|
|
634
|
+
*/
|
|
635
|
+
static createMinimal(width = 40): PercentageProgressBar {
|
|
636
|
+
return new PercentageProgressBar(width, {
|
|
637
|
+
style: 'minimal',
|
|
638
|
+
showStats: false,
|
|
639
|
+
multiLine: true,
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* Create a block-style percentage progress bar
|
|
645
|
+
*/
|
|
646
|
+
static createBlocks(width = 40): PercentageProgressBar {
|
|
647
|
+
return new PercentageProgressBar(width, { style: 'blocks', showStats: true, multiLine: true });
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* Progress manager for batch operations
|
|
653
|
+
*/
|
|
654
|
+
export class BatchProgressManager {
|
|
655
|
+
private bars: Map<string, ProgressBar> = new Map();
|
|
656
|
+
private totalOperations = 0;
|
|
657
|
+
private completedOperations = 0;
|
|
658
|
+
|
|
659
|
+
createBar(id: string, options?: ProgressBarOptions): ProgressBar {
|
|
660
|
+
const bar = new ProgressBar(options);
|
|
661
|
+
this.bars.set(id, bar);
|
|
662
|
+
return bar;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
getBar(id: string): ProgressBar | undefined {
|
|
666
|
+
return this.bars.get(id);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
setTotal(total: number): void {
|
|
670
|
+
this.totalOperations = total;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
updateOverall(text: string): void {
|
|
674
|
+
const percentage =
|
|
675
|
+
this.totalOperations > 0
|
|
676
|
+
? Math.round((this.completedOperations / this.totalOperations) * 100)
|
|
677
|
+
: 0;
|
|
678
|
+
|
|
679
|
+
console.log(
|
|
680
|
+
chalk.cyan(
|
|
681
|
+
`📊 Overall Progress: ${percentage}% (${this.completedOperations}/${this.totalOperations})`
|
|
682
|
+
)
|
|
683
|
+
);
|
|
684
|
+
if (text) {
|
|
685
|
+
console.log(chalk.gray(` → ${text}`));
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
completeOperation(text?: string): void {
|
|
690
|
+
this.completedOperations++;
|
|
691
|
+
if (text) {
|
|
692
|
+
this.updateOverall(text);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
cleanup(): void {
|
|
697
|
+
this.bars.forEach((bar) => bar.stop());
|
|
698
|
+
this.bars.clear();
|
|
699
|
+
}
|
|
700
|
+
}
|