@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.
- package/README.md +254 -0
- package/bin/claude-commands +132 -0
- package/lib/claude-code-compatibility.js +545 -0
- package/lib/command-selector.js +245 -0
- package/lib/config.js +182 -0
- package/lib/context-utils.js +80 -0
- package/lib/dependency-validator.js +354 -0
- package/lib/error-factory.js +394 -0
- package/lib/error-handler-utils.js +432 -0
- package/lib/error-recovery-system.js +563 -0
- package/lib/failure-recovery-installer.js +370 -0
- package/lib/hook-installer-core.js +330 -0
- package/lib/hook-installer.js +187 -0
- package/lib/hook-metadata-service.js +352 -0
- package/lib/hook-validator.js +358 -0
- package/lib/installation-configuration.js +380 -0
- package/lib/installation-instruction-generator.js +564 -0
- package/lib/installer.js +68 -0
- package/lib/package-manager-service.js +270 -0
- package/lib/permission-error-handler.js +543 -0
- package/lib/platform-utils.js +491 -0
- package/lib/setup-wizard-ui.js +245 -0
- package/lib/setup-wizard.js +355 -0
- package/lib/system-requirements-checker.js +558 -0
- package/lib/utils.js +15 -0
- package/lib/validation-utils.js +320 -0
- package/lib/version-validator-service.js +326 -0
- package/package.json +73 -0
- package/scripts/postinstall.js +182 -0
- package/scripts/validate.js +94 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Factory
|
|
3
|
+
*
|
|
4
|
+
* Standardized error creation factory for consistent error handling across the application.
|
|
5
|
+
* Works in conjunction with ErrorHandlerUtils to provide comprehensive error management.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Standardized error creation methods
|
|
9
|
+
* - Consistent error codes and structures
|
|
10
|
+
* - Context-aware error generation
|
|
11
|
+
* - Integration with error handling workflows
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const ErrorHandlerUtils = require('./error-handler-utils');
|
|
15
|
+
|
|
16
|
+
class ErrorFactory {
|
|
17
|
+
constructor() {
|
|
18
|
+
this.errorHandler = new ErrorHandlerUtils();
|
|
19
|
+
this.config = {
|
|
20
|
+
errorCodes: this.errorHandler.config.errorCodes,
|
|
21
|
+
defaultContext: {
|
|
22
|
+
timestamp: () => new Date().toISOString(),
|
|
23
|
+
platform: process.platform,
|
|
24
|
+
nodeVersion: process.version
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Create standardized error object
|
|
31
|
+
* @param {string} code - Error code
|
|
32
|
+
* @param {string} message - Error message
|
|
33
|
+
* @param {Object} details - Additional error details
|
|
34
|
+
* @param {Object} context - Error context
|
|
35
|
+
* @returns {Error} Standardized error object
|
|
36
|
+
*/
|
|
37
|
+
createStandardError(code, message, details = {}, context = {}) {
|
|
38
|
+
const error = new Error(message);
|
|
39
|
+
error.code = code;
|
|
40
|
+
error.details = details;
|
|
41
|
+
error.context = { ...this.config.defaultContext, ...context };
|
|
42
|
+
error.timestamp = new Date().toISOString();
|
|
43
|
+
return error;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Create permission-related errors
|
|
48
|
+
*/
|
|
49
|
+
createPermissionError(message, path, context = {}) {
|
|
50
|
+
return this.createStandardError(
|
|
51
|
+
this.config.errorCodes.EACCES,
|
|
52
|
+
message,
|
|
53
|
+
{ path, type: 'permission' },
|
|
54
|
+
context
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
createNotFoundError(message, path, context = {}) {
|
|
59
|
+
return this.createStandardError(
|
|
60
|
+
this.config.errorCodes.ENOENT,
|
|
61
|
+
message,
|
|
62
|
+
{ path, type: 'not_found' },
|
|
63
|
+
context
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
createPermissionDeniedError(operation, path, context = {}) {
|
|
68
|
+
return this.createStandardError(
|
|
69
|
+
this.config.errorCodes.EPERM,
|
|
70
|
+
`Permission denied for ${operation} on ${path}`,
|
|
71
|
+
{ operation, path, type: 'permission_denied' },
|
|
72
|
+
context
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Create validation-related errors
|
|
78
|
+
*/
|
|
79
|
+
createValidationError(message, field, value, context = {}) {
|
|
80
|
+
return this.createStandardError(
|
|
81
|
+
this.config.errorCodes.VALIDATION_ERROR,
|
|
82
|
+
message,
|
|
83
|
+
{ field, value, type: 'validation' },
|
|
84
|
+
context
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
createInvalidInputError(message, input, expectedType = null, context = {}) {
|
|
89
|
+
return this.createStandardError(
|
|
90
|
+
this.config.errorCodes.INVALID_INPUT,
|
|
91
|
+
message,
|
|
92
|
+
{ input, expectedType, type: 'invalid_input' },
|
|
93
|
+
context
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
createConfigurationError(message, configPath, configData = null, context = {}) {
|
|
98
|
+
return this.createStandardError(
|
|
99
|
+
this.config.errorCodes.INVALID_CONFIGURATION,
|
|
100
|
+
message,
|
|
101
|
+
{ configPath, configData, type: 'configuration' },
|
|
102
|
+
context
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
createMissingRequiredFieldError(field, object, context = {}) {
|
|
107
|
+
return this.createStandardError(
|
|
108
|
+
this.config.errorCodes.MISSING_REQUIRED_FIELD,
|
|
109
|
+
`Missing required field: ${field}`,
|
|
110
|
+
{ field, object, type: 'missing_field' },
|
|
111
|
+
context
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Create dependency-related errors
|
|
117
|
+
*/
|
|
118
|
+
createDependencyNotFoundError(dependency, details = {}, context = {}) {
|
|
119
|
+
return this.createStandardError(
|
|
120
|
+
this.config.errorCodes.NOT_FOUND,
|
|
121
|
+
`Dependency not found: ${dependency}`,
|
|
122
|
+
{ dependency, ...details, type: 'dependency_not_found' },
|
|
123
|
+
context
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
createVersionMismatchError(dependency, current, required, context = {}) {
|
|
128
|
+
return this.createStandardError(
|
|
129
|
+
this.config.errorCodes.VERSION_MISMATCH,
|
|
130
|
+
`Version mismatch for ${dependency}: current ${current}, required ${required}`,
|
|
131
|
+
{ dependency, current, required, type: 'version_mismatch' },
|
|
132
|
+
context
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
createDependencyConflictError(dependency1, dependency2, reason, context = {}) {
|
|
137
|
+
return this.createStandardError(
|
|
138
|
+
this.config.errorCodes.DEPENDENCY_CONFLICT,
|
|
139
|
+
`Dependency conflict between ${dependency1} and ${dependency2}: ${reason}`,
|
|
140
|
+
{ dependency1, dependency2, reason, type: 'dependency_conflict' },
|
|
141
|
+
context
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Create system-related errors
|
|
147
|
+
*/
|
|
148
|
+
createSystemError(message, details = {}, context = {}) {
|
|
149
|
+
return this.createStandardError(
|
|
150
|
+
this.config.errorCodes.SYSTEM_FAILURE,
|
|
151
|
+
message,
|
|
152
|
+
{ ...details, type: 'system' },
|
|
153
|
+
context
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
createInsufficientResourcesError(resource, available, required, context = {}) {
|
|
158
|
+
return this.createStandardError(
|
|
159
|
+
this.config.errorCodes.INSUFFICIENT_RESOURCES,
|
|
160
|
+
`Insufficient ${resource}: available ${available}, required ${required}`,
|
|
161
|
+
{ resource, available, required, type: 'insufficient_resources' },
|
|
162
|
+
context
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
createCorruptionError(target, details = {}, context = {}) {
|
|
167
|
+
return this.createStandardError(
|
|
168
|
+
this.config.errorCodes.CORRUPTION,
|
|
169
|
+
`Corruption detected in ${target}`,
|
|
170
|
+
{ target, ...details, type: 'corruption' },
|
|
171
|
+
context
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Create installation-related errors
|
|
177
|
+
*/
|
|
178
|
+
createInstallationError(operation, details = {}, context = {}) {
|
|
179
|
+
return this.createStandardError(
|
|
180
|
+
this.config.errorCodes.INSTALLATION_FAILED,
|
|
181
|
+
`Installation failed during ${operation}`,
|
|
182
|
+
{ operation, ...details, type: 'installation' },
|
|
183
|
+
context
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
createBackupError(message, path, details = {}, context = {}) {
|
|
188
|
+
return this.createStandardError(
|
|
189
|
+
this.config.errorCodes.BACKUP_FAILED,
|
|
190
|
+
message,
|
|
191
|
+
{ path, ...details, type: 'backup' },
|
|
192
|
+
context
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
createRollbackError(message, operation, details = {}, context = {}) {
|
|
197
|
+
return this.createStandardError(
|
|
198
|
+
this.config.errorCodes.ROLLBACK_FAILED,
|
|
199
|
+
message,
|
|
200
|
+
{ operation, ...details, type: 'rollback' },
|
|
201
|
+
context
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Create network-related errors
|
|
207
|
+
*/
|
|
208
|
+
createNetworkError(message, url, timeout = null, context = {}) {
|
|
209
|
+
return this.createStandardError(
|
|
210
|
+
this.config.errorCodes.TIMEOUT,
|
|
211
|
+
message,
|
|
212
|
+
{ url, timeout, type: 'network' },
|
|
213
|
+
context
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
createConnectionError(message, host, port = null, context = {}) {
|
|
218
|
+
return this.createStandardError(
|
|
219
|
+
this.config.errorCodes.ECONNREFUSED,
|
|
220
|
+
message,
|
|
221
|
+
{ host, port, type: 'connection' },
|
|
222
|
+
context
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
createDnsError(message, hostname, context = {}) {
|
|
227
|
+
return this.createStandardError(
|
|
228
|
+
this.config.errorCodes.ENOTFOUND,
|
|
229
|
+
message,
|
|
230
|
+
{ hostname, type: 'dns' },
|
|
231
|
+
context
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Create operation-related errors
|
|
237
|
+
*/
|
|
238
|
+
createOperationFailedError(operation, reason, details = {}, context = {}) {
|
|
239
|
+
return this.createStandardError(
|
|
240
|
+
this.config.errorCodes.OPERATION_FAILED,
|
|
241
|
+
`Operation failed: ${operation} - ${reason}`,
|
|
242
|
+
{ operation, reason, ...details, type: 'operation' },
|
|
243
|
+
context
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
createUnknownError(message = 'An unknown error occurred', details = {}, context = {}) {
|
|
248
|
+
return this.createStandardError(
|
|
249
|
+
this.config.errorCodes.UNKNOWN_ERROR,
|
|
250
|
+
message,
|
|
251
|
+
{ ...details, type: 'unknown' },
|
|
252
|
+
context
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Wrap an existing error with enhanced context
|
|
258
|
+
* @param {Error} originalError - Original error to wrap
|
|
259
|
+
* @param {Object} additionalContext - Additional context to add
|
|
260
|
+
* @returns {Error} Enhanced error
|
|
261
|
+
*/
|
|
262
|
+
wrapError(originalError, additionalContext = {}) {
|
|
263
|
+
if (!originalError) {
|
|
264
|
+
return this.createUnknownError('No error provided', {}, additionalContext);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const enhanced = this.errorHandler.createEnhancedError(originalError, additionalContext);
|
|
268
|
+
|
|
269
|
+
// Create new error with enhanced information
|
|
270
|
+
const wrappedError = new Error(enhanced.message);
|
|
271
|
+
wrappedError.code = enhanced.code;
|
|
272
|
+
wrappedError.details = enhanced.details || {};
|
|
273
|
+
wrappedError.context = enhanced.context;
|
|
274
|
+
wrappedError.category = enhanced.category;
|
|
275
|
+
wrappedError.severity = enhanced.severity;
|
|
276
|
+
wrappedError.recoverable = enhanced.recoverable;
|
|
277
|
+
wrappedError.originalError = originalError;
|
|
278
|
+
wrappedError.timestamp = enhanced.timestamp;
|
|
279
|
+
|
|
280
|
+
return wrappedError;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Create error from string with automatic categorization
|
|
285
|
+
* @param {string} errorString - Error string
|
|
286
|
+
* @param {Object} context - Error context
|
|
287
|
+
* @returns {Error} Categorized error
|
|
288
|
+
*/
|
|
289
|
+
createFromString(errorString, context = {}) {
|
|
290
|
+
if (!errorString || typeof errorString !== 'string') {
|
|
291
|
+
return this.createInvalidInputError('Invalid error string provided', errorString, 'string', context);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Try to detect error type from string content
|
|
295
|
+
const lowerString = errorString.toLowerCase();
|
|
296
|
+
|
|
297
|
+
if (lowerString.includes('permission') || lowerString.includes('access')) {
|
|
298
|
+
return this.createPermissionError(errorString, null, context);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (lowerString.includes('not found') || lowerString.includes('missing')) {
|
|
302
|
+
return this.createNotFoundError(errorString, null, context);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (lowerString.includes('network') || lowerString.includes('timeout')) {
|
|
306
|
+
return this.createNetworkError(errorString, null, null, context);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
if (lowerString.includes('validation') || lowerString.includes('invalid')) {
|
|
310
|
+
return this.createValidationError(errorString, null, null, context);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Default to generic error
|
|
314
|
+
return this.createStandardError(
|
|
315
|
+
this.config.errorCodes.STRING_ERROR,
|
|
316
|
+
errorString,
|
|
317
|
+
{ originalString: errorString, type: 'string_error' },
|
|
318
|
+
context
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Create error with automatic retry configuration
|
|
324
|
+
* @param {string} code - Error code
|
|
325
|
+
* @param {string} message - Error message
|
|
326
|
+
* @param {Object} details - Error details
|
|
327
|
+
* @param {Object} retryConfig - Retry configuration
|
|
328
|
+
* @param {Object} context - Error context
|
|
329
|
+
* @returns {Error} Error with retry configuration
|
|
330
|
+
*/
|
|
331
|
+
createRetryableError(code, message, details = {}, retryConfig = {}, context = {}) {
|
|
332
|
+
const error = this.createStandardError(code, message, details, context);
|
|
333
|
+
|
|
334
|
+
error.retryConfig = {
|
|
335
|
+
maxAttempts: 3,
|
|
336
|
+
delay: 1000,
|
|
337
|
+
backoff: 'exponential',
|
|
338
|
+
retryable: true,
|
|
339
|
+
...retryConfig
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
return error;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Create contextual error for specific operations
|
|
347
|
+
* @param {string} operation - Operation being performed
|
|
348
|
+
* @param {Error|string} originalError - Original error or error message
|
|
349
|
+
* @param {Object} operationContext - Operation-specific context
|
|
350
|
+
* @returns {Error} Contextual error
|
|
351
|
+
*/
|
|
352
|
+
createContextualError(operation, originalError, operationContext = {}) {
|
|
353
|
+
const context = {
|
|
354
|
+
operation,
|
|
355
|
+
...operationContext,
|
|
356
|
+
timestamp: new Date().toISOString()
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
if (originalError instanceof Error) {
|
|
360
|
+
return this.wrapError(originalError, context);
|
|
361
|
+
} else if (typeof originalError === 'string') {
|
|
362
|
+
return this.createFromString(originalError, context);
|
|
363
|
+
} else {
|
|
364
|
+
return this.createOperationFailedError(operation, 'Unknown error occurred', { originalError }, context);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Batch create multiple errors with consistent context
|
|
370
|
+
* @param {Array} errorSpecs - Array of error specifications
|
|
371
|
+
* @param {Object} sharedContext - Shared context for all errors
|
|
372
|
+
* @returns {Array<Error>} Array of created errors
|
|
373
|
+
*/
|
|
374
|
+
createBatch(errorSpecs, sharedContext = {}) {
|
|
375
|
+
return errorSpecs.map(spec => {
|
|
376
|
+
const { code, message, details = {}, context = {} } = spec;
|
|
377
|
+
const combinedContext = { ...sharedContext, ...context };
|
|
378
|
+
return this.createStandardError(code, message, details, combinedContext);
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Get error factory instance (singleton pattern)
|
|
384
|
+
* @returns {ErrorFactory} Error factory instance
|
|
385
|
+
*/
|
|
386
|
+
static getInstance() {
|
|
387
|
+
if (!ErrorFactory._instance) {
|
|
388
|
+
ErrorFactory._instance = new ErrorFactory();
|
|
389
|
+
}
|
|
390
|
+
return ErrorFactory._instance;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
module.exports = ErrorFactory;
|