depfixer 1.0.0 → 1.1.1

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 (85) hide show
  1. package/dist/commands/audit.d.ts +19 -0
  2. package/dist/commands/audit.d.ts.map +1 -0
  3. package/dist/commands/audit.js +170 -0
  4. package/dist/commands/audit.js.map +1 -0
  5. package/dist/commands/fix.d.ts +10 -3
  6. package/dist/commands/fix.d.ts.map +1 -1
  7. package/dist/commands/fix.js +407 -41
  8. package/dist/commands/fix.js.map +1 -1
  9. package/dist/commands/graph.d.ts +1 -1
  10. package/dist/commands/graph.d.ts.map +1 -1
  11. package/dist/commands/graph.js +17 -12
  12. package/dist/commands/graph.js.map +1 -1
  13. package/dist/commands/login.d.ts.map +1 -1
  14. package/dist/commands/login.js +120 -19
  15. package/dist/commands/login.js.map +1 -1
  16. package/dist/commands/logout.d.ts.map +1 -1
  17. package/dist/commands/logout.js +6 -0
  18. package/dist/commands/logout.js.map +1 -1
  19. package/dist/commands/migrate.d.ts +22 -0
  20. package/dist/commands/migrate.d.ts.map +1 -0
  21. package/dist/commands/migrate.js +874 -0
  22. package/dist/commands/migrate.js.map +1 -0
  23. package/dist/commands/smart.d.ts +23 -0
  24. package/dist/commands/smart.d.ts.map +1 -0
  25. package/dist/commands/smart.js +1024 -0
  26. package/dist/commands/smart.js.map +1 -0
  27. package/dist/commands/whoami.d.ts +14 -0
  28. package/dist/commands/whoami.d.ts.map +1 -0
  29. package/dist/commands/whoami.js +65 -0
  30. package/dist/commands/whoami.js.map +1 -0
  31. package/dist/index.js +165 -40
  32. package/dist/index.js.map +1 -1
  33. package/dist/services/analytics.d.ts +108 -0
  34. package/dist/services/analytics.d.ts.map +1 -0
  35. package/dist/services/analytics.js +305 -0
  36. package/dist/services/analytics.js.map +1 -0
  37. package/dist/services/api-client.d.ts +159 -0
  38. package/dist/services/api-client.d.ts.map +1 -1
  39. package/dist/services/api-client.js +192 -10
  40. package/dist/services/api-client.js.map +1 -1
  41. package/dist/services/auth-manager.d.ts +14 -0
  42. package/dist/services/auth-manager.d.ts.map +1 -1
  43. package/dist/services/auth-manager.js +30 -0
  44. package/dist/services/auth-manager.js.map +1 -1
  45. package/dist/services/cache-manager.d.ts +62 -22
  46. package/dist/services/cache-manager.d.ts.map +1 -1
  47. package/dist/services/cache-manager.js +116 -30
  48. package/dist/services/cache-manager.js.map +1 -1
  49. package/dist/services/device-id.d.ts +20 -0
  50. package/dist/services/device-id.d.ts.map +1 -0
  51. package/dist/services/device-id.js +70 -0
  52. package/dist/services/device-id.js.map +1 -0
  53. package/dist/services/package-json.d.ts +44 -5
  54. package/dist/services/package-json.d.ts.map +1 -1
  55. package/dist/services/package-json.js +273 -20
  56. package/dist/services/package-json.js.map +1 -1
  57. package/dist/services/payment-flow.d.ts +108 -0
  58. package/dist/services/payment-flow.d.ts.map +1 -0
  59. package/dist/services/payment-flow.js +476 -0
  60. package/dist/services/payment-flow.js.map +1 -0
  61. package/dist/services/session-manager.d.ts +92 -0
  62. package/dist/services/session-manager.d.ts.map +1 -0
  63. package/dist/services/session-manager.js +218 -0
  64. package/dist/services/session-manager.js.map +1 -0
  65. package/dist/utils/design-system.d.ts +90 -0
  66. package/dist/utils/design-system.d.ts.map +1 -0
  67. package/dist/utils/design-system.js +338 -0
  68. package/dist/utils/design-system.js.map +1 -0
  69. package/dist/utils/output.d.ts +48 -1
  70. package/dist/utils/output.d.ts.map +1 -1
  71. package/dist/utils/output.js +180 -17
  72. package/dist/utils/output.js.map +1 -1
  73. package/dist/utils/print.d.ts +116 -0
  74. package/dist/utils/print.d.ts.map +1 -0
  75. package/dist/utils/print.js +190 -0
  76. package/dist/utils/print.js.map +1 -0
  77. package/package.json +13 -2
  78. package/dist/commands/analyze.d.ts +0 -18
  79. package/dist/commands/analyze.d.ts.map +0 -1
  80. package/dist/commands/analyze.js +0 -404
  81. package/dist/commands/analyze.js.map +0 -1
  82. package/dist/services/gitignore.d.ts +0 -19
  83. package/dist/services/gitignore.d.ts.map +0 -1
  84. package/dist/services/gitignore.js +0 -64
  85. package/dist/services/gitignore.js.map +0 -1
@@ -0,0 +1,218 @@
1
+ import * as fs from 'fs/promises';
2
+ import * as path from 'path';
3
+ import * as crypto from 'crypto';
4
+ import * as os from 'os';
5
+ /**
6
+ * Session Manager
7
+ * Manages CLI session state for the new payment flow.
8
+ *
9
+ * Key features:
10
+ * - Stores session in ~/.depfixer/projects/{projectHash}/session.json
11
+ * - Tracks analysis ID, cost, payment status
12
+ * - Verifies package.json hash for integrity
13
+ * - Supports resume of unpaid analyses
14
+ * - Centralized storage (no .depfixer in project directory)
15
+ */
16
+ export class SessionManager {
17
+ cacheDir;
18
+ sessionFile;
19
+ projectDir;
20
+ constructor(projectDir = process.cwd()) {
21
+ this.projectDir = projectDir;
22
+ // Use centralized ~/.depfixer/projects/{hash}/ directory
23
+ const projectHash = this.getProjectHash(projectDir);
24
+ this.cacheDir = path.join(os.homedir(), '.depfixer', 'projects', projectHash);
25
+ this.sessionFile = path.join(this.cacheDir, 'session.json');
26
+ }
27
+ /**
28
+ * Generate a short hash from project path for unique folder name
29
+ */
30
+ getProjectHash(projectDir) {
31
+ // Normalize path and create hash
32
+ const normalizedPath = path.resolve(projectDir).toLowerCase();
33
+ return crypto.createHash('sha256').update(normalizedPath).digest('hex').substring(0, 12);
34
+ }
35
+ /**
36
+ * Calculate SHA256 hash of content
37
+ */
38
+ calculateHash(content) {
39
+ return crypto.createHash('sha256').update(content).digest('hex');
40
+ }
41
+ /**
42
+ * Save a new session after analysis
43
+ */
44
+ async saveSession(data) {
45
+ await this.ensureCacheDir();
46
+ const session = {
47
+ lastSession: {
48
+ ...data,
49
+ timestamp: Date.now(),
50
+ projectPath: this.projectDir, // Store project path for reference
51
+ },
52
+ };
53
+ await fs.writeFile(this.sessionFile, JSON.stringify(session, null, 2), 'utf-8');
54
+ }
55
+ /**
56
+ * Load the current session
57
+ */
58
+ async loadSession() {
59
+ try {
60
+ const content = await fs.readFile(this.sessionFile, 'utf-8');
61
+ const session = JSON.parse(content);
62
+ return session.lastSession || null;
63
+ }
64
+ catch (error) {
65
+ if (error.code === 'ENOENT') {
66
+ return null;
67
+ }
68
+ throw error;
69
+ }
70
+ }
71
+ /**
72
+ * Check if a session exists
73
+ */
74
+ async hasSession() {
75
+ try {
76
+ await fs.access(this.sessionFile);
77
+ return true;
78
+ }
79
+ catch {
80
+ return false;
81
+ }
82
+ }
83
+ /**
84
+ * Update session status (e.g., mark as PAID)
85
+ */
86
+ async updateStatus(status) {
87
+ const session = await this.loadSession();
88
+ if (!session) {
89
+ throw new Error('No session to update');
90
+ }
91
+ session.status = status;
92
+ const sessionFile = { lastSession: session };
93
+ await fs.writeFile(this.sessionFile, JSON.stringify(sessionFile, null, 2), 'utf-8');
94
+ }
95
+ /**
96
+ * Verify that package.json hasn't changed since analysis
97
+ */
98
+ async verifyHash(currentContent) {
99
+ const session = await this.loadSession();
100
+ if (!session) {
101
+ return false;
102
+ }
103
+ const currentHash = this.calculateHash(currentContent);
104
+ return currentHash === session.originalFileHash;
105
+ }
106
+ /**
107
+ * Get human-readable time since analysis
108
+ */
109
+ getTimeSinceAnalysis(session) {
110
+ const diffMs = Date.now() - session.timestamp;
111
+ const diffMins = Math.floor(diffMs / 60000);
112
+ const diffHours = Math.floor(diffMins / 60);
113
+ const diffDays = Math.floor(diffHours / 24);
114
+ if (diffDays > 0) {
115
+ return `${diffDays} day${diffDays > 1 ? 's' : ''} ago`;
116
+ }
117
+ else if (diffHours > 0) {
118
+ return `${diffHours} hour${diffHours > 1 ? 's' : ''} ago`;
119
+ }
120
+ else if (diffMins > 0) {
121
+ return `${diffMins} minute${diffMins > 1 ? 's' : ''} ago`;
122
+ }
123
+ else {
124
+ return 'just now';
125
+ }
126
+ }
127
+ /**
128
+ * Get session description for display
129
+ */
130
+ getSessionDescription(session) {
131
+ const timeAgo = this.getTimeSinceAnalysis(session);
132
+ switch (session.intent) {
133
+ case 'MIGRATE':
134
+ return `${timeAgo} (MIGRATE → ${session.args?.target || 'unknown'})`;
135
+ case 'AUDIT':
136
+ return `${timeAgo} (AUDIT)`;
137
+ case 'ANALYZE':
138
+ return `${timeAgo} (ANALYZE)`;
139
+ default:
140
+ return timeAgo;
141
+ }
142
+ }
143
+ /**
144
+ * Clear the session (after successful fix or on user request)
145
+ */
146
+ async clearSession() {
147
+ try {
148
+ await fs.unlink(this.sessionFile);
149
+ }
150
+ catch (error) {
151
+ if (error.code !== 'ENOENT') {
152
+ throw error;
153
+ }
154
+ }
155
+ }
156
+ /**
157
+ * Get the session file path
158
+ */
159
+ getSessionFilePath() {
160
+ return this.sessionFile;
161
+ }
162
+ /**
163
+ * Ensure cache directory exists
164
+ */
165
+ async ensureCacheDir() {
166
+ try {
167
+ await fs.mkdir(this.cacheDir, { recursive: true });
168
+ }
169
+ catch (error) {
170
+ if (error.code !== 'EEXIST') {
171
+ throw error;
172
+ }
173
+ }
174
+ }
175
+ /**
176
+ * Migrate from old cache format (analysis-history.json) if present
177
+ * This provides backward compatibility with existing installations
178
+ */
179
+ async migrateFromOldCache() {
180
+ const oldCacheFile = path.join(this.cacheDir, 'analysis-history.json');
181
+ try {
182
+ const content = await fs.readFile(oldCacheFile, 'utf-8');
183
+ const oldCache = JSON.parse(content);
184
+ // Get the most recent entry from the old history
185
+ const history = oldCache.history || [];
186
+ if (history.length === 0) {
187
+ return false;
188
+ }
189
+ const latest = history[history.length - 1];
190
+ // Convert to new format
191
+ const newSession = {
192
+ analysisId: latest.analysisId,
193
+ timestamp: latest.timestamp,
194
+ intent: latest.mode === 'migrate' ? 'MIGRATE' : 'ANALYZE',
195
+ args: latest.targetVersion ? { target: latest.targetVersion } : undefined,
196
+ originalFileHash: latest.packageJsonHash,
197
+ cost: 0, // Unknown from old format
198
+ status: 'UNPAID', // Assume unpaid
199
+ projectName: latest.projectName || 'unknown',
200
+ packageCount: 0, // Unknown from old format
201
+ tierName: 'Unknown',
202
+ };
203
+ await this.saveSession(newSession);
204
+ // Optionally: rename old file to .bak
205
+ await fs.rename(oldCacheFile, oldCacheFile + '.migrated');
206
+ return true;
207
+ }
208
+ catch (error) {
209
+ if (error.code === 'ENOENT') {
210
+ return false;
211
+ }
212
+ // Log but don't fail on migration errors
213
+ console.error('Warning: Failed to migrate old cache:', error.message);
214
+ return false;
215
+ }
216
+ }
217
+ }
218
+ //# sourceMappingURL=session-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../../src/services/session-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * DepFixer CLI Design System
3
+ *
4
+ * A consistent visual language for the premium "hacker-chic" CLI experience.
5
+ */
6
+ import chalk from 'chalk';
7
+ export declare const colors: {
8
+ brand: import("chalk").ChalkInstance;
9
+ brandBold: import("chalk").ChalkInstance;
10
+ dim: import("chalk").ChalkInstance;
11
+ gray: import("chalk").ChalkInstance;
12
+ white: import("chalk").ChalkInstance;
13
+ whiteBold: import("chalk").ChalkInstance;
14
+ action: import("chalk").ChalkInstance;
15
+ actionBold: import("chalk").ChalkInstance;
16
+ success: import("chalk").ChalkInstance;
17
+ successBold: import("chalk").ChalkInstance;
18
+ danger: import("chalk").ChalkInstance;
19
+ dangerBold: import("chalk").ChalkInstance;
20
+ warning: import("chalk").ChalkInstance;
21
+ warningBold: import("chalk").ChalkInstance;
22
+ version: import("chalk").ChalkInstance;
23
+ versionOld: import("chalk").ChalkInstance;
24
+ major: import("chalk").ChalkInstance;
25
+ minor: import("chalk").ChalkInstance;
26
+ patch: import("chalk").ChalkInstance;
27
+ };
28
+ export declare function printCliHeader(mode?: 'analyze' | 'migrate'): void;
29
+ export declare function printSectionHeader(title: string, icon?: string): void;
30
+ export declare function renderHealthBar(score: number): string;
31
+ export declare function getHealthStatus(score: number): {
32
+ text: string;
33
+ color: typeof chalk;
34
+ };
35
+ export declare function printCostBox(options: {
36
+ cost: number;
37
+ tierName: string;
38
+ prompt?: string;
39
+ isMigration?: boolean;
40
+ hasActivePass?: boolean;
41
+ }): void;
42
+ export declare function printSuccessBox(options: {
43
+ updated: number;
44
+ removed: number;
45
+ backupPath: string;
46
+ enginesUpdated?: number;
47
+ }): void;
48
+ export declare function printProjectHeader(name: string, framework?: string, version?: string): void;
49
+ export declare function printMigrationPlanHeader(framework: string, fromVersion: string, toVersion: string): void;
50
+ export declare function printProjectionStats(options: {
51
+ currentHealth: number;
52
+ projectedHealth: number;
53
+ packageCount: number;
54
+ breakingChanges: number;
55
+ }): void;
56
+ export declare function printDiagnosis(issueCount: number): void;
57
+ export declare function printAccountInfo(options: {
58
+ name?: string;
59
+ email?: string;
60
+ credits: number;
61
+ }): void;
62
+ /**
63
+ * Print user details after login/register
64
+ * Shows name, email, and current credit balance
65
+ */
66
+ export declare function printUserDetails(options: {
67
+ name?: string;
68
+ email?: string;
69
+ credits: number;
70
+ hasActivePass?: boolean;
71
+ showHeader?: boolean;
72
+ }): void;
73
+ /**
74
+ * Print credit check info showing both needed and available credits
75
+ */
76
+ export declare function printCreditCheck(options: {
77
+ needed: number;
78
+ available: number;
79
+ hasActivePass?: boolean;
80
+ }): void;
81
+ export declare function printApplyingHeader(): void;
82
+ export declare function printAppliedChange(packageName: string, action: 'updated' | 'removed'): void;
83
+ export declare function printNotes(notes: string[]): void;
84
+ export declare function getSeverityBadge(severity: string): string;
85
+ export declare function getChangeTypeBadge(changeType: string): string;
86
+ /**
87
+ * Truncate text to max length with ellipsis
88
+ */
89
+ export declare function truncateReason(text: string, maxLength?: number): string;
90
+ //# sourceMappingURL=design-system.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"design-system.d.ts","sourceRoot":"","sources":["../../src/utils/design-system.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,338 @@
1
+ /**
2
+ * DepFixer CLI Design System
3
+ *
4
+ * A consistent visual language for the premium "hacker-chic" CLI experience.
5
+ */
6
+ import chalk from 'chalk';
7
+ import boxen from 'boxen';
8
+ // ============================================================================
9
+ // BRAND COLORS
10
+ // ============================================================================
11
+ export const colors = {
12
+ // Primary brand color (matches web logo)
13
+ brand: chalk.hex('#00D4FF'),
14
+ brandBold: chalk.bold.hex('#00D4FF'),
15
+ // Secondary
16
+ dim: chalk.dim,
17
+ gray: chalk.gray,
18
+ white: chalk.white,
19
+ whiteBold: chalk.bold.white,
20
+ // Actions
21
+ action: chalk.yellow,
22
+ actionBold: chalk.bold.yellow,
23
+ // Status
24
+ success: chalk.green,
25
+ successBold: chalk.bold.green,
26
+ danger: chalk.red,
27
+ dangerBold: chalk.bold.red,
28
+ warning: chalk.yellow,
29
+ warningBold: chalk.bold.yellow,
30
+ // Semantic
31
+ version: chalk.green,
32
+ versionOld: chalk.red,
33
+ major: chalk.red,
34
+ minor: chalk.yellow,
35
+ patch: chalk.blue,
36
+ };
37
+ // ============================================================================
38
+ // HEADER
39
+ // ============================================================================
40
+ // ASCII art logo - DepFixer text (medium size)
41
+ function getDepFixerLogo(tagline) {
42
+ const c = chalk.hex('#00D4FF'); // cyan brand color
43
+ return `
44
+ ${c('██████╗ ███████╗ ██████╗ ███████╗██╗██╗ ██╗███████╗██████╗')}
45
+ ${c('██╔══██╗ ██╔════╝ ██╔══██╗██╔════╝██║╚██╗██╔╝██╔════╝██╔══██╗')}
46
+ ${c('██║ ██║ █████╗ ██████╔╝█████╗ ██║ ╚███╔╝ █████╗ ██████╔╝')}
47
+ ${c('██║ ██║ ██╔══╝ ██╔═══╝ ██╔══╝ ██║ ██╔██╗ ██╔══╝ ██╔══██╗')}
48
+ ${c('██████╔╝ ███████╗ ██║ ██║ ██║██╔╝ ██╗███████╗██║ ██║')}
49
+ ${c('╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝')}
50
+ ${chalk.dim(' ' + tagline)}`;
51
+ }
52
+ export function printCliHeader(mode = 'analyze') {
53
+ const tagline = mode === 'migrate'
54
+ ? 'Upgrade Fearlessly. We Handle the Rest.'
55
+ : 'Dependency Hell? We\'ve Got the Cure.';
56
+ console.log(getDepFixerLogo(tagline));
57
+ console.log();
58
+ console.log(colors.brandBold('⚡ DepFixer CLI') + colors.gray(' v1.0.0'));
59
+ console.log(colors.gray('─'.repeat(50)));
60
+ }
61
+ export function printSectionHeader(title, icon = '') {
62
+ console.log();
63
+ console.log(colors.whiteBold(`${icon ? icon + ' ' : ''}${title}`));
64
+ console.log(colors.gray('─'.repeat(50)));
65
+ }
66
+ // ============================================================================
67
+ // HEALTH BAR
68
+ // ============================================================================
69
+ export function renderHealthBar(score) {
70
+ const filled = Math.round(score / 10);
71
+ const empty = 10 - filled;
72
+ let barColor;
73
+ if (score >= 70) {
74
+ barColor = chalk.green;
75
+ }
76
+ else if (score >= 40) {
77
+ barColor = chalk.yellow;
78
+ }
79
+ else {
80
+ barColor = chalk.red;
81
+ }
82
+ const bar = barColor('█'.repeat(filled)) + chalk.gray('░'.repeat(empty));
83
+ return `[${bar}]`;
84
+ }
85
+ export function getHealthStatus(score) {
86
+ // Thresholds aligned with renderHealthBar: green >= 70, yellow >= 40, red < 40
87
+ if (score >= 70)
88
+ return { text: 'HEALTHY', color: chalk.green };
89
+ if (score >= 40)
90
+ return { text: 'WARNING', color: chalk.yellow };
91
+ if (score >= 20)
92
+ return { text: 'POOR', color: chalk.red };
93
+ return { text: 'CRITICAL', color: chalk.red };
94
+ }
95
+ // ============================================================================
96
+ // COST BOX (The "Receipt")
97
+ // ============================================================================
98
+ export function printCostBox(options) {
99
+ const { cost, tierName, prompt, isMigration, hasActivePass } = options;
100
+ const label = isMigration ? 'MIGRATION COST' : 'COST TO ANALYZE';
101
+ const tierLabel = tierName.includes('Tier') ? tierName : `Tier: ${tierName}`;
102
+ let content;
103
+ if (hasActivePass) {
104
+ // Panic Pass - show unlimited access (gold theme)
105
+ content =
106
+ `🎫 PANIC PASS: ${chalk.yellow.bold('UNLIMITED ACCESS')}\n` +
107
+ `📦 PLAN SIZE: ${colors.white(tierLabel)}\n\n` +
108
+ `${colors.dim('No credits will be deducted.')}`;
109
+ }
110
+ else {
111
+ content =
112
+ `💰 ${label}: ${colors.actionBold(`${cost} CREDITS`)}\n` +
113
+ `📦 PLAN SIZE: ${colors.white(tierLabel)}`;
114
+ }
115
+ console.log();
116
+ console.log(boxen(content, {
117
+ padding: 1,
118
+ margin: { top: 0, bottom: 0, left: 1, right: 1 },
119
+ borderStyle: 'round',
120
+ borderColor: hasActivePass ? 'yellow' : 'cyan',
121
+ }));
122
+ // Add prompt outside the box
123
+ if (prompt) {
124
+ console.log(colors.gray(`[?] ${prompt}`));
125
+ }
126
+ }
127
+ // ============================================================================
128
+ // SUCCESS BOX
129
+ // ============================================================================
130
+ export function printSuccessBox(options) {
131
+ const { updated, removed, backupPath, enginesUpdated } = options;
132
+ console.log();
133
+ console.log(colors.successBold('✨ SUCCESS'));
134
+ console.log(colors.gray('─'.repeat(50)));
135
+ console.log();
136
+ if (updated > 0) {
137
+ console.log(colors.success(` ✓ ${updated} Package${updated === 1 ? '' : 's'} Updated`));
138
+ }
139
+ if (removed > 0) {
140
+ console.log(colors.success(` ✓ ${removed} Package${removed === 1 ? '' : 's'} Removed`));
141
+ }
142
+ if (enginesUpdated && enginesUpdated > 0) {
143
+ console.log(colors.success(` ✓ ${enginesUpdated} Engine${enginesUpdated === 1 ? '' : 's'} Updated (Node.js/npm)`));
144
+ }
145
+ console.log(colors.success(` ✓ Backup: `) + colors.dim(backupPath));
146
+ console.log();
147
+ console.log(colors.actionBold(' 👉 NEXT STEP:'));
148
+ console.log(colors.dim(' Run the following command to finalize changes:'));
149
+ console.log();
150
+ console.log(` ${colors.brand('$ npm install')}`);
151
+ console.log();
152
+ }
153
+ // ============================================================================
154
+ // PROJECT INFO
155
+ // ============================================================================
156
+ export function printProjectHeader(name, framework, version) {
157
+ console.log();
158
+ console.log(colors.whiteBold(`📦 PROJECT: ${colors.brand(name)}`));
159
+ if (framework && version) {
160
+ console.log(colors.dim(` Framework: ${framework} ${version}`));
161
+ }
162
+ else if (framework) {
163
+ console.log(colors.dim(` Framework: ${framework}`));
164
+ }
165
+ }
166
+ // ============================================================================
167
+ // MIGRATION HEADER
168
+ // ============================================================================
169
+ export function printMigrationPlanHeader(framework, fromVersion, toVersion) {
170
+ console.log();
171
+ console.log(colors.brandBold(`🚀 MIGRATION PLAN: ${framework} ${fromVersion} → ${toVersion}`));
172
+ console.log(colors.gray('─'.repeat(50)));
173
+ }
174
+ // ============================================================================
175
+ // PROJECTION STATS
176
+ // ============================================================================
177
+ export function printProjectionStats(options) {
178
+ const { currentHealth, projectedHealth, packageCount, breakingChanges } = options;
179
+ console.log();
180
+ console.log(colors.whiteBold('📊 Projection:'));
181
+ const currentColor = currentHealth < 40 ? colors.danger : colors.warning;
182
+ const projectedColor = projectedHealth >= 70 ? colors.success : colors.warning;
183
+ console.log(` • Health: ${currentColor(`${currentHealth}/100`)} → ${projectedColor(`${projectedHealth}/100`)} (Estimated)`);
184
+ console.log(` • Packages: ${packageCount} updates`);
185
+ if (breakingChanges > 0) {
186
+ console.log(` • Breaking: ${colors.warning(`⚠️ ${breakingChanges} Major Change${breakingChanges > 1 ? 's' : ''}`)}`);
187
+ }
188
+ }
189
+ // ============================================================================
190
+ // DIAGNOSIS BOX
191
+ // ============================================================================
192
+ export function printDiagnosis(issueCount) {
193
+ console.log();
194
+ console.log(colors.whiteBold('💡 DIAGNOSIS:'));
195
+ console.log(colors.dim(' Deep dependency graph conflicts detected.'));
196
+ console.log(colors.dim(' Manual resolution is likely to fail.'));
197
+ console.log();
198
+ console.log(colors.whiteBold('🔒 SOLUTION:'));
199
+ console.log(colors.success(' ✓ Deterministic fix calculated.'));
200
+ console.log(colors.dim(' [?] Unlock recommended versions?'));
201
+ }
202
+ // ============================================================================
203
+ // ACCOUNT INFO
204
+ // ============================================================================
205
+ export function printAccountInfo(options) {
206
+ const { name, email, credits } = options;
207
+ console.log();
208
+ console.log(colors.whiteBold('👤 ACCOUNT'));
209
+ console.log(colors.gray('─'.repeat(40)));
210
+ if (name) {
211
+ console.log(` Name: ${colors.white(name)}`);
212
+ }
213
+ if (email) {
214
+ console.log(` Email: ${colors.brand(email)}`);
215
+ }
216
+ console.log(` Balance: ${colors.success(`${credits} credits`)}`);
217
+ }
218
+ /**
219
+ * Print user details after login/register
220
+ * Shows name, email, and current credit balance
221
+ */
222
+ export function printUserDetails(options) {
223
+ const { name, email, credits, hasActivePass, showHeader = true } = options;
224
+ if (showHeader) {
225
+ console.log();
226
+ console.log(colors.successBold('✓ Logged in successfully'));
227
+ }
228
+ console.log();
229
+ console.log(colors.whiteBold('👤 ACCOUNT DETAILS'));
230
+ console.log(colors.gray('─'.repeat(40)));
231
+ if (name) {
232
+ console.log(` Name: ${colors.white(name)}`);
233
+ }
234
+ if (email) {
235
+ console.log(` Email: ${colors.brand(email)}`);
236
+ }
237
+ if (hasActivePass) {
238
+ console.log(` Plan: ${colors.success('24H Unlimited Pass')} ${colors.successBold('✓')}`);
239
+ }
240
+ console.log(` Credits: ${colors.actionBold(`${credits}`)} available`);
241
+ }
242
+ /**
243
+ * Print credit check info showing both needed and available credits
244
+ */
245
+ export function printCreditCheck(options) {
246
+ const { needed, available, hasActivePass } = options;
247
+ console.log();
248
+ console.log(colors.whiteBold('💳 CREDITS'));
249
+ console.log(colors.gray('─'.repeat(40)));
250
+ if (hasActivePass) {
251
+ console.log(` Plan: ${colors.success('24H Unlimited Pass')} ${colors.successBold('✓')}`);
252
+ console.log(` Cost: ${colors.dim('Covered by pass')}`);
253
+ }
254
+ else {
255
+ console.log(` Available: ${colors.actionBold(`${available}`)} credits`);
256
+ console.log(` Needed: ${colors.white(`${needed}`)} credits`);
257
+ if (available >= needed) {
258
+ console.log(` Status: ${colors.success('Sufficient balance')} ${colors.successBold('✓')}`);
259
+ }
260
+ else {
261
+ console.log(` Status: ${colors.danger('Insufficient balance')} ${colors.dangerBold('✗')}`);
262
+ console.log(` Shortfall: ${colors.danger(`${needed - available}`)} credits`);
263
+ }
264
+ }
265
+ }
266
+ // ============================================================================
267
+ // APPLYING CHANGES
268
+ // ============================================================================
269
+ export function printApplyingHeader() {
270
+ console.log();
271
+ console.log(colors.whiteBold('🔧 Applying Patches...'));
272
+ }
273
+ export function printAppliedChange(packageName, action) {
274
+ const icon = action === 'updated' ? colors.success('✔') : colors.danger('✗');
275
+ const actionText = action === 'updated' ? 'updated' : 'removed';
276
+ console.log(` ${icon} ${packageName} ${actionText}`);
277
+ }
278
+ // ============================================================================
279
+ // NOTES SECTION
280
+ // ============================================================================
281
+ export function printNotes(notes) {
282
+ if (notes.length === 0)
283
+ return;
284
+ console.log();
285
+ console.log(colors.whiteBold('💡 NOTES:'));
286
+ for (const note of notes) {
287
+ console.log(` ${colors.dim(note)}`);
288
+ }
289
+ }
290
+ // ============================================================================
291
+ // SEVERITY BADGE
292
+ // ============================================================================
293
+ export function getSeverityBadge(severity) {
294
+ switch (severity?.toLowerCase()) {
295
+ case 'critical':
296
+ return colors.dangerBold('CRIT');
297
+ case 'high':
298
+ return colors.danger('HIGH');
299
+ case 'medium':
300
+ return colors.warning('MED ');
301
+ case 'low':
302
+ return colors.dim('LOW ');
303
+ default:
304
+ return colors.dim('INFO');
305
+ }
306
+ }
307
+ // ============================================================================
308
+ // CHANGE TYPE BADGE
309
+ // ============================================================================
310
+ export function getChangeTypeBadge(changeType) {
311
+ switch (changeType?.toLowerCase()) {
312
+ case 'major':
313
+ return colors.major('Major ⚠️');
314
+ case 'minor':
315
+ return colors.minor('Minor');
316
+ case 'patch':
317
+ return colors.patch('Patch');
318
+ case 'deprec':
319
+ case 'deprecated':
320
+ return colors.warning('Deprec.');
321
+ default:
322
+ return colors.dim(changeType || '');
323
+ }
324
+ }
325
+ // ============================================================================
326
+ // HELPERS
327
+ // ============================================================================
328
+ /**
329
+ * Truncate text to max length with ellipsis
330
+ */
331
+ export function truncateReason(text, maxLength = 40) {
332
+ if (!text)
333
+ return '';
334
+ if (text.length <= maxLength)
335
+ return text;
336
+ return text.substring(0, maxLength - 3) + '...';
337
+ }
338
+ //# sourceMappingURL=design-system.js.map