@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.
Files changed (90) hide show
  1. package/dist/cli/index.js +45 -124
  2. package/dist/index.d.ts +2130 -62
  3. package/dist/index.js +5865 -84
  4. package/dist/index.js.map +1 -0
  5. package/package.json +3 -7
  6. package/dist/api/builder.d.ts +0 -154
  7. package/dist/api/builder.js +0 -341
  8. package/dist/api/generators/base/BaseGenerator.d.ts +0 -186
  9. package/dist/api/generators/base/BaseGenerator.js +0 -565
  10. package/dist/api/generators/base/FileManager.d.ts +0 -88
  11. package/dist/api/generators/base/FileManager.js +0 -202
  12. package/dist/api/generators/base/PythonTypeMapper.d.ts +0 -16
  13. package/dist/api/generators/base/PythonTypeMapper.js +0 -71
  14. package/dist/api/generators/base/TemplateEngine.d.ts +0 -126
  15. package/dist/api/generators/base/TemplateEngine.js +0 -133
  16. package/dist/api/generators/base/TypeMapper.d.ts +0 -129
  17. package/dist/api/generators/base/TypeMapper.js +0 -153
  18. package/dist/api/generators/base/TypeScriptTypeMapper.d.ts +0 -51
  19. package/dist/api/generators/base/TypeScriptTypeMapper.js +0 -232
  20. package/dist/api/generators/base/builders/DirectoryBuilder.d.ts +0 -99
  21. package/dist/api/generators/base/builders/DirectoryBuilder.js +0 -215
  22. package/dist/api/generators/base/builders/FileBuilder.d.ts +0 -160
  23. package/dist/api/generators/base/builders/FileBuilder.js +0 -406
  24. package/dist/api/generators/base/builders/IndexBuilder.d.ts +0 -126
  25. package/dist/api/generators/base/builders/IndexBuilder.js +0 -290
  26. package/dist/api/generators/base/enhanced-errors.d.ts +0 -84
  27. package/dist/api/generators/base/enhanced-errors.js +0 -259
  28. package/dist/api/generators/base/error-handler.d.ts +0 -89
  29. package/dist/api/generators/base/error-handler.js +0 -243
  30. package/dist/api/generators/base/errors.d.ts +0 -251
  31. package/dist/api/generators/base/errors.js +0 -692
  32. package/dist/api/generators/base/index.d.ts +0 -99
  33. package/dist/api/generators/base/index.js +0 -160
  34. package/dist/api/generators/base/types.d.ts +0 -433
  35. package/dist/api/generators/base/types.js +0 -12
  36. package/dist/api/generators/types.d.ts +0 -53
  37. package/dist/api/generators/types.js +0 -4
  38. package/dist/api/generators/typescript.d.ts +0 -190
  39. package/dist/api/generators/typescript.js +0 -819
  40. package/dist/api/index.d.ts +0 -51
  41. package/dist/api/index.js +0 -50
  42. package/dist/cli/commands/generate/typescript.d.ts +0 -10
  43. package/dist/cli/commands/generate/typescript.js +0 -52
  44. package/dist/cli/commands/generate.d.ts +0 -15
  45. package/dist/cli/commands/generate.js +0 -159
  46. package/dist/cli/commands/index.d.ts +0 -29
  47. package/dist/cli/commands/index.js +0 -100
  48. package/dist/cli/commands/typeschema/generate.d.ts +0 -19
  49. package/dist/cli/commands/typeschema/generate.js +0 -124
  50. package/dist/cli/commands/typeschema.d.ts +0 -10
  51. package/dist/cli/commands/typeschema.js +0 -47
  52. package/dist/cli/index.d.ts +0 -9
  53. package/dist/cli/utils/log.d.ts +0 -10
  54. package/dist/cli/utils/log.js +0 -23
  55. package/dist/cli/utils/prompts.d.ts +0 -56
  56. package/dist/cli/utils/prompts.js +0 -202
  57. package/dist/cli/utils/spinner.d.ts +0 -110
  58. package/dist/cli/utils/spinner.js +0 -266
  59. package/dist/config.d.ts +0 -217
  60. package/dist/config.js +0 -591
  61. package/dist/logger.d.ts +0 -157
  62. package/dist/logger.js +0 -281
  63. package/dist/typeschema/cache.d.ts +0 -80
  64. package/dist/typeschema/cache.js +0 -239
  65. package/dist/typeschema/core/binding.d.ts +0 -11
  66. package/dist/typeschema/core/binding.js +0 -143
  67. package/dist/typeschema/core/field-builder.d.ts +0 -12
  68. package/dist/typeschema/core/field-builder.js +0 -123
  69. package/dist/typeschema/core/identifier.d.ts +0 -13
  70. package/dist/typeschema/core/identifier.js +0 -94
  71. package/dist/typeschema/core/nested-types.d.ts +0 -9
  72. package/dist/typeschema/core/nested-types.js +0 -93
  73. package/dist/typeschema/core/transformer.d.ts +0 -11
  74. package/dist/typeschema/core/transformer.js +0 -235
  75. package/dist/typeschema/generator.d.ts +0 -36
  76. package/dist/typeschema/generator.js +0 -243
  77. package/dist/typeschema/index.d.ts +0 -15
  78. package/dist/typeschema/index.js +0 -15
  79. package/dist/typeschema/parser.d.ts +0 -79
  80. package/dist/typeschema/parser.js +0 -274
  81. package/dist/typeschema/profile/processor.d.ts +0 -14
  82. package/dist/typeschema/profile/processor.js +0 -261
  83. package/dist/typeschema/register.d.ts +0 -21
  84. package/dist/typeschema/register.js +0 -117
  85. package/dist/typeschema/types.d.ts +0 -240
  86. package/dist/typeschema/types.js +0 -19
  87. package/dist/utils/codegen-logger.d.ts +0 -102
  88. package/dist/utils/codegen-logger.js +0 -196
  89. package/dist/utils.d.ts +0 -22
  90. 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
- }