Skip to content

Commit d913106

Browse files
committed
fix: personalize export sub module count issue
1 parent 87aa7db commit d913106

10 files changed

Lines changed: 285 additions & 97 deletions

File tree

packages/contentstack-utilities/src/index.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,11 @@ export { default as TablePrompt } from './inquirer-table-prompt';
7878
export { Logger };
7979
export { default as authenticationHandler } from './authentication-handler';
8080
export { v2Logger as log, cliErrorHandler, handleAndLogError, getLogPath } from './logger/log';
81-
export { CLIProgressManager, SummaryManager } from './progress-summary';
81+
export {
82+
CLIProgressManager,
83+
SummaryManager,
84+
PrimaryProcessStrategy,
85+
ProgressStrategyRegistry,
86+
CustomProgressStrategy,
87+
DefaultProgressStrategy
88+
} from './progress-summary';

packages/contentstack-utilities/src/interfaces/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,17 @@ export interface ModuleResult {
155155
successCount: number;
156156
failureCount: number;
157157
failures: Array<{ item: string; error: string }>;
158+
processes?: Array<{ processName: string; [key: string]: any }>;
158159
}
159160

160161
export interface SummaryOptions {
161162
operationName: string; // 'EXPORT', 'IMPORT', 'MIGRATION', etc.
162163
context?: any;
163164
branchName?: string; // Optional branch name for operations
164165
}
166+
167+
export interface ProgressResult {
168+
total: number;
169+
success: number;
170+
failures: number;
171+
}

packages/contentstack-utilities/src/progress-summary/cli-progress-manager.ts

Lines changed: 138 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import ProgressBar from 'cli-progress';
44
import SummaryManager from './summary-manager';
55
import { ProcessProgress, ProgressManagerOptions, Failure } from '../interfaces';
66
import { configHandler } from '..';
7+
import { ProgressStrategyRegistry } from './progress-strategy';
78

89
interface ProgressCallback {
910
onModuleStart?: (moduleName: string) => void;
@@ -56,7 +57,7 @@ export default class CLIProgressManager {
5657
this.multiBar = null;
5758
this.currentProcess = null;
5859
this.callbacks = {};
59-
this.branchName = ''; // Default branch name
60+
this.branchName = '';
6061

6162
this.initializeProgress();
6263
this.setupGlobalSummaryIntegration();
@@ -93,10 +94,56 @@ export default class CLIProgressManager {
9394
}
9495

9596
/**
96-
* Print the final summary for all modules
97+
* Print the final summary for all modules using strategies
9798
*/
9899
static printGlobalSummary(): void {
99-
CLIProgressManager.globalSummary?.printFinalSummary();
100+
if (!CLIProgressManager.globalSummary) {
101+
return;
102+
}
103+
104+
// Apply strategy-based corrections before printing
105+
CLIProgressManager.applyStrategyCorrections();
106+
107+
// Print the final summary
108+
CLIProgressManager.globalSummary.printFinalSummary();
109+
}
110+
111+
/**
112+
* Apply strategy-based corrections to module data
113+
*/
114+
private static applyStrategyCorrections(): void {
115+
if (!CLIProgressManager.globalSummary) return;
116+
117+
const modules = Array.from(CLIProgressManager.globalSummary.getModules().values());
118+
119+
modules.forEach((module) => {
120+
// Check if this module has a registered strategy
121+
if (ProgressStrategyRegistry.has(module.name)) {
122+
const strategy = ProgressStrategyRegistry.get(module.name);
123+
124+
// Create a processes map from module data if available
125+
const processesMap = new Map<string, ProcessProgress>();
126+
127+
// If module has process data, populate the map
128+
if (module.processes && Array.isArray(module.processes)) {
129+
module.processes.forEach((processData: any) => {
130+
if (processData.processName) {
131+
processesMap.set(processData.processName, processData);
132+
}
133+
});
134+
}
135+
136+
// Calculate corrected progress using strategy
137+
const correctedResult = strategy.calculate(processesMap);
138+
139+
if (correctedResult) {
140+
// Update module with corrected counts
141+
module.totalItems = correctedResult.total;
142+
module.successCount = correctedResult.success;
143+
module.failureCount = correctedResult.failures;
144+
}
145+
}
146+
});
100147
}
101148

102149
/**
@@ -154,6 +201,8 @@ export default class CLIProgressManager {
154201
CLIProgressManager.globalSummary?.startModule(name);
155202
},
156203
onModuleComplete: (name, success, error) => {
204+
// Register process data with summary manager before completing
205+
this.registerProcessDataWithSummary(name);
157206
CLIProgressManager.globalSummary?.completeModule(name, success, error);
158207
},
159208
onProgress: (name, success, itemName, error) => {
@@ -166,6 +215,26 @@ export default class CLIProgressManager {
166215
}
167216
}
168217

218+
/**
219+
* Register process data with summary manager for strategy calculations
220+
*/
221+
private registerProcessDataWithSummary(moduleName: string): void {
222+
if (!CLIProgressManager.globalSummary) return;
223+
224+
// Register each process with the summary manager
225+
this.processes.forEach((processData, processName) => {
226+
CLIProgressManager.globalSummary?.registerProcessData(moduleName, processName, {
227+
processName,
228+
total: processData.total,
229+
current: processData.current,
230+
successCount: processData.successCount,
231+
failureCount: processData.failureCount,
232+
status: processData.status,
233+
failures: processData.failures,
234+
});
235+
});
236+
}
237+
169238
/**
170239
* Set callbacks for external integration
171240
*/
@@ -180,6 +249,32 @@ export default class CLIProgressManager {
180249
return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
181250
}
182251

252+
/**
253+
* Format process name with smart truncation (modules should use short names)
254+
*/
255+
private formatProcessName(processName: string): string {
256+
const cleaned = processName.trim();
257+
258+
if (cleaned.length <= 20) {
259+
return cleaned;
260+
}
261+
262+
return cleaned.length <= 20 ? cleaned : cleaned.substring(0, 20) + '...';
263+
}
264+
265+
/**
266+
* Format percentage for consistent alignment (always 3 characters)
267+
*/
268+
private formatPercentage(percentage: number): string {
269+
if (percentage === 100) {
270+
return '100';
271+
} else if (percentage >= 10) {
272+
return ` ${percentage}`;
273+
} else {
274+
return ` ${percentage}`;
275+
}
276+
}
277+
183278
private initializeProgress(): void {
184279
if (this.showConsoleLogs) {
185280
return;
@@ -217,7 +312,7 @@ export default class CLIProgressManager {
217312
this.progressBar.start(this.total, 0, {
218313
label: chalk.gray(` └─ ${displayName}`.padEnd(25)),
219314
status: chalk.gray('Starting...'),
220-
percentage: '0',
315+
percentage: ' 0',
221316
});
222317
} else {
223318
this.spinner = ora(`${chalk.bold(this.moduleName)}: Processing...`).start();
@@ -241,19 +336,36 @@ export default class CLIProgressManager {
241336
};
242337

243338
if (!this.showConsoleLogs) {
244-
const truncatedName = processName.length > 20 ? processName.substring(0, 17) + '...' : processName;
245-
const indentedLabel = ` ├─ ${truncatedName}`.padEnd(25);
339+
const displayName = this.formatProcessName(processName);
340+
const indentedLabel = ` ├─ ${displayName}`.padEnd(25);
246341
process.progressBar = this.multiBar.create(total, 0, {
247342
label: chalk.gray(indentedLabel),
248343
status: chalk.gray('Pending'),
249-
percentage: '0',
344+
percentage: ' 0',
250345
});
251346
}
252347

253348
this.processes.set(processName, process);
254349
return this;
255350
}
256351

352+
/**
353+
* Update the total for a specific process (for dynamic totals after API calls)
354+
*/
355+
updateProcessTotal(processName: string, newTotal: number): this {
356+
if (!this.enableNestedProgress) return this;
357+
358+
const process = this.processes.get(processName);
359+
if (process) {
360+
process.total = newTotal;
361+
if (process.progressBar && !this.showConsoleLogs) {
362+
// Update the progress bar with the new total
363+
process.progressBar.setTotal(newTotal);
364+
}
365+
}
366+
return this;
367+
}
368+
257369
/**
258370
* Start a specific process
259371
*/
@@ -264,12 +376,12 @@ export default class CLIProgressManager {
264376
if (process) {
265377
process.status = 'active';
266378
if (!this.showConsoleLogs && process.progressBar) {
267-
const truncatedName = processName.length > 20 ? processName.substring(0, 17) + '...' : processName;
268-
const indentedLabel = ` ├─ ${truncatedName}`.padEnd(25);
379+
const displayName = this.formatProcessName(processName);
380+
const indentedLabel = ` ├─ ${displayName}`.padEnd(25);
269381
process.progressBar.update(0, {
270382
label: chalk.yellow(indentedLabel),
271383
status: chalk.yellow('Processing'),
272-
percentage: '0',
384+
percentage: ' 0',
273385
});
274386
}
275387
this.currentProcess = processName;
@@ -288,15 +400,16 @@ export default class CLIProgressManager {
288400
process.status = success ? 'completed' : 'failed';
289401
if (!this.showConsoleLogs && process.progressBar) {
290402
const percentage = Math.round((process.current / process.total) * 100);
403+
const formattedPercentage = this.formatPercentage(percentage);
291404
const statusText = success
292405
? chalk.green(`✓ Complete (${process.successCount}/${process.current})`)
293406
: chalk.red(`✗ Failed (${process.successCount}/${process.current})`);
294-
const truncatedName = processName.length > 20 ? processName.substring(0, 17) + '...' : processName;
295-
const indentedLabel = ` ├─ ${truncatedName}`.padEnd(25);
407+
const displayName = this.formatProcessName(processName);
408+
const indentedLabel = ` ├─ ${displayName}`.padEnd(25);
296409
process.progressBar.update(process.total, {
297410
label: success ? chalk.green(indentedLabel) : chalk.red(indentedLabel),
298411
status: statusText,
299-
percentage: percentage.toString(),
412+
percentage: formattedPercentage,
300413
});
301414
}
302415
}
@@ -312,22 +425,24 @@ export default class CLIProgressManager {
312425
const process = this.processes.get(processName);
313426
if (process && process.progressBar) {
314427
const percentage = Math.round((process.current / process.total) * 100);
315-
const truncatedName = processName.length > 20 ? processName.substring(0, 17) + '...' : processName;
316-
const indentedLabel = ` ├─ ${truncatedName}`.padEnd(25);
428+
const formattedPercentage = this.formatPercentage(percentage);
429+
const displayName = this.formatProcessName(processName);
430+
const indentedLabel = ` ├─ ${displayName}`.padEnd(25);
317431
process.progressBar.update(process.current, {
318432
label: chalk.yellow(indentedLabel),
319433
status: chalk.yellow(message),
320-
percentage: percentage.toString(),
434+
percentage: formattedPercentage,
321435
});
322436
}
323437
} else if (this.progressBar) {
324438
const percentage = Math.round(this.progressBar.getProgress() * 100);
439+
const formattedPercentage = this.formatPercentage(percentage);
325440
const formattedName = this.formatModuleName(this.moduleName);
326441
const displayName = formattedName.length > 20 ? formattedName.substring(0, 17) + '...' : formattedName;
327442
this.progressBar.update(this.progressBar.getProgress() * this.total, {
328443
label: chalk.yellow(` └─ ${displayName}`.padEnd(25)),
329444
status: chalk.yellow(message),
330-
percentage: percentage.toString(),
445+
percentage: formattedPercentage,
331446
});
332447
} else if (this.spinner) {
333448
this.spinner.text = `${chalk.bold(this.moduleName)}: ${message}`;
@@ -371,14 +486,15 @@ export default class CLIProgressManager {
371486
// Only update progress bar if console logs are disabled
372487
if (!this.showConsoleLogs && process.progressBar) {
373488
const percentage = Math.round((process.current / process.total) * 100);
489+
const formattedPercentage = this.formatPercentage(percentage);
374490
const statusText = `${process.successCount}${process.failureCount}✗`;
375491

376-
const truncatedName = targetProcess.length > 20 ? targetProcess.substring(0, 17) + '...' : targetProcess;
377-
const indentedLabel = ` ├─ ${truncatedName}`.padEnd(25);
492+
const displayName = this.formatProcessName(targetProcess);
493+
const indentedLabel = ` ├─ ${displayName}`.padEnd(25);
378494
process.progressBar.increment(1, {
379495
label: chalk.cyan(indentedLabel),
380496
status: chalk.cyan(statusText),
381-
percentage: percentage.toString(),
497+
percentage: formattedPercentage,
382498
});
383499
}
384500
}
@@ -387,6 +503,7 @@ export default class CLIProgressManager {
387503
if (!this.showConsoleLogs) {
388504
if (this.progressBar) {
389505
const percentage = Math.round(((this.successCount + this.failureCount) / this.total) * 100);
506+
const formattedPercentage = this.formatPercentage(percentage);
390507
const totalProcessed = this.successCount + this.failureCount;
391508

392509
// Show completion status when finished, otherwise show running count
@@ -405,7 +522,7 @@ export default class CLIProgressManager {
405522
this.progressBar.increment(1, {
406523
label: labelColor(` └─ ${displayName}`.padEnd(25)),
407524
status: statusText,
408-
percentage: percentage.toString(),
525+
percentage: formattedPercentage,
409526
});
410527
} else if (this.spinner) {
411528
const total = this.successCount + this.failureCount;
Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,17 @@
11
import SummaryManager from './summary-manager';
22
import CLIProgressManager from './cli-progress-manager';
3+
import {
4+
PrimaryProcessStrategy,
5+
CustomProgressStrategy,
6+
ProgressStrategyRegistry,
7+
DefaultProgressStrategy,
8+
} from './progress-strategy';
39

4-
export { SummaryManager, CLIProgressManager };
10+
export {
11+
SummaryManager,
12+
CLIProgressManager,
13+
PrimaryProcessStrategy,
14+
CustomProgressStrategy,
15+
ProgressStrategyRegistry,
16+
DefaultProgressStrategy,
17+
};

0 commit comments

Comments
 (0)