pcu 0.2.6

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.
Files changed (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +478 -0
  3. package/bin/pcu.js +15 -0
  4. package/dist/application/services/CatalogUpdateService.d.ts +190 -0
  5. package/dist/application/services/CatalogUpdateService.d.ts.map +1 -0
  6. package/dist/application/services/CatalogUpdateService.js +521 -0
  7. package/dist/application/services/CatalogUpdateService.js.map +1 -0
  8. package/dist/application/services/WorkspaceService.d.ts +139 -0
  9. package/dist/application/services/WorkspaceService.d.ts.map +1 -0
  10. package/dist/application/services/WorkspaceService.js +340 -0
  11. package/dist/application/services/WorkspaceService.js.map +1 -0
  12. package/dist/cli/commands/CheckCommand.d.ts +41 -0
  13. package/dist/cli/commands/CheckCommand.d.ts.map +1 -0
  14. package/dist/cli/commands/CheckCommand.js +168 -0
  15. package/dist/cli/commands/CheckCommand.js.map +1 -0
  16. package/dist/cli/commands/UpdateCommand.d.ts +69 -0
  17. package/dist/cli/commands/UpdateCommand.d.ts.map +1 -0
  18. package/dist/cli/commands/UpdateCommand.js +361 -0
  19. package/dist/cli/commands/UpdateCommand.js.map +1 -0
  20. package/dist/cli/formatters/OutputFormatter.d.ts +99 -0
  21. package/dist/cli/formatters/OutputFormatter.d.ts.map +1 -0
  22. package/dist/cli/formatters/OutputFormatter.js +551 -0
  23. package/dist/cli/formatters/OutputFormatter.js.map +1 -0
  24. package/dist/cli/index.d.ts +12 -0
  25. package/dist/cli/index.d.ts.map +1 -0
  26. package/dist/cli/index.js +271 -0
  27. package/dist/cli/index.js.map +1 -0
  28. package/dist/cli/options/GlobalOptions.d.ts +117 -0
  29. package/dist/cli/options/GlobalOptions.d.ts.map +1 -0
  30. package/dist/cli/options/GlobalOptions.js +278 -0
  31. package/dist/cli/options/GlobalOptions.js.map +1 -0
  32. package/dist/cli/options/index.d.ts +5 -0
  33. package/dist/cli/options/index.d.ts.map +1 -0
  34. package/dist/cli/options/index.js +5 -0
  35. package/dist/cli/options/index.js.map +1 -0
  36. package/dist/cli/validators/CommandValidator.d.ts +60 -0
  37. package/dist/cli/validators/CommandValidator.d.ts.map +1 -0
  38. package/dist/cli/validators/CommandValidator.js +319 -0
  39. package/dist/cli/validators/CommandValidator.js.map +1 -0
  40. package/dist/cli/validators/index.d.ts +5 -0
  41. package/dist/cli/validators/index.d.ts.map +1 -0
  42. package/dist/cli/validators/index.js +5 -0
  43. package/dist/cli/validators/index.js.map +1 -0
  44. package/dist/common/config/Config.d.ts +142 -0
  45. package/dist/common/config/Config.d.ts.map +1 -0
  46. package/dist/common/config/Config.js +355 -0
  47. package/dist/common/config/Config.js.map +1 -0
  48. package/dist/common/config/index.d.ts +6 -0
  49. package/dist/common/config/index.d.ts.map +1 -0
  50. package/dist/common/config/index.js +6 -0
  51. package/dist/common/config/index.js.map +1 -0
  52. package/dist/common/logger/Logger.d.ts +110 -0
  53. package/dist/common/logger/Logger.d.ts.map +1 -0
  54. package/dist/common/logger/Logger.js +289 -0
  55. package/dist/common/logger/Logger.js.map +1 -0
  56. package/dist/common/logger/index.d.ts +6 -0
  57. package/dist/common/logger/index.d.ts.map +1 -0
  58. package/dist/common/logger/index.js +6 -0
  59. package/dist/common/logger/index.js.map +1 -0
  60. package/dist/common/types/cli.d.ts +265 -0
  61. package/dist/common/types/cli.d.ts.map +1 -0
  62. package/dist/common/types/cli.js +5 -0
  63. package/dist/common/types/cli.js.map +1 -0
  64. package/dist/common/types/core.d.ts +270 -0
  65. package/dist/common/types/core.d.ts.map +1 -0
  66. package/dist/common/types/core.js +32 -0
  67. package/dist/common/types/core.js.map +1 -0
  68. package/dist/common/types/index.d.ts +8 -0
  69. package/dist/common/types/index.d.ts.map +1 -0
  70. package/dist/common/types/index.js +8 -0
  71. package/dist/common/types/index.js.map +1 -0
  72. package/dist/common/utils/async.d.ts +74 -0
  73. package/dist/common/utils/async.d.ts.map +1 -0
  74. package/dist/common/utils/async.js +228 -0
  75. package/dist/common/utils/async.js.map +1 -0
  76. package/dist/common/utils/format.d.ts +32 -0
  77. package/dist/common/utils/format.d.ts.map +1 -0
  78. package/dist/common/utils/format.js +121 -0
  79. package/dist/common/utils/format.js.map +1 -0
  80. package/dist/common/utils/git.d.ts +44 -0
  81. package/dist/common/utils/git.d.ts.map +1 -0
  82. package/dist/common/utils/git.js +147 -0
  83. package/dist/common/utils/git.js.map +1 -0
  84. package/dist/common/utils/index.d.ts +11 -0
  85. package/dist/common/utils/index.d.ts.map +1 -0
  86. package/dist/common/utils/index.js +11 -0
  87. package/dist/common/utils/index.js.map +1 -0
  88. package/dist/common/utils/string.d.ts +56 -0
  89. package/dist/common/utils/string.d.ts.map +1 -0
  90. package/dist/common/utils/string.js +134 -0
  91. package/dist/common/utils/string.js.map +1 -0
  92. package/dist/common/utils/validation.d.ts +88 -0
  93. package/dist/common/utils/validation.d.ts.map +1 -0
  94. package/dist/common/utils/validation.js +281 -0
  95. package/dist/common/utils/validation.js.map +1 -0
  96. package/dist/domain/entities/Catalog.d.ts +117 -0
  97. package/dist/domain/entities/Catalog.d.ts.map +1 -0
  98. package/dist/domain/entities/Catalog.js +240 -0
  99. package/dist/domain/entities/Catalog.js.map +1 -0
  100. package/dist/domain/entities/Package.d.ts +143 -0
  101. package/dist/domain/entities/Package.d.ts.map +1 -0
  102. package/dist/domain/entities/Package.js +272 -0
  103. package/dist/domain/entities/Package.js.map +1 -0
  104. package/dist/domain/entities/Workspace.d.ts +95 -0
  105. package/dist/domain/entities/Workspace.d.ts.map +1 -0
  106. package/dist/domain/entities/Workspace.js +173 -0
  107. package/dist/domain/entities/Workspace.js.map +1 -0
  108. package/dist/domain/repositories/WorkspaceRepository.d.ts +41 -0
  109. package/dist/domain/repositories/WorkspaceRepository.d.ts.map +1 -0
  110. package/dist/domain/repositories/WorkspaceRepository.js +8 -0
  111. package/dist/domain/repositories/WorkspaceRepository.js.map +1 -0
  112. package/dist/domain/value-objects/CatalogCollection.d.ts +106 -0
  113. package/dist/domain/value-objects/CatalogCollection.d.ts.map +1 -0
  114. package/dist/domain/value-objects/CatalogCollection.js +230 -0
  115. package/dist/domain/value-objects/CatalogCollection.js.map +1 -0
  116. package/dist/domain/value-objects/PackageCollection.d.ts +122 -0
  117. package/dist/domain/value-objects/PackageCollection.d.ts.map +1 -0
  118. package/dist/domain/value-objects/PackageCollection.js +263 -0
  119. package/dist/domain/value-objects/PackageCollection.js.map +1 -0
  120. package/dist/domain/value-objects/Version.d.ts +141 -0
  121. package/dist/domain/value-objects/Version.d.ts.map +1 -0
  122. package/dist/domain/value-objects/Version.js +268 -0
  123. package/dist/domain/value-objects/Version.js.map +1 -0
  124. package/dist/domain/value-objects/WorkspaceConfig.d.ts +144 -0
  125. package/dist/domain/value-objects/WorkspaceConfig.d.ts.map +1 -0
  126. package/dist/domain/value-objects/WorkspaceConfig.js +357 -0
  127. package/dist/domain/value-objects/WorkspaceConfig.js.map +1 -0
  128. package/dist/domain/value-objects/WorkspaceId.d.ts +51 -0
  129. package/dist/domain/value-objects/WorkspaceId.d.ts.map +1 -0
  130. package/dist/domain/value-objects/WorkspaceId.js +104 -0
  131. package/dist/domain/value-objects/WorkspaceId.js.map +1 -0
  132. package/dist/domain/value-objects/WorkspacePath.d.ts +75 -0
  133. package/dist/domain/value-objects/WorkspacePath.d.ts.map +1 -0
  134. package/dist/domain/value-objects/WorkspacePath.js +128 -0
  135. package/dist/domain/value-objects/WorkspacePath.js.map +1 -0
  136. package/dist/infrastructure/cache/Cache.d.ts +161 -0
  137. package/dist/infrastructure/cache/Cache.d.ts.map +1 -0
  138. package/dist/infrastructure/cache/Cache.js +398 -0
  139. package/dist/infrastructure/cache/Cache.js.map +1 -0
  140. package/dist/infrastructure/cache/index.d.ts +6 -0
  141. package/dist/infrastructure/cache/index.d.ts.map +1 -0
  142. package/dist/infrastructure/cache/index.js +6 -0
  143. package/dist/infrastructure/cache/index.js.map +1 -0
  144. package/dist/infrastructure/external-services/NpmRegistryService.d.ts +106 -0
  145. package/dist/infrastructure/external-services/NpmRegistryService.d.ts.map +1 -0
  146. package/dist/infrastructure/external-services/NpmRegistryService.js +305 -0
  147. package/dist/infrastructure/external-services/NpmRegistryService.js.map +1 -0
  148. package/dist/infrastructure/file-system/FileSystemService.d.ts +120 -0
  149. package/dist/infrastructure/file-system/FileSystemService.d.ts.map +1 -0
  150. package/dist/infrastructure/file-system/FileSystemService.js +663 -0
  151. package/dist/infrastructure/file-system/FileSystemService.js.map +1 -0
  152. package/dist/infrastructure/repositories/FileWorkspaceRepository.d.ts +57 -0
  153. package/dist/infrastructure/repositories/FileWorkspaceRepository.d.ts.map +1 -0
  154. package/dist/infrastructure/repositories/FileWorkspaceRepository.js +179 -0
  155. package/dist/infrastructure/repositories/FileWorkspaceRepository.js.map +1 -0
  156. package/package.json +127 -0
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Output Formatter
3
+ *
4
+ * Provides formatted output for CLI commands in various formats.
5
+ * Supports table, JSON, YAML, and minimal output formats.
6
+ */
7
+ import { ImpactAnalysis, OutdatedReport, UpdateResult } from '../../application/services/CatalogUpdateService.js';
8
+ import { WorkspaceStats, WorkspaceValidationReport } from '../../application/services/WorkspaceService.js';
9
+ export type OutputFormat = 'table' | 'json' | 'yaml' | 'minimal';
10
+ export declare class OutputFormatter {
11
+ private readonly format;
12
+ private readonly useColor;
13
+ constructor(format?: OutputFormat, useColor?: boolean);
14
+ /**
15
+ * Format outdated dependencies report
16
+ */
17
+ formatOutdatedReport(report: OutdatedReport): string;
18
+ /**
19
+ * Format update result
20
+ */
21
+ formatUpdateResult(result: UpdateResult): string;
22
+ /**
23
+ * Format impact analysis
24
+ */
25
+ formatImpactAnalysis(analysis: ImpactAnalysis): string;
26
+ /**
27
+ * Format workspace validation report
28
+ */
29
+ formatValidationReport(report: WorkspaceValidationReport): string;
30
+ /**
31
+ * Format workspace statistics
32
+ */
33
+ formatWorkspaceStats(stats: WorkspaceStats): string;
34
+ /**
35
+ * Format simple message with optional styling
36
+ */
37
+ formatMessage(message: string, type?: 'success' | 'error' | 'warning' | 'info'): string;
38
+ /**
39
+ * Format outdated dependencies as table
40
+ */
41
+ private formatOutdatedTable;
42
+ /**
43
+ * Format outdated dependencies minimally (npm-check-updates style)
44
+ */
45
+ private formatOutdatedMinimal;
46
+ /**
47
+ * Format update result as table
48
+ */
49
+ private formatUpdateTable;
50
+ /**
51
+ * Format update result minimally (npm-check-updates style)
52
+ */
53
+ private formatUpdateMinimal;
54
+ /**
55
+ * Format impact analysis as table
56
+ */
57
+ private formatImpactTable;
58
+ /**
59
+ * Format impact analysis minimally
60
+ */
61
+ private formatImpactMinimal;
62
+ /**
63
+ * Format validation report as table
64
+ */
65
+ private formatValidationTable;
66
+ /**
67
+ * Format validation report minimally
68
+ */
69
+ private formatValidationMinimal;
70
+ /**
71
+ * Format workspace statistics as table
72
+ */
73
+ private formatStatsTable;
74
+ /**
75
+ * Format workspace statistics minimally
76
+ */
77
+ private formatStatsMinimal;
78
+ /**
79
+ * Apply color if color is enabled
80
+ */
81
+ private colorize;
82
+ /**
83
+ * Colorize table headers
84
+ */
85
+ private colorizeHeaders;
86
+ /**
87
+ * Get color for update type
88
+ */
89
+ private getUpdateTypeColor;
90
+ /**
91
+ * Get color for risk level
92
+ */
93
+ private getRiskColor;
94
+ /**
95
+ * Colorize version differences between current and latest
96
+ */
97
+ private colorizeVersionDiff;
98
+ }
99
+ //# sourceMappingURL=OutputFormatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OutputFormatter.d.ts","sourceRoot":"","sources":["../../../src/cli/formatters/OutputFormatter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,cAAc,EACd,cAAc,EACd,YAAY,EACb,MAAM,oDAAoD,CAAC;AAC5D,OAAO,EACL,cAAc,EACd,yBAAyB,EAC1B,MAAM,gDAAgD,CAAC;AAMxD,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAMjE,qBAAa,eAAe;IAExB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBADR,MAAM,GAAE,YAAsB,EAC9B,QAAQ,GAAE,OAAc;IAG3C;;OAEG;IACH,oBAAoB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM;IAcpD;;OAEG;IACH,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM;IAchD;;OAEG;IACH,oBAAoB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM;IActD;;OAEG;IACH,sBAAsB,CAAC,MAAM,EAAE,yBAAyB,GAAG,MAAM;IAcjE;;OAEG;IACH,oBAAoB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM;IAcnD;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAe,GAAG,MAAM;IAkB/F;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAsD3B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAwD7B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAsEzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA+C3B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA4EzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAQ3B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAgD7B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAQ/B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAgCxB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAQ1B;;OAEG;IACH,OAAO,CAAC,QAAQ;IAIhB;;OAEG;IACH,OAAO,CAAC,eAAe;IAIvB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAa1B;;OAEG;IACH,OAAO,CAAC,YAAY;IAapB;;OAEG;IACH,OAAO,CAAC,mBAAmB;CA6E5B"}
@@ -0,0 +1,551 @@
1
+ /**
2
+ * Output Formatter
3
+ *
4
+ * Provides formatted output for CLI commands in various formats.
5
+ * Supports table, JSON, YAML, and minimal output formats.
6
+ */
7
+ import Table from 'cli-table3';
8
+ import YAML from 'yaml';
9
+ import chalk from 'chalk';
10
+ // Build ANSI escape regex without literal control characters
11
+ const ANSI_ESCAPE = String.fromCharCode(27);
12
+ const ansiRegex = new RegExp(`${ANSI_ESCAPE}\\[[0-9;]*m`, 'g');
13
+ export class OutputFormatter {
14
+ format;
15
+ useColor;
16
+ constructor(format = 'table', useColor = true) {
17
+ this.format = format;
18
+ this.useColor = useColor;
19
+ }
20
+ /**
21
+ * Format outdated dependencies report
22
+ */
23
+ formatOutdatedReport(report) {
24
+ switch (this.format) {
25
+ case 'json':
26
+ return JSON.stringify(report, null, 2);
27
+ case 'yaml':
28
+ return YAML.stringify(report);
29
+ case 'minimal':
30
+ return this.formatOutdatedMinimal(report);
31
+ case 'table':
32
+ default:
33
+ return this.formatOutdatedTable(report);
34
+ }
35
+ }
36
+ /**
37
+ * Format update result
38
+ */
39
+ formatUpdateResult(result) {
40
+ switch (this.format) {
41
+ case 'json':
42
+ return JSON.stringify(result, null, 2);
43
+ case 'yaml':
44
+ return YAML.stringify(result);
45
+ case 'minimal':
46
+ return this.formatUpdateMinimal(result);
47
+ case 'table':
48
+ default:
49
+ return this.formatUpdateTable(result);
50
+ }
51
+ }
52
+ /**
53
+ * Format impact analysis
54
+ */
55
+ formatImpactAnalysis(analysis) {
56
+ switch (this.format) {
57
+ case 'json':
58
+ return JSON.stringify(analysis, null, 2);
59
+ case 'yaml':
60
+ return YAML.stringify(analysis);
61
+ case 'minimal':
62
+ return this.formatImpactMinimal(analysis);
63
+ case 'table':
64
+ default:
65
+ return this.formatImpactTable(analysis);
66
+ }
67
+ }
68
+ /**
69
+ * Format workspace validation report
70
+ */
71
+ formatValidationReport(report) {
72
+ switch (this.format) {
73
+ case 'json':
74
+ return JSON.stringify(report, null, 2);
75
+ case 'yaml':
76
+ return YAML.stringify(report);
77
+ case 'minimal':
78
+ return this.formatValidationMinimal(report);
79
+ case 'table':
80
+ default:
81
+ return this.formatValidationTable(report);
82
+ }
83
+ }
84
+ /**
85
+ * Format workspace statistics
86
+ */
87
+ formatWorkspaceStats(stats) {
88
+ switch (this.format) {
89
+ case 'json':
90
+ return JSON.stringify(stats, null, 2);
91
+ case 'yaml':
92
+ return YAML.stringify(stats);
93
+ case 'minimal':
94
+ return this.formatStatsMinimal(stats);
95
+ case 'table':
96
+ default:
97
+ return this.formatStatsTable(stats);
98
+ }
99
+ }
100
+ /**
101
+ * Format simple message with optional styling
102
+ */
103
+ formatMessage(message, type = 'info') {
104
+ if (!this.useColor) {
105
+ return message;
106
+ }
107
+ switch (type) {
108
+ case 'success':
109
+ return chalk.green(message);
110
+ case 'error':
111
+ return chalk.red(message);
112
+ case 'warning':
113
+ return chalk.yellow(message);
114
+ case 'info':
115
+ default:
116
+ return chalk.blue(message);
117
+ }
118
+ }
119
+ /**
120
+ * Format outdated dependencies as table
121
+ */
122
+ formatOutdatedTable(report) {
123
+ const lines = [];
124
+ // Header
125
+ lines.push(this.colorize(chalk.bold, `\n📦 Workspace: ${report.workspace.name}`));
126
+ lines.push(this.colorize(chalk.gray, `Path: ${report.workspace.path}`));
127
+ if (!report.hasUpdates) {
128
+ lines.push(this.colorize(chalk.green, '\n✅ All catalog dependencies are up to date!'));
129
+ return lines.join('\n');
130
+ }
131
+ lines.push(this.colorize(chalk.yellow, `\n🔄 Found ${report.totalOutdated} outdated dependencies\n`));
132
+ for (const catalogInfo of report.catalogs) {
133
+ if (catalogInfo.outdatedCount === 0)
134
+ continue;
135
+ lines.push(this.colorize(chalk.bold, `📋 Catalog: ${catalogInfo.catalogName}`));
136
+ const table = new Table({
137
+ head: this.colorizeHeaders(['Package', 'Current', 'Latest', 'Type', 'Packages']),
138
+ style: { head: [], border: [] },
139
+ colWidths: [25, 15, 15, 8, 20],
140
+ });
141
+ for (const dep of catalogInfo.outdatedDependencies) {
142
+ const typeColor = this.getUpdateTypeColor(dep.updateType);
143
+ const securityIcon = dep.isSecurityUpdate ? '🔒 ' : '';
144
+ // Colorize version differences
145
+ const { currentColored, latestColored } = this.colorizeVersionDiff(dep.currentVersion, dep.latestVersion, dep.updateType);
146
+ table.push([
147
+ `${securityIcon}${dep.packageName}`,
148
+ currentColored,
149
+ latestColored,
150
+ this.colorize(typeColor, dep.updateType),
151
+ `${dep.affectedPackages.length} package(s)`,
152
+ ]);
153
+ }
154
+ lines.push(table.toString());
155
+ lines.push('');
156
+ }
157
+ return lines.join('\n');
158
+ }
159
+ /**
160
+ * Format outdated dependencies minimally (npm-check-updates style)
161
+ */
162
+ formatOutdatedMinimal(report) {
163
+ if (!report.hasUpdates) {
164
+ return 'All dependencies up to date';
165
+ }
166
+ // Collect all dependencies first to calculate max package name width
167
+ const allDeps = [];
168
+ for (const catalogInfo of report.catalogs) {
169
+ for (const dep of catalogInfo.outdatedDependencies) {
170
+ const securityIcon = dep.isSecurityUpdate ? '🔒 ' : '';
171
+ const { currentColored, latestColored } = this.colorizeVersionDiff(dep.currentVersion, dep.latestVersion, dep.updateType);
172
+ allDeps.push({
173
+ securityIcon,
174
+ packageName: dep.packageName,
175
+ currentColored,
176
+ latestColored,
177
+ });
178
+ }
179
+ }
180
+ // Calculate max widths for alignment
181
+ const maxNameWidth = Math.max(...allDeps.map((dep) => (dep.securityIcon + dep.packageName).length));
182
+ // Calculate max version widths (need to strip color codes for accurate width calculation)
183
+ const stripAnsi = (str) => str.replace(ansiRegex, '');
184
+ const maxCurrentWidth = Math.max(...allDeps.map((dep) => stripAnsi(dep.currentColored).length));
185
+ // Format lines with proper alignment
186
+ const lines = [];
187
+ for (const dep of allDeps) {
188
+ const nameWithIcon = dep.securityIcon + dep.packageName;
189
+ const paddedName = nameWithIcon.padEnd(maxNameWidth);
190
+ // For current version alignment, we need to pad the visible text, not the colored version
191
+ const currentVisible = stripAnsi(dep.currentColored);
192
+ const currentPadding = maxCurrentWidth - currentVisible.length;
193
+ const paddedCurrent = dep.currentColored + ' '.repeat(currentPadding);
194
+ lines.push(`${paddedName} ${paddedCurrent} → ${dep.latestColored}`);
195
+ }
196
+ return lines.join('\n');
197
+ }
198
+ /**
199
+ * Format update result as table
200
+ */
201
+ formatUpdateTable(result) {
202
+ const lines = [];
203
+ // Header
204
+ lines.push(this.colorize(chalk.bold, `\n📦 Workspace: ${result.workspace.name}`));
205
+ if (result.success) {
206
+ lines.push(this.colorize(chalk.green, '✅ Update completed successfully!'));
207
+ }
208
+ else {
209
+ lines.push(this.colorize(chalk.red, '❌ Update completed with errors'));
210
+ }
211
+ lines.push('');
212
+ // Updated dependencies
213
+ if (result.updatedDependencies.length > 0) {
214
+ lines.push(this.colorize(chalk.green, `🎉 Updated ${result.totalUpdated} dependencies:`));
215
+ const table = new Table({
216
+ head: this.colorizeHeaders(['Catalog', 'Package', 'From', 'To', 'Type']),
217
+ style: { head: [], border: [] },
218
+ colWidths: [15, 25, 15, 15, 8],
219
+ });
220
+ for (const dep of result.updatedDependencies) {
221
+ const typeColor = this.getUpdateTypeColor(dep.updateType);
222
+ // Colorize version differences
223
+ const { currentColored, latestColored } = this.colorizeVersionDiff(dep.fromVersion, dep.toVersion, dep.updateType);
224
+ table.push([
225
+ dep.catalogName,
226
+ dep.packageName,
227
+ currentColored,
228
+ latestColored,
229
+ this.colorize(typeColor, dep.updateType),
230
+ ]);
231
+ }
232
+ lines.push(table.toString());
233
+ lines.push('');
234
+ }
235
+ // Skipped dependencies
236
+ if (result.skippedDependencies.length > 0) {
237
+ lines.push(this.colorize(chalk.yellow, `⚠️ Skipped ${result.totalSkipped} dependencies:`));
238
+ for (const dep of result.skippedDependencies) {
239
+ lines.push(` ${dep.catalogName}:${dep.packageName} - ${dep.reason}`);
240
+ }
241
+ lines.push('');
242
+ }
243
+ // Errors
244
+ if (result.errors.length > 0) {
245
+ lines.push(this.colorize(chalk.red, `❌ ${result.totalErrors} errors occurred:`));
246
+ for (const error of result.errors) {
247
+ const prefix = error.fatal ? '💥' : '⚠️ ';
248
+ lines.push(` ${prefix} ${error.catalogName}:${error.packageName} - ${error.error}`);
249
+ }
250
+ }
251
+ return lines.join('\n');
252
+ }
253
+ /**
254
+ * Format update result minimally (npm-check-updates style)
255
+ */
256
+ formatUpdateMinimal(result) {
257
+ const lines = [];
258
+ if (result.success) {
259
+ lines.push(`Updated ${result.totalUpdated} dependencies`);
260
+ }
261
+ else {
262
+ lines.push(`Update failed with ${result.totalErrors} errors`);
263
+ }
264
+ if (result.updatedDependencies.length > 0) {
265
+ // Collect version info for alignment calculation
266
+ const depsWithVersions = result.updatedDependencies.map((dep) => {
267
+ const { currentColored, latestColored } = this.colorizeVersionDiff(dep.fromVersion, dep.toVersion, dep.updateType);
268
+ return {
269
+ packageName: dep.packageName,
270
+ currentColored,
271
+ latestColored,
272
+ };
273
+ });
274
+ // Calculate max widths for alignment
275
+ const maxNameWidth = Math.max(...depsWithVersions.map((dep) => dep.packageName.length));
276
+ const stripAnsi = (str) => str.replace(ansiRegex, '');
277
+ const maxCurrentWidth = Math.max(...depsWithVersions.map((dep) => stripAnsi(dep.currentColored).length));
278
+ for (const dep of depsWithVersions) {
279
+ const paddedName = dep.packageName.padEnd(maxNameWidth);
280
+ // Pad current version for alignment
281
+ const currentVisible = stripAnsi(dep.currentColored);
282
+ const currentPadding = maxCurrentWidth - currentVisible.length;
283
+ const paddedCurrent = dep.currentColored + ' '.repeat(currentPadding);
284
+ lines.push(`${paddedName} ${paddedCurrent} → ${dep.latestColored}`);
285
+ }
286
+ }
287
+ return lines.join('\n');
288
+ }
289
+ /**
290
+ * Format impact analysis as table
291
+ */
292
+ formatImpactTable(analysis) {
293
+ const lines = [];
294
+ // Header
295
+ lines.push(this.colorize(chalk.bold, `\n🔍 Impact Analysis: ${analysis.packageName}`));
296
+ lines.push(this.colorize(chalk.gray, `Catalog: ${analysis.catalogName}`));
297
+ lines.push(this.colorize(chalk.gray, `Update: ${analysis.currentVersion} → ${analysis.proposedVersion}`));
298
+ lines.push(this.colorize(chalk.gray, `Type: ${analysis.updateType}`));
299
+ // Risk level
300
+ const riskColor = this.getRiskColor(analysis.riskLevel);
301
+ lines.push(this.colorize(riskColor, `Risk Level: ${analysis.riskLevel.toUpperCase()}`));
302
+ lines.push('');
303
+ // Affected packages
304
+ if (analysis.affectedPackages.length > 0) {
305
+ lines.push(this.colorize(chalk.bold, '📦 Affected Packages:'));
306
+ const table = new Table({
307
+ head: this.colorizeHeaders(['Package', 'Path', 'Dependency Type', 'Risk']),
308
+ style: { head: [], border: [] },
309
+ colWidths: [20, 30, 15, 10],
310
+ });
311
+ for (const pkg of analysis.affectedPackages) {
312
+ const riskColor = this.getRiskColor(pkg.compatibilityRisk);
313
+ table.push([
314
+ pkg.packageName,
315
+ pkg.packagePath,
316
+ pkg.dependencyType,
317
+ this.colorize(riskColor, pkg.compatibilityRisk),
318
+ ]);
319
+ }
320
+ lines.push(table.toString());
321
+ lines.push('');
322
+ }
323
+ // Security impact
324
+ if (analysis.securityImpact.hasVulnerabilities) {
325
+ lines.push(this.colorize(chalk.bold, '🔒 Security Impact:'));
326
+ if (analysis.securityImpact.fixedVulnerabilities > 0) {
327
+ lines.push(this.colorize(chalk.green, ` ✅ Fixes ${analysis.securityImpact.fixedVulnerabilities} vulnerabilities`));
328
+ }
329
+ if (analysis.securityImpact.newVulnerabilities > 0) {
330
+ lines.push(this.colorize(chalk.red, ` ⚠️ Introduces ${analysis.securityImpact.newVulnerabilities} vulnerabilities`));
331
+ }
332
+ lines.push('');
333
+ }
334
+ // Recommendations
335
+ if (analysis.recommendations.length > 0) {
336
+ lines.push(this.colorize(chalk.bold, '💡 Recommendations:'));
337
+ for (const rec of analysis.recommendations) {
338
+ lines.push(` ${rec}`);
339
+ }
340
+ }
341
+ return lines.join('\n');
342
+ }
343
+ /**
344
+ * Format impact analysis minimally
345
+ */
346
+ formatImpactMinimal(analysis) {
347
+ return [
348
+ `${analysis.packageName}: ${analysis.currentVersion} → ${analysis.proposedVersion}`,
349
+ `Risk: ${analysis.riskLevel}`,
350
+ `Affected: ${analysis.affectedPackages.length} packages`,
351
+ ].join('\n');
352
+ }
353
+ /**
354
+ * Format validation report as table
355
+ */
356
+ formatValidationTable(report) {
357
+ const lines = [];
358
+ // Header
359
+ const statusIcon = report.isValid ? '✅' : '❌';
360
+ const statusColor = report.isValid ? chalk.green : chalk.red;
361
+ lines.push(this.colorize(chalk.bold, `\n${statusIcon} Workspace Validation`));
362
+ lines.push(this.colorize(statusColor, `Status: ${report.isValid ? 'VALID' : 'INVALID'}`));
363
+ lines.push('');
364
+ // Workspace info
365
+ lines.push(this.colorize(chalk.bold, '📦 Workspace Information:'));
366
+ lines.push(` Path: ${report.workspace.path}`);
367
+ lines.push(` Name: ${report.workspace.name}`);
368
+ lines.push(` Packages: ${report.workspace.packageCount}`);
369
+ lines.push(` Catalogs: ${report.workspace.catalogCount}`);
370
+ lines.push('');
371
+ // Errors
372
+ if (report.errors.length > 0) {
373
+ lines.push(this.colorize(chalk.red, '❌ Errors:'));
374
+ for (const error of report.errors) {
375
+ lines.push(` • ${error}`);
376
+ }
377
+ lines.push('');
378
+ }
379
+ // Warnings
380
+ if (report.warnings.length > 0) {
381
+ lines.push(this.colorize(chalk.yellow, '⚠️ Warnings:'));
382
+ for (const warning of report.warnings) {
383
+ lines.push(` • ${warning}`);
384
+ }
385
+ lines.push('');
386
+ }
387
+ // Recommendations
388
+ if (report.recommendations.length > 0) {
389
+ lines.push(this.colorize(chalk.blue, '💡 Recommendations:'));
390
+ for (const rec of report.recommendations) {
391
+ lines.push(` • ${rec}`);
392
+ }
393
+ }
394
+ return lines.join('\n');
395
+ }
396
+ /**
397
+ * Format validation report minimally
398
+ */
399
+ formatValidationMinimal(report) {
400
+ const status = report.isValid ? 'VALID' : 'INVALID';
401
+ const errors = report.errors.length;
402
+ const warnings = report.warnings.length;
403
+ return `${status} (${errors} errors, ${warnings} warnings)`;
404
+ }
405
+ /**
406
+ * Format workspace statistics as table
407
+ */
408
+ formatStatsTable(stats) {
409
+ const lines = [];
410
+ lines.push(this.colorize(chalk.bold, `\n📊 Workspace Statistics`));
411
+ lines.push(this.colorize(chalk.gray, `Workspace: ${stats.workspace.name}`));
412
+ lines.push('');
413
+ const table = new Table({
414
+ head: this.colorizeHeaders(['Metric', 'Count']),
415
+ style: { head: [], border: [] },
416
+ colWidths: [30, 10],
417
+ });
418
+ table.push(['Total Packages', stats.packages.total.toString()]);
419
+ table.push(['Packages with Catalog Refs', stats.packages.withCatalogReferences.toString()]);
420
+ table.push(['Total Catalogs', stats.catalogs.total.toString()]);
421
+ table.push(['Catalog Entries', stats.catalogs.totalEntries.toString()]);
422
+ table.push(['Total Dependencies', stats.dependencies.total.toString()]);
423
+ table.push(['Catalog References', stats.dependencies.catalogReferences.toString()]);
424
+ table.push(['Dependencies', stats.dependencies.byType.dependencies.toString()]);
425
+ table.push(['Dev Dependencies', stats.dependencies.byType.devDependencies.toString()]);
426
+ table.push(['Peer Dependencies', stats.dependencies.byType.peerDependencies.toString()]);
427
+ table.push([
428
+ 'Optional Dependencies',
429
+ stats.dependencies.byType.optionalDependencies.toString(),
430
+ ]);
431
+ lines.push(table.toString());
432
+ return lines.join('\n');
433
+ }
434
+ /**
435
+ * Format workspace statistics minimally
436
+ */
437
+ formatStatsMinimal(stats) {
438
+ return [
439
+ `Packages: ${stats.packages.total}`,
440
+ `Catalogs: ${stats.catalogs.total}`,
441
+ `Dependencies: ${stats.dependencies.total}`,
442
+ ].join(', ');
443
+ }
444
+ /**
445
+ * Apply color if color is enabled
446
+ */
447
+ colorize(colorFn, text) {
448
+ return this.useColor ? colorFn(text) : text;
449
+ }
450
+ /**
451
+ * Colorize table headers
452
+ */
453
+ colorizeHeaders(headers) {
454
+ return this.useColor ? headers.map((h) => chalk.bold.cyan(h)) : headers;
455
+ }
456
+ /**
457
+ * Get color for update type
458
+ */
459
+ getUpdateTypeColor(updateType) {
460
+ switch (updateType) {
461
+ case 'major':
462
+ return chalk.cyan;
463
+ case 'minor':
464
+ return chalk.green;
465
+ case 'patch':
466
+ return chalk.cyan;
467
+ default:
468
+ return chalk.gray;
469
+ }
470
+ }
471
+ /**
472
+ * Get color for risk level
473
+ */
474
+ getRiskColor(riskLevel) {
475
+ switch (riskLevel) {
476
+ case 'high':
477
+ return chalk.red;
478
+ case 'medium':
479
+ return chalk.yellow;
480
+ case 'low':
481
+ return chalk.green;
482
+ default:
483
+ return chalk.gray;
484
+ }
485
+ }
486
+ /**
487
+ * Colorize version differences between current and latest
488
+ */
489
+ colorizeVersionDiff(current, latest, updateType) {
490
+ if (!this.useColor) {
491
+ return { currentColored: current, latestColored: latest };
492
+ }
493
+ // Parse version numbers to identify different parts
494
+ const parseVersion = (version) => {
495
+ // Remove leading ^ or ~ or other prefix characters
496
+ const cleanVersion = version.replace(/^[\^~>=<]+/, '');
497
+ const parts = cleanVersion.split('.');
498
+ return {
499
+ major: parts[0] || '0',
500
+ minor: parts[1] || '0',
501
+ patch: parts[2] || '0',
502
+ extra: parts.slice(3).join('.'),
503
+ prefix: version.substring(0, version.length - cleanVersion.length),
504
+ };
505
+ };
506
+ const currentParts = parseVersion(current);
507
+ const latestParts = parseVersion(latest);
508
+ // Determine color based on update type for highlighting differences
509
+ const diffColor = this.getUpdateTypeColor(updateType);
510
+ // Build colored version strings by comparing each part
511
+ const colorCurrentPart = (part, latestPart, isChanged) => {
512
+ if (isChanged && part !== latestPart) {
513
+ return chalk.dim.white(part); // Dim white for old version part
514
+ }
515
+ return chalk.white(part); // Unchanged parts in white
516
+ };
517
+ const colorLatestPart = (part, currentPart, isChanged) => {
518
+ if (isChanged && part !== currentPart) {
519
+ return diffColor(part); // Highlight the new version part with update type color
520
+ }
521
+ return chalk.white(part); // Unchanged parts in white
522
+ };
523
+ // Check which parts are different
524
+ const majorChanged = currentParts.major !== latestParts.major;
525
+ const minorChanged = currentParts.minor !== latestParts.minor;
526
+ const patchChanged = currentParts.patch !== latestParts.patch;
527
+ const extraChanged = currentParts.extra !== latestParts.extra;
528
+ // Build colored current version
529
+ let currentColored = currentParts.prefix;
530
+ currentColored += colorCurrentPart(currentParts.major, latestParts.major, majorChanged);
531
+ currentColored += '.';
532
+ currentColored += colorCurrentPart(currentParts.minor, latestParts.minor, minorChanged);
533
+ currentColored += '.';
534
+ currentColored += colorCurrentPart(currentParts.patch, latestParts.patch, patchChanged);
535
+ if (currentParts.extra) {
536
+ currentColored += '.' + colorCurrentPart(currentParts.extra, latestParts.extra, extraChanged);
537
+ }
538
+ // Build colored latest version
539
+ let latestColored = latestParts.prefix;
540
+ latestColored += colorLatestPart(latestParts.major, currentParts.major, majorChanged);
541
+ latestColored += '.';
542
+ latestColored += colorLatestPart(latestParts.minor, currentParts.minor, minorChanged);
543
+ latestColored += '.';
544
+ latestColored += colorLatestPart(latestParts.patch, currentParts.patch, patchChanged);
545
+ if (latestParts.extra) {
546
+ latestColored += '.' + colorLatestPart(latestParts.extra, currentParts.extra, extraChanged);
547
+ }
548
+ return { currentColored, latestColored };
549
+ }
550
+ }
551
+ //# sourceMappingURL=OutputFormatter.js.map