@atomic-ehr/codegen 0.0.1-canary.20250821160126.c552195 → 0.0.1-canary.20250822150706.c3b8669

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 (122) hide show
  1. package/dist/api/builder.d.ts +3 -3
  2. package/dist/api/builder.d.ts.map +1 -1
  3. package/dist/api/builder.js +374 -0
  4. package/dist/api/generators/base/BaseGenerator.d.ts +4 -4
  5. package/dist/api/generators/base/BaseGenerator.d.ts.map +1 -1
  6. package/dist/api/generators/base/BaseGenerator.js +572 -0
  7. package/dist/api/generators/base/FileManager.d.ts +2 -2
  8. package/dist/api/generators/base/FileManager.d.ts.map +1 -1
  9. package/dist/api/generators/base/FileManager.js +204 -0
  10. package/dist/api/generators/base/PythonTypeMapper.d.ts +2 -2
  11. package/dist/api/generators/base/PythonTypeMapper.d.ts.map +1 -1
  12. package/dist/api/generators/base/PythonTypeMapper.js +71 -0
  13. package/dist/api/generators/base/TemplateEngine.d.ts +1 -1
  14. package/dist/api/generators/base/TemplateEngine.d.ts.map +1 -1
  15. package/dist/api/generators/base/TemplateEngine.js +133 -0
  16. package/dist/api/generators/base/TypeMapper.js +153 -0
  17. package/dist/api/generators/base/TypeScriptTypeMapper.d.ts +1 -1
  18. package/dist/api/generators/base/TypeScriptTypeMapper.d.ts.map +1 -1
  19. package/dist/api/generators/base/TypeScriptTypeMapper.js +232 -0
  20. package/dist/api/generators/base/builders/DirectoryBuilder.d.ts +4 -4
  21. package/dist/api/generators/base/builders/DirectoryBuilder.d.ts.map +1 -1
  22. package/dist/api/generators/base/builders/DirectoryBuilder.js +215 -0
  23. package/dist/api/generators/base/builders/FileBuilder.d.ts +2 -2
  24. package/dist/api/generators/base/builders/FileBuilder.d.ts.map +1 -1
  25. package/dist/api/generators/base/builders/FileBuilder.js +408 -0
  26. package/dist/api/generators/base/builders/IndexBuilder.d.ts +2 -2
  27. package/dist/api/generators/base/builders/IndexBuilder.d.ts.map +1 -1
  28. package/dist/api/generators/base/builders/IndexBuilder.js +290 -0
  29. package/dist/api/generators/base/enhanced-errors.d.ts +2 -2
  30. package/dist/api/generators/base/enhanced-errors.d.ts.map +1 -1
  31. package/dist/api/generators/base/enhanced-errors.js +259 -0
  32. package/dist/api/generators/base/error-handler.d.ts +1 -1
  33. package/dist/api/generators/base/error-handler.d.ts.map +1 -1
  34. package/dist/api/generators/base/error-handler.js +243 -0
  35. package/dist/api/generators/base/errors.d.ts +2 -2
  36. package/dist/api/generators/base/errors.d.ts.map +1 -1
  37. package/dist/api/generators/base/errors.js +694 -0
  38. package/dist/api/generators/base/index.d.ts +22 -22
  39. package/dist/api/generators/base/index.d.ts.map +1 -1
  40. package/dist/api/generators/base/index.js +161 -0
  41. package/dist/api/generators/base/types.d.ts +2 -2
  42. package/dist/api/generators/base/types.d.ts.map +1 -1
  43. package/dist/api/generators/base/types.js +12 -0
  44. package/dist/api/generators/rest-client.d.ts +2 -2
  45. package/dist/api/generators/rest-client.d.ts.map +1 -1
  46. package/dist/api/generators/rest-client.js +847 -0
  47. package/dist/api/generators/search-parameter-enhancer.d.ts +1 -1
  48. package/dist/api/generators/search-parameter-enhancer.d.ts.map +1 -1
  49. package/dist/api/generators/search-parameter-enhancer.js +801 -0
  50. package/dist/api/generators/types.js +4 -0
  51. package/dist/api/generators/typescript.d.ts +3 -3
  52. package/dist/api/generators/typescript.d.ts.map +1 -1
  53. package/dist/api/generators/typescript.js +537 -0
  54. package/dist/api/generators/validation-generator.js +632 -0
  55. package/dist/api/index.d.ts +10 -10
  56. package/dist/api/index.d.ts.map +1 -1
  57. package/dist/api/index.js +51 -0
  58. package/dist/cli/commands/generate/typescript.d.ts +1 -1
  59. package/dist/cli/commands/generate/typescript.d.ts.map +1 -1
  60. package/dist/cli/commands/generate/typescript.js +52 -0
  61. package/dist/cli/commands/generate.d.ts +5 -12
  62. package/dist/cli/commands/generate.d.ts.map +1 -1
  63. package/dist/cli/commands/generate.js +158 -0
  64. package/dist/cli/commands/index.d.ts +2 -1
  65. package/dist/cli/commands/index.d.ts.map +1 -1
  66. package/dist/cli/commands/index.js +100 -0
  67. package/dist/cli/commands/typeschema/generate.js +130 -0
  68. package/dist/cli/commands/typeschema.js +48 -0
  69. package/dist/cli/index.js +12 -8664
  70. package/dist/cli/utils/log.d.ts +2 -2
  71. package/dist/cli/utils/log.d.ts.map +1 -1
  72. package/dist/cli/utils/log.js +23 -0
  73. package/dist/cli/utils/prompts.js +224 -0
  74. package/dist/cli/utils/spinner.js +270 -0
  75. package/dist/config.d.ts +22 -2
  76. package/dist/config.d.ts.map +1 -1
  77. package/dist/config.js +703 -0
  78. package/dist/index.d.ts +2 -2
  79. package/dist/index.d.ts.map +1 -1
  80. package/dist/index.js +84 -38
  81. package/dist/logger.js +290 -0
  82. package/dist/typeschema/cache.d.ts +2 -2
  83. package/dist/typeschema/cache.d.ts.map +1 -1
  84. package/dist/typeschema/cache.js +285 -0
  85. package/dist/typeschema/core/binding.d.ts +1 -1
  86. package/dist/typeschema/core/binding.d.ts.map +1 -1
  87. package/dist/typeschema/core/binding.js +187 -0
  88. package/dist/typeschema/core/field-builder.d.ts +1 -1
  89. package/dist/typeschema/core/field-builder.d.ts.map +1 -1
  90. package/dist/typeschema/core/field-builder.js +259 -0
  91. package/dist/typeschema/core/identifier.js +117 -0
  92. package/dist/typeschema/core/nested-types.d.ts +1 -1
  93. package/dist/typeschema/core/nested-types.d.ts.map +1 -1
  94. package/dist/typeschema/core/nested-types.js +111 -0
  95. package/dist/typeschema/core/transformer.d.ts +2 -2
  96. package/dist/typeschema/core/transformer.d.ts.map +1 -1
  97. package/dist/typeschema/core/transformer.js +345 -0
  98. package/dist/typeschema/generator.d.ts +3 -3
  99. package/dist/typeschema/generator.d.ts.map +1 -1
  100. package/dist/typeschema/generator.js +352 -0
  101. package/dist/typeschema/index.d.ts +14 -14
  102. package/dist/typeschema/index.d.ts.map +1 -1
  103. package/dist/typeschema/index.js +92 -0
  104. package/dist/typeschema/parser.d.ts +2 -2
  105. package/dist/typeschema/parser.d.ts.map +1 -1
  106. package/dist/typeschema/parser.js +310 -0
  107. package/dist/typeschema/profile/processor.d.ts +1 -1
  108. package/dist/typeschema/profile/processor.d.ts.map +1 -1
  109. package/dist/typeschema/profile/processor.js +268 -0
  110. package/dist/typeschema/schema.js +456 -0
  111. package/dist/typeschema/type-schema.types.js +39 -0
  112. package/dist/typeschema/types.js +4 -0
  113. package/dist/typeschema/utils.d.ts +1 -1
  114. package/dist/typeschema/utils.d.ts.map +1 -1
  115. package/dist/typeschema/utils.js +13 -0
  116. package/dist/typeschema/value-set/processor.d.ts +1 -1
  117. package/dist/typeschema/value-set/processor.d.ts.map +1 -1
  118. package/dist/typeschema/value-set/processor.js +168 -0
  119. package/dist/utils/codegen-logger.js +204 -0
  120. package/dist/utils.js +42 -0
  121. package/package.json +15 -4
  122. package/dist/index-e7pfye24.js +0 -8532
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Common types used in generated code
3
+ */
4
+ export {};
@@ -5,9 +5,9 @@
5
5
  * Built using the BaseGenerator architecture with TypeMapper, TemplateEngine, and FileManager.
6
6
  */
7
7
  import type { TypeSchema } from "../../typeschema/type-schema.types";
8
- import { BaseGenerator } from "./base/BaseGenerator";
9
- import { type TypeScriptTypeMapperOptions } from "./base/TypeScriptTypeMapper";
10
- import type { BaseGeneratorOptions, GeneratedFile, TemplateContext, TypeMapper } from "./base/types";
8
+ import { BaseGenerator } from "./base/BaseGenerator.js";
9
+ import { type TypeScriptTypeMapperOptions } from "./base/TypeScriptTypeMapper.js";
10
+ import type { BaseGeneratorOptions, GeneratedFile, TemplateContext, TypeMapper } from "./base/types.js";
11
11
  /**
12
12
  * TypeScript-specific generator options
13
13
  */
@@ -1 +1 @@
1
- {"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../../src/api/generators/typescript.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"typescript.d.ts","sourceRoot":"","sources":["../../../src/api/generators/typescript.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,537 @@
1
+ /**
2
+ * Modern TypeScript Generator built on BaseGenerator
3
+ *
4
+ * This is the new, clean implementation that replaces the monolithic typescript.ts generator.
5
+ * Built using the BaseGenerator architecture with TypeMapper, TemplateEngine, and FileManager.
6
+ */
7
+ import { BaseGenerator } from "./base/BaseGenerator.js";
8
+ import { TypeScriptTypeMapper, } from "./base/TypeScriptTypeMapper.js";
9
+ /**
10
+ * Modern TypeScript Generator
11
+ *
12
+ * Generates clean, type-safe TypeScript interfaces from FHIR TypeSchema documents.
13
+ * Uses the new BaseGenerator architecture for maintainability and extensibility.
14
+ */
15
+ export class TypeScriptGenerator extends BaseGenerator {
16
+ profilesByPackage = new Map();
17
+ resourceTypes = new Set();
18
+ get tsOptions() {
19
+ return this.options;
20
+ }
21
+ getLanguageName() {
22
+ return "TypeScript";
23
+ }
24
+ getFileExtension() {
25
+ return ".ts";
26
+ }
27
+ createTypeMapper() {
28
+ const options = this.options;
29
+ return new TypeScriptTypeMapper({
30
+ namingConvention: (options.namingConvention ?? "PascalCase") === "PascalCase"
31
+ ? "PascalCase"
32
+ : "camelCase",
33
+ moduleFormat: options.moduleFormat === "cjs" ? "commonjs" : "esm",
34
+ preferUndefined: true,
35
+ ...options.typeMapperOptions,
36
+ });
37
+ }
38
+ async generateSchemaContent(schema, context) {
39
+ // Skip unsupported schema types
40
+ if (this.shouldSkipSchema(schema)) {
41
+ return "";
42
+ }
43
+ // Collect resource types for Reference generic
44
+ if (schema.identifier.kind === "resource") {
45
+ this.resourceTypes.add(this.typeMapper.formatTypeName(schema.identifier.name));
46
+ }
47
+ // Update filename for profiles to include proper directory structure
48
+ // if (false) {
49
+ // // Profile support removed - not in core schema
50
+ // const sanitizedPackage = this.sanitizePackageName(
51
+ // schema.identifier.package || "unknown",
52
+ // );
53
+ // const profileFileName = this.typeMapper.formatFileName(
54
+ // schema.identifier.name,
55
+ // );
56
+ // context.filename = `profiles/${sanitizedPackage}/${profileFileName}`;
57
+ // // Track profile for index generation
58
+ // if (!this.profilesByPackage.has(schema.identifier.package || "unknown")) {
59
+ // this.profilesByPackage.set(schema.identifier.package || "unknown", []);
60
+ // }
61
+ // this.profilesByPackage.get(schema.identifier.package || "unknown")?.push({
62
+ // filename: profileFileName,
63
+ // interfaceName: this.typeMapper.formatTypeName(schema.identifier.name),
64
+ // });
65
+ // }
66
+ // Handle Reference type specially
67
+ if (schema.identifier.name === "Reference") {
68
+ return this.generateReferenceInterface(schema);
69
+ }
70
+ // Generate TypeScript content directly (no templates for simplicity)
71
+ const mainInterface = this.generateTypeScriptInterface(schema);
72
+ // Generate nested types if present
73
+ let nestedInterfaces = "";
74
+ if ("nested" in schema && schema.nested && Array.isArray(schema.nested)) {
75
+ const nestedInterfaceStrings = schema.nested.map((nestedType) => this.generateNestedTypeInterface(schema.identifier.name, nestedType));
76
+ nestedInterfaces = nestedInterfaceStrings.join("\n\n");
77
+ }
78
+ // Combine main interface with nested interfaces
79
+ if (nestedInterfaces) {
80
+ return `${mainInterface}\n\n${nestedInterfaces}`;
81
+ }
82
+ return mainInterface;
83
+ }
84
+ filterAndSortSchemas(schemas) {
85
+ return schemas.filter((schema) => !this.shouldSkipSchema(schema));
86
+ }
87
+ async validateContent(content, context) {
88
+ const hasValidExport = /export\s+(interface|class|type|enum)\s+\w+/.test(content);
89
+ const hasValidSyntax = content.includes("{") && content.includes("}");
90
+ if (!hasValidExport) {
91
+ throw new Error(`Generated content for ${context.schema.identifier.name} does not contain valid export statements`);
92
+ }
93
+ if (!hasValidSyntax) {
94
+ throw new Error(`Generated content for ${context.schema.identifier.name} has invalid syntax (missing braces)`);
95
+ }
96
+ }
97
+ /**
98
+ * Transform multiple schemas into TypeScript
99
+ */
100
+ async transformSchemas(schemas) {
101
+ const results = [];
102
+ for (const schema of schemas) {
103
+ const result = await this.transformSchema(schema);
104
+ if (result) {
105
+ results.push(result);
106
+ }
107
+ }
108
+ return results;
109
+ }
110
+ /**
111
+ * Transform a single schema into TypeScript
112
+ */
113
+ async transformSchema(schema) {
114
+ if (this.shouldSkipSchema(schema)) {
115
+ return undefined;
116
+ }
117
+ // Create template context
118
+ const context = {
119
+ schema,
120
+ typeMapper: this.typeMapper,
121
+ filename: this.getFilenameForSchema(schema),
122
+ language: "TypeScript",
123
+ timestamp: new Date().toISOString(),
124
+ };
125
+ // Generate content using template engine
126
+ const content = await this.generateSchemaContent(schema, context);
127
+ if (!content.trim()) {
128
+ return undefined;
129
+ }
130
+ // Extract imports and exports from generated content
131
+ const imports = this.extractImportsFromContent(content, schema);
132
+ const exports = this.extractExportsFromContent(content, schema);
133
+ const filename = this.getFilenameForSchema(schema);
134
+ return {
135
+ content,
136
+ imports,
137
+ exports: Array.from(exports),
138
+ filename,
139
+ };
140
+ }
141
+ shouldSkipSchema(schema) {
142
+ if (schema.identifier.kind === "value-set" ||
143
+ schema.identifier.kind === "binding" ||
144
+ schema.identifier.kind === "primitive-type") {
145
+ return true;
146
+ }
147
+ // Profile support removed - not in core schema specification
148
+ if (schema.identifier.url?.includes("/extension/") &&
149
+ !this.tsOptions.includeExtensions) {
150
+ return true;
151
+ }
152
+ return false;
153
+ }
154
+ getFilenameForSchema(schema) {
155
+ const baseName = this.typeMapper.formatFileName(schema.identifier.name);
156
+ return `${baseName}${this.getFileExtension()}`;
157
+ }
158
+ extractImportsFromContent(content, _schema) {
159
+ const imports = new Map();
160
+ const importRegex = /import\s+(?:type\s+)?{\s*([^}]+)\s*}\s+from\s+['"]([^'"]+)['"];?/g;
161
+ let match;
162
+ while ((match = importRegex.exec(content)) !== null) {
163
+ const symbolsStr = match[1];
164
+ const path = match[2];
165
+ if (!symbolsStr || !path)
166
+ continue;
167
+ const symbols = symbolsStr.split(",").map((s) => s.trim());
168
+ for (const symbol of symbols) {
169
+ imports.set(symbol, path);
170
+ }
171
+ }
172
+ return imports;
173
+ }
174
+ extractExportsFromContent(content, schema) {
175
+ const exports = new Set();
176
+ const exportRegex = /export\s+(?:interface|class|enum|type)\s+([A-Za-z_$][A-Za-z0-9_$]*)/g;
177
+ let match;
178
+ while ((match = exportRegex.exec(content)) !== null) {
179
+ if (match[1])
180
+ exports.add(match[1]);
181
+ }
182
+ exports.add(this.typeMapper.formatTypeName(schema.identifier.name));
183
+ return exports;
184
+ }
185
+ sanitizePackageName(packageName) {
186
+ return packageName.replace(/[^a-zA-Z0-9-_.]/g, "-");
187
+ }
188
+ /**
189
+ * Generate special Reference interface with generics
190
+ */
191
+ generateReferenceInterface(schema) {
192
+ const lines = [];
193
+ const imports = new Set();
194
+ if ("fields" in schema && schema.fields) {
195
+ for (const [, field] of Object.entries(schema.fields)) {
196
+ const importDeps = this.collectFieldImports(field);
197
+ importDeps.forEach((imp) => imports.add(imp));
198
+ }
199
+ }
200
+ lines.push("import type { ResourceType } from './utilities.js';");
201
+ if (imports.size > 0) {
202
+ const sortedImports = Array.from(imports).sort();
203
+ for (const importName of sortedImports) {
204
+ lines.push(`import type { ${importName} } from './${importName}.js';`);
205
+ }
206
+ }
207
+ lines.push(""); // Add blank line after imports
208
+ // Add JSDoc comment
209
+ if (this.tsOptions.includeDocuments && schema.description) {
210
+ lines.push("/**");
211
+ lines.push(` * ${schema.description}`);
212
+ if (schema.identifier.url) {
213
+ lines.push(` * @see ${schema.identifier.url}`);
214
+ }
215
+ if (schema.identifier.package) {
216
+ lines.push(` * @package ${schema.identifier.package}`);
217
+ }
218
+ lines.push(" * @template T - The resource type being referenced");
219
+ lines.push(" */");
220
+ }
221
+ // Generate generic interface declaration
222
+ lines.push("export interface Reference<T extends ResourceType = ResourceType> {");
223
+ if ("fields" in schema && schema.fields) {
224
+ for (const [fieldName, field] of Object.entries(schema.fields)) {
225
+ if (fieldName === "type") {
226
+ // Special handling for the type field to use the generic parameter
227
+ lines.push(" type?: T;");
228
+ }
229
+ else {
230
+ const fieldLine = this.generateFieldLine(fieldName, field);
231
+ if (fieldLine) {
232
+ lines.push(` ${fieldLine}`);
233
+ }
234
+ }
235
+ }
236
+ }
237
+ lines.push("}");
238
+ return lines.join("\n");
239
+ }
240
+ /**
241
+ * Generate TypeScript interface directly without templates
242
+ */
243
+ generateTypeScriptInterface(schema) {
244
+ const lines = [];
245
+ const interfaceName = this.typeMapper.formatTypeName(schema.identifier.name);
246
+ const imports = new Set();
247
+ if ("fields" in schema && schema.fields) {
248
+ for (const [, field] of Object.entries(schema.fields)) {
249
+ const importDeps = this.collectFieldImports(field);
250
+ importDeps.forEach((imp) => imports.add(imp));
251
+ }
252
+ }
253
+ // Collect imports from nested types
254
+ if ("nested" in schema && schema.nested && Array.isArray(schema.nested)) {
255
+ for (const nestedType of schema.nested) {
256
+ if (nestedType.fields) {
257
+ for (const [, field] of Object.entries(nestedType.fields)) {
258
+ const importDeps = this.collectFieldImports(field);
259
+ importDeps.forEach((imp) => imports.add(imp));
260
+ }
261
+ }
262
+ }
263
+ }
264
+ // Generate import statements
265
+ if (imports.size > 0) {
266
+ const sortedImports = Array.from(imports).sort();
267
+ for (const importName of sortedImports) {
268
+ lines.push(`import type { ${importName} } from './${importName}.js';`);
269
+ }
270
+ lines.push(""); // Add blank line after imports
271
+ }
272
+ // Add JSDoc comment if enabled
273
+ if (this.tsOptions.includeDocuments && schema.description) {
274
+ lines.push("/**");
275
+ lines.push(` * ${schema.description}`);
276
+ if (schema.identifier.url) {
277
+ lines.push(` * @see ${schema.identifier.url}`);
278
+ }
279
+ if (schema.identifier.package) {
280
+ lines.push(` * @package ${schema.identifier.package}`);
281
+ }
282
+ lines.push(" */");
283
+ }
284
+ // Generate interface declaration
285
+ lines.push(`export interface ${interfaceName} {`);
286
+ // Add resourceType for FHIR resources
287
+ if (schema.identifier.kind === "resource") {
288
+ lines.push(` resourceType: '${interfaceName}';`);
289
+ }
290
+ // Generate fields (if any)
291
+ if ("fields" in schema && schema.fields) {
292
+ for (const [fieldName, field] of Object.entries(schema.fields)) {
293
+ const fieldLine = this.generateFieldLine(fieldName, field);
294
+ if (fieldLine) {
295
+ lines.push(` ${fieldLine}`);
296
+ }
297
+ }
298
+ }
299
+ lines.push("}");
300
+ return lines.join("\n");
301
+ }
302
+ /**
303
+ * Collect import dependencies from a field
304
+ */
305
+ collectFieldImports(field) {
306
+ const imports = [];
307
+ if ("type" in field && field.type) {
308
+ // Handle nested types - they don't need imports as they're in the same file
309
+ if (field.type.kind === "nested") {
310
+ // Nested types are generated in the same file, no import needed
311
+ return imports;
312
+ }
313
+ const languageType = this.typeMapper.mapType(field.type);
314
+ // Only import non-primitive types that are not built-in
315
+ if (!languageType.isPrimitive && languageType.name !== "any") {
316
+ const builtInTypes = [
317
+ "string",
318
+ "number",
319
+ "boolean",
320
+ "Date",
321
+ "object",
322
+ "unknown",
323
+ "any",
324
+ ];
325
+ if (!builtInTypes.includes(languageType.name)) {
326
+ imports.push(languageType.name);
327
+ }
328
+ }
329
+ }
330
+ return imports;
331
+ }
332
+ /**
333
+ * Extract resource types from reference field constraints
334
+ */
335
+ extractReferenceTypes(referenceConstraints) {
336
+ const resourceTypes = [];
337
+ if (!Array.isArray(referenceConstraints)) {
338
+ return resourceTypes;
339
+ }
340
+ for (const constraint of referenceConstraints) {
341
+ if (!constraint || typeof constraint !== "object") {
342
+ continue;
343
+ }
344
+ if (constraint.kind === "resource" && constraint.name) {
345
+ const resourceType = this.typeMapper.formatTypeName(constraint.name);
346
+ resourceTypes.push(resourceType);
347
+ }
348
+ }
349
+ return [...new Set(resourceTypes)]; // Remove duplicates
350
+ }
351
+ /**
352
+ * Generate nested type interface
353
+ */
354
+ generateNestedTypeInterface(parentTypeName, nestedType) {
355
+ const lines = [];
356
+ const nestedTypeName = this.typeMapper.formatTypeName(`${parentTypeName}${this.capitalizeFirst(nestedType.identifier.name)}`);
357
+ // Add JSDoc comment if enabled
358
+ if (this.tsOptions.includeDocuments && nestedType.description) {
359
+ lines.push("/**");
360
+ lines.push(` * ${nestedType.description}`);
361
+ if (nestedType.identifier.url) {
362
+ lines.push(` * @see ${nestedType.identifier.url}`);
363
+ }
364
+ lines.push(" */");
365
+ }
366
+ // Generate interface declaration
367
+ lines.push(`export interface ${nestedTypeName} {`);
368
+ // Generate fields
369
+ if (nestedType.fields) {
370
+ for (const [fieldName, field] of Object.entries(nestedType.fields)) {
371
+ const fieldLine = this.generateFieldLine(fieldName, field);
372
+ if (fieldLine) {
373
+ lines.push(` ${fieldLine}`);
374
+ }
375
+ }
376
+ }
377
+ lines.push("}");
378
+ return lines.join("\n");
379
+ }
380
+ /**
381
+ * Capitalize first letter of string
382
+ */
383
+ capitalizeFirst(str) {
384
+ return str.charAt(0).toUpperCase() + str.slice(1);
385
+ }
386
+ /**
387
+ * Generate a single field line
388
+ */
389
+ generateFieldLine(fieldName, field) {
390
+ let typeString = "any";
391
+ let required = false;
392
+ let isArray = false;
393
+ if ("type" in field && field.type) {
394
+ const languageType = this.typeMapper.mapType(field.type);
395
+ typeString = languageType.name;
396
+ // Handle nested types specially
397
+ if (field.type.kind === "nested") {
398
+ // Extract parent name from URL like "http://hl7.org/fhir/StructureDefinition/Patient#contact"
399
+ const urlParts = field.type.url?.split("#") || [];
400
+ if (urlParts.length === 2) {
401
+ const parentName = urlParts[0].split("/").pop() || "";
402
+ const nestedName = field.type.name;
403
+ typeString = this.typeMapper.formatTypeName(`${parentName}${this.capitalizeFirst(nestedName)}`);
404
+ }
405
+ else {
406
+ typeString = this.typeMapper.formatTypeName(field.type.name);
407
+ }
408
+ }
409
+ else if (typeString === "Reference" &&
410
+ field.reference &&
411
+ Array.isArray(field.reference)) {
412
+ const referenceTypes = this.extractReferenceTypes(field.reference);
413
+ if (referenceTypes.length > 0) {
414
+ referenceTypes.forEach((type) => this.resourceTypes.add(type));
415
+ const unionType = referenceTypes
416
+ .map((type) => `'${type}'`)
417
+ .join(" | ");
418
+ typeString = `Reference<${unionType}>`;
419
+ }
420
+ }
421
+ }
422
+ if ("required" in field) {
423
+ required = field.required;
424
+ }
425
+ if ("array" in field) {
426
+ isArray = field.array;
427
+ }
428
+ const optional = required ? "" : "?";
429
+ const arrayType = isArray ? "[]" : "";
430
+ return `${fieldName}${optional}: ${typeString}${arrayType};`;
431
+ }
432
+ // ==========================================
433
+ /**
434
+ * Extract exported symbols from TypeScript content
435
+ */
436
+ extractExports(content) {
437
+ const exports = [];
438
+ const exportListPattern = /export\s*\{\s*([^}]+)\s*\}/g;
439
+ let match;
440
+ while ((match = exportListPattern.exec(content)) !== null) {
441
+ if (match[1]) {
442
+ const names = match[1]
443
+ .split(",")
444
+ .map((name) => name.trim())
445
+ .filter(Boolean);
446
+ exports.push(...names);
447
+ }
448
+ }
449
+ const directExportPatterns = [
450
+ /export\s+interface\s+(\w+)/g, // export interface Name
451
+ /export\s+type\s+(\w+)/g, // export type Name
452
+ /export\s+class\s+(\w+)/g, // export class Name
453
+ /export\s+enum\s+(\w+)/g, // export enum Name
454
+ /export\s+const\s+(\w+)/g, // export const name
455
+ /export\s+function\s+(\w+)/g, // export function name
456
+ ];
457
+ for (const pattern of directExportPatterns) {
458
+ let match;
459
+ while ((match = pattern.exec(content)) !== null) {
460
+ if (match[1]) {
461
+ exports.push(match[1]);
462
+ }
463
+ }
464
+ }
465
+ return [...new Set(exports)];
466
+ }
467
+ /**
468
+ * Set output directory for compatibility with API builder
469
+ */
470
+ setOutputDir(directory) {
471
+ this.options.outputDir = directory;
472
+ }
473
+ /**
474
+ * Update generator options for compatibility with API builder
475
+ */
476
+ setOptions(options) {
477
+ this.options = { ...this.options, ...options };
478
+ }
479
+ /**
480
+ * Get current options for compatibility with API builder
481
+ */
482
+ getOptions() {
483
+ return { ...this.options };
484
+ }
485
+ /**
486
+ * Run post-generation hooks - generate utility files
487
+ */
488
+ async runPostGenerationHooks() {
489
+ await super.runPostGenerationHooks();
490
+ await this.generateUtilitiesFile();
491
+ }
492
+ /**
493
+ * Generate utilities.ts file with ResourceType union
494
+ */
495
+ async generateUtilitiesFile() {
496
+ if (this.resourceTypes.size === 0) {
497
+ this.logger.warn("No resource types found, skipping utilities.ts generation");
498
+ return;
499
+ }
500
+ const lines = [];
501
+ // Add file header comment
502
+ lines.push("/**");
503
+ lines.push(" * FHIR Resource Type Utilities");
504
+ lines.push(" * This file contains utility types for FHIR resources.");
505
+ lines.push(" * ");
506
+ lines.push(" * @generated This file is auto-generated. Do not edit manually.");
507
+ lines.push(" */");
508
+ lines.push("");
509
+ // Generate ResourceType union
510
+ const sortedResourceTypes = Array.from(this.resourceTypes).sort();
511
+ lines.push("/**");
512
+ lines.push(" * Union of all FHIR resource types in this package");
513
+ lines.push(" */");
514
+ lines.push("export type ResourceType =");
515
+ for (let i = 0; i < sortedResourceTypes.length; i++) {
516
+ const isLast = i === sortedResourceTypes.length - 1;
517
+ const separator = isLast ? ";" : "";
518
+ lines.push(` | '${sortedResourceTypes[i]}'${separator}`);
519
+ }
520
+ lines.push("");
521
+ // Generate helper type for Resource references
522
+ lines.push("/**");
523
+ lines.push(" * Helper type for creating typed References");
524
+ lines.push(" * @example Reference<'Patient' | 'Practitioner'> - Reference that can point to Patient or Practitioner");
525
+ lines.push(" */");
526
+ lines.push("export type TypedReference<T extends ResourceType> = {");
527
+ lines.push(" reference?: string;");
528
+ lines.push(" type?: T;");
529
+ lines.push(" identifier?: any; // Simplified for utility");
530
+ lines.push(" display?: string;");
531
+ lines.push("};");
532
+ const content = lines.join("\n");
533
+ // Write the utilities file
534
+ await this.fileManager.writeFile("utilities.ts", content);
535
+ this.logger.info(`Generated utilities.ts with ${this.resourceTypes.size} resource types`);
536
+ }
537
+ }