@wundr.io/cli 1.0.0
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/README.md +551 -0
- package/bin/wundr.js +39 -0
- package/dist/ai/ai-service.d.ts +152 -0
- package/dist/ai/ai-service.d.ts.map +1 -0
- package/dist/ai/ai-service.js +430 -0
- package/dist/ai/ai-service.js.map +1 -0
- package/dist/ai/claude-client.d.ts +130 -0
- package/dist/ai/claude-client.d.ts.map +1 -0
- package/dist/ai/claude-client.js +339 -0
- package/dist/ai/claude-client.js.map +1 -0
- package/dist/ai/conversation-manager.d.ts +164 -0
- package/dist/ai/conversation-manager.d.ts.map +1 -0
- package/dist/ai/conversation-manager.js +612 -0
- package/dist/ai/conversation-manager.js.map +1 -0
- package/dist/ai/index.d.ts +5 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +8 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/cli.d.ts +36 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +173 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/ai.d.ts +89 -0
- package/dist/commands/ai.d.ts.map +1 -0
- package/dist/commands/ai.js +735 -0
- package/dist/commands/ai.js.map +1 -0
- package/dist/commands/analyze-optimized.d.ts +14 -0
- package/dist/commands/analyze-optimized.d.ts.map +1 -0
- package/dist/commands/analyze-optimized.js +437 -0
- package/dist/commands/analyze-optimized.js.map +1 -0
- package/dist/commands/analyze.d.ts +65 -0
- package/dist/commands/analyze.d.ts.map +1 -0
- package/dist/commands/analyze.js +435 -0
- package/dist/commands/analyze.js.map +1 -0
- package/dist/commands/batch.d.ts +71 -0
- package/dist/commands/batch.d.ts.map +1 -0
- package/dist/commands/batch.js +738 -0
- package/dist/commands/batch.js.map +1 -0
- package/dist/commands/chat.d.ts +71 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/chat.js +674 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/claude-init.d.ts +28 -0
- package/dist/commands/claude-init.d.ts.map +1 -0
- package/dist/commands/claude-init.js +587 -0
- package/dist/commands/claude-init.js.map +1 -0
- package/dist/commands/claude-setup.d.ts +32 -0
- package/dist/commands/claude-setup.d.ts.map +1 -0
- package/dist/commands/claude-setup.js +570 -0
- package/dist/commands/claude-setup.js.map +1 -0
- package/dist/commands/computer-setup-commands.d.ts +39 -0
- package/dist/commands/computer-setup-commands.d.ts.map +1 -0
- package/dist/commands/computer-setup-commands.js +563 -0
- package/dist/commands/computer-setup-commands.js.map +1 -0
- package/dist/commands/computer-setup.d.ts +7 -0
- package/dist/commands/computer-setup.d.ts.map +1 -0
- package/dist/commands/computer-setup.js +481 -0
- package/dist/commands/computer-setup.js.map +1 -0
- package/dist/commands/create-command.d.ts +7 -0
- package/dist/commands/create-command.d.ts.map +1 -0
- package/dist/commands/create-command.js +158 -0
- package/dist/commands/create-command.js.map +1 -0
- package/dist/commands/create.d.ts +74 -0
- package/dist/commands/create.d.ts.map +1 -0
- package/dist/commands/create.js +556 -0
- package/dist/commands/create.js.map +1 -0
- package/dist/commands/dashboard.d.ts +91 -0
- package/dist/commands/dashboard.d.ts.map +1 -0
- package/dist/commands/dashboard.js +537 -0
- package/dist/commands/dashboard.js.map +1 -0
- package/dist/commands/govern.d.ts +70 -0
- package/dist/commands/govern.d.ts.map +1 -0
- package/dist/commands/govern.js +480 -0
- package/dist/commands/govern.js.map +1 -0
- package/dist/commands/init.d.ts +55 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +584 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/performance-optimizer.d.ts +30 -0
- package/dist/commands/performance-optimizer.d.ts.map +1 -0
- package/dist/commands/performance-optimizer.js +649 -0
- package/dist/commands/performance-optimizer.js.map +1 -0
- package/dist/commands/plugins.d.ts +87 -0
- package/dist/commands/plugins.d.ts.map +1 -0
- package/dist/commands/plugins.js +685 -0
- package/dist/commands/plugins.js.map +1 -0
- package/dist/commands/setup.d.ts +29 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +399 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/test-init.d.ts +9 -0
- package/dist/commands/test-init.d.ts.map +1 -0
- package/dist/commands/test-init.js +222 -0
- package/dist/commands/test-init.js.map +1 -0
- package/dist/commands/test.d.ts +25 -0
- package/dist/commands/test.d.ts.map +1 -0
- package/dist/commands/test.js +217 -0
- package/dist/commands/test.js.map +1 -0
- package/dist/commands/watch.d.ts +76 -0
- package/dist/commands/watch.d.ts.map +1 -0
- package/dist/commands/watch.js +610 -0
- package/dist/commands/watch.js.map +1 -0
- package/dist/context/context-manager.d.ts +155 -0
- package/dist/context/context-manager.d.ts.map +1 -0
- package/dist/context/context-manager.js +383 -0
- package/dist/context/context-manager.js.map +1 -0
- package/dist/context/index.d.ts +3 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +6 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/session-manager.d.ts +207 -0
- package/dist/context/session-manager.d.ts.map +1 -0
- package/dist/context/session-manager.js +682 -0
- package/dist/context/session-manager.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/interactive/interactive-mode.d.ts +76 -0
- package/dist/interactive/interactive-mode.d.ts.map +1 -0
- package/dist/interactive/interactive-mode.js +730 -0
- package/dist/interactive/interactive-mode.js.map +1 -0
- package/dist/nlp/command-mapper.d.ts +174 -0
- package/dist/nlp/command-mapper.d.ts.map +1 -0
- package/dist/nlp/command-mapper.js +623 -0
- package/dist/nlp/command-mapper.js.map +1 -0
- package/dist/nlp/command-parser.d.ts +106 -0
- package/dist/nlp/command-parser.d.ts.map +1 -0
- package/dist/nlp/command-parser.js +416 -0
- package/dist/nlp/command-parser.js.map +1 -0
- package/dist/nlp/index.d.ts +5 -0
- package/dist/nlp/index.d.ts.map +1 -0
- package/dist/nlp/index.js +8 -0
- package/dist/nlp/index.js.map +1 -0
- package/dist/nlp/intent-classifier.d.ts +59 -0
- package/dist/nlp/intent-classifier.d.ts.map +1 -0
- package/dist/nlp/intent-classifier.js +384 -0
- package/dist/nlp/intent-classifier.js.map +1 -0
- package/dist/nlp/intent-parser.d.ts +152 -0
- package/dist/nlp/intent-parser.d.ts.map +1 -0
- package/dist/nlp/intent-parser.js +739 -0
- package/dist/nlp/intent-parser.js.map +1 -0
- package/dist/plugins/plugin-manager.d.ts +120 -0
- package/dist/plugins/plugin-manager.d.ts.map +1 -0
- package/dist/plugins/plugin-manager.js +595 -0
- package/dist/plugins/plugin-manager.js.map +1 -0
- package/dist/types/index.d.ts +224 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/config-manager.d.ts +73 -0
- package/dist/utils/config-manager.d.ts.map +1 -0
- package/dist/utils/config-manager.js +339 -0
- package/dist/utils/config-manager.js.map +1 -0
- package/dist/utils/error-handler.d.ts +46 -0
- package/dist/utils/error-handler.d.ts.map +1 -0
- package/dist/utils/error-handler.js +169 -0
- package/dist/utils/error-handler.js.map +1 -0
- package/dist/utils/logger.d.ts +25 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +94 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +119 -0
- package/src/ai/ai-service.ts +595 -0
- package/src/ai/claude-client.ts +490 -0
- package/src/ai/conversation-manager.ts +907 -0
- package/src/ai/index.ts +8 -0
- package/src/cli.ts +202 -0
- package/src/commands/ai.ts +995 -0
- package/src/commands/analyze-optimized.ts +641 -0
- package/src/commands/analyze.ts +576 -0
- package/src/commands/batch.ts +935 -0
- package/src/commands/chat.ts +876 -0
- package/src/commands/claude-init.ts +715 -0
- package/src/commands/claude-setup.ts +697 -0
- package/src/commands/computer-setup-commands.ts +709 -0
- package/src/commands/computer-setup.ts +565 -0
- package/src/commands/create-command.ts +175 -0
- package/src/commands/create.ts +727 -0
- package/src/commands/dashboard.ts +691 -0
- package/src/commands/govern.ts +635 -0
- package/src/commands/init.ts +677 -0
- package/src/commands/performance-optimizer.ts +864 -0
- package/src/commands/plugins.ts +848 -0
- package/src/commands/setup.ts +508 -0
- package/src/commands/test-init.ts +242 -0
- package/src/commands/test.ts +264 -0
- package/src/commands/watch.ts +755 -0
- package/src/context/context-manager.ts +546 -0
- package/src/context/index.ts +9 -0
- package/src/context/session-manager.ts +1019 -0
- package/src/index.ts +64 -0
- package/src/interactive/interactive-mode.ts +830 -0
- package/src/nlp/command-mapper.ts +885 -0
- package/src/nlp/command-parser.ts +564 -0
- package/src/nlp/index.ts +4 -0
- package/src/nlp/intent-classifier.ts +458 -0
- package/src/nlp/intent-parser.ts +1101 -0
- package/src/plugins/plugin-manager.ts +744 -0
- package/src/types/index.ts +252 -0
- package/src/types/modules.d.ts +56 -0
- package/src/utils/config-manager.ts +391 -0
- package/src/utils/error-handler.ts +192 -0
- package/src/utils/logger.ts +104 -0
- package/templates/batch/ci-cd.yaml +62 -0
- package/templates/component/{{fileName}}.test.tsx +17 -0
- package/templates/component/{{fileName}}.tsx +21 -0
- package/templates/service/{{fileName}}.ts +98 -0
- package/templates/wundr-test.config.js +0 -0
- package/test-suites/api/health.spec.ts +134 -0
- package/test-suites/helpers/test-config.ts +84 -0
- package/test-suites/ui/accessibility.spec.ts +102 -0
- package/test-suites/ui/smoke.spec.ts +92 -0
|
@@ -0,0 +1,508 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple Setup Commands - Main setup entry points
|
|
3
|
+
* Provides the primary wundr setup commands that integrate with computer-setup
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import ora from 'ora';
|
|
9
|
+
import inquirer from 'inquirer';
|
|
10
|
+
import { ConfigManager } from '../utils/config-manager';
|
|
11
|
+
import { PluginManager } from '../plugins/plugin-manager';
|
|
12
|
+
import { logger } from '../utils/logger';
|
|
13
|
+
// Note: Using relative path import due to workspace resolution issues in this monorepo setup
|
|
14
|
+
// The computer-setup package must be built first before building this CLI package
|
|
15
|
+
import {
|
|
16
|
+
SetupPlatform,
|
|
17
|
+
SetupProgress,
|
|
18
|
+
SetupResult,
|
|
19
|
+
RealSetupOrchestrator,
|
|
20
|
+
} from '../../../computer-setup/dist';
|
|
21
|
+
|
|
22
|
+
export class SetupCommands {
|
|
23
|
+
private orchestrator: RealSetupOrchestrator;
|
|
24
|
+
private platform: SetupPlatform;
|
|
25
|
+
|
|
26
|
+
constructor(
|
|
27
|
+
private program: Command,
|
|
28
|
+
private configManager: ConfigManager,
|
|
29
|
+
private pluginManager: PluginManager
|
|
30
|
+
) {
|
|
31
|
+
this.platform = this.detectPlatform();
|
|
32
|
+
this.orchestrator = new RealSetupOrchestrator(this.platform);
|
|
33
|
+
this.registerCommands();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private registerCommands(): void {
|
|
37
|
+
// Main setup command (wundr setup)
|
|
38
|
+
this.program
|
|
39
|
+
.command('setup')
|
|
40
|
+
.description('Set up developer machine with required tools')
|
|
41
|
+
.option(
|
|
42
|
+
'-p, --profile <profile>',
|
|
43
|
+
'Use specific profile (frontend, backend, fullstack, devops)',
|
|
44
|
+
'fullstack'
|
|
45
|
+
)
|
|
46
|
+
.option(
|
|
47
|
+
'--dry-run',
|
|
48
|
+
'Show what would be installed without making changes'
|
|
49
|
+
)
|
|
50
|
+
.option('--interactive', 'Run in interactive mode')
|
|
51
|
+
.action(async options => {
|
|
52
|
+
await this.runSetup(options);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Setup with specific profile (wundr setup:profile frontend)
|
|
56
|
+
const setupProfile = this.program
|
|
57
|
+
.command('setup:profile')
|
|
58
|
+
.description('Set up using a specific developer profile');
|
|
59
|
+
|
|
60
|
+
setupProfile
|
|
61
|
+
.command('frontend')
|
|
62
|
+
.description('Set up frontend development environment')
|
|
63
|
+
.action(async () => {
|
|
64
|
+
await this.runSetup({ profile: 'frontend' });
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
setupProfile
|
|
68
|
+
.command('backend')
|
|
69
|
+
.description('Set up backend development environment')
|
|
70
|
+
.action(async () => {
|
|
71
|
+
await this.runSetup({ profile: 'backend' });
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
setupProfile
|
|
75
|
+
.command('fullstack')
|
|
76
|
+
.description('Set up full-stack development environment')
|
|
77
|
+
.action(async () => {
|
|
78
|
+
await this.runSetup({ profile: 'fullstack' });
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
setupProfile
|
|
82
|
+
.command('devops')
|
|
83
|
+
.description('Set up DevOps engineering environment')
|
|
84
|
+
.action(async () => {
|
|
85
|
+
await this.runSetup({ profile: 'devops' });
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Validate setup (wundr setup:validate)
|
|
89
|
+
this.program
|
|
90
|
+
.command('setup:validate')
|
|
91
|
+
.description('Validate current development environment setup')
|
|
92
|
+
.option('--profile <profile>', 'Validate against specific profile')
|
|
93
|
+
.option('--fix', 'Attempt to fix issues found')
|
|
94
|
+
.action(async options => {
|
|
95
|
+
await this.validateSetup(options);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// Resume setup (wundr setup:resume)
|
|
99
|
+
this.program
|
|
100
|
+
.command('setup:resume')
|
|
101
|
+
.description('Resume interrupted setup from saved state')
|
|
102
|
+
.action(async () => {
|
|
103
|
+
await this.resumeSetup();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Personalize setup (wundr setup:personalize)
|
|
107
|
+
this.program
|
|
108
|
+
.command('setup:personalize')
|
|
109
|
+
.description('Run personalization and configuration')
|
|
110
|
+
.action(async () => {
|
|
111
|
+
await this.personalizeSetup();
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private async runSetup(options: any): Promise<void> {
|
|
116
|
+
console.log(chalk.cyan('\n🚀 Wundr Development Environment Setup'));
|
|
117
|
+
console.log(chalk.gray('Setting up your development machine...\n'));
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
// Check for resumable setup
|
|
121
|
+
const canResume = await this.orchestrator.canResume();
|
|
122
|
+
if (canResume && !options.dryRun) {
|
|
123
|
+
const { resume } = await inquirer.prompt([
|
|
124
|
+
{
|
|
125
|
+
type: 'confirm',
|
|
126
|
+
name: 'resume',
|
|
127
|
+
message: 'Found incomplete setup. Resume from where you left off?',
|
|
128
|
+
default: true,
|
|
129
|
+
},
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
if (resume) {
|
|
133
|
+
return await this.resumeSetup();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Get profile
|
|
138
|
+
let profileName = options.profile;
|
|
139
|
+
if (options.interactive && !profileName) {
|
|
140
|
+
profileName = await this.selectProfile();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Validate profile
|
|
144
|
+
const availableProfiles = this.orchestrator.getAvailableProfiles();
|
|
145
|
+
|
|
146
|
+
// Try different matching strategies
|
|
147
|
+
let profile = availableProfiles.find(
|
|
148
|
+
p => p.name.toLowerCase() === profileName.toLowerCase()
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
if (!profile) {
|
|
152
|
+
// Try partial match
|
|
153
|
+
profile = availableProfiles.find(
|
|
154
|
+
p =>
|
|
155
|
+
p.name.toLowerCase().includes(profileName.toLowerCase()) ||
|
|
156
|
+
profileName
|
|
157
|
+
.toLowerCase()
|
|
158
|
+
.includes(p.name.toLowerCase().split(' ')[0])
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Map common aliases
|
|
163
|
+
if (!profile) {
|
|
164
|
+
const aliases: Record<string, string> = {
|
|
165
|
+
fullstack: 'Full Stack Developer',
|
|
166
|
+
'full-stack': 'Full Stack Developer',
|
|
167
|
+
frontend: 'Frontend Developer',
|
|
168
|
+
backend: 'Backend Developer',
|
|
169
|
+
devops: 'DevOps Engineer',
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const mappedName = aliases[profileName.toLowerCase()];
|
|
173
|
+
if (mappedName) {
|
|
174
|
+
profile = availableProfiles.find(p => p.name === mappedName);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (!profile) {
|
|
179
|
+
console.error(chalk.red(`❌ Unknown profile: ${profileName}`));
|
|
180
|
+
console.log(chalk.cyan('\n📋 Available profiles:'));
|
|
181
|
+
availableProfiles.forEach(p =>
|
|
182
|
+
console.log(
|
|
183
|
+
` • ${chalk.white(p.name)}: ${chalk.gray(p.description)}`
|
|
184
|
+
)
|
|
185
|
+
);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
console.log(
|
|
190
|
+
chalk.cyan(`\n📋 Selected Profile: ${chalk.white(profile.name)}`)
|
|
191
|
+
);
|
|
192
|
+
console.log(chalk.gray(`${profile.description}`));
|
|
193
|
+
console.log(
|
|
194
|
+
chalk.gray(`Estimated time: ${profile.estimatedTimeMinutes} minutes\n`)
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
if (options.dryRun) {
|
|
198
|
+
console.log(
|
|
199
|
+
chalk.yellow('🔍 DRY RUN - Showing what would be installed:\n')
|
|
200
|
+
);
|
|
201
|
+
console.log(chalk.cyan('Required tools:'));
|
|
202
|
+
profile.requiredTools.forEach(tool => console.log(` ✓ ${tool}`));
|
|
203
|
+
if (profile.optionalTools.length > 0) {
|
|
204
|
+
console.log(chalk.cyan('\nOptional tools:'));
|
|
205
|
+
profile.optionalTools.forEach(tool => console.log(` • ${tool}`));
|
|
206
|
+
}
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Progress tracking
|
|
211
|
+
const progressCallback = (progress: SetupProgress) => {
|
|
212
|
+
process.stdout.clearLine(0);
|
|
213
|
+
process.stdout.cursorTo(0);
|
|
214
|
+
const progressBar = this.createProgressBar(progress.percentage);
|
|
215
|
+
process.stdout.write(
|
|
216
|
+
`${progressBar} ${progress.percentage.toFixed(1)}% - ${progress.currentStep}`
|
|
217
|
+
);
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
console.log(chalk.cyan('🚀 Starting setup...\n'));
|
|
221
|
+
|
|
222
|
+
const result: SetupResult = await this.orchestrator.orchestrate(
|
|
223
|
+
profileName,
|
|
224
|
+
{
|
|
225
|
+
dryRun: options.dryRun,
|
|
226
|
+
skipExisting: true,
|
|
227
|
+
parallel: false,
|
|
228
|
+
generateReport: true,
|
|
229
|
+
},
|
|
230
|
+
progressCallback
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
console.log('\n'); // New line after progress
|
|
234
|
+
|
|
235
|
+
if (result.success) {
|
|
236
|
+
console.log(chalk.green('\n✅ Setup completed successfully!'));
|
|
237
|
+
console.log(
|
|
238
|
+
chalk.gray(`Duration: ${Math.round(result.duration / 1000)}s\n`)
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
this.showSetupSummary(result);
|
|
242
|
+
this.showNextSteps();
|
|
243
|
+
} else {
|
|
244
|
+
console.log(chalk.red('\n❌ Setup failed!'));
|
|
245
|
+
this.showErrors(result);
|
|
246
|
+
console.log(chalk.cyan('\n💡 Resume with: wundr setup:resume'));
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
} catch (error) {
|
|
250
|
+
console.error(chalk.red('\n❌ Setup failed:'), (error as Error).message);
|
|
251
|
+
console.log(chalk.cyan('\n💡 Resume with: wundr setup:resume'));
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
private async validateSetup(options: any): Promise<void> {
|
|
257
|
+
console.log(chalk.cyan('\n🔍 Validating development environment...\n'));
|
|
258
|
+
|
|
259
|
+
const spinner = ora('Running validation checks...').start();
|
|
260
|
+
|
|
261
|
+
// Basic validation checks
|
|
262
|
+
const checks = [
|
|
263
|
+
{ name: 'Node.js', test: () => this.checkCommand('node --version') },
|
|
264
|
+
{ name: 'Git', test: () => this.checkCommand('git --version') },
|
|
265
|
+
{ name: 'Homebrew', test: () => this.checkCommand('brew --version') },
|
|
266
|
+
{ name: 'Docker', test: () => this.checkCommand('docker --version') },
|
|
267
|
+
];
|
|
268
|
+
|
|
269
|
+
const results: Array<{
|
|
270
|
+
name: string;
|
|
271
|
+
status: 'pass' | 'fail';
|
|
272
|
+
version?: string;
|
|
273
|
+
error?: string;
|
|
274
|
+
}> = [];
|
|
275
|
+
|
|
276
|
+
for (const check of checks) {
|
|
277
|
+
try {
|
|
278
|
+
const result = await check.test();
|
|
279
|
+
results.push({
|
|
280
|
+
name: check.name,
|
|
281
|
+
status: 'pass',
|
|
282
|
+
version: result,
|
|
283
|
+
});
|
|
284
|
+
} catch (error) {
|
|
285
|
+
results.push({
|
|
286
|
+
name: check.name,
|
|
287
|
+
status: 'fail',
|
|
288
|
+
error: (error as Error).message,
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
spinner.stop();
|
|
294
|
+
|
|
295
|
+
console.log(chalk.cyan('📊 Validation Results:\n'));
|
|
296
|
+
results.forEach(result => {
|
|
297
|
+
const icon = result.status === 'pass' ? '✅' : '❌';
|
|
298
|
+
const status =
|
|
299
|
+
result.status === 'pass'
|
|
300
|
+
? chalk.green(`${result.version || 'installed'}`)
|
|
301
|
+
: chalk.red('not found');
|
|
302
|
+
console.log(`${icon} ${result.name}: ${status}`);
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
const failed = results.filter(r => r.status === 'fail');
|
|
306
|
+
if (failed.length > 0) {
|
|
307
|
+
console.log(chalk.yellow(`\n⚠️ ${failed.length} issues found`));
|
|
308
|
+
|
|
309
|
+
if (options.fix) {
|
|
310
|
+
console.log(chalk.cyan('\n🔧 Attempting to fix issues...'));
|
|
311
|
+
await this.runSetup({ profile: options.profile || 'fullstack' });
|
|
312
|
+
} else {
|
|
313
|
+
console.log(
|
|
314
|
+
chalk.cyan('\n💡 Fix issues with: wundr setup:validate --fix')
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
} else {
|
|
318
|
+
console.log(chalk.green('\n✅ All checks passed! Environment is ready.'));
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
private async resumeSetup(): Promise<void> {
|
|
323
|
+
console.log(chalk.cyan('\n🔄 Resuming setup...\n'));
|
|
324
|
+
|
|
325
|
+
const progressCallback = (progress: SetupProgress) => {
|
|
326
|
+
process.stdout.clearLine(0);
|
|
327
|
+
process.stdout.cursorTo(0);
|
|
328
|
+
const progressBar = this.createProgressBar(progress.percentage);
|
|
329
|
+
process.stdout.write(
|
|
330
|
+
`${progressBar} ${progress.percentage.toFixed(1)}% - ${progress.currentStep}`
|
|
331
|
+
);
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
try {
|
|
335
|
+
const result = await this.orchestrator.resume(progressCallback);
|
|
336
|
+
console.log('\n');
|
|
337
|
+
|
|
338
|
+
if (result.success) {
|
|
339
|
+
console.log(chalk.green('✅ Setup completed successfully!'));
|
|
340
|
+
this.showSetupSummary(result);
|
|
341
|
+
this.showNextSteps();
|
|
342
|
+
} else {
|
|
343
|
+
console.log(chalk.red('❌ Resume failed!'));
|
|
344
|
+
this.showErrors(result);
|
|
345
|
+
process.exit(1);
|
|
346
|
+
}
|
|
347
|
+
} catch (error) {
|
|
348
|
+
console.error(chalk.red('❌ Resume failed:'), (error as Error).message);
|
|
349
|
+
process.exit(1);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
private async personalizeSetup(): Promise<void> {
|
|
354
|
+
console.log(chalk.cyan('\n👤 Personal Configuration Setup\n'));
|
|
355
|
+
|
|
356
|
+
const answers = await inquirer.prompt([
|
|
357
|
+
{
|
|
358
|
+
type: 'input',
|
|
359
|
+
name: 'name',
|
|
360
|
+
message: 'Your name:',
|
|
361
|
+
validate: (input: string) => input.length > 0 || 'Name is required',
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
type: 'input',
|
|
365
|
+
name: 'email',
|
|
366
|
+
message: 'Your email:',
|
|
367
|
+
validate: (input: string) =>
|
|
368
|
+
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input) || 'Valid email required',
|
|
369
|
+
},
|
|
370
|
+
{
|
|
371
|
+
type: 'list',
|
|
372
|
+
name: 'shell',
|
|
373
|
+
message: 'Preferred shell:',
|
|
374
|
+
choices: ['zsh', 'bash', 'fish'],
|
|
375
|
+
default: 'zsh',
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
type: 'confirm',
|
|
379
|
+
name: 'aliases',
|
|
380
|
+
message: 'Install helpful shell aliases?',
|
|
381
|
+
default: true,
|
|
382
|
+
},
|
|
383
|
+
]);
|
|
384
|
+
|
|
385
|
+
console.log(chalk.cyan('\n⚙️ Configuring personal settings...'));
|
|
386
|
+
|
|
387
|
+
// Configure Git
|
|
388
|
+
try {
|
|
389
|
+
await this.runCommand(`git config --global user.name "${answers.name}"`);
|
|
390
|
+
await this.runCommand(
|
|
391
|
+
`git config --global user.email "${answers.email}"`
|
|
392
|
+
);
|
|
393
|
+
console.log(chalk.green('✅ Git configured'));
|
|
394
|
+
} catch (error) {
|
|
395
|
+
console.log(chalk.yellow('⚠️ Could not configure Git'));
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
console.log(chalk.green('\n✅ Personalization complete!'));
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
private async selectProfile(): Promise<string> {
|
|
402
|
+
const profiles = this.orchestrator.getAvailableProfiles();
|
|
403
|
+
|
|
404
|
+
const { selectedProfile } = await inquirer.prompt([
|
|
405
|
+
{
|
|
406
|
+
type: 'list',
|
|
407
|
+
name: 'selectedProfile',
|
|
408
|
+
message: 'Select your development profile:',
|
|
409
|
+
choices: profiles.map(p => ({
|
|
410
|
+
name: `${p.name} - ${p.description}`,
|
|
411
|
+
value: p.name.toLowerCase().replace(/\s+/g, ''),
|
|
412
|
+
short: p.name,
|
|
413
|
+
})),
|
|
414
|
+
},
|
|
415
|
+
]);
|
|
416
|
+
|
|
417
|
+
return selectedProfile;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
private createProgressBar(percentage: number): string {
|
|
421
|
+
const width = 20;
|
|
422
|
+
const filled = Math.round((percentage / 100) * width);
|
|
423
|
+
const empty = width - filled;
|
|
424
|
+
return (
|
|
425
|
+
chalk.cyan('[') +
|
|
426
|
+
chalk.green('='.repeat(filled)) +
|
|
427
|
+
chalk.gray('-'.repeat(empty)) +
|
|
428
|
+
chalk.cyan(']')
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
private showSetupSummary(result: SetupResult): void {
|
|
433
|
+
if (result.completedSteps.length > 0) {
|
|
434
|
+
console.log(
|
|
435
|
+
chalk.cyan(`🎯 Completed (${result.completedSteps.length}):`)
|
|
436
|
+
);
|
|
437
|
+
result.completedSteps
|
|
438
|
+
.slice(0, 5)
|
|
439
|
+
.forEach(step => console.log(` ✅ ${step.replace('install-', '')}`));
|
|
440
|
+
if (result.completedSteps.length > 5) {
|
|
441
|
+
console.log(` ... and ${result.completedSteps.length - 5} more`);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (result.skippedSteps.length > 0) {
|
|
446
|
+
console.log(
|
|
447
|
+
chalk.yellow(`\n⏭️ Skipped (${result.skippedSteps.length}):`)
|
|
448
|
+
);
|
|
449
|
+
result.skippedSteps
|
|
450
|
+
.slice(0, 3)
|
|
451
|
+
.forEach(step =>
|
|
452
|
+
console.log(
|
|
453
|
+
` ⏭️ ${step.replace('install-', '')} (already installed)`
|
|
454
|
+
)
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
private showErrors(result: SetupResult): void {
|
|
460
|
+
if (result.failedSteps.length > 0) {
|
|
461
|
+
console.log(chalk.red(`❌ Failed (${result.failedSteps.length}):`));
|
|
462
|
+
result.failedSteps.forEach(step =>
|
|
463
|
+
console.log(` ❌ ${step.replace('install-', '')}`)
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
if (result.errors.length > 0) {
|
|
468
|
+
console.log(chalk.red('\n🔍 Errors:'));
|
|
469
|
+
result.errors
|
|
470
|
+
.slice(0, 3)
|
|
471
|
+
.forEach(error => console.log(` • ${error.message}`));
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
private showNextSteps(): void {
|
|
476
|
+
console.log(chalk.cyan('\n📝 Next Steps:'));
|
|
477
|
+
const steps = [
|
|
478
|
+
'Restart your terminal to apply changes',
|
|
479
|
+
'Validate setup: wundr setup:validate',
|
|
480
|
+
'Personalize: wundr setup:personalize',
|
|
481
|
+
'Start coding! 🚀',
|
|
482
|
+
];
|
|
483
|
+
|
|
484
|
+
steps.forEach((step, i) => {
|
|
485
|
+
console.log(` ${i + 1}. ${step}`);
|
|
486
|
+
});
|
|
487
|
+
console.log();
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
private detectPlatform(): SetupPlatform {
|
|
491
|
+
return {
|
|
492
|
+
os: process.platform as 'darwin' | 'linux' | 'win32',
|
|
493
|
+
arch: process.arch as 'x64' | 'arm64',
|
|
494
|
+
version: process.version || 'unknown',
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
private async checkCommand(command: string): Promise<string> {
|
|
499
|
+
const { execa } = await import('execa');
|
|
500
|
+
const { stdout } = await execa('sh', ['-c', command]);
|
|
501
|
+
return stdout?.split('\n')[0] || '';
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
private async runCommand(command: string): Promise<void> {
|
|
505
|
+
const { execa } = await import('execa');
|
|
506
|
+
await execa('sh', ['-c', command]);
|
|
507
|
+
}
|
|
508
|
+
}
|