@paulduvall/claude-dev-toolkit 0.0.1-alpha.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.
@@ -0,0 +1,558 @@
1
+ /**
2
+ * System Requirements Checker
3
+ *
4
+ * Validates system compatibility and requirements checking.
5
+ * Extracted from DependencyValidator as part of Phase 1 bloater refactoring.
6
+ *
7
+ * Features:
8
+ * - Operating system compatibility checking
9
+ * - Architecture validation
10
+ * - Memory requirements validation
11
+ * - Disk space availability checking
12
+ * - Node.js version validation
13
+ * - System environment analysis
14
+ */
15
+
16
+ const fs = require('fs');
17
+ const path = require('path');
18
+ const os = require('os');
19
+ const VersionValidatorService = require('./version-validator-service');
20
+ const PlatformUtils = require('./platform-utils');
21
+
22
+ class SystemRequirementsChecker {
23
+ constructor() {
24
+ this.versionValidator = new VersionValidatorService();
25
+ this.platformUtils = new PlatformUtils();
26
+ this.systemInfo = this._gatherSystemInfo();
27
+ }
28
+
29
+ /**
30
+ * Gather system information
31
+ * @returns {Object} System information
32
+ * @private
33
+ */
34
+ _gatherSystemInfo() {
35
+ return {
36
+ platform: process.platform,
37
+ arch: process.arch,
38
+ nodeVersion: process.version,
39
+ totalMemory: os.totalmem(),
40
+ freeMemory: os.freemem(),
41
+ cpus: os.cpus().length,
42
+ osType: os.type(),
43
+ osRelease: os.release(),
44
+ hostname: os.hostname(),
45
+ uptime: os.uptime()
46
+ };
47
+ }
48
+
49
+ /**
50
+ * Validate system requirements
51
+ * @param {Object} requirements - System requirements to validate
52
+ * @returns {Object} System compatibility result
53
+ */
54
+ validateSystemRequirements(requirements) {
55
+ const context = this._createSystemValidationContext(requirements);
56
+ const result = this._initializeSystemValidationResult();
57
+
58
+ this._validateOperatingSystem(result, context);
59
+ this._validateArchitecture(result, context);
60
+ this._validateNodeVersion(result, context);
61
+ this._validateMemoryRequirements(result, context);
62
+ this._validateDiskSpace(result, context);
63
+ this._calculateOverallCompatibility(result);
64
+
65
+ return result;
66
+ }
67
+
68
+ /**
69
+ * Check if the current system meets minimum requirements
70
+ * @param {Object} minimumRequirements - Minimum system requirements
71
+ * @returns {Object} Compatibility check result
72
+ */
73
+ checkMinimumRequirements(minimumRequirements) {
74
+ const checks = {
75
+ platform: this._checkPlatformRequirement(minimumRequirements.platform),
76
+ architecture: this._checkArchitectureRequirement(minimumRequirements.architecture),
77
+ memory: this._checkMemoryRequirement(minimumRequirements.memory),
78
+ diskSpace: this._checkDiskSpaceRequirement(minimumRequirements.diskSpace),
79
+ nodeVersion: this._checkNodeVersionRequirement(minimumRequirements.nodeVersion)
80
+ };
81
+
82
+ const allSatisfied = Object.values(checks).every(check => check.satisfied);
83
+
84
+ return {
85
+ compatible: allSatisfied,
86
+ checks: checks,
87
+ systemInfo: this.systemInfo,
88
+ recommendations: this._generateCompatibilityRecommendations(checks)
89
+ };
90
+ }
91
+
92
+ /**
93
+ * Get detailed system information
94
+ * @returns {Object} Comprehensive system information
95
+ */
96
+ getSystemInfo() {
97
+ return {
98
+ ...this.systemInfo,
99
+ environment: {
100
+ nodeVersion: process.version,
101
+ platform: process.platform,
102
+ arch: process.arch
103
+ },
104
+ resources: {
105
+ totalMemory: this._formatMemory(this.systemInfo.totalMemory),
106
+ freeMemory: this._formatMemory(this.systemInfo.freeMemory),
107
+ usedMemory: this._formatMemory(this.systemInfo.totalMemory - this.systemInfo.freeMemory),
108
+ memoryUsagePercent: Math.round((1 - this.systemInfo.freeMemory / this.systemInfo.totalMemory) * 100)
109
+ },
110
+ capabilities: {
111
+ supportedPlatforms: this.platformUtils.getSupportedPlatforms(),
112
+ supportedArchitectures: ['x64', 'arm64'],
113
+ minimumNodeVersion: '16.0.0'
114
+ }
115
+ };
116
+ }
117
+
118
+ /**
119
+ * Check if system supports a specific platform
120
+ * @param {string|Array<string>} supportedPlatforms - Platform or platforms to check
121
+ * @returns {Object} Platform compatibility result
122
+ */
123
+ checkPlatformCompatibility(supportedPlatforms) {
124
+ const platforms = Array.isArray(supportedPlatforms) ? supportedPlatforms : [supportedPlatforms];
125
+ const currentPlatform = this.systemInfo.platform;
126
+
127
+ return {
128
+ compatible: platforms.includes(currentPlatform),
129
+ currentPlatform: currentPlatform,
130
+ supportedPlatforms: platforms,
131
+ platformName: this.platformUtils.getPlatformName(currentPlatform)
132
+ };
133
+ }
134
+
135
+ /**
136
+ * Check if system has enough memory for requirements
137
+ * @param {string|number} memoryRequirement - Memory requirement (e.g., "512MB" or bytes)
138
+ * @returns {Object} Memory check result
139
+ */
140
+ checkMemoryRequirement(memoryRequirement) {
141
+ const requiredBytes = typeof memoryRequirement === 'string'
142
+ ? this._parseMemoryRequirement(memoryRequirement)
143
+ : memoryRequirement;
144
+
145
+ const available = this.systemInfo.freeMemory;
146
+ const total = this.systemInfo.totalMemory;
147
+
148
+ return {
149
+ satisfied: total >= requiredBytes,
150
+ required: this._formatMemory(requiredBytes),
151
+ available: this._formatMemory(available),
152
+ total: this._formatMemory(total),
153
+ utilizationPercent: Math.round((1 - available / total) * 100)
154
+ };
155
+ }
156
+
157
+ /**
158
+ * Check disk space availability
159
+ * @param {string} path - Path to check (defaults to current directory)
160
+ * @param {string|number} spaceRequirement - Required space
161
+ * @returns {Object} Disk space check result
162
+ */
163
+ checkDiskSpaceRequirement(path = process.cwd(), spaceRequirement = null) {
164
+ const result = {
165
+ path: path,
166
+ available: true,
167
+ writable: false,
168
+ error: null
169
+ };
170
+
171
+ try {
172
+ // Check if path is writable
173
+ const testFile = require('path').join(path, `.diskspace-test-${Date.now()}`);
174
+ fs.writeFileSync(testFile, 'test');
175
+ fs.unlinkSync(testFile);
176
+ result.writable = true;
177
+
178
+ if (spaceRequirement) {
179
+ // This is a simplified check - in production, you'd want to use a library like 'fs-extra' or native bindings
180
+ result.sufficientSpace = true;
181
+ result.required = typeof spaceRequirement === 'string'
182
+ ? spaceRequirement
183
+ : this._formatMemory(spaceRequirement);
184
+ }
185
+ } catch (error) {
186
+ result.available = false;
187
+ result.error = error.message;
188
+ }
189
+
190
+ return result;
191
+ }
192
+
193
+ /**
194
+ * Check Node.js version compatibility
195
+ * @param {string} minimumVersion - Minimum Node.js version required
196
+ * @returns {Object} Node.js compatibility result
197
+ */
198
+ checkNodeCompatibility(minimumVersion = '16.0.0') {
199
+ const currentVersion = this.systemInfo.nodeVersion.replace(/^v/, '');
200
+ const isCompatible = this.versionValidator.isGreaterOrEqual(currentVersion, minimumVersion);
201
+
202
+ return {
203
+ compatible: isCompatible,
204
+ currentVersion: this.systemInfo.nodeVersion,
205
+ minimumRequired: minimumVersion,
206
+ recommendation: isCompatible
207
+ ? 'Node.js version is compatible'
208
+ : `Upgrade Node.js to ${minimumVersion} or higher`
209
+ };
210
+ }
211
+
212
+ /**
213
+ * Generate system compatibility report
214
+ * @param {Object} requirements - System requirements to check against
215
+ * @returns {Object} Comprehensive compatibility report
216
+ */
217
+ generateCompatibilityReport(requirements = {}) {
218
+ const systemCheck = this.validateSystemRequirements(requirements);
219
+ const nodeCheck = this.checkNodeCompatibility(requirements.nodeVersion);
220
+ const platformCheck = this.checkPlatformCompatibility(requirements.platforms);
221
+ const memoryCheck = this.checkMemoryRequirement(requirements.memory);
222
+
223
+ const allChecks = [
224
+ { name: 'System Requirements', ...systemCheck },
225
+ { name: 'Node.js Compatibility', ...nodeCheck },
226
+ { name: 'Platform Compatibility', ...platformCheck },
227
+ { name: 'Memory Requirements', ...memoryCheck }
228
+ ];
229
+
230
+ const overallCompatible = allChecks.every(check =>
231
+ check.compatible !== false && check.satisfied !== false
232
+ );
233
+
234
+ return {
235
+ timestamp: new Date().toISOString(),
236
+ overallCompatible: overallCompatible,
237
+ systemInfo: this.getSystemInfo(),
238
+ checks: allChecks,
239
+ issues: allChecks
240
+ .filter(check => check.compatible === false || check.satisfied === false)
241
+ .map(check => `${check.name}: ${check.recommendation || 'Not compatible'}`),
242
+ recommendations: this._generateOverallRecommendations(allChecks)
243
+ };
244
+ }
245
+
246
+ /**
247
+ * Create system validation context
248
+ * @param {Object} requirements - System requirements
249
+ * @returns {Object} Validation context
250
+ * @private
251
+ */
252
+ _createSystemValidationContext(requirements) {
253
+ return {
254
+ requirements,
255
+ systemInfo: this.systemInfo
256
+ };
257
+ }
258
+
259
+ /**
260
+ * Initialize system validation result
261
+ * @returns {Object} Empty validation result
262
+ * @private
263
+ */
264
+ _initializeSystemValidationResult() {
265
+ return {
266
+ compatible: true,
267
+ checks: {}
268
+ };
269
+ }
270
+
271
+ /**
272
+ * Validate operating system compatibility
273
+ * @param {Object} result - Result object to modify
274
+ * @param {Object} context - Validation context
275
+ * @private
276
+ */
277
+ _validateOperatingSystem(result, context) {
278
+ result.checks.os = {
279
+ satisfied: context.requirements.os ?
280
+ context.requirements.os.includes(context.systemInfo.platform) : true,
281
+ current: context.systemInfo.platform,
282
+ required: context.requirements.os,
283
+ platformName: this.platformUtils.getPlatformName(context.systemInfo.platform)
284
+ };
285
+ }
286
+
287
+ /**
288
+ * Validate architecture compatibility
289
+ * @param {Object} result - Result object to modify
290
+ * @param {Object} context - Validation context
291
+ * @private
292
+ */
293
+ _validateArchitecture(result, context) {
294
+ result.checks.arch = {
295
+ satisfied: context.requirements.arch ?
296
+ context.requirements.arch.includes(context.systemInfo.arch) : true,
297
+ current: context.systemInfo.arch,
298
+ required: context.requirements.arch
299
+ };
300
+ }
301
+
302
+ /**
303
+ * Validate Node.js version requirements
304
+ * @param {Object} result - Result object to modify
305
+ * @param {Object} context - Validation context
306
+ * @private
307
+ */
308
+ _validateNodeVersion(result, context) {
309
+ if (context.requirements.nodeVersion) {
310
+ const nodeVersionCheck = this.versionValidator.validateVersionRequirement(
311
+ context.requirements.nodeVersion,
312
+ context.systemInfo.nodeVersion
313
+ );
314
+ result.checks.nodeVersion = {
315
+ satisfied: nodeVersionCheck.satisfies,
316
+ current: context.systemInfo.nodeVersion,
317
+ required: context.requirements.nodeVersion
318
+ };
319
+ } else {
320
+ result.checks.nodeVersion = { satisfied: true };
321
+ }
322
+ }
323
+
324
+ /**
325
+ * Validate memory requirements
326
+ * @param {Object} result - Result object to modify
327
+ * @param {Object} context - Validation context
328
+ * @private
329
+ */
330
+ _validateMemoryRequirements(result, context) {
331
+ if (context.requirements.memory) {
332
+ const requiredMemoryBytes = this._parseMemoryRequirement(context.requirements.memory);
333
+ result.checks.memory = {
334
+ satisfied: context.systemInfo.totalMemory >= requiredMemoryBytes,
335
+ current: this._formatMemory(context.systemInfo.totalMemory),
336
+ free: this._formatMemory(context.systemInfo.freeMemory),
337
+ required: context.requirements.memory
338
+ };
339
+ } else {
340
+ result.checks.memory = { satisfied: true };
341
+ }
342
+ }
343
+
344
+ /**
345
+ * Validate disk space requirements
346
+ * @param {Object} result - Result object to modify
347
+ * @param {Object} context - Validation context
348
+ * @private
349
+ */
350
+ _validateDiskSpace(result, context) {
351
+ const diskCheck = this.checkDiskSpaceRequirement(process.cwd(), context.requirements.diskSpace);
352
+ result.checks.diskSpace = {
353
+ satisfied: diskCheck.available && diskCheck.writable,
354
+ available: diskCheck.available,
355
+ writable: diskCheck.writable,
356
+ required: context.requirements.diskSpace || 'N/A'
357
+ };
358
+ }
359
+
360
+ /**
361
+ * Calculate overall system compatibility
362
+ * @param {Object} result - Result object to modify
363
+ * @private
364
+ */
365
+ _calculateOverallCompatibility(result) {
366
+ result.compatible = Object.values(result.checks).every(check => check.satisfied);
367
+ }
368
+
369
+ /**
370
+ * Parse memory requirement string (private)
371
+ * @param {string} memory - Memory requirement (e.g., "512MB")
372
+ * @returns {number} Memory in bytes
373
+ * @private
374
+ */
375
+ _parseMemoryRequirement(memory) {
376
+ const units = {
377
+ 'B': 1,
378
+ 'KB': 1024,
379
+ 'MB': 1024 * 1024,
380
+ 'GB': 1024 * 1024 * 1024
381
+ };
382
+
383
+ const match = memory.match(/(\d+)\s*(B|KB|MB|GB)/i);
384
+ if (match) {
385
+ return parseInt(match[1]) * (units[match[2].toUpperCase()] || 1);
386
+ }
387
+
388
+ return 0;
389
+ }
390
+
391
+ /**
392
+ * Format memory bytes to human readable string
393
+ * @param {number} bytes - Memory in bytes
394
+ * @returns {string} Formatted memory string
395
+ * @private
396
+ */
397
+ _formatMemory(bytes) {
398
+ const units = ['B', 'KB', 'MB', 'GB'];
399
+ let size = bytes;
400
+ let unitIndex = 0;
401
+
402
+ while (size >= 1024 && unitIndex < units.length - 1) {
403
+ size /= 1024;
404
+ unitIndex++;
405
+ }
406
+
407
+ return `${Math.round(size * 100) / 100}${units[unitIndex]}`;
408
+ }
409
+
410
+
411
+ /**
412
+ * Check platform requirement
413
+ * @param {string|Array<string>} platformRequirement - Required platform(s)
414
+ * @returns {Object} Platform check result
415
+ * @private
416
+ */
417
+ _checkPlatformRequirement(platformRequirement) {
418
+ if (!platformRequirement) return { satisfied: true };
419
+
420
+ const platforms = Array.isArray(platformRequirement) ? platformRequirement : [platformRequirement];
421
+ return {
422
+ satisfied: platforms.includes(this.systemInfo.platform),
423
+ current: this.systemInfo.platform,
424
+ required: platforms
425
+ };
426
+ }
427
+
428
+ /**
429
+ * Check architecture requirement
430
+ * @param {string|Array<string>} archRequirement - Required architecture(s)
431
+ * @returns {Object} Architecture check result
432
+ * @private
433
+ */
434
+ _checkArchitectureRequirement(archRequirement) {
435
+ if (!archRequirement) return { satisfied: true };
436
+
437
+ const architectures = Array.isArray(archRequirement) ? archRequirement : [archRequirement];
438
+ return {
439
+ satisfied: architectures.includes(this.systemInfo.arch),
440
+ current: this.systemInfo.arch,
441
+ required: architectures
442
+ };
443
+ }
444
+
445
+ /**
446
+ * Check memory requirement
447
+ * @param {string} memoryRequirement - Memory requirement
448
+ * @returns {Object} Memory check result
449
+ * @private
450
+ */
451
+ _checkMemoryRequirement(memoryRequirement) {
452
+ if (!memoryRequirement) return { satisfied: true };
453
+
454
+ const requiredBytes = this._parseMemoryRequirement(memoryRequirement);
455
+ return {
456
+ satisfied: this.systemInfo.totalMemory >= requiredBytes,
457
+ current: this._formatMemory(this.systemInfo.totalMemory),
458
+ required: memoryRequirement
459
+ };
460
+ }
461
+
462
+ /**
463
+ * Check disk space requirement
464
+ * @param {string} diskRequirement - Disk space requirement
465
+ * @returns {Object} Disk space check result
466
+ * @private
467
+ */
468
+ _checkDiskSpaceRequirement(diskRequirement) {
469
+ if (!diskRequirement) return { satisfied: true };
470
+
471
+ const diskCheck = this.checkDiskSpaceRequirement(process.cwd(), diskRequirement);
472
+ return {
473
+ satisfied: diskCheck.available && diskCheck.writable,
474
+ current: 'Available',
475
+ required: diskRequirement
476
+ };
477
+ }
478
+
479
+ /**
480
+ * Check Node.js version requirement
481
+ * @param {string} nodeVersionRequirement - Node.js version requirement
482
+ * @returns {Object} Node version check result
483
+ * @private
484
+ */
485
+ _checkNodeVersionRequirement(nodeVersionRequirement) {
486
+ if (!nodeVersionRequirement) return { satisfied: true };
487
+
488
+ const nodeCheck = this.checkNodeCompatibility(nodeVersionRequirement);
489
+ return {
490
+ satisfied: nodeCheck.compatible,
491
+ current: nodeCheck.currentVersion,
492
+ required: nodeVersionRequirement
493
+ };
494
+ }
495
+
496
+ /**
497
+ * Generate compatibility recommendations
498
+ * @param {Object} checks - Compatibility check results
499
+ * @returns {Array<string>} List of recommendations
500
+ * @private
501
+ */
502
+ _generateCompatibilityRecommendations(checks) {
503
+ const recommendations = [];
504
+
505
+ Object.entries(checks).forEach(([checkName, result]) => {
506
+ if (!result.satisfied) {
507
+ switch (checkName) {
508
+ case 'platform':
509
+ recommendations.push(`Switch to a supported platform: ${result.required.join(', ')}`);
510
+ break;
511
+ case 'architecture':
512
+ recommendations.push(`Use a supported architecture: ${result.required.join(', ')}`);
513
+ break;
514
+ case 'memory':
515
+ recommendations.push(`Increase system memory to at least ${result.required}`);
516
+ break;
517
+ case 'diskSpace':
518
+ recommendations.push(`Ensure sufficient disk space: ${result.required}`);
519
+ break;
520
+ case 'nodeVersion':
521
+ recommendations.push(`Upgrade Node.js to version ${result.required} or higher`);
522
+ break;
523
+ }
524
+ }
525
+ });
526
+
527
+ return recommendations;
528
+ }
529
+
530
+ /**
531
+ * Generate overall recommendations
532
+ * @param {Array} allChecks - All compatibility checks
533
+ * @returns {Array<string>} Overall recommendations
534
+ * @private
535
+ */
536
+ _generateOverallRecommendations(allChecks) {
537
+ const recommendations = [];
538
+
539
+ const failedChecks = allChecks.filter(check =>
540
+ check.compatible === false || check.satisfied === false
541
+ );
542
+
543
+ if (failedChecks.length === 0) {
544
+ recommendations.push('System is fully compatible with requirements');
545
+ } else {
546
+ recommendations.push('Address the following compatibility issues:');
547
+ failedChecks.forEach(check => {
548
+ if (check.recommendation) {
549
+ recommendations.push(`- ${check.recommendation}`);
550
+ }
551
+ });
552
+ }
553
+
554
+ return recommendations;
555
+ }
556
+ }
557
+
558
+ module.exports = SystemRequirementsChecker;
package/lib/utils.js ADDED
@@ -0,0 +1,15 @@
1
+ // Utility functions for Claude Dev Toolkit
2
+ const path = require('path');
3
+ const fs = require('fs');
4
+
5
+ module.exports = {
6
+ ensureDirectory: (dirPath) => {
7
+ if (!fs.existsSync(dirPath)) {
8
+ fs.mkdirSync(dirPath, { recursive: true });
9
+ }
10
+ },
11
+
12
+ isValidCommand: (commandName) => {
13
+ return /^[a-z][a-z0-9-]*$/.test(commandName);
14
+ }
15
+ };