@wundr.io/cli 1.0.1 ā 1.0.2-dev.20260530180455.e1307186
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/wundr.js +13 -5
- package/package.json +30 -9
- package/src/ai/ai-service.ts +6 -4
- package/src/ai/claude-client.ts +6 -2
- package/src/ai/conversation-manager.ts +12 -5
- package/src/cli.ts +42 -13
- package/src/commands/ai.ts +340 -64
- package/src/commands/alignment.ts +1212 -0
- package/src/commands/analyze-optimized.ts +371 -33
- package/src/commands/analyze.ts +8 -6
- package/src/commands/batch.ts +166 -26
- package/src/commands/chat.ts +20 -10
- package/src/commands/claude-init.ts +31 -27
- package/src/commands/claude-setup.ts +761 -81
- package/src/commands/computer-setup.ts +524 -12
- package/src/commands/create-command.ts +3 -3
- package/src/commands/create.ts +9 -6
- package/src/commands/dashboard.ts +11 -6
- package/src/commands/govern.ts +11 -6
- package/src/commands/governance.ts +1005 -0
- package/src/commands/guardian.ts +887 -0
- package/src/commands/init.ts +104 -11
- package/src/commands/orchestrator.ts +789 -0
- package/src/commands/performance-optimizer.ts +15 -10
- package/src/commands/plugins.ts +8 -5
- package/src/commands/project-update.ts +1156 -0
- package/src/commands/rag.ts +1011 -0
- package/src/commands/session.ts +631 -0
- package/src/commands/setup.ts +42 -344
- package/src/commands/test-init.ts +3 -2
- package/src/commands/test.ts +3 -2
- package/src/commands/watch.ts +21 -11
- package/src/commands/worktree.ts +1057 -0
- package/src/context/context-manager.ts +5 -2
- package/src/context/session-manager.ts +18 -7
- package/src/framework/command-interface.ts +520 -0
- package/src/framework/command-registry.ts +942 -0
- package/src/framework/completion-exporter.ts +383 -0
- package/src/framework/debug-logger.ts +519 -0
- package/src/framework/error-handler.ts +867 -0
- package/src/framework/help-generator.ts +540 -0
- package/src/framework/index.ts +169 -0
- package/src/framework/interactive-repl.ts +703 -0
- package/src/framework/output-formatter.ts +834 -0
- package/src/framework/progress-manager.ts +539 -0
- package/src/index.ts +3 -2
- package/src/interactive/interactive-mode.ts +14 -7
- package/src/lib/conflict-resolution.ts +818 -0
- package/src/lib/merge-strategy.ts +550 -0
- package/src/lib/safety-mechanisms.ts +451 -0
- package/src/lib/state-detection.ts +1030 -0
- package/src/nlp/command-mapper.ts +8 -3
- package/src/nlp/command-parser.ts +5 -2
- package/src/nlp/intent-parser.ts +23 -9
- package/src/plugins/plugin-manager.ts +50 -24
- package/src/tests/computer-setup-integration.test.ts +46 -15
- package/src/types/index.ts +1 -1
- package/src/types/modules.d.ts +425 -1
- package/src/utils/backup-rollback-manager.ts +19 -14
- package/src/utils/claude-config-installer.ts +119 -28
- package/src/utils/config-manager.ts +9 -6
- package/src/utils/error-handler.ts +3 -1
- package/src/utils/logger.ts +35 -12
- package/templates/batch/ci-cd.yaml +7 -7
- package/test-suites/api/health.spec.ts +20 -23
- package/test-suites/helpers/test-config.ts +14 -13
- package/test-suites/ui/accessibility.spec.ts +27 -22
- package/test-suites/ui/smoke.spec.ts +26 -21
- package/src/commands/computer-setup-commands.ts +0 -869
package/src/commands/setup.ts
CHANGED
|
@@ -1,35 +1,29 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Simple Setup Commands - Main setup entry points
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
|
+
* `wundr setup` (and its sub-commands) delegate to the SAME code path as
|
|
5
|
+
* `wundr computer-setup` (runComputerSetup -> ComputerSetupManager), so there is
|
|
6
|
+
* a single orchestrator engine across the whole CLI. The old RealSetupOrchestrator
|
|
7
|
+
* has been retired.
|
|
4
8
|
*/
|
|
5
9
|
|
|
6
|
-
import { Command } from 'commander';
|
|
7
10
|
import chalk from 'chalk';
|
|
8
|
-
import ora from 'ora';
|
|
9
11
|
import inquirer from 'inquirer';
|
|
10
|
-
import
|
|
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';
|
|
12
|
+
import ora from 'ora';
|
|
21
13
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
14
|
+
import { runComputerSetup } from './computer-setup';
|
|
15
|
+
|
|
16
|
+
import type { PluginManager } from '../plugins/plugin-manager';
|
|
17
|
+
import type { ConfigManager } from '../utils/config-manager';
|
|
25
18
|
|
|
19
|
+
import type { Command } from 'commander';
|
|
20
|
+
|
|
21
|
+
export class SetupCommands {
|
|
26
22
|
constructor(
|
|
27
23
|
private program: Command,
|
|
28
24
|
private configManager: ConfigManager,
|
|
29
25
|
private pluginManager: PluginManager
|
|
30
26
|
) {
|
|
31
|
-
this.platform = this.detectPlatform();
|
|
32
|
-
this.orchestrator = new RealSetupOrchestrator(this.platform);
|
|
33
27
|
this.registerCommands();
|
|
34
28
|
}
|
|
35
29
|
|
|
@@ -48,6 +42,7 @@ export class SetupCommands {
|
|
|
48
42
|
'Show what would be installed without making changes'
|
|
49
43
|
)
|
|
50
44
|
.option('--interactive', 'Run in interactive mode')
|
|
45
|
+
.option('--no-remote-access', 'Skip remote-access provisioning')
|
|
51
46
|
.action(async options => {
|
|
52
47
|
await this.runSetup(options);
|
|
53
48
|
});
|
|
@@ -57,33 +52,14 @@ export class SetupCommands {
|
|
|
57
52
|
.command('setup:profile')
|
|
58
53
|
.description('Set up using a specific developer profile');
|
|
59
54
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
});
|
|
55
|
+
for (const profile of ['frontend', 'backend', 'fullstack', 'devops']) {
|
|
56
|
+
setupProfile
|
|
57
|
+
.command(profile)
|
|
58
|
+
.description(`Set up ${profile} development environment`)
|
|
59
|
+
.action(async () => {
|
|
60
|
+
await this.runSetup({ profile });
|
|
61
|
+
});
|
|
62
|
+
}
|
|
87
63
|
|
|
88
64
|
// Validate setup (wundr setup:validate)
|
|
89
65
|
this.program
|
|
@@ -95,12 +71,14 @@ export class SetupCommands {
|
|
|
95
71
|
await this.validateSetup(options);
|
|
96
72
|
});
|
|
97
73
|
|
|
98
|
-
// Resume setup (wundr setup:resume)
|
|
74
|
+
// Resume setup (wundr setup:resume) ā re-runs idempotently, skipping
|
|
75
|
+
// already-installed tools (the setup flow is now idempotent).
|
|
99
76
|
this.program
|
|
100
77
|
.command('setup:resume')
|
|
101
|
-
.description('
|
|
102
|
-
.
|
|
103
|
-
|
|
78
|
+
.description('Re-run setup, skipping tools that are already installed')
|
|
79
|
+
.option('-p, --profile <profile>', 'Profile to resume', 'fullstack')
|
|
80
|
+
.action(async options => {
|
|
81
|
+
await this.runSetup({ ...options, skipExisting: true });
|
|
104
82
|
});
|
|
105
83
|
|
|
106
84
|
// Personalize setup (wundr setup:personalize)
|
|
@@ -113,144 +91,15 @@ export class SetupCommands {
|
|
|
113
91
|
}
|
|
114
92
|
|
|
115
93
|
private async runSetup(options: any): Promise<void> {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
}
|
|
94
|
+
// Single source of truth: the same handler that backs `wundr computer-setup`.
|
|
95
|
+
await runComputerSetup({
|
|
96
|
+
profile: options.profile,
|
|
97
|
+
mode: options.interactive ? 'interactive' : 'automated',
|
|
98
|
+
dryRun: Boolean(options.dryRun),
|
|
99
|
+
interactive: Boolean(options.interactive),
|
|
100
|
+
skipExisting: Boolean(options.skipExisting),
|
|
101
|
+
remoteAccess: options.remoteAccess,
|
|
102
|
+
});
|
|
254
103
|
}
|
|
255
104
|
|
|
256
105
|
private async validateSetup(options: any): Promise<void> {
|
|
@@ -258,7 +107,6 @@ export class SetupCommands {
|
|
|
258
107
|
|
|
259
108
|
const spinner = ora('Running validation checks...').start();
|
|
260
109
|
|
|
261
|
-
// Basic validation checks
|
|
262
110
|
const checks = [
|
|
263
111
|
{ name: 'Node.js', test: () => this.checkCommand('node --version') },
|
|
264
112
|
{ name: 'Git', test: () => this.checkCommand('git --version') },
|
|
@@ -270,23 +118,17 @@ export class SetupCommands {
|
|
|
270
118
|
name: string;
|
|
271
119
|
status: 'pass' | 'fail';
|
|
272
120
|
version?: string;
|
|
273
|
-
error?: string;
|
|
274
121
|
}> = [];
|
|
275
122
|
|
|
276
123
|
for (const check of checks) {
|
|
277
124
|
try {
|
|
278
|
-
const result = await check.test();
|
|
279
125
|
results.push({
|
|
280
126
|
name: check.name,
|
|
281
127
|
status: 'pass',
|
|
282
|
-
version:
|
|
283
|
-
});
|
|
284
|
-
} catch (error) {
|
|
285
|
-
results.push({
|
|
286
|
-
name: check.name,
|
|
287
|
-
status: 'fail',
|
|
288
|
-
error: (error as Error).message,
|
|
128
|
+
version: await check.test(),
|
|
289
129
|
});
|
|
130
|
+
} catch {
|
|
131
|
+
results.push({ name: check.name, status: 'fail' });
|
|
290
132
|
}
|
|
291
133
|
}
|
|
292
134
|
|
|
@@ -297,7 +139,7 @@ export class SetupCommands {
|
|
|
297
139
|
const icon = result.status === 'pass' ? 'ā
' : 'ā';
|
|
298
140
|
const status =
|
|
299
141
|
result.status === 'pass'
|
|
300
|
-
? chalk.green(
|
|
142
|
+
? chalk.green(result.version || 'installed')
|
|
301
143
|
: chalk.red('not found');
|
|
302
144
|
console.log(`${icon} ${result.name}: ${status}`);
|
|
303
145
|
});
|
|
@@ -305,7 +147,6 @@ export class SetupCommands {
|
|
|
305
147
|
const failed = results.filter(r => r.status === 'fail');
|
|
306
148
|
if (failed.length > 0) {
|
|
307
149
|
console.log(chalk.yellow(`\nā ļø ${failed.length} issues found`));
|
|
308
|
-
|
|
309
150
|
if (options.fix) {
|
|
310
151
|
console.log(chalk.cyan('\nš§ Attempting to fix issues...'));
|
|
311
152
|
await this.runSetup({ profile: options.profile || 'fullstack' });
|
|
@@ -319,37 +160,6 @@ export class SetupCommands {
|
|
|
319
160
|
}
|
|
320
161
|
}
|
|
321
162
|
|
|
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
163
|
private async personalizeSetup(): Promise<void> {
|
|
354
164
|
console.log(chalk.cyan('\nš¤ Personal Configuration Setup\n'));
|
|
355
165
|
|
|
@@ -367,134 +177,22 @@ export class SetupCommands {
|
|
|
367
177
|
validate: (input: string) =>
|
|
368
178
|
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(input) || 'Valid email required',
|
|
369
179
|
},
|
|
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
180
|
]);
|
|
384
181
|
|
|
385
182
|
console.log(chalk.cyan('\nāļø Configuring personal settings...'));
|
|
386
|
-
|
|
387
|
-
// Configure Git
|
|
388
183
|
try {
|
|
389
184
|
await this.runCommand(`git config --global user.name "${answers.name}"`);
|
|
390
185
|
await this.runCommand(
|
|
391
186
|
`git config --global user.email "${answers.email}"`
|
|
392
187
|
);
|
|
393
188
|
console.log(chalk.green('ā
Git configured'));
|
|
394
|
-
} catch
|
|
189
|
+
} catch {
|
|
395
190
|
console.log(chalk.yellow('ā ļø Could not configure Git'));
|
|
396
191
|
}
|
|
397
192
|
|
|
398
193
|
console.log(chalk.green('\nā
Personalization complete!'));
|
|
399
194
|
}
|
|
400
195
|
|
|
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
196
|
private async checkCommand(command: string): Promise<string> {
|
|
499
197
|
const { execa } = await import('execa');
|
|
500
198
|
const { stdout } = await execa('sh', ['-c', command]);
|
package/src/commands/test.ts
CHANGED
package/src/commands/watch.ts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import { Command } from 'commander';
|
|
2
|
-
import { watch, FSWatcher } from 'chokidar';
|
|
3
|
-
import fs from 'fs-extra';
|
|
4
1
|
import path from 'path';
|
|
2
|
+
|
|
5
3
|
import chalk from 'chalk';
|
|
4
|
+
import { watch } from 'chokidar';
|
|
5
|
+
import fs from 'fs-extra';
|
|
6
6
|
import YAML from 'yaml';
|
|
7
|
-
|
|
8
|
-
import { PluginManager } from '../plugins/plugin-manager';
|
|
9
|
-
import { logger } from '../utils/logger';
|
|
7
|
+
|
|
10
8
|
import { errorHandler } from '../utils/error-handler';
|
|
11
|
-
import {
|
|
9
|
+
import { logger } from '../utils/logger';
|
|
10
|
+
|
|
11
|
+
import type { PluginManager } from '../plugins/plugin-manager';
|
|
12
|
+
import type { WatchConfig, WatchCommand } from '../types';
|
|
13
|
+
import type { ConfigManager } from '../utils/config-manager';
|
|
14
|
+
import type { FSWatcher } from 'chokidar';
|
|
15
|
+
import type { Command } from 'commander';
|
|
12
16
|
|
|
13
17
|
/**
|
|
14
18
|
* Watch commands for real-time monitoring
|
|
@@ -552,7 +556,9 @@ export class WatchCommands {
|
|
|
552
556
|
}
|
|
553
557
|
|
|
554
558
|
private shouldExecuteCommand(cmd: WatchCommand, filePath: string): boolean {
|
|
555
|
-
if (!cmd.condition)
|
|
559
|
+
if (!cmd.condition) {
|
|
560
|
+
return true;
|
|
561
|
+
}
|
|
556
562
|
|
|
557
563
|
// Implement condition checking logic
|
|
558
564
|
switch (cmd.condition) {
|
|
@@ -728,11 +734,15 @@ export class WatchCommands {
|
|
|
728
734
|
}
|
|
729
735
|
|
|
730
736
|
private getTestCommand(framework: string, options: any): string {
|
|
731
|
-
const baseCmd = framework === 'npm' ?
|
|
737
|
+
const baseCmd = framework === 'npm' ? 'npm test' : `npx ${framework}`;
|
|
732
738
|
const flags: string[] = [];
|
|
733
739
|
|
|
734
|
-
if (options.coverage)
|
|
735
|
-
|
|
740
|
+
if (options.coverage) {
|
|
741
|
+
flags.push('--coverage');
|
|
742
|
+
}
|
|
743
|
+
if (options.changedOnly) {
|
|
744
|
+
flags.push('--changedSince=HEAD');
|
|
745
|
+
}
|
|
736
746
|
|
|
737
747
|
return `${baseCmd} ${flags.join(' ')}`;
|
|
738
748
|
}
|