@atomic-ehr/codegen 0.0.1-canary.20251006092200.fdb4a88 → 0.0.1-canary.20251006094042.7f0be72
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/dist/cli/index.js +45 -124
- package/dist/index.d.ts +2130 -62
- package/dist/index.js +5865 -84
- package/dist/index.js.map +1 -0
- package/package.json +3 -7
- package/dist/api/builder.d.ts +0 -154
- package/dist/api/builder.js +0 -341
- package/dist/api/generators/base/BaseGenerator.d.ts +0 -186
- package/dist/api/generators/base/BaseGenerator.js +0 -565
- package/dist/api/generators/base/FileManager.d.ts +0 -88
- package/dist/api/generators/base/FileManager.js +0 -202
- package/dist/api/generators/base/PythonTypeMapper.d.ts +0 -16
- package/dist/api/generators/base/PythonTypeMapper.js +0 -71
- package/dist/api/generators/base/TemplateEngine.d.ts +0 -126
- package/dist/api/generators/base/TemplateEngine.js +0 -133
- package/dist/api/generators/base/TypeMapper.d.ts +0 -129
- package/dist/api/generators/base/TypeMapper.js +0 -153
- package/dist/api/generators/base/TypeScriptTypeMapper.d.ts +0 -51
- package/dist/api/generators/base/TypeScriptTypeMapper.js +0 -232
- package/dist/api/generators/base/builders/DirectoryBuilder.d.ts +0 -99
- package/dist/api/generators/base/builders/DirectoryBuilder.js +0 -215
- package/dist/api/generators/base/builders/FileBuilder.d.ts +0 -160
- package/dist/api/generators/base/builders/FileBuilder.js +0 -406
- package/dist/api/generators/base/builders/IndexBuilder.d.ts +0 -126
- package/dist/api/generators/base/builders/IndexBuilder.js +0 -290
- package/dist/api/generators/base/enhanced-errors.d.ts +0 -84
- package/dist/api/generators/base/enhanced-errors.js +0 -259
- package/dist/api/generators/base/error-handler.d.ts +0 -89
- package/dist/api/generators/base/error-handler.js +0 -243
- package/dist/api/generators/base/errors.d.ts +0 -251
- package/dist/api/generators/base/errors.js +0 -692
- package/dist/api/generators/base/index.d.ts +0 -99
- package/dist/api/generators/base/index.js +0 -160
- package/dist/api/generators/base/types.d.ts +0 -433
- package/dist/api/generators/base/types.js +0 -12
- package/dist/api/generators/types.d.ts +0 -53
- package/dist/api/generators/types.js +0 -4
- package/dist/api/generators/typescript.d.ts +0 -190
- package/dist/api/generators/typescript.js +0 -819
- package/dist/api/index.d.ts +0 -51
- package/dist/api/index.js +0 -50
- package/dist/cli/commands/generate/typescript.d.ts +0 -10
- package/dist/cli/commands/generate/typescript.js +0 -52
- package/dist/cli/commands/generate.d.ts +0 -15
- package/dist/cli/commands/generate.js +0 -159
- package/dist/cli/commands/index.d.ts +0 -29
- package/dist/cli/commands/index.js +0 -100
- package/dist/cli/commands/typeschema/generate.d.ts +0 -19
- package/dist/cli/commands/typeschema/generate.js +0 -124
- package/dist/cli/commands/typeschema.d.ts +0 -10
- package/dist/cli/commands/typeschema.js +0 -47
- package/dist/cli/index.d.ts +0 -9
- package/dist/cli/utils/log.d.ts +0 -10
- package/dist/cli/utils/log.js +0 -23
- package/dist/cli/utils/prompts.d.ts +0 -56
- package/dist/cli/utils/prompts.js +0 -202
- package/dist/cli/utils/spinner.d.ts +0 -110
- package/dist/cli/utils/spinner.js +0 -266
- package/dist/config.d.ts +0 -217
- package/dist/config.js +0 -591
- package/dist/logger.d.ts +0 -157
- package/dist/logger.js +0 -281
- package/dist/typeschema/cache.d.ts +0 -80
- package/dist/typeschema/cache.js +0 -239
- package/dist/typeschema/core/binding.d.ts +0 -11
- package/dist/typeschema/core/binding.js +0 -143
- package/dist/typeschema/core/field-builder.d.ts +0 -12
- package/dist/typeschema/core/field-builder.js +0 -123
- package/dist/typeschema/core/identifier.d.ts +0 -13
- package/dist/typeschema/core/identifier.js +0 -94
- package/dist/typeschema/core/nested-types.d.ts +0 -9
- package/dist/typeschema/core/nested-types.js +0 -93
- package/dist/typeschema/core/transformer.d.ts +0 -11
- package/dist/typeschema/core/transformer.js +0 -235
- package/dist/typeschema/generator.d.ts +0 -36
- package/dist/typeschema/generator.js +0 -243
- package/dist/typeschema/index.d.ts +0 -15
- package/dist/typeschema/index.js +0 -15
- package/dist/typeschema/parser.d.ts +0 -79
- package/dist/typeschema/parser.js +0 -274
- package/dist/typeschema/profile/processor.d.ts +0 -14
- package/dist/typeschema/profile/processor.js +0 -261
- package/dist/typeschema/register.d.ts +0 -21
- package/dist/typeschema/register.js +0 -117
- package/dist/typeschema/types.d.ts +0 -240
- package/dist/typeschema/types.js +0 -19
- package/dist/utils/codegen-logger.d.ts +0 -102
- package/dist/utils/codegen-logger.js +0 -196
- package/dist/utils.d.ts +0 -22
- package/dist/utils.js +0 -42
|
@@ -1,692 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Comprehensive error handling system for the base generator
|
|
3
|
-
*
|
|
4
|
-
* This module provides rich, contextual error classes that help developers
|
|
5
|
-
* at all skill levels understand and resolve issues quickly.
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Base error class for all generator-related errors
|
|
9
|
-
*
|
|
10
|
-
* Provides common functionality like context tracking, suggestions,
|
|
11
|
-
* and detailed error reporting that makes debugging easier.
|
|
12
|
-
*/
|
|
13
|
-
export class GeneratorError extends Error {
|
|
14
|
-
phase;
|
|
15
|
-
context;
|
|
16
|
-
/** When this error occurred */
|
|
17
|
-
timestamp;
|
|
18
|
-
/** Unique error ID for tracking */
|
|
19
|
-
errorId;
|
|
20
|
-
constructor(message,
|
|
21
|
-
/** Phase of generation where error occurred */
|
|
22
|
-
phase,
|
|
23
|
-
/** Additional context about the error */
|
|
24
|
-
context) {
|
|
25
|
-
super(message);
|
|
26
|
-
this.phase = phase;
|
|
27
|
-
this.context = context;
|
|
28
|
-
this.name = this.constructor.name;
|
|
29
|
-
this.timestamp = new Date();
|
|
30
|
-
this.errorId = this.generateErrorId();
|
|
31
|
-
// Maintain proper stack trace in V8
|
|
32
|
-
if (Error.captureStackTrace) {
|
|
33
|
-
Error.captureStackTrace(this, this.constructor);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Generate a unique error ID for tracking
|
|
38
|
-
*/
|
|
39
|
-
generateErrorId() {
|
|
40
|
-
return `${this.constructor.name}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Get formatted error message with full context
|
|
44
|
-
* This provides a comprehensive view of what went wrong
|
|
45
|
-
*/
|
|
46
|
-
getDetailedMessage() {
|
|
47
|
-
const lines = [
|
|
48
|
-
`❌ ${this.constructor.name}: ${this.message}`,
|
|
49
|
-
` Error ID: ${this.errorId}`,
|
|
50
|
-
` Phase: ${this.phase}`,
|
|
51
|
-
` Time: ${this.timestamp.toISOString()}`,
|
|
52
|
-
];
|
|
53
|
-
if (this.context && Object.keys(this.context).length > 0) {
|
|
54
|
-
lines.push("");
|
|
55
|
-
lines.push("📍 Context:");
|
|
56
|
-
Object.entries(this.context).forEach(([key, value]) => {
|
|
57
|
-
lines.push(` ${key}: ${this.formatContextValue(value)}`);
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
return lines.join("\n");
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Format context values for display
|
|
64
|
-
*/
|
|
65
|
-
formatContextValue(value) {
|
|
66
|
-
if (value === null || value === undefined) {
|
|
67
|
-
return String(value);
|
|
68
|
-
}
|
|
69
|
-
if (typeof value === "string") {
|
|
70
|
-
return `"${value}"`;
|
|
71
|
-
}
|
|
72
|
-
if (typeof value === "object") {
|
|
73
|
-
try {
|
|
74
|
-
return JSON.stringify(value, null, 2);
|
|
75
|
-
}
|
|
76
|
-
catch {
|
|
77
|
-
return "[Object]";
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
return String(value);
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Get error severity level
|
|
84
|
-
*/
|
|
85
|
-
getSeverity() {
|
|
86
|
-
return "error";
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Check if this error is recoverable
|
|
90
|
-
*/
|
|
91
|
-
isRecoverable() {
|
|
92
|
-
return false;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Get related documentation links
|
|
96
|
-
*/
|
|
97
|
-
getDocumentationLinks() {
|
|
98
|
-
return [
|
|
99
|
-
"https://github.com/atomic-ehr/codegen/docs/troubleshooting.md",
|
|
100
|
-
`https://github.com/atomic-ehr/codegen/docs/errors/${this.constructor.name}.md`,
|
|
101
|
-
];
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Schema validation errors with intelligent suggestions
|
|
106
|
-
*/
|
|
107
|
-
export class SchemaValidationError extends GeneratorError {
|
|
108
|
-
schema;
|
|
109
|
-
validationErrors;
|
|
110
|
-
userContext;
|
|
111
|
-
constructor(message,
|
|
112
|
-
/** The schema that failed validation */
|
|
113
|
-
schema,
|
|
114
|
-
/** Specific validation errors */
|
|
115
|
-
validationErrors,
|
|
116
|
-
/** Additional user context for better suggestions */
|
|
117
|
-
userContext) {
|
|
118
|
-
super(message, "validation", {
|
|
119
|
-
schemaName: schema.identifier?.name || "unknown",
|
|
120
|
-
schemaKind: schema.identifier?.kind || "unknown",
|
|
121
|
-
schemaPackage: schema.identifier?.package || "unknown",
|
|
122
|
-
validationErrors,
|
|
123
|
-
userContext,
|
|
124
|
-
});
|
|
125
|
-
this.schema = schema;
|
|
126
|
-
this.validationErrors = validationErrors;
|
|
127
|
-
this.userContext = userContext;
|
|
128
|
-
}
|
|
129
|
-
getSuggestions() {
|
|
130
|
-
const suggestions = [];
|
|
131
|
-
// Add basic validation suggestions
|
|
132
|
-
suggestions.push("Verify the schema follows the TypeSchema specification");
|
|
133
|
-
suggestions.push("Check that all required fields are present and properly typed");
|
|
134
|
-
// Context-aware suggestions based on specific errors
|
|
135
|
-
for (const error of this.validationErrors) {
|
|
136
|
-
if (error.includes("identifier.name")) {
|
|
137
|
-
suggestions.push("✨ Add a valid identifier.name field to your schema");
|
|
138
|
-
suggestions.push('💡 Example: identifier: { name: "Patient", kind: "resource" }');
|
|
139
|
-
}
|
|
140
|
-
if (error.includes("identifier.kind")) {
|
|
141
|
-
suggestions.push('🎯 Set identifier.kind to: "resource", "complex-type", "profile", or "primitive-type"');
|
|
142
|
-
suggestions.push("📚 Check FHIR specification for the correct kind value");
|
|
143
|
-
}
|
|
144
|
-
if (error.includes("circular")) {
|
|
145
|
-
suggestions.push("🔄 Remove circular references between schemas");
|
|
146
|
-
suggestions.push("💡 Use forward declarations for recursive types");
|
|
147
|
-
suggestions.push("🔍 Look for schemas that reference each other in a loop");
|
|
148
|
-
}
|
|
149
|
-
if (error.includes("fields")) {
|
|
150
|
-
suggestions.push("📝 Check that all fields have proper type definitions");
|
|
151
|
-
suggestions.push("🔧 Ensure field types reference valid TypeSchema identifiers");
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
// Beginner-specific suggestions
|
|
155
|
-
if (this.userContext?.isBeginnerMode) {
|
|
156
|
-
suggestions.push("");
|
|
157
|
-
suggestions.push("🎓 Beginner Tips:");
|
|
158
|
-
suggestions.push("📖 Start with the Quick Start guide: docs/getting-started/quick-start.md");
|
|
159
|
-
suggestions.push("🔍 Use --verbose flag for detailed error information");
|
|
160
|
-
suggestions.push("🧪 Test with a simple schema first to verify your setup");
|
|
161
|
-
if (this.userContext.previousSuccessfulSchemas?.length) {
|
|
162
|
-
suggestions.push(`✅ Compare with your working schema: ${this.userContext.previousSuccessfulSchemas[0]}`);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
// Advanced suggestions for experienced users
|
|
166
|
-
if (!this.userContext?.isBeginnerMode) {
|
|
167
|
-
suggestions.push("");
|
|
168
|
-
suggestions.push("🔧 Advanced Debugging:");
|
|
169
|
-
suggestions.push("🕵️ Enable schema validation debugging");
|
|
170
|
-
suggestions.push("📊 Check schema statistics and complexity metrics");
|
|
171
|
-
suggestions.push("⚡ Consider schema preprocessing if dealing with complex inheritance");
|
|
172
|
-
}
|
|
173
|
-
return suggestions;
|
|
174
|
-
}
|
|
175
|
-
isRecoverable() {
|
|
176
|
-
// Simple validation errors like missing fields are usually recoverable
|
|
177
|
-
return this.validationErrors.every((error) => !error.includes("circular") && !error.includes("corruption"));
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Template processing errors with debugging information
|
|
182
|
-
*/
|
|
183
|
-
export class TemplateError extends GeneratorError {
|
|
184
|
-
templateName;
|
|
185
|
-
templateContext;
|
|
186
|
-
debugInfo;
|
|
187
|
-
constructor(message,
|
|
188
|
-
/** Name of the template that failed */
|
|
189
|
-
templateName,
|
|
190
|
-
/** Context data passed to the template */
|
|
191
|
-
templateContext,
|
|
192
|
-
/** Additional debugging information */
|
|
193
|
-
debugInfo) {
|
|
194
|
-
super(message, "generation", {
|
|
195
|
-
templateName,
|
|
196
|
-
contextKeys: Object.keys(templateContext),
|
|
197
|
-
availableTemplates: debugInfo?.availableTemplates?.length || 0,
|
|
198
|
-
debugInfo,
|
|
199
|
-
});
|
|
200
|
-
this.templateName = templateName;
|
|
201
|
-
this.templateContext = templateContext;
|
|
202
|
-
this.debugInfo = debugInfo;
|
|
203
|
-
}
|
|
204
|
-
getSuggestions() {
|
|
205
|
-
const suggestions = [];
|
|
206
|
-
// Template existence suggestions
|
|
207
|
-
if (this.debugInfo?.availableTemplates?.length) {
|
|
208
|
-
if (!this.debugInfo.availableTemplates.includes(this.templateName)) {
|
|
209
|
-
suggestions.push(`❌ Template '${this.templateName}' not found`);
|
|
210
|
-
suggestions.push("📂 Available templates:");
|
|
211
|
-
this.debugInfo.availableTemplates.forEach((template) => {
|
|
212
|
-
suggestions.push(` • ${template}`);
|
|
213
|
-
});
|
|
214
|
-
// Suggest similar template names using Levenshtein distance
|
|
215
|
-
const similar = this.findSimilarTemplates(this.templateName, this.debugInfo.availableTemplates);
|
|
216
|
-
if (similar.length > 0) {
|
|
217
|
-
suggestions.push("🤔 Did you mean:");
|
|
218
|
-
similar.forEach((template) => {
|
|
219
|
-
suggestions.push(` • ${template}`);
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
// Missing variables suggestions
|
|
225
|
-
if (this.debugInfo?.missingVariables?.length) {
|
|
226
|
-
suggestions.push("📝 Missing template variables:");
|
|
227
|
-
this.debugInfo.missingVariables.forEach((variable) => {
|
|
228
|
-
suggestions.push(` • ${variable}`);
|
|
229
|
-
});
|
|
230
|
-
suggestions.push("💡 Add these variables to your template context");
|
|
231
|
-
// Suggest similar variable names from context
|
|
232
|
-
const contextKeys = Object.keys(this.templateContext);
|
|
233
|
-
this.debugInfo.missingVariables.forEach((missing) => {
|
|
234
|
-
const similar = contextKeys.filter((key) => this.levenshteinDistance(missing.toLowerCase(), key.toLowerCase()) <= 2);
|
|
235
|
-
if (similar.length > 0) {
|
|
236
|
-
suggestions.push(` Similar to: ${similar.join(", ")}`);
|
|
237
|
-
}
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
// Template syntax suggestions
|
|
241
|
-
if (this.debugInfo?.lineNumber) {
|
|
242
|
-
suggestions.push(`🐛 Check template syntax around line ${this.debugInfo.lineNumber}`);
|
|
243
|
-
if (this.debugInfo.columnNumber) {
|
|
244
|
-
suggestions.push(` Column: ${this.debugInfo.columnNumber}`);
|
|
245
|
-
}
|
|
246
|
-
if (this.debugInfo.templateSource) {
|
|
247
|
-
const lines = this.debugInfo.templateSource.split("\n");
|
|
248
|
-
const errorLine = lines[this.debugInfo.lineNumber - 1];
|
|
249
|
-
if (errorLine) {
|
|
250
|
-
suggestions.push(` Code: ${errorLine.trim()}`);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
// General template debugging
|
|
255
|
-
suggestions.push("🔧 Template debugging steps:");
|
|
256
|
-
suggestions.push(" • Enable template debugging: { debug: true }");
|
|
257
|
-
suggestions.push(" • Verify template file exists and has correct syntax");
|
|
258
|
-
suggestions.push(" • Check template variable names match context keys");
|
|
259
|
-
suggestions.push(" • Ensure template engine is properly configured");
|
|
260
|
-
return suggestions;
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* Find templates with similar names using Levenshtein distance
|
|
264
|
-
*/
|
|
265
|
-
findSimilarTemplates(target, available) {
|
|
266
|
-
return available
|
|
267
|
-
.filter((template) => {
|
|
268
|
-
const distance = this.levenshteinDistance(target.toLowerCase(), template.toLowerCase());
|
|
269
|
-
return distance <= 2 && distance > 0;
|
|
270
|
-
})
|
|
271
|
-
.slice(0, 3)
|
|
272
|
-
.sort((a, b) => this.levenshteinDistance(target.toLowerCase(), a.toLowerCase()) -
|
|
273
|
-
this.levenshteinDistance(target.toLowerCase(), b.toLowerCase()));
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* Calculate Levenshtein distance between two strings
|
|
277
|
-
*/
|
|
278
|
-
levenshteinDistance(str1, str2) {
|
|
279
|
-
const matrix = Array(str2.length + 1)
|
|
280
|
-
.fill(null)
|
|
281
|
-
.map(() => Array(str1.length + 1).fill(0));
|
|
282
|
-
for (let i = 0; i <= str1.length; i++)
|
|
283
|
-
matrix[0][i] = i;
|
|
284
|
-
for (let j = 0; j <= str2.length; j++)
|
|
285
|
-
matrix[j][0] = j;
|
|
286
|
-
for (let j = 1; j <= str2.length; j++) {
|
|
287
|
-
for (let i = 1; i <= str1.length; i++) {
|
|
288
|
-
const indicator = str1[i - 1] === str2[j - 1] ? 0 : 1;
|
|
289
|
-
matrix[j][i] = Math.min(matrix[j]?.[i - 1] + 1, // deletion
|
|
290
|
-
matrix[j - 1]?.[i] + 1, // insertion
|
|
291
|
-
matrix[j - 1]?.[i - 1] + indicator);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
return matrix[str2.length]?.[str1.length];
|
|
295
|
-
}
|
|
296
|
-
isRecoverable() {
|
|
297
|
-
// Template errors are usually recoverable by fixing template or context
|
|
298
|
-
return true;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
/**
|
|
302
|
-
* File operation errors with recovery suggestions
|
|
303
|
-
*/
|
|
304
|
-
export class FileOperationError extends GeneratorError {
|
|
305
|
-
operation;
|
|
306
|
-
filePath;
|
|
307
|
-
originalError;
|
|
308
|
-
recoveryOptions;
|
|
309
|
-
constructor(message,
|
|
310
|
-
/** Type of file operation that failed */
|
|
311
|
-
operation,
|
|
312
|
-
/** Path of the file that caused the error */
|
|
313
|
-
filePath,
|
|
314
|
-
/** Original system error if available */
|
|
315
|
-
originalError,
|
|
316
|
-
/** Recovery options and suggestions */
|
|
317
|
-
recoveryOptions) {
|
|
318
|
-
super(message, "writing", {
|
|
319
|
-
operation,
|
|
320
|
-
filePath,
|
|
321
|
-
originalErrorMessage: originalError?.message,
|
|
322
|
-
originalErrorCode: originalError?.code,
|
|
323
|
-
recoveryOptions,
|
|
324
|
-
});
|
|
325
|
-
this.operation = operation;
|
|
326
|
-
this.filePath = filePath;
|
|
327
|
-
this.originalError = originalError;
|
|
328
|
-
this.recoveryOptions = recoveryOptions;
|
|
329
|
-
}
|
|
330
|
-
getSuggestions() {
|
|
331
|
-
const suggestions = [];
|
|
332
|
-
const errorCode = this.originalError?.code;
|
|
333
|
-
// Operation-specific suggestions
|
|
334
|
-
switch (this.operation) {
|
|
335
|
-
case "create":
|
|
336
|
-
case "write":
|
|
337
|
-
suggestions.push("📁 File writing troubleshooting:");
|
|
338
|
-
suggestions.push(" • Check if the output directory exists");
|
|
339
|
-
suggestions.push(" • Verify write permissions for the target directory");
|
|
340
|
-
suggestions.push(" • Ensure no other process has the file locked");
|
|
341
|
-
if (this.filePath.includes(" ")) {
|
|
342
|
-
suggestions.push(" • File path contains spaces - check path escaping");
|
|
343
|
-
}
|
|
344
|
-
if (this.recoveryOptions?.alternativePaths?.length) {
|
|
345
|
-
suggestions.push("🔄 Alternative output directories:");
|
|
346
|
-
this.recoveryOptions.alternativePaths.forEach((path) => {
|
|
347
|
-
suggestions.push(` • ${path}`);
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
|
-
break;
|
|
351
|
-
case "read":
|
|
352
|
-
suggestions.push("📖 File reading troubleshooting:");
|
|
353
|
-
suggestions.push(" • Verify the file exists at the specified path");
|
|
354
|
-
suggestions.push(" • Check file read permissions");
|
|
355
|
-
suggestions.push(" • Ensure file is not corrupted");
|
|
356
|
-
break;
|
|
357
|
-
case "delete":
|
|
358
|
-
suggestions.push("🗑️ File deletion troubleshooting:");
|
|
359
|
-
suggestions.push(" • Check if file is locked by another process");
|
|
360
|
-
suggestions.push(" • Verify delete permissions for the directory");
|
|
361
|
-
suggestions.push(" • Ensure file exists before attempting deletion");
|
|
362
|
-
break;
|
|
363
|
-
}
|
|
364
|
-
// Error code specific suggestions
|
|
365
|
-
switch (errorCode) {
|
|
366
|
-
case "EACCES":
|
|
367
|
-
suggestions.push("🔐 Permission Error:");
|
|
368
|
-
suggestions.push(" • Current user lacks necessary file permissions");
|
|
369
|
-
if (this.recoveryOptions?.permissionFix) {
|
|
370
|
-
suggestions.push(` • Fix command: ${this.recoveryOptions.permissionFix}`);
|
|
371
|
-
}
|
|
372
|
-
else {
|
|
373
|
-
suggestions.push(` • Try: chmod 755 "${this.filePath}"`);
|
|
374
|
-
}
|
|
375
|
-
suggestions.push(" • Consider running with elevated permissions");
|
|
376
|
-
suggestions.push(" • Check directory ownership and permissions");
|
|
377
|
-
break;
|
|
378
|
-
case "ENOSPC":
|
|
379
|
-
suggestions.push("💾 Disk Space Error:");
|
|
380
|
-
suggestions.push(" • Insufficient disk space available");
|
|
381
|
-
suggestions.push(" • Free up disk space and retry");
|
|
382
|
-
suggestions.push(" • Consider using a different output directory");
|
|
383
|
-
if (this.recoveryOptions?.diskSpaceRequired) {
|
|
384
|
-
const mb = Math.ceil(this.recoveryOptions.diskSpaceRequired / 1024 / 1024);
|
|
385
|
-
suggestions.push(` • Required space: ~${mb}MB`);
|
|
386
|
-
}
|
|
387
|
-
break;
|
|
388
|
-
case "ENOENT":
|
|
389
|
-
suggestions.push("📂 File Not Found:");
|
|
390
|
-
suggestions.push(" • File or directory does not exist");
|
|
391
|
-
suggestions.push(" • Check the file path for typos");
|
|
392
|
-
suggestions.push(" • Ensure parent directories exist");
|
|
393
|
-
suggestions.push(` • Create directory: mkdir -p "$(dirname "${this.filePath}")"`);
|
|
394
|
-
break;
|
|
395
|
-
case "EMFILE":
|
|
396
|
-
case "ENFILE":
|
|
397
|
-
suggestions.push("📊 Too Many Open Files:");
|
|
398
|
-
suggestions.push(" • System has reached file handle limit");
|
|
399
|
-
suggestions.push(" • Close unused files and retry");
|
|
400
|
-
suggestions.push(" • Consider processing files in smaller batches");
|
|
401
|
-
break;
|
|
402
|
-
}
|
|
403
|
-
// Recovery suggestions
|
|
404
|
-
if (this.recoveryOptions?.canRetry) {
|
|
405
|
-
suggestions.push("");
|
|
406
|
-
suggestions.push("🔄 Recovery Options:");
|
|
407
|
-
suggestions.push(" • This operation can be retried safely");
|
|
408
|
-
suggestions.push(" • Fix the underlying issue and run again");
|
|
409
|
-
}
|
|
410
|
-
// General debugging
|
|
411
|
-
suggestions.push("");
|
|
412
|
-
suggestions.push("🔍 General Debugging:");
|
|
413
|
-
suggestions.push(" • Check system logs for more details");
|
|
414
|
-
suggestions.push(" • Verify disk health if errors persist");
|
|
415
|
-
suggestions.push(" • Test with a simpler file path");
|
|
416
|
-
return suggestions;
|
|
417
|
-
}
|
|
418
|
-
isRecoverable() {
|
|
419
|
-
return this.recoveryOptions?.canRetry || false;
|
|
420
|
-
}
|
|
421
|
-
/**
|
|
422
|
-
* Get specific recovery actions that can be taken
|
|
423
|
-
*/
|
|
424
|
-
getRecoveryActions() {
|
|
425
|
-
const actions = [];
|
|
426
|
-
const errorCode = this.originalError?.code;
|
|
427
|
-
switch (errorCode) {
|
|
428
|
-
case "EACCES":
|
|
429
|
-
actions.push({
|
|
430
|
-
action: "Fix file permissions",
|
|
431
|
-
command: `chmod 755 "${this.filePath}"`,
|
|
432
|
-
automatic: false,
|
|
433
|
-
riskLevel: "medium",
|
|
434
|
-
});
|
|
435
|
-
break;
|
|
436
|
-
case "ENOENT":
|
|
437
|
-
actions.push({
|
|
438
|
-
action: "Create missing directory",
|
|
439
|
-
command: `mkdir -p "$(dirname "${this.filePath}")"`,
|
|
440
|
-
automatic: true,
|
|
441
|
-
riskLevel: "low",
|
|
442
|
-
});
|
|
443
|
-
break;
|
|
444
|
-
case "ENOSPC":
|
|
445
|
-
actions.push({
|
|
446
|
-
action: "Free up disk space",
|
|
447
|
-
automatic: false,
|
|
448
|
-
riskLevel: "low",
|
|
449
|
-
});
|
|
450
|
-
break;
|
|
451
|
-
}
|
|
452
|
-
return actions;
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
/**
|
|
456
|
-
* Type mapping errors for language-specific type conversion issues
|
|
457
|
-
*/
|
|
458
|
-
export class TypeMappingError extends GeneratorError {
|
|
459
|
-
fhirType;
|
|
460
|
-
targetLanguage;
|
|
461
|
-
mappingContext;
|
|
462
|
-
constructor(message,
|
|
463
|
-
/** FHIR type that couldn't be mapped */
|
|
464
|
-
fhirType,
|
|
465
|
-
/** Target language name */
|
|
466
|
-
targetLanguage,
|
|
467
|
-
/** Additional mapping context */
|
|
468
|
-
mappingContext) {
|
|
469
|
-
super(message, "generation", {
|
|
470
|
-
fhirType,
|
|
471
|
-
targetLanguage,
|
|
472
|
-
availableMappings: mappingContext?.availableMappings?.length || 0,
|
|
473
|
-
hasSchema: !!mappingContext?.schema,
|
|
474
|
-
});
|
|
475
|
-
this.fhirType = fhirType;
|
|
476
|
-
this.targetLanguage = targetLanguage;
|
|
477
|
-
this.mappingContext = mappingContext;
|
|
478
|
-
}
|
|
479
|
-
getSuggestions() {
|
|
480
|
-
const suggestions = [];
|
|
481
|
-
suggestions.push(`🎯 Type mapping issue for '${this.fhirType}' → ${this.targetLanguage}`);
|
|
482
|
-
// Check for available mappings
|
|
483
|
-
if (this.mappingContext?.availableMappings?.length) {
|
|
484
|
-
suggestions.push("📋 Available type mappings:");
|
|
485
|
-
this.mappingContext.availableMappings.forEach((mapping) => {
|
|
486
|
-
suggestions.push(` • ${mapping}`);
|
|
487
|
-
});
|
|
488
|
-
// Suggest similar types
|
|
489
|
-
const similar = this.mappingContext.availableMappings.filter((mapping) => mapping.toLowerCase().includes(this.fhirType.toLowerCase()) ||
|
|
490
|
-
this.fhirType.toLowerCase().includes(mapping.toLowerCase()));
|
|
491
|
-
if (similar.length > 0) {
|
|
492
|
-
suggestions.push("🤔 Similar types found:");
|
|
493
|
-
similar.forEach((mapping) => {
|
|
494
|
-
suggestions.push(` • ${mapping}`);
|
|
495
|
-
});
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
// Suggested mappings
|
|
499
|
-
if (this.mappingContext?.suggestedMappings) {
|
|
500
|
-
suggestions.push("💡 Suggested mappings:");
|
|
501
|
-
Object.entries(this.mappingContext.suggestedMappings).forEach(([fhir, target]) => {
|
|
502
|
-
suggestions.push(` • ${fhir} → ${target}`);
|
|
503
|
-
});
|
|
504
|
-
}
|
|
505
|
-
// General type mapping suggestions
|
|
506
|
-
suggestions.push("");
|
|
507
|
-
suggestions.push("🔧 Fixing type mapping issues:");
|
|
508
|
-
suggestions.push(` • Add '${this.fhirType}' mapping in ${this.targetLanguage}TypeMapper`);
|
|
509
|
-
suggestions.push(" • Check if the FHIR type name is spelled correctly");
|
|
510
|
-
suggestions.push(" • Verify the type mapper is properly configured");
|
|
511
|
-
suggestions.push(" • Consider adding a fallback type mapping");
|
|
512
|
-
// Language-specific suggestions
|
|
513
|
-
switch (this.targetLanguage.toLowerCase()) {
|
|
514
|
-
case "typescript":
|
|
515
|
-
suggestions.push(" • Add to TYPESCRIPT_PRIMITIVES map");
|
|
516
|
-
suggestions.push(" • Implement in mapPrimitive() method");
|
|
517
|
-
break;
|
|
518
|
-
case "python":
|
|
519
|
-
suggestions.push(" • Add to PYTHON_TYPE_MAP dictionary");
|
|
520
|
-
suggestions.push(" • Consider using typing module types");
|
|
521
|
-
break;
|
|
522
|
-
case "rust":
|
|
523
|
-
suggestions.push(" • Add to RUST_TYPE_MAP");
|
|
524
|
-
suggestions.push(" • Consider Option<T> for nullable types");
|
|
525
|
-
break;
|
|
526
|
-
}
|
|
527
|
-
return suggestions;
|
|
528
|
-
}
|
|
529
|
-
isRecoverable() {
|
|
530
|
-
return true; // Type mapping errors can usually be fixed by updating the mapper
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
/**
|
|
534
|
-
* Configuration errors with validation details
|
|
535
|
-
*/
|
|
536
|
-
export class ConfigurationError extends GeneratorError {
|
|
537
|
-
configKey;
|
|
538
|
-
providedValue;
|
|
539
|
-
expectedValue;
|
|
540
|
-
validOptions;
|
|
541
|
-
constructor(message,
|
|
542
|
-
/** Configuration key that has an issue */
|
|
543
|
-
configKey,
|
|
544
|
-
/** The invalid value that was provided */
|
|
545
|
-
providedValue,
|
|
546
|
-
/** Expected value type or format */
|
|
547
|
-
expectedValue,
|
|
548
|
-
/** Valid options if applicable */
|
|
549
|
-
validOptions) {
|
|
550
|
-
super(message, "initialization", {
|
|
551
|
-
configKey,
|
|
552
|
-
providedValue,
|
|
553
|
-
providedType: typeof providedValue,
|
|
554
|
-
expectedValue,
|
|
555
|
-
validOptions,
|
|
556
|
-
});
|
|
557
|
-
this.configKey = configKey;
|
|
558
|
-
this.providedValue = providedValue;
|
|
559
|
-
this.expectedValue = expectedValue;
|
|
560
|
-
this.validOptions = validOptions;
|
|
561
|
-
}
|
|
562
|
-
getSuggestions() {
|
|
563
|
-
const suggestions = [];
|
|
564
|
-
suggestions.push(`⚙️ Configuration error for '${this.configKey}'`);
|
|
565
|
-
suggestions.push(` Provided: ${JSON.stringify(this.providedValue)} (${typeof this.providedValue})`);
|
|
566
|
-
if (this.expectedValue) {
|
|
567
|
-
suggestions.push(` Expected: ${this.expectedValue}`);
|
|
568
|
-
}
|
|
569
|
-
if (this.validOptions?.length) {
|
|
570
|
-
suggestions.push(" Valid options:");
|
|
571
|
-
this.validOptions.forEach((option) => {
|
|
572
|
-
suggestions.push(` • ${JSON.stringify(option)}`);
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
|
-
suggestions.push("");
|
|
576
|
-
suggestions.push("🔧 Configuration fixes:");
|
|
577
|
-
suggestions.push(` • Check the '${this.configKey}' value in your configuration`);
|
|
578
|
-
suggestions.push(" • Refer to the configuration documentation");
|
|
579
|
-
suggestions.push(" • Use TypeScript for better config validation");
|
|
580
|
-
suggestions.push(" • Check for typos in configuration keys");
|
|
581
|
-
// Specific suggestions based on config key
|
|
582
|
-
switch (this.configKey) {
|
|
583
|
-
case "outputDir":
|
|
584
|
-
suggestions.push(" • Ensure the output directory path exists");
|
|
585
|
-
suggestions.push(" • Use absolute paths for better reliability");
|
|
586
|
-
break;
|
|
587
|
-
case "logger":
|
|
588
|
-
suggestions.push(" • Provide a valid logger instance");
|
|
589
|
-
suggestions.push(" • Use createLogger() from utils/codegen-logger");
|
|
590
|
-
break;
|
|
591
|
-
case "validation":
|
|
592
|
-
suggestions.push(' • Set to true, false, or "strict"');
|
|
593
|
-
break;
|
|
594
|
-
}
|
|
595
|
-
return suggestions;
|
|
596
|
-
}
|
|
597
|
-
isRecoverable() {
|
|
598
|
-
return true; // Configuration errors are usually fixable
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
/**
|
|
602
|
-
* Batch operation error for multiple failures
|
|
603
|
-
*/
|
|
604
|
-
export class BatchOperationError extends GeneratorError {
|
|
605
|
-
errors;
|
|
606
|
-
constructor(message,
|
|
607
|
-
/** Individual errors that occurred */
|
|
608
|
-
errors) {
|
|
609
|
-
super(message, "generation", {
|
|
610
|
-
errorCount: errors.length,
|
|
611
|
-
errorTypes: [...new Set(errors.map((e) => e.constructor.name))],
|
|
612
|
-
phases: [...new Set(errors.map((e) => e.phase))],
|
|
613
|
-
});
|
|
614
|
-
this.errors = errors;
|
|
615
|
-
}
|
|
616
|
-
getSuggestions() {
|
|
617
|
-
// Aggregate unique suggestions from all errors
|
|
618
|
-
const allSuggestions = this.errors.flatMap((e) => e.getSuggestions());
|
|
619
|
-
const uniqueSuggestions = [...new Set(allSuggestions)];
|
|
620
|
-
const suggestions = [];
|
|
621
|
-
suggestions.push(`📊 Batch operation failed with ${this.errors.length} errors:`);
|
|
622
|
-
// Group errors by type
|
|
623
|
-
const errorGroups = new Map();
|
|
624
|
-
this.errors.forEach((error) => {
|
|
625
|
-
const type = error.constructor.name;
|
|
626
|
-
if (!errorGroups.has(type)) {
|
|
627
|
-
errorGroups.set(type, []);
|
|
628
|
-
}
|
|
629
|
-
errorGroups.get(type)?.push(error);
|
|
630
|
-
});
|
|
631
|
-
// Show error breakdown
|
|
632
|
-
suggestions.push("");
|
|
633
|
-
suggestions.push("🔍 Error breakdown:");
|
|
634
|
-
for (const [type, typeErrors] of errorGroups) {
|
|
635
|
-
suggestions.push(` • ${type}: ${typeErrors.length} occurrences`);
|
|
636
|
-
}
|
|
637
|
-
// Show most common suggestions with proper prefixing
|
|
638
|
-
suggestions.push("💡 Most relevant suggestions:");
|
|
639
|
-
const prefixedSuggestions = uniqueSuggestions.slice(0, 8).map((suggestion) => ` ${suggestion}`);
|
|
640
|
-
suggestions.push(...prefixedSuggestions);
|
|
641
|
-
return suggestions;
|
|
642
|
-
}
|
|
643
|
-
/**
|
|
644
|
-
* Get detailed breakdown of all errors
|
|
645
|
-
*/
|
|
646
|
-
getErrorBreakdown() {
|
|
647
|
-
const lines = [];
|
|
648
|
-
this.errors.forEach((error, index) => {
|
|
649
|
-
lines.push(`${index + 1}. ${error.constructor.name}: ${error.message}`);
|
|
650
|
-
if (error.context?.schemaName) {
|
|
651
|
-
lines.push(` Schema: ${error.context.schemaName}`);
|
|
652
|
-
}
|
|
653
|
-
if (error.context?.filename) {
|
|
654
|
-
lines.push(` File: ${error.context.filename}`);
|
|
655
|
-
}
|
|
656
|
-
lines.push("");
|
|
657
|
-
});
|
|
658
|
-
return lines.join("\n");
|
|
659
|
-
}
|
|
660
|
-
isRecoverable() {
|
|
661
|
-
// Batch is recoverable if at least some individual errors are recoverable
|
|
662
|
-
return this.errors.some((error) => error.isRecoverable());
|
|
663
|
-
}
|
|
664
|
-
/**
|
|
665
|
-
* Get errors that are recoverable
|
|
666
|
-
*/
|
|
667
|
-
getRecoverableErrors() {
|
|
668
|
-
return this.errors.filter((error) => error.isRecoverable());
|
|
669
|
-
}
|
|
670
|
-
/**
|
|
671
|
-
* Get errors that are not recoverable
|
|
672
|
-
*/
|
|
673
|
-
getNonRecoverableErrors() {
|
|
674
|
-
return this.errors.filter((error) => !error.isRecoverable());
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
/**
|
|
678
|
-
* Utility function to create context-aware errors
|
|
679
|
-
* Helps maintain consistent error creation patterns
|
|
680
|
-
*/
|
|
681
|
-
export function createErrorWithContext(ErrorClass, message, context, additionalContext) {
|
|
682
|
-
const fullContext = {
|
|
683
|
-
filename: context.filename,
|
|
684
|
-
importsCount: context.imports.size,
|
|
685
|
-
exportsCount: context.exports.size,
|
|
686
|
-
hasSchema: !!context.schema,
|
|
687
|
-
templateName: context.templateName,
|
|
688
|
-
...additionalContext,
|
|
689
|
-
};
|
|
690
|
-
// Create error with the enhanced context - need to pass phase parameter
|
|
691
|
-
return new ErrorClass(message, "generation", fullContext);
|
|
692
|
-
}
|