@atomic-ehr/codegen 0.0.1-canary.20251006070905.fb6ed98 → 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 -94
  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 -43
  76. package/dist/typeschema/generator.js +0 -264
  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 -262
  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,565 +0,0 @@
1
- /**
2
- * Abstract base generator class
3
- *
4
- * This is the foundation of the generator system. All language-specific generators
5
- * extend this class to inherit common functionality while implementing their own
6
- * specific logic for type mapping, content generation, and validation.
7
- */
8
- import { createLogger } from "../../../utils/codegen-logger";
9
- import { ErrorHandler, GeneratorErrorBoundary } from "./error-handler";
10
- import { ConfigurationError, SchemaValidationError } from "./errors";
11
- import { FileManager } from "./FileManager";
12
- /**
13
- * Abstract base generator class with comprehensive functionality
14
- *
15
- * Provides common functionality for all generators including:
16
- * - Schema validation and processing
17
- * - File management with fluent API
18
- * - Template processing
19
- * - Error handling and recovery
20
- * - Progress monitoring
21
- * - Performance optimization
22
- */
23
- export class BaseGenerator {
24
- /** Validated and merged options */
25
- options;
26
- /** Logger instance for this generator */
27
- logger;
28
- /** File manager for all file operations */
29
- fileManager;
30
- /** Template engine for content generation (optional) */
31
- templateEngine;
32
- /** Language-specific type mapper */
33
- typeMapper;
34
- /** Enhanced error handler for comprehensive error reporting */
35
- errorHandler;
36
- /** Error boundary for catching and handling all generator errors */
37
- errorBoundary;
38
- /** Progress callback if provided */
39
- progressCallback;
40
- /** Generated files tracking */
41
- generatedFiles = [];
42
- /** Generation start time for performance metrics */
43
- generationStartTime = 0;
44
- /** Cache for expensive operations */
45
- cache = new Map();
46
- constructor(options) {
47
- // Validate configuration first
48
- const validation = this.validateConfiguration(options);
49
- if (!validation.isValid) {
50
- throw new ConfigurationError(`Invalid generator configuration: ${validation.errors.join(", ")}`, "configuration", options);
51
- }
52
- // Merge with defaults and store
53
- this.options = this.mergeWithDefaults(options);
54
- // Initialize logger
55
- this.logger =
56
- options.logger ||
57
- createLogger({
58
- prefix: this.getLanguageName(),
59
- verbose: this.options.verbose || false,
60
- });
61
- // Initialize core components
62
- this.fileManager = this.createFileManager();
63
- this.templateEngine = this.createTemplateEngine();
64
- this.typeMapper = this.createTypeMapper();
65
- // Initialize enhanced error handling
66
- this.errorHandler = new ErrorHandler({
67
- logger: this.logger,
68
- verbose: this.options.verbose || false,
69
- beginnerMode: this.options.beginnerMode || false,
70
- outputFormat: this.options.errorFormat || "console",
71
- });
72
- this.errorBoundary = new GeneratorErrorBoundary(this.errorHandler);
73
- this.logger.debug(`${this.getLanguageName()} generator initialized`);
74
- // Log any configuration warnings
75
- if (validation.warnings.length > 0) {
76
- validation.warnings.forEach((warning) => {
77
- this.logger.warn(`Configuration warning: ${warning}`);
78
- });
79
- }
80
- }
81
- // ==========================================
82
- // Optional Abstract Methods - Can be overridden
83
- // ==========================================
84
- /**
85
- * Get generator capabilities - can be overridden for introspection
86
- */
87
- getCapabilities() {
88
- return {
89
- language: this.getLanguageName(),
90
- fileExtensions: [this.getFileExtension()],
91
- supportsTemplates: true,
92
- supportsCustomTypeMapping: true,
93
- supportsIncrementalGeneration: false,
94
- supportsValidation: true,
95
- supportedSchemaKinds: ["resource", "complex-type", "profile", "logical"],
96
- version: "1.0.0",
97
- };
98
- }
99
- /**
100
- * Create file manager instance - can be overridden for custom file handling
101
- */
102
- createFileManager() {
103
- return new FileManager({
104
- outputDir: this.options.outputDir,
105
- logger: this.logger.child("FileManager"),
106
- overwrite: this.options.overwrite,
107
- });
108
- }
109
- /**
110
- * Create template engine instance - can be overridden for custom templates
111
- * Returns undefined if template engine is not needed
112
- */
113
- createTemplateEngine() {
114
- // Default implementation returns undefined (no template engine)
115
- // Subclasses can override to provide template engine if needed
116
- return undefined;
117
- }
118
- // ==========================================
119
- // Public API - Main entry points
120
- // ==========================================
121
- /**
122
- * Generate code from TypeSchema documents
123
- * This is the main method that orchestrates the entire generation process
124
- * @param schemas - Array of TypeSchema documents
125
- */
126
- async generate(schemas) {
127
- return this.errorBoundary.withErrorBoundary(async () => {
128
- this.generationStartTime = performance.now();
129
- this.generatedFiles = [];
130
- this.logger.info(`Starting ${this.getLanguageName()} generation for ${schemas.length} schemas`);
131
- // Phase 1: Schema validation
132
- this.reportProgress("validation", 0, schemas.length, "Validating schemas...");
133
- await this.validateSchemas(schemas);
134
- // Phase 2: Schema processing and filtering
135
- this.reportProgress("generation", 0, schemas.length, "Processing schemas...");
136
- const processedSchemas = this.filterAndSortSchemas(schemas);
137
- this.logger.debug(`Filtered to ${processedSchemas.length} schemas for generation`);
138
- // Phase 3: Content generation
139
- await this.generateFiles(processedSchemas);
140
- // Phase 4: Post-generation hooks
141
- await this.runPostGenerationHooks();
142
- this.reportProgress("complete", schemas.length, schemas.length, "Generation complete");
143
- const duration = performance.now() - this.generationStartTime;
144
- this.logger.info(`Generated ${this.generatedFiles.length} files in ${duration.toFixed(2)}ms ` +
145
- `(avg ${(duration / this.generatedFiles.length).toFixed(2)}ms per file)`);
146
- return this.generatedFiles;
147
- }, { operationName: "generate" });
148
- }
149
- /**
150
- * Generate and return content without writing files (useful for testing)
151
- * @param schemas - Array of TypeSchema documents
152
- */
153
- async build(schemas) {
154
- // Temporarily disable file writing by mocking the writeFile method
155
- const originalWriteFile = this.fileManager.writeFile;
156
- const mockWriteResults = new Map();
157
- this.fileManager.writeFile = async (path, content) => {
158
- const result = {
159
- path: `${this.options.outputDir}/${path}`,
160
- size: Buffer.byteLength(content, "utf-8"),
161
- writeTime: 0,
162
- };
163
- mockWriteResults.set(path, result);
164
- return result;
165
- };
166
- try {
167
- const result = await this.generate(schemas);
168
- // Update file paths to reflect what would have been written
169
- result.forEach((file) => {
170
- const mockResult = mockWriteResults.get(file.filename);
171
- if (mockResult) {
172
- file.path = mockResult.path;
173
- file.size = mockResult.size;
174
- }
175
- });
176
- return result;
177
- }
178
- finally {
179
- // Restore original file writing function
180
- this.fileManager.writeFile = originalWriteFile;
181
- }
182
- }
183
- // ==========================================
184
- // Fluent API - Builder pattern methods
185
- // ==========================================
186
- /**
187
- * Create a file builder for fluent file generation
188
- * @param filename - Name of the file to create
189
- */
190
- file(filename) {
191
- if (!this.templateEngine) {
192
- throw new Error("Template engine is required for fluent file generation. Override createTemplateEngine() in your generator.");
193
- }
194
- const { FileBuilder } = require("./builders/FileBuilder");
195
- return new FileBuilder({
196
- filename: this.ensureFileExtension(filename),
197
- fileManager: this.fileManager,
198
- templateEngine: this.templateEngine,
199
- typeMapper: this.typeMapper,
200
- logger: this.logger.child("FileBuilder"),
201
- });
202
- }
203
- /**
204
- * Create a directory builder for batch operations
205
- * @param path - Directory path relative to output directory
206
- */
207
- directory(path) {
208
- const { DirectoryBuilder } = require("./builders/DirectoryBuilder");
209
- return new DirectoryBuilder({
210
- path,
211
- fileManager: this.fileManager,
212
- logger: this.logger.child("DirectoryBuilder"),
213
- });
214
- }
215
- /**
216
- * Create an index file builder
217
- * @param directory - Directory to create index for
218
- */
219
- index(directory = ".") {
220
- if (!this.templateEngine) {
221
- throw new Error("Template engine is required for index file generation. Override createTemplateEngine() in your generator.");
222
- }
223
- const { IndexBuilder } = require("./builders/IndexBuilder");
224
- return new IndexBuilder({
225
- directory,
226
- fileManager: this.fileManager,
227
- templateEngine: this.templateEngine,
228
- logger: this.logger.child("IndexBuilder"),
229
- });
230
- }
231
- /**
232
- * Set progress callback for monitoring generation
233
- * @param callback - Progress callback function
234
- */
235
- onProgress(callback) {
236
- this.progressCallback = callback;
237
- return this;
238
- }
239
- // ==========================================
240
- // Configuration and Validation
241
- // ==========================================
242
- /**
243
- * Validate generator configuration
244
- */
245
- validateConfiguration(options) {
246
- const errors = [];
247
- const warnings = [];
248
- const suggestions = [];
249
- // Required options validation
250
- if (!options.outputDir) {
251
- errors.push("outputDir is required");
252
- suggestions.push("Provide a valid output directory path");
253
- }
254
- // Type validation
255
- if (options.outputDir && typeof options.outputDir !== "string") {
256
- errors.push("outputDir must be a string");
257
- }
258
- if (options.overwrite !== undefined && typeof options.overwrite !== "boolean") {
259
- errors.push("overwrite must be a boolean");
260
- }
261
- if (options.validate !== undefined && typeof options.validate !== "boolean") {
262
- errors.push("validate must be a boolean");
263
- }
264
- // Warnings for suboptimal configuration
265
- if (options.outputDir && !require("node:path").isAbsolute(options.outputDir)) {
266
- warnings.push("Using relative path for outputDir - consider using absolute path");
267
- suggestions.push("Use path.resolve() to convert to absolute path");
268
- }
269
- if (options.validate === false) {
270
- warnings.push("Validation is disabled - this may lead to invalid generated code");
271
- suggestions.push("Consider enabling validation for better code quality");
272
- }
273
- return {
274
- isValid: errors.length === 0,
275
- errors,
276
- warnings,
277
- suggestions,
278
- };
279
- }
280
- /**
281
- * Merge options with defaults
282
- */
283
- mergeWithDefaults(options) {
284
- return {
285
- overwrite: true,
286
- validate: true,
287
- verbose: false,
288
- beginnerMode: false,
289
- errorFormat: "console",
290
- ...options,
291
- };
292
- }
293
- // ==========================================
294
- // Schema Processing
295
- // ==========================================
296
- /**
297
- * Validate schemas before processing
298
- */
299
- async validateSchemas(schemas) {
300
- if (!this.options.validate) {
301
- this.logger.debug("Schema validation disabled");
302
- return;
303
- }
304
- this.logger.info(`🔍 Starting schema validation for ${schemas.length} schemas`);
305
- this.logger.debug("Schema validation enabled - performing comprehensive validation");
306
- const operations = schemas.map((schema) => () => this.errorBoundary.withErrorBoundary(async () => {
307
- await this.validateSchema(schema);
308
- this.reportProgress("validation", schemas.indexOf(schema) + 1, schemas.length, `Validated ${schema.identifier?.name || "schema"}`);
309
- }, { schema, operationName: "validateSchema" }));
310
- await this.errorBoundary.withBatchErrorBoundary(operations, {
311
- operationName: "validateSchemas",
312
- });
313
- this.logger.debug(`Successfully validated ${schemas.length} schemas`);
314
- }
315
- /**
316
- * Validate individual schema
317
- */
318
- async validateSchema(schema) {
319
- const errors = [];
320
- const schemaName = schema.identifier?.name || "unknown";
321
- this.logger.debug(`🔍 Validating schema: ${schemaName} (kind: ${schema.identifier?.kind})`);
322
- // Basic structure validation
323
- if (!schema.identifier) {
324
- errors.push("Schema missing identifier");
325
- this.logger.warn(`❌ Schema missing identifier: ${JSON.stringify(schema, null, 2).substring(0, 200)}...`);
326
- }
327
- else {
328
- if (!schema.identifier.name) {
329
- errors.push("Schema identifier missing name");
330
- }
331
- if (!schema.identifier.kind) {
332
- errors.push("Schema identifier missing kind");
333
- }
334
- else {
335
- const validKinds = [
336
- "resource",
337
- "complex-type",
338
- "profile",
339
- "primitive-type",
340
- "logical",
341
- "value-set",
342
- "binding",
343
- "extension",
344
- ];
345
- if (!validKinds.includes(schema.identifier.kind)) {
346
- errors.push(`Schema identifier.kind must be one of: ${validKinds.join(", ")}`);
347
- }
348
- }
349
- }
350
- // Field validation
351
- if ("fields" in schema && schema.fields) {
352
- for (const [fieldName, field] of Object.entries(schema.fields)) {
353
- if (!fieldName.trim()) {
354
- errors.push("Field name cannot be empty");
355
- }
356
- if (!field) {
357
- errors.push(`Field '${fieldName}' is null or undefined`);
358
- }
359
- // Add more field-specific validation as needed
360
- }
361
- }
362
- // Circular reference detection (make it a warning, not an error for FHIR schemas)
363
- if (await this.detectCircularReferences(schema)) {
364
- this.logger.warn(`⚠️ Circular reference detected in schema '${schemaName}' - this may be expected for FHIR primitive types`);
365
- // Don't add to errors - FHIR schemas often have legitimate circular references
366
- }
367
- if (errors.length > 0) {
368
- this.logger.error(`❌ Schema validation failed for '${schemaName}': ${errors.join(", ")}`);
369
- this.logger.debug(`Schema details: ${JSON.stringify(schema, null, 2)}`);
370
- throw new SchemaValidationError(`Schema validation failed for '${schema.identifier?.name || "unknown"}'`, schema, errors);
371
- }
372
- this.logger.debug(`✅ Schema validation passed for '${schemaName}'`);
373
- }
374
- /**
375
- * Detect circular references in schema dependencies
376
- */
377
- async detectCircularReferences(schema) {
378
- // Simple implementation - can be enhanced for complex cases
379
- const visited = new Set();
380
- const visiting = new Set();
381
- const checkCircular = (currentSchema) => {
382
- const name = currentSchema.identifier?.name;
383
- if (!name)
384
- return false;
385
- if (visiting.has(name)) {
386
- return true; // Circular reference found
387
- }
388
- if (visited.has(name)) {
389
- return false; // Already processed
390
- }
391
- visiting.add(name);
392
- // Check field references
393
- if ("fields" in currentSchema && currentSchema.fields) {
394
- for (const field of Object.values(currentSchema.fields)) {
395
- if (field?.type?.name === name) {
396
- return true; // Self-reference
397
- }
398
- // Add more complex reference checking as needed
399
- }
400
- }
401
- visiting.delete(name);
402
- visited.add(name);
403
- return false;
404
- };
405
- return checkCircular(schema);
406
- }
407
- // ==========================================
408
- // File Generation
409
- // ==========================================
410
- /**
411
- * Generate files from processed schemas
412
- */
413
- async generateFiles(schemas) {
414
- const operations = schemas.map((schema, index) => () => this.errorBoundary.withErrorBoundary(async () => {
415
- const file = await this.generateFileForSchema(schema, index, schemas.length);
416
- this.generatedFiles.push(file);
417
- return file;
418
- }, { schema, operationName: "generateFile" }));
419
- await this.errorBoundary.withBatchErrorBoundary(operations, {
420
- operationName: "generateFiles",
421
- });
422
- this.logger.debug(`Generated ${this.generatedFiles.length} files`);
423
- }
424
- /**
425
- * Generate a single file from a schema
426
- */
427
- async generateFileForSchema(schema, index, total) {
428
- const fileStartTime = performance.now();
429
- // Create template context
430
- const context = {
431
- schema,
432
- typeMapper: this.typeMapper,
433
- filename: this.typeMapper.formatFileName(schema.identifier?.name || "unknown"),
434
- language: this.getLanguageName(),
435
- timestamp: new Date().toISOString(),
436
- imports: new Map(),
437
- exports: new Set(),
438
- };
439
- // Generate content
440
- const content = await this.generateSchemaContent(schema, context);
441
- // Validate content if enabled
442
- if (this.options.validate) {
443
- await this.validateContent(content, context);
444
- }
445
- // Write file
446
- const filename = context.filename + this.getFileExtension();
447
- const writeResult = await this.fileManager.writeFile(filename, content);
448
- const generationTime = performance.now() - fileStartTime;
449
- // Report progress
450
- this.reportProgress("writing", index + 1, total, `Generated ${filename} (${writeResult.size} bytes)`);
451
- // Create GeneratedFile result
452
- const generatedFile = {
453
- path: writeResult.path,
454
- filename,
455
- content,
456
- exports: this.extractExports(content),
457
- size: writeResult.size,
458
- timestamp: new Date(),
459
- metadata: {
460
- generationTime,
461
- schemaCount: 1,
462
- templateName: context.templateName?.toString(),
463
- warnings: [],
464
- },
465
- };
466
- return generatedFile;
467
- }
468
- // ==========================================
469
- // Helper Methods
470
- // ==========================================
471
- /**
472
- * Ensure filename has correct extension
473
- */
474
- ensureFileExtension(filename) {
475
- const extension = this.getFileExtension();
476
- return filename.endsWith(extension) ? filename : `${filename}${extension}`;
477
- }
478
- /**
479
- * Extract exported symbols from generated content
480
- * Can be overridden by language-specific implementations
481
- */
482
- extractExports(content) {
483
- const exports = [];
484
- // Handle export { name1, name2 } syntax
485
- const exportListRegex = /export\s*\{\s*([^}]+)\s*\}/g;
486
- let match;
487
- while ((match = exportListRegex.exec(content)) !== null) {
488
- if (match[1]) {
489
- const names = match[1]
490
- .split(",")
491
- .map((name) => name.trim())
492
- .filter(Boolean);
493
- exports.push(...names);
494
- }
495
- }
496
- // Handle direct export declarations
497
- const directExportRegex = /export\s+(?:const|let|var|function|class|interface|type|enum)\s+(\w+)/g;
498
- while ((match = directExportRegex.exec(content)) !== null) {
499
- if (match[1]) {
500
- exports.push(match[1]);
501
- }
502
- }
503
- // Remove duplicates
504
- return [...new Set(exports)];
505
- }
506
- /**
507
- * Report progress to callback if provided
508
- */
509
- reportProgress(phase, current, total, message, schema) {
510
- if (this.progressCallback) {
511
- this.progressCallback(phase, current, total, message, schema);
512
- }
513
- if (message && this.options.verbose) {
514
- this.logger.debug(`[${phase}] ${message} (${current}/${total})`);
515
- }
516
- }
517
- /**
518
- * Run post-generation hooks
519
- * Can be overridden to add custom post-processing
520
- */
521
- async runPostGenerationHooks() {
522
- // Default implementation does nothing
523
- // Subclasses can override to add custom logic
524
- }
525
- /**
526
- * Get cached value or compute and cache it
527
- */
528
- getCachedOrCompute(key, computeFn) {
529
- if (this.cache.has(key)) {
530
- return this.cache.get(key);
531
- }
532
- const result = computeFn();
533
- if (result instanceof Promise) {
534
- return result.then((value) => {
535
- this.cache.set(key, value);
536
- return value;
537
- });
538
- }
539
- else {
540
- this.cache.set(key, result);
541
- return result;
542
- }
543
- }
544
- /**
545
- * Clear internal cache
546
- */
547
- clearCache() {
548
- this.cache.clear();
549
- }
550
- /**
551
- * Get generation statistics
552
- */
553
- getGenerationStats() {
554
- const totalSize = this.generatedFiles.reduce((sum, file) => sum + file.size, 0);
555
- const generationTime = performance.now() - this.generationStartTime;
556
- return {
557
- filesGenerated: this.generatedFiles.length,
558
- totalSize,
559
- averageFileSize: this.generatedFiles.length > 0 ? totalSize / this.generatedFiles.length : 0,
560
- generationTime,
561
- averageTimePerFile: this.generatedFiles.length > 0 ? generationTime / this.generatedFiles.length : 0,
562
- cacheHitRate: 0, // TODO: Implement cache hit tracking
563
- };
564
- }
565
- }
@@ -1,88 +0,0 @@
1
- /**
2
- * Core file management system with batching and performance optimizations
3
- *
4
- * This replaces scattered writeFile calls with a comprehensive file management
5
- * system that provides better error handling, performance, and maintainability.
6
- */
7
- import type { CodegenLogger } from "../../../utils/codegen-logger";
8
- import type { FileStats } from "./types";
9
- export interface FileManagerOptions {
10
- outputDir: string;
11
- logger: CodegenLogger;
12
- overwrite?: boolean;
13
- batchSize?: number;
14
- }
15
- export interface WriteFileResult {
16
- path: string;
17
- size: number;
18
- writeTime: number;
19
- }
20
- /**
21
- * High-performance file manager with batching and error recovery
22
- *
23
- * Features:
24
- * - Automatic directory creation
25
- * - Batch operations for better performance
26
- * - Comprehensive error handling with recovery suggestions
27
- * - Import path resolution
28
- * - File existence checks
29
- */
30
- export declare class FileManager {
31
- private readonly options;
32
- private readonly logger;
33
- constructor(options: FileManagerOptions);
34
- /**
35
- * Write a file with automatic directory creation
36
- * @param relativePath Path relative to output directory
37
- * @param content File content
38
- * @param options Write options
39
- */
40
- writeFile(relativePath: string, content: string, options?: {
41
- encoding?: BufferEncoding;
42
- overwrite?: boolean;
43
- }): Promise<WriteFileResult>;
44
- /**
45
- * Write multiple files in batch for better performance
46
- * @param files Map of relative path to content
47
- */
48
- writeBatch(files: Map<string, string>): Promise<WriteFileResult[]>;
49
- /**
50
- * Ensure directory exists, creating parent directories as needed
51
- * @param dirPath Full directory path
52
- */
53
- ensureDirectory(dirPath: string): Promise<void>;
54
- /**
55
- * Clean directory by removing all contents
56
- * @param relativePath Path relative to output directory
57
- */
58
- cleanDirectory(relativePath?: string): Promise<void>;
59
- /**
60
- * Get relative import path between two files
61
- * @param fromFile Source file path
62
- * @param toFile Target file path
63
- */
64
- getRelativeImportPath(fromFile: string, toFile: string): string;
65
- /**
66
- * Check if a file would be overwritten
67
- * @param relativePath Path relative to output directory
68
- */
69
- wouldOverwrite(relativePath: string): Promise<boolean>;
70
- /**
71
- * Get file statistics
72
- * @param relativePath Path relative to output directory
73
- */
74
- getFileStats(relativePath: string): Promise<FileStats | null>;
75
- /**
76
- * Get output directory
77
- */
78
- getOutputDirectory(): string;
79
- /**
80
- * Set batch size for operations
81
- * @param size Batch size
82
- */
83
- setBatchSize(size: number): void;
84
- /**
85
- * Get current batch size
86
- */
87
- getBatchSize(): number;
88
- }