@atomic-ehr/codegen 0.0.1-canary.20250830224431.6d211a5 → 0.0.1-canary.20250830233015.ec9aae7
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.
|
@@ -100,6 +100,14 @@ export declare class TypeScriptGenerator extends BaseGenerator<TypeScriptGenerat
|
|
|
100
100
|
* Get the TypeScript type name for a binding
|
|
101
101
|
*/
|
|
102
102
|
private getValueSetTypeName;
|
|
103
|
+
/**
|
|
104
|
+
* Check if a field has enum values that should be inlined
|
|
105
|
+
*/
|
|
106
|
+
private shouldUseInlineEnum;
|
|
107
|
+
/**
|
|
108
|
+
* Generate inline enum type from field enum values
|
|
109
|
+
*/
|
|
110
|
+
private generateInlineEnumType;
|
|
103
111
|
private shouldSkipSchema;
|
|
104
112
|
private getFilenameForSchema;
|
|
105
113
|
private extractImportsFromContent;
|
|
@@ -153,6 +161,10 @@ export declare class TypeScriptGenerator extends BaseGenerator<TypeScriptGenerat
|
|
|
153
161
|
* Get current options for compatibility with API builder
|
|
154
162
|
*/
|
|
155
163
|
getOptions(): TypeScriptGeneratorOptions;
|
|
164
|
+
/**
|
|
165
|
+
* Override generate to clean directory first
|
|
166
|
+
*/
|
|
167
|
+
generate(schemas: TypeSchema[]): Promise<GeneratedFile[]>;
|
|
156
168
|
/**
|
|
157
169
|
* Run post-generation hooks - generate utility files
|
|
158
170
|
*/
|
|
@@ -183,6 +183,10 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
183
183
|
if (!binding) {
|
|
184
184
|
return false;
|
|
185
185
|
}
|
|
186
|
+
// If generateValueSets is false, never use value set types
|
|
187
|
+
if (!this.tsOptions.generateValueSets) {
|
|
188
|
+
return false;
|
|
189
|
+
}
|
|
186
190
|
const valueSetTypeName = this.typeMapper.formatTypeName(binding.name);
|
|
187
191
|
return this.collectedValueSets.has(valueSetTypeName);
|
|
188
192
|
}
|
|
@@ -192,6 +196,31 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
192
196
|
getValueSetTypeName(binding) {
|
|
193
197
|
return this.typeMapper.formatTypeName(binding.name);
|
|
194
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Check if a field has enum values that should be inlined
|
|
201
|
+
*/
|
|
202
|
+
shouldUseInlineEnum(field) {
|
|
203
|
+
if (!field) {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
// Only use inline enums when generateValueSets is false
|
|
207
|
+
if (this.tsOptions.generateValueSets) {
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
// Check if field has enum values directly on the field
|
|
211
|
+
return field.enum && Array.isArray(field.enum) && field.enum.length > 0;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Generate inline enum type from field enum values
|
|
215
|
+
*/
|
|
216
|
+
generateInlineEnumType(field) {
|
|
217
|
+
if (!field.enum || !Array.isArray(field.enum)) {
|
|
218
|
+
return "string"; // fallback
|
|
219
|
+
}
|
|
220
|
+
// Create union type from enum values
|
|
221
|
+
const enumValues = field.enum.map((value) => `'${value}'`).join(' | ');
|
|
222
|
+
return enumValues;
|
|
223
|
+
}
|
|
195
224
|
shouldSkipSchema(schema) {
|
|
196
225
|
if (schema.identifier.kind === "value-set" ||
|
|
197
226
|
schema.identifier.kind === "binding" ||
|
|
@@ -411,7 +440,7 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
411
440
|
if ("choices" in field && field.choices && Array.isArray(field.choices)) {
|
|
412
441
|
return imports;
|
|
413
442
|
}
|
|
414
|
-
// Handle value set imports
|
|
443
|
+
// Handle value set imports (only when generateValueSets is true)
|
|
415
444
|
if (field.binding && this.shouldUseValueSetType(field.binding)) {
|
|
416
445
|
const valueSetTypeName = this.getValueSetTypeName(field.binding);
|
|
417
446
|
imports.push(valueSetTypeName);
|
|
@@ -527,6 +556,10 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
527
556
|
const valueSetTypeName = this.getValueSetTypeName(field.binding);
|
|
528
557
|
typeString = valueSetTypeName;
|
|
529
558
|
}
|
|
559
|
+
else if (field.binding && this.shouldUseInlineEnum(field)) {
|
|
560
|
+
// Generate inline enum union type when generateValueSets is false
|
|
561
|
+
typeString = this.generateInlineEnumType(field);
|
|
562
|
+
}
|
|
530
563
|
else {
|
|
531
564
|
// Existing type mapping logic
|
|
532
565
|
const languageType = this.typeMapper.mapType(field.type);
|
|
@@ -621,6 +654,16 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
621
654
|
getOptions() {
|
|
622
655
|
return { ...this.options };
|
|
623
656
|
}
|
|
657
|
+
/**
|
|
658
|
+
* Override generate to clean directory first
|
|
659
|
+
*/
|
|
660
|
+
async generate(schemas) {
|
|
661
|
+
// Clean output directory before generation
|
|
662
|
+
await this.fileManager.cleanDirectory();
|
|
663
|
+
this.logger.debug("Cleaned output directory before generation");
|
|
664
|
+
// Call parent implementation
|
|
665
|
+
return super.generate(schemas);
|
|
666
|
+
}
|
|
624
667
|
/**
|
|
625
668
|
* Run post-generation hooks - generate utility files
|
|
626
669
|
*/
|
|
@@ -781,13 +824,13 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
781
824
|
// Export utilities
|
|
782
825
|
lines.push('export * from "./utilities.js";');
|
|
783
826
|
// Export value sets if any were generated
|
|
784
|
-
if (this.collectedValueSets.size > 0) {
|
|
827
|
+
if (this.tsOptions.generateValueSets && this.collectedValueSets.size > 0) {
|
|
785
828
|
lines.push('');
|
|
786
829
|
lines.push('// Value Sets');
|
|
787
830
|
lines.push('export * from "./valuesets/index.js";');
|
|
788
831
|
}
|
|
789
832
|
const content = lines.join('\n');
|
|
790
833
|
await this.fileManager.writeFile('index.ts', content);
|
|
791
|
-
this.logger.info(`Generated index.ts with type exports${this.collectedValueSets.size > 0 ? ' and value sets' : ''}`);
|
|
834
|
+
this.logger.info(`Generated index.ts with type exports${this.tsOptions.generateValueSets && this.collectedValueSets.size > 0 ? ' and value sets' : ''}`);
|
|
792
835
|
}
|
|
793
836
|
}
|
package/dist/cli/index.js
CHANGED
|
@@ -1265,15 +1265,15 @@ ${D.map((B)=>` '${B}': ${B};`).join(`
|
|
|
1265
1265
|
|
|
1266
1266
|
`);if(E)return`${B}
|
|
1267
1267
|
|
|
1268
|
-
${E}`;return B}filterAndSortSchemas(D){return this.collectedValueSets=this.collectValueSets(D),D.filter((F)=>!this.shouldSkipSchema(F))}async validateContent(D,F){let B=/export\s+(interface|class|type|enum)\s+\w+/.test(D),E=D.includes("{")&&D.includes("}");if(!B)throw new Error(`Generated content for ${F.schema.identifier.name} does not contain valid export statements`);if(!E)throw new Error(`Generated content for ${F.schema.identifier.name} has invalid syntax (missing braces)`)}async transformSchemas(D){let F=[];for(let B of D){let E=await this.transformSchema(B);if(E)F.push(E)}return F}async transformSchema(D){if(this.shouldSkipSchema(D))return;let F={schema:D,typeMapper:this.typeMapper,filename:this.getFilenameForSchema(D),language:"TypeScript",timestamp:new Date().toISOString()},B=await this.generateSchemaContent(D,F);if(!B.trim())return;let E=this.extractImportsFromContent(B,D),C=this.extractExportsFromContent(B,D),u=this.getFilenameForSchema(D);return{content:B,imports:E,exports:Array.from(C),filename:u}}shouldGenerateValueSet(D){if(!i2(D)||!D.enum||!Array.isArray(D.enum)||D.enum.length===0)return!1;switch(this.options.valueSetMode||"required-only"){case"all":return!0;case"required-only":return D.strength==="required";case"custom":return(this.options.valueSetStrengths||["required"]).includes(D.strength);default:return D.strength==="required"}}collectValueSets(D){let F=new Map;for(let B of D)if(this.shouldGenerateValueSet(B)&&i2(B)){let E=this.typeMapper.formatTypeName(B.identifier.name);F.set(E,B)}return F}shouldUseValueSetType(D){if(!D)return!1;let F=this.typeMapper.formatTypeName(D.name);return this.collectedValueSets.has(F)}getValueSetTypeName(D){return this.typeMapper.formatTypeName(D.name)}shouldSkipSchema(D){if(D.identifier.kind==="value-set"||D.identifier.kind==="binding"||D.identifier.kind==="primitive-type")return!0;if(!this.tsOptions.includeExtensions){let F=D.identifier.url;if(F&&F.includes("StructureDefinition/")){let B=F.split("StructureDefinition/")[1];if(B){let E=B.includes("-"),C=D.identifier.kind==="profile";if(E&&C)return!0}}}return!1}getFilenameForSchema(D){return`${this.typeMapper.formatFileName(D.identifier.name)}${this.getFileExtension()}`}extractImportsFromContent(D,F){let B=new Map,E=/import\s+(?:type\s+)?{\s*([^}]+)\s*}\s+from\s+['"]([^'"]+)['"];?/g,C;while((C=E.exec(D))!==null){let u=C[1],$=C[2];if(!u||!$)continue;let X=u.split(",").map((Q)=>Q.trim());for(let Q of X)B.set(Q,$)}return B}extractExportsFromContent(D,F){let B=new Set,E=/export\s+(?:interface|class|enum|type)\s+([A-Za-z_$][A-Za-z0-9_$]*)/g,C;while((C=E.exec(D))!==null)if(C[1])B.add(C[1]);return B.add(this.typeMapper.formatTypeName(F.identifier.name)),B}sanitizePackageName(D){return D.replace(/[^a-zA-Z0-9-_.]/g,"-")}generateReferenceInterface(D){let F=[],B=new Set;if("fields"in D&&D.fields)for(let[,E]of Object.entries(D.fields))this.collectFieldImports(E).forEach((u)=>B.add(u));if(F.push("import type { ResourceType } from './utilities.js';"),B.size>0){let E=Array.from(B).sort();for(let C of E)F.push(`import type { ${C} } from './${C}.js';`)}if(F.push(""),this.tsOptions.includeDocuments&&D.description){if(F.push("/**"),F.push(` * ${D.description}`),D.identifier.url)F.push(` * @see ${D.identifier.url}`);if(D.identifier.package)F.push(` * @package ${D.identifier.package}`);F.push(" * @template T - The resource type being referenced"),F.push(" */")}if(F.push("export interface Reference<T extends ResourceType = ResourceType> {"),"fields"in D&&D.fields)for(let[E,C]of Object.entries(D.fields))if(E==="type")F.push(" type?: T;");else{let u=this.generateFieldLines(E,C);for(let $ of u)if($)F.push(` ${$}`)}return F.push("}"),F.join(`
|
|
1268
|
+
${E}`;return B}filterAndSortSchemas(D){return this.collectedValueSets=this.collectValueSets(D),D.filter((F)=>!this.shouldSkipSchema(F))}async validateContent(D,F){let B=/export\s+(interface|class|type|enum)\s+\w+/.test(D),E=D.includes("{")&&D.includes("}");if(!B)throw new Error(`Generated content for ${F.schema.identifier.name} does not contain valid export statements`);if(!E)throw new Error(`Generated content for ${F.schema.identifier.name} has invalid syntax (missing braces)`)}async transformSchemas(D){let F=[];for(let B of D){let E=await this.transformSchema(B);if(E)F.push(E)}return F}async transformSchema(D){if(this.shouldSkipSchema(D))return;let F={schema:D,typeMapper:this.typeMapper,filename:this.getFilenameForSchema(D),language:"TypeScript",timestamp:new Date().toISOString()},B=await this.generateSchemaContent(D,F);if(!B.trim())return;let E=this.extractImportsFromContent(B,D),C=this.extractExportsFromContent(B,D),u=this.getFilenameForSchema(D);return{content:B,imports:E,exports:Array.from(C),filename:u}}shouldGenerateValueSet(D){if(!i2(D)||!D.enum||!Array.isArray(D.enum)||D.enum.length===0)return!1;switch(this.options.valueSetMode||"required-only"){case"all":return!0;case"required-only":return D.strength==="required";case"custom":return(this.options.valueSetStrengths||["required"]).includes(D.strength);default:return D.strength==="required"}}collectValueSets(D){let F=new Map;for(let B of D)if(this.shouldGenerateValueSet(B)&&i2(B)){let E=this.typeMapper.formatTypeName(B.identifier.name);F.set(E,B)}return F}shouldUseValueSetType(D){if(!D)return!1;if(!this.tsOptions.generateValueSets)return!1;let F=this.typeMapper.formatTypeName(D.name);return this.collectedValueSets.has(F)}getValueSetTypeName(D){return this.typeMapper.formatTypeName(D.name)}shouldUseInlineEnum(D){if(!D)return!1;if(this.tsOptions.generateValueSets)return!1;return D.enum&&Array.isArray(D.enum)&&D.enum.length>0}generateInlineEnumType(D){if(!D.enum||!Array.isArray(D.enum))return"string";return D.enum.map((B)=>`'${B}'`).join(" | ")}shouldSkipSchema(D){if(D.identifier.kind==="value-set"||D.identifier.kind==="binding"||D.identifier.kind==="primitive-type")return!0;if(!this.tsOptions.includeExtensions){let F=D.identifier.url;if(F&&F.includes("StructureDefinition/")){let B=F.split("StructureDefinition/")[1];if(B){let E=B.includes("-"),C=D.identifier.kind==="profile";if(E&&C)return!0}}}return!1}getFilenameForSchema(D){return`${this.typeMapper.formatFileName(D.identifier.name)}${this.getFileExtension()}`}extractImportsFromContent(D,F){let B=new Map,E=/import\s+(?:type\s+)?{\s*([^}]+)\s*}\s+from\s+['"]([^'"]+)['"];?/g,C;while((C=E.exec(D))!==null){let u=C[1],$=C[2];if(!u||!$)continue;let X=u.split(",").map((Q)=>Q.trim());for(let Q of X)B.set(Q,$)}return B}extractExportsFromContent(D,F){let B=new Set,E=/export\s+(?:interface|class|enum|type)\s+([A-Za-z_$][A-Za-z0-9_$]*)/g,C;while((C=E.exec(D))!==null)if(C[1])B.add(C[1]);return B.add(this.typeMapper.formatTypeName(F.identifier.name)),B}sanitizePackageName(D){return D.replace(/[^a-zA-Z0-9-_.]/g,"-")}generateReferenceInterface(D){let F=[],B=new Set;if("fields"in D&&D.fields)for(let[,E]of Object.entries(D.fields))this.collectFieldImports(E).forEach((u)=>B.add(u));if(F.push("import type { ResourceType } from './utilities.js';"),B.size>0){let E=Array.from(B).sort();for(let C of E)F.push(`import type { ${C} } from './${C}.js';`)}if(F.push(""),this.tsOptions.includeDocuments&&D.description){if(F.push("/**"),F.push(` * ${D.description}`),D.identifier.url)F.push(` * @see ${D.identifier.url}`);if(D.identifier.package)F.push(` * @package ${D.identifier.package}`);F.push(" * @template T - The resource type being referenced"),F.push(" */")}if(F.push("export interface Reference<T extends ResourceType = ResourceType> {"),"fields"in D&&D.fields)for(let[E,C]of Object.entries(D.fields))if(E==="type")F.push(" type?: T;");else{let u=this.generateFieldLines(E,C);for(let $ of u)if($)F.push(` ${$}`)}return F.push("}"),F.join(`
|
|
1269
1269
|
`)}generateTypeScriptInterface(D){let F=[],B=this.typeMapper.formatTypeName(D.identifier.name),E=new Set,C=new Set;if("fields"in D&&D.fields)for(let[,u]of Object.entries(D.fields)){let $=this.collectFieldImports(u);for(let X of $)if(this.collectedValueSets.has(X))C.add(X);else E.add(X)}if("nested"in D&&D.nested&&Array.isArray(D.nested)){for(let u of D.nested)if(u.fields)for(let[,$]of Object.entries(u.fields)){let X=this.collectFieldImports($);for(let Q of X)if(this.collectedValueSets.has(Q))C.add(Q);else E.add(Q)}}if(E.size>0){let u=Array.from(E).sort();for(let $ of u)F.push(`import type { ${$} } from './${$}.js';`)}if(C.size>0){let $=Array.from(C).sort().join(", ");F.push(`import type { ${$} } from './valuesets/index.js';`)}if(E.size>0||C.size>0)F.push("");if(this.tsOptions.includeDocuments&&D.description){if(F.push("/**"),F.push(` * ${D.description}`),D.identifier.url)F.push(` * @see ${D.identifier.url}`);if(D.identifier.package)F.push(` * @package ${D.identifier.package}`);F.push(" */")}if(F.push(`export interface ${B} {`),D.identifier.kind==="resource")F.push(` resourceType: '${B}';`);if("fields"in D&&D.fields)for(let[u,$]of Object.entries(D.fields)){let X=this.generateFieldLines(u,$);for(let Q of X)if(Q)F.push(` ${Q}`)}return F.push("}"),F.join(`
|
|
1270
1270
|
`)}collectFieldImports(D){let F=[];if("choices"in D&&D.choices&&Array.isArray(D.choices))return F;if(D.binding&&this.shouldUseValueSetType(D.binding)){let B=this.getValueSetTypeName(D.binding);return F.push(B),F}if("type"in D&&D.type){if(D.type.kind==="nested")return F;let B=this.typeMapper.mapType(D.type);if(!B.isPrimitive&&B.name!=="any"){if(!["string","number","boolean","Date","object","unknown","any"].includes(B.name))F.push(B.name)}}return[...new Set(F)]}extractReferenceTypes(D){let F=[];if(!Array.isArray(D))return F;for(let B of D){if(!B||typeof B!=="object")continue;if(B.kind==="resource"&&B.name){let E=this.typeMapper.formatTypeName(B.name);F.push(E)}}return[...new Set(F)]}generateNestedTypeInterface(D,F){let B=[],E=this.typeMapper.formatTypeName(`${D}${this.capitalizeFirst(F.identifier.name)}`);if(this.tsOptions.includeDocuments&&F.description){if(B.push("/**"),B.push(` * ${F.description}`),F.identifier.url)B.push(` * @see ${F.identifier.url}`);B.push(" */")}if(B.push(`export interface ${E} {`),F.fields)for(let[C,u]of Object.entries(F.fields)){let $=this.generateFieldLines(C,u);for(let X of $)if(X)B.push(` ${X}`)}return B.push("}"),B.join(`
|
|
1271
|
-
`)}capitalizeFirst(D){return D.charAt(0).toUpperCase()+D.slice(1)}generateFieldLines(D,F){if("choices"in F&&F.choices&&Array.isArray(F.choices))return[];let B=this.generateFieldLine(D,F);return B?[B]:[]}generateFieldLine(D,F){let B="any",E=!1,C=!1;if("type"in F&&F.type){if(F.binding&&this.shouldUseValueSetType(F.binding))B=this.getValueSetTypeName(F.binding);else if(B=this.typeMapper.mapType(F.type).name,F.type.kind==="nested"){let Q=F.type.url?.split("#")||[];if(Q.length===2){let z=Q[0].split("/").pop()||"",Y=F.type.name;B=this.typeMapper.formatTypeName(`${z}${this.capitalizeFirst(Y)}`)}else B=this.typeMapper.formatTypeName(F.type.name)}else if(B==="Reference"&&F.reference&&Array.isArray(F.reference)){let Q=this.extractReferenceTypes(F.reference);if(Q.length>0)Q.forEach((Y)=>this.resourceTypes.add(Y)),B=`Reference<${Q.map((Y)=>`'${Y}'`).join(" | ")}>`}}if("required"in F)E=F.required;if("array"in F)C=F.array;return`${D}${E?"":"?"}: ${B}${C?"[]":""};`}extractExports(D){let F=[],B=/export\s*\{\s*([^}]+)\s*\}/g,E;while((E=B.exec(D))!==null)if(E[1]){let u=E[1].split(",").map(($)=>$.trim()).filter(Boolean);F.push(...u)}let C=[/export\s+interface\s+(\w+)/g,/export\s+type\s+(\w+)/g,/export\s+class\s+(\w+)/g,/export\s+enum\s+(\w+)/g,/export\s+const\s+(\w+)/g,/export\s+function\s+(\w+)/g];for(let u of C){let $;while(($=u.exec(D))!==null)if($[1])F.push($[1])}return[...new Set(F)]}setOutputDir(D){this.options.outputDir=D}setOptions(D){this.options={...this.options,...D}}getOptions(){return{...this.options}}async runPostGenerationHooks(){await super.runPostGenerationHooks(),await this.generateValueSetFiles(),await this.generateUtilitiesFile(),await this.generateMainIndexFile()}async generateUtilitiesFile(){if(this.resourceTypes.size===0){this.logger.warn("No resource types found, skipping utilities.ts generation");return}let D=[];D.push("/**"),D.push(" * FHIR Resource Type Utilities"),D.push(" * This file contains utility types for FHIR resources."),D.push(" * "),D.push(" * @generated This file is auto-generated. Do not edit manually."),D.push(" */"),D.push("");let F=Array.from(this.resourceTypes).sort();D.push("/**"),D.push(" * Union of all FHIR resource types in this package"),D.push(" */"),D.push("export type ResourceType =");for(let E=0;E<F.length;E++){let u=E===F.length-1?";":"";D.push(` | '${F[E]}'${u}`)}D.push(""),D.push("/**"),D.push(" * Helper type for creating typed References"),D.push(" * @example Reference<'Patient' | 'Practitioner'> - Reference that can point to Patient or Practitioner"),D.push(" */"),D.push("export type TypedReference<T extends ResourceType> = {"),D.push(" reference?: string;"),D.push(" type?: T;"),D.push(" identifier?: any; // Simplified for utility"),D.push(" display?: string;"),D.push("};");let B=D.join(`
|
|
1271
|
+
`)}capitalizeFirst(D){return D.charAt(0).toUpperCase()+D.slice(1)}generateFieldLines(D,F){if("choices"in F&&F.choices&&Array.isArray(F.choices))return[];let B=this.generateFieldLine(D,F);return B?[B]:[]}generateFieldLine(D,F){let B="any",E=!1,C=!1;if("type"in F&&F.type){if(F.binding&&this.shouldUseValueSetType(F.binding))B=this.getValueSetTypeName(F.binding);else if(F.binding&&this.shouldUseInlineEnum(F))B=this.generateInlineEnumType(F);else if(B=this.typeMapper.mapType(F.type).name,F.type.kind==="nested"){let Q=F.type.url?.split("#")||[];if(Q.length===2){let z=Q[0].split("/").pop()||"",Y=F.type.name;B=this.typeMapper.formatTypeName(`${z}${this.capitalizeFirst(Y)}`)}else B=this.typeMapper.formatTypeName(F.type.name)}else if(B==="Reference"&&F.reference&&Array.isArray(F.reference)){let Q=this.extractReferenceTypes(F.reference);if(Q.length>0)Q.forEach((Y)=>this.resourceTypes.add(Y)),B=`Reference<${Q.map((Y)=>`'${Y}'`).join(" | ")}>`}}if("required"in F)E=F.required;if("array"in F)C=F.array;return`${D}${E?"":"?"}: ${B}${C?"[]":""};`}extractExports(D){let F=[],B=/export\s*\{\s*([^}]+)\s*\}/g,E;while((E=B.exec(D))!==null)if(E[1]){let u=E[1].split(",").map(($)=>$.trim()).filter(Boolean);F.push(...u)}let C=[/export\s+interface\s+(\w+)/g,/export\s+type\s+(\w+)/g,/export\s+class\s+(\w+)/g,/export\s+enum\s+(\w+)/g,/export\s+const\s+(\w+)/g,/export\s+function\s+(\w+)/g];for(let u of C){let $;while(($=u.exec(D))!==null)if($[1])F.push($[1])}return[...new Set(F)]}setOutputDir(D){this.options.outputDir=D}setOptions(D){this.options={...this.options,...D}}getOptions(){return{...this.options}}async generate(D){return await this.fileManager.cleanDirectory(),this.logger.debug("Cleaned output directory before generation"),super.generate(D)}async runPostGenerationHooks(){await super.runPostGenerationHooks(),await this.generateValueSetFiles(),await this.generateUtilitiesFile(),await this.generateMainIndexFile()}async generateUtilitiesFile(){if(this.resourceTypes.size===0){this.logger.warn("No resource types found, skipping utilities.ts generation");return}let D=[];D.push("/**"),D.push(" * FHIR Resource Type Utilities"),D.push(" * This file contains utility types for FHIR resources."),D.push(" * "),D.push(" * @generated This file is auto-generated. Do not edit manually."),D.push(" */"),D.push("");let F=Array.from(this.resourceTypes).sort();D.push("/**"),D.push(" * Union of all FHIR resource types in this package"),D.push(" */"),D.push("export type ResourceType =");for(let E=0;E<F.length;E++){let u=E===F.length-1?";":"";D.push(` | '${F[E]}'${u}`)}D.push(""),D.push("/**"),D.push(" * Helper type for creating typed References"),D.push(" * @example Reference<'Patient' | 'Practitioner'> - Reference that can point to Patient or Practitioner"),D.push(" */"),D.push("export type TypedReference<T extends ResourceType> = {"),D.push(" reference?: string;"),D.push(" type?: T;"),D.push(" identifier?: any; // Simplified for utility"),D.push(" display?: string;"),D.push("};");let B=D.join(`
|
|
1272
1272
|
`);await this.fileManager.writeFile("utilities.ts",B),this.logger.info(`Generated utilities.ts with ${this.resourceTypes.size} resource types`)}generateValueSetFile(D){let F=this.typeMapper.formatTypeName(D.identifier.name),B=D.enum?.map((C)=>` '${C}'`).join(`,
|
|
1273
1273
|
`)||"",E=[];if(this.options.includeDocuments){if(E.push("/**"),E.push(` * ${D.identifier.name} value set`),D.description)E.push(` * ${D.description}`);if(D.valueset?.url)E.push(` * @see ${D.valueset.url}`);if(D.identifier.package)E.push(` * @package ${D.identifier.package}`);E.push(" * @generated This file is auto-generated. Do not edit manually."),E.push(" */"),E.push("")}if(E.push(`export const ${F}Values = [`),B)E.push(B);if(E.push("] as const;"),E.push(""),E.push(`export type ${F} = typeof ${F}Values[number];`),this.tsOptions.includeValueSetHelpers)E.push(""),E.push(`export const isValid${F} = (value: string): value is ${F} =>`),E.push(` ${F}Values.includes(value as ${F});`);return E.join(`
|
|
1274
1274
|
`)}async generateValueSetFiles(){if(!this.tsOptions.generateValueSets||this.collectedValueSets.size===0)return;for(let[D,F]of this.collectedValueSets){let B=this.generateValueSetFile(F),E=`valuesets/${D}.ts`;await this.fileManager.writeFile(E,B),this.logger.info(`Generated value set: ${E}`)}await this.generateValueSetIndexFile()}async generateValueSetIndexFile(){let D=[];if(this.tsOptions.includeDocuments)D.push("/**"),D.push(" * FHIR Value Sets"),D.push(" * This file re-exports all generated value sets."),D.push(" * "),D.push(" * @generated This file is auto-generated. Do not edit manually."),D.push(" */"),D.push("");let F=Array.from(this.collectedValueSets.keys()).sort();for(let E of F)D.push(`export * from './${E}.js';`);let B=D.join(`
|
|
1275
|
-
`);await this.fileManager.writeFile("valuesets/index.ts",B),this.logger.info(`Generated valuesets/index.ts with ${this.collectedValueSets.size} value sets`)}async generateMainIndexFile(){if(!this.options.generateIndex)return;let D=[];if(this.tsOptions.includeDocuments)D.push("/**"),D.push(" * FHIR R4 TypeScript Types"),D.push(" * Generated from FHIR StructureDefinitions"),D.push(" * "),D.push(" * @generated This file is auto-generated. Do not edit manually."),D.push(" */"),D.push("");if(D.push('export * from "./utilities.js";'),this.collectedValueSets.size>0)D.push(""),D.push("// Value Sets"),D.push('export * from "./valuesets/index.js";');let F=D.join(`
|
|
1276
|
-
`);await this.fileManager.writeFile("index.ts",F),this.logger.info(`Generated index.ts with type exports${this.collectedValueSets.size>0?" and value sets":""}`)}}class UF{schemas=[];options;generators=new Map;progressCallback;cache;pendingOperations=[];typeSchemaGenerator;logger;typeSchemaConfig;constructor(D={}){if(this.options={outputDir:D.outputDir||"./generated",verbose:D.verbose??!1,overwrite:D.overwrite??!0,validate:D.validate??!0,cache:D.cache??!0,typeSchemaConfig:D.typeSchemaConfig},this.typeSchemaConfig=D.typeSchemaConfig,this.logger=D.logger||JD({verbose:this.options.verbose,prefix:"API"}),this.options.cache)this.cache=new mD(this.typeSchemaConfig)}fromPackage(D,F){this.logger.debug(`Loading from FHIR package: ${D}@${F||"latest"}`);let B=this.loadFromPackage(D,F);return this.pendingOperations.push(B),this}fromFiles(...D){this.logger.debug(`Loading from ${D.length} TypeSchema files`);let F=this.loadFromFiles(D);return this.pendingOperations.push(F),this}fromSchemas(D){return this.logger.debug(`Adding ${D.length} TypeSchemas to generation`),this.schemas=[...this.schemas,...D],this}typescript(D={}){let F=`${this.options.outputDir}/types`,B=new RF({outputDir:F,moduleFormat:D.moduleFormat||"esm",generateIndex:D.generateIndex??!0,includeDocuments:D.includeDocuments??!0,namingConvention:D.namingConvention||"PascalCase",includeExtensions:D.includeExtensions??!1,includeProfiles:D.includeProfiles??!1,generateValueSets:D.generateValueSets??!1,includeValueSetHelpers:D.includeValueSetHelpers??!1,valueSetStrengths:D.valueSetStrengths??["required"],logger:this.logger.child("TS"),valueSetMode:D.valueSetMode??"required-only",valueSetDirectory:D.valueSetDirectory??"valuesets",verbose:this.options.verbose,validate:!0,overwrite:this.options.overwrite});return this.generators.set("typescript",B),this.logger.debug(`Configured TypeScript generator (${D.moduleFormat||"esm"})`),this}restClient(D={}){let F=`${this.options.outputDir}/client`,B=new KF({outputDir:F,logger:this.logger.child("REST"),...D});return this.generators.set("restclient",B),this.logger.debug(`Configured REST client generator (${D.clientName||"FHIRClient"})`),this}onProgress(D){return this.progressCallback=D,this}outputTo(D){this.logger.debug(`Setting output directory: ${D}`),this.options.outputDir=D;for(let F of this.generators.values())if(F.setOutputDir)F.setOutputDir(D);return this}verbose(D=!0){return this.options.verbose=D,this}validate(D=!0){return this.options.validate=D,this}ensureTypeScriptForRestClient(){let D=this.generators.has("restclient"),F=this.generators.has("typescript");if(D&&!F)this.logger.debug("Automatically adding TypeScript generator for REST client"),this.typescript({moduleFormat:"esm",generateIndex:!0,includeDocuments:!1,namingConvention:"PascalCase"})}async generate(){this.ensureTypeScriptForRestClient();let D=performance.now(),F={success:!1,outputDir:this.options.outputDir,filesGenerated:[],errors:[],warnings:[],duration:0};this.logger.debug(`Starting generation with ${this.generators.size} generators`);try{if(this.reportProgress("Loading",0,4,"Loading TypeSchema data..."),await this.resolveSchemas(),this.logger.debug(`Resolved ${this.schemas.length} schemas`),this.reportProgress("Validating",1,4,"Validating TypeSchema documents..."),this.options.validate)this.logger.debug("Starting schema validation"),await this.validateSchemas(F),this.logger.debug("Schema validation completed");this.reportProgress("Generating",2,4,"Generating code..."),this.logger.debug(`Executing ${this.generators.size} generators`),await this.executeGenerators(F),this.reportProgress("Complete",4,4,"Generation completed successfully"),F.success=F.errors.length===0,this.logger.debug(`Generation completed: ${F.filesGenerated.length} files`)}catch(B){this.logger.error("Code generation failed",B instanceof Error?B:new Error(String(B))),F.errors.push(B instanceof Error?B.message:String(B)),F.success=!1}finally{F.duration=performance.now()-D}return F}async build(){await this.resolveSchemas();let D={};for(let[F,B]of this.generators.entries())if(B.build)D[F]=await B.build(this.schemas);return D}reset(){return this.schemas=[],this.generators.clear(),this.progressCallback=void 0,this}getSchemas(){return[...this.schemas]}getGenerators(){return Array.from(this.generators.keys())}async loadFromPackage(D,F){let B=new SD({verbose:this.options.verbose,logger:this.logger.child("Schema"),treeshake:this.typeSchemaConfig?.treeshake},this.typeSchemaConfig);this.typeSchemaGenerator=B;let E=await B.generateFromPackage(D,F);if(this.schemas=[...this.schemas,...E],this.cache)this.cache.setMany(E)}async loadFromFiles(D){if(!this.typeSchemaGenerator)this.typeSchemaGenerator=new SD({verbose:this.options.verbose,logger:this.logger.child("Schema"),treeshake:this.typeSchemaConfig?.treeshake},this.typeSchemaConfig);let B=await new _0({format:"auto",validate:this.options.validate}).parseFromFiles(D);if(this.schemas=[...this.schemas,...B],this.cache)this.cache.setMany(B)}async resolveSchemas(){if(this.pendingOperations.length>0)await Promise.all(this.pendingOperations),this.pendingOperations=[]}async validateSchemas(D){return}async executeGenerators(D){let F=this.generators.size,B=0;for(let[E,C]of this.generators.entries()){this.reportProgress("Generating",2+B/F,4,`Generating ${E}...`);try{let u=await C.generate(this.schemas);D.filesGenerated.push(...u.map(($)=>$.path||$.filename))}catch(u){D.errors.push(`${E} generator failed: ${u instanceof Error?u.message:String(u)}`)}B++}}reportProgress(D,F,B,E){if(this.progressCallback)this.progressCallback(D,F,B,E);if(this.options.verbose&&E)this.logger.debug(`[${D}] ${E}`)}}import{existsSync as nB}from"node:fs";import{readFile as iB}from"node:fs/promises";import{resolve as j6}from"node:path";var LF={outputDir:"./generated",verbose:!1,overwrite:!0,validate:!0,cache:!0,restClient:{clientName:"FHIRClient",includeValidation:!1,includeErrorHandling:!0,includeRequestInterceptors:!1,baseUrlOverride:"",enhancedSearch:!1,chainedSearchBuilder:!1,searchAutocomplete:!0,generateValueSetEnums:!0,includeUtilities:!0,generateValidators:!1,useCanonicalManager:!0,defaultTimeout:30000,defaultRetries:0,includeDocumentation:!0,generateExamples:!1},typescript:{moduleFormat:"esm",generateIndex:!0,includeDocuments:!1,namingConvention:"PascalCase",strictMode:!0,includeProfiles:!0,includeExtensions:!1,includeCodeSystems:!1,includeOperations:!1,generateValueSets:!1,valueSetDirectory:"valuesets",valueSetMode:"required-only",valueSetStrengths:["required"],includeValueSetHelpers:!1,fhirVersion:"R4",resourceTypes:[],maxDepth:10,profileOptions:{generateKind:"interface",includeConstraints:!0,includeDocumentation:!0,strictMode:!1,subfolder:"profiles"},generateBuilders:!1,builderOptions:{includeValidation:!0,includeFactoryMethods:!0,includeInterfaces:!0,generateNestedBuilders:!0,includeHelperMethods:!0,supportPartialBuild:!0,includeJSDoc:!0,generateFactories:!0,includeTypeGuards:!0,handleChoiceTypes:!0,generateArrayHelpers:!0},validatorOptions:{includeCardinality:!0,includeTypes:!0,includeConstraints:!0,includeInvariants:!1,validateRequired:!0,allowAdditional:!1,strictValidation:!1,collectMetrics:!1,generateAssertions:!0,generatePartialValidators:!0,optimizePerformance:!0,includeJSDoc:!0,generateCompositeValidators:!0},guardOptions:{includeRuntimeValidation:!0,includeErrorMessages:!0,treeShakeable:!0,targetTSVersion:"5.0",strictGuards:!1,includeNullChecks:!0,verbose:!1}},typeSchema:{enablePersistence:!0,cacheDir:".typeschema-cache",maxAge:86400000,validateCached:!0,forceRegenerate:!1,shareCache:!0,cacheKeyPrefix:"",treeshake:[],singleFile:!1,profiles:{autoDetect:!0}},packages:[],files:[],$schema:""},NF=["atomic-codegen.config.ts","atomic-codegen.config.js","atomic-codegen.config.json",".atomic-codegenrc","atomic-codegen.json",".atomic-codegen.json","codegen.config.json","codegen.json"];class w6{validate(D){let F={valid:!0,errors:[],warnings:[]};if(!D||typeof D!=="object")return F.valid=!1,F.errors.push({path:"root",message:"Configuration must be an object",value:D}),F;let B=D;if(B.outputDir!==void 0&&typeof B.outputDir!=="string")F.errors.push({path:"outputDir",message:"outputDir must be a string",value:B.outputDir});let E=["verbose","overwrite","validate","cache"];for(let C of E)if(B[C]!==void 0&&typeof B[C]!=="boolean")F.errors.push({path:C,message:`${C} must be a boolean`,value:B[C]});if(B.typescript!==void 0){let C=this.validateTypeScriptConfig(B.typescript);F.errors.push(...C)}if(B.typeSchema!==void 0){let C=this.validateTypeSchemaConfig(B.typeSchema);F.errors.push(...C)}if(B.restClient!==void 0){let C=this.validateRestClientConfig(B.restClient);F.errors.push(...C)}if(B.packages!==void 0)if(!Array.isArray(B.packages))F.errors.push({path:"packages",message:"packages must be an array",value:B.packages});else B.packages.forEach((C,u)=>{if(typeof C!=="string")F.errors.push({path:`packages[${u}]`,message:"package name must be a string",value:C})});if(B.files!==void 0)if(!Array.isArray(B.files))F.errors.push({path:"files",message:"files must be an array",value:B.files});else B.files.forEach((C,u)=>{if(typeof C!=="string")F.errors.push({path:`files[${u}]`,message:"file path must be a string",value:C})});if(F.valid=F.errors.length===0,F.valid)F.config=B;return F}validateTypeScriptConfig(D){let F=[];if(typeof D!=="object"||D===null)return F.push({path:"typescript",message:"typescript config must be an object",value:D}),F;let B=D;if(B.moduleFormat!==void 0){if(!["esm","cjs"].includes(B.moduleFormat))F.push({path:"typescript.moduleFormat",message:'moduleFormat must be "esm" or "cjs"',value:B.moduleFormat})}if(B.namingConvention!==void 0){if(!["PascalCase","camelCase"].includes(B.namingConvention))F.push({path:"typescript.namingConvention",message:'namingConvention must be "PascalCase" or "camelCase"',value:B.namingConvention})}let E=["generateIndex","includeDocuments","strictMode","includeProfiles","includeExtensions","includeCodeSystems","includeOperations","generateValueSets","includeValueSetHelpers"];for(let C of E)if(B[C]!==void 0&&typeof B[C]!=="boolean")F.push({path:`typescript.${C}`,message:`${C} must be a boolean`,value:B[C]});if(B.validatorOptions!==void 0){let C=this.validateValidatorOptions(B.validatorOptions);F.push(...C)}if(B.guardOptions!==void 0){let C=this.validateGuardOptions(B.guardOptions);F.push(...C)}if(B.profileOptions!==void 0){let C=this.validateProfileOptions(B.profileOptions);F.push(...C)}return F}validateValidatorOptions(D){let F=[];if(typeof D!=="object"||D===null)return F.push({path:"typescript.validatorOptions",message:"validatorOptions must be an object",value:D}),F;let B=D,E=["includeCardinality","includeTypes","includeConstraints","includeInvariants","validateRequired","allowAdditional","strictValidation","collectMetrics","generateAssertions","generatePartialValidators","optimizePerformance","includeJSDoc","generateCompositeValidators"];for(let C of E)if(B[C]!==void 0&&typeof B[C]!=="boolean")F.push({path:`typescript.validatorOptions.${C}`,message:`${C} must be a boolean`,value:B[C]});return F}validateRestClientConfig(D){let F=[];if(typeof D!=="object"||D===null)return F.push({path:"restClient",message:"restClient config must be an object",value:D}),F;let B=D;if(B.clientName!==void 0&&typeof B.clientName!=="string")F.push({path:"restClient.clientName",message:"clientName must be a string",value:B.clientName});if(B.baseUrlOverride!==void 0&&typeof B.baseUrlOverride!=="string")F.push({path:"restClient.baseUrlOverride",message:"baseUrlOverride must be a string",value:B.baseUrlOverride});if(B.defaultTimeout!==void 0){if(typeof B.defaultTimeout!=="number"||B.defaultTimeout<=0)F.push({path:"restClient.defaultTimeout",message:"defaultTimeout must be a positive number",value:B.defaultTimeout})}if(B.defaultRetries!==void 0){if(typeof B.defaultRetries!=="number"||B.defaultRetries<0)F.push({path:"restClient.defaultRetries",message:"defaultRetries must be a non-negative number",value:B.defaultRetries})}let E=["includeValidation","includeErrorHandling","includeRequestInterceptors","enhancedSearch","chainedSearchBuilder","searchAutocomplete","generateValueSetEnums","includeUtilities","generateValidators","useCanonicalManager","includeDocumentation","generateExamples"];for(let C of E)if(B[C]!==void 0&&typeof B[C]!=="boolean")F.push({path:`restClient.${C}`,message:`${C} must be a boolean`,value:B[C]});return F}validateGuardOptions(D){let F=[];if(typeof D!=="object"||D===null)return F.push({path:"typescript.guardOptions",message:"guardOptions must be an object",value:D}),F;let B=D;if(B.targetTSVersion!==void 0){if(!["3.8","4.0","4.5","5.0"].includes(B.targetTSVersion))F.push({path:"typescript.guardOptions.targetTSVersion",message:'targetTSVersion must be one of: "3.8", "4.0", "4.5", "5.0"',value:B.targetTSVersion})}let E=["includeRuntimeValidation","includeErrorMessages","treeShakeable","strictGuards","includeNullChecks","verbose"];for(let C of E)if(B[C]!==void 0&&typeof B[C]!=="boolean")F.push({path:`typescript.guardOptions.${C}`,message:`${C} must be a boolean`,value:B[C]});return F}validateProfileOptions(D){let F=[];if(typeof D!=="object"||D===null)return F.push({path:"typescript.profileOptions",message:"profileOptions must be an object",value:D}),F;let B=D;if(B.generateKind!==void 0){if(!["interface","type","both"].includes(B.generateKind))F.push({path:"typescript.profileOptions.generateKind",message:'generateKind must be "interface", "type", or "both"',value:B.generateKind})}if(B.subfolder!==void 0&&typeof B.subfolder!=="string")F.push({path:"typescript.profileOptions.subfolder",message:"subfolder must be a string",value:B.subfolder});let E=["includeConstraints","includeDocumentation","strictMode"];for(let C of E)if(B[C]!==void 0&&typeof B[C]!=="boolean")F.push({path:`typescript.profileOptions.${C}`,message:`${C} must be a boolean`,value:B[C]});return F}validateTypeSchemaConfig(D){let F=[];if(typeof D!=="object"||D===null)return F.push({path:"typeSchema",message:"typeSchema config must be an object",value:D}),F;let B=D,E=["enablePersistence","validateCached","forceRegenerate","shareCache"];for(let u of E)if(B[u]!==void 0&&typeof B[u]!=="boolean")F.push({path:`typeSchema.${u}`,message:`${u} must be a boolean`,value:B[u]});let C=["cacheDir","cacheKeyPrefix"];for(let u of C)if(B[u]!==void 0&&typeof B[u]!=="string")F.push({path:`typeSchema.${u}`,message:`${u} must be a string`,value:B[u]});if(B.maxAge!==void 0){if(typeof B.maxAge!=="number"||B.maxAge<=0)F.push({path:"typeSchema.maxAge",message:"maxAge must be a positive number",value:B.maxAge})}if(B.profiles!==void 0)if(typeof B.profiles!=="object"||B.profiles===null)F.push({path:"typeSchema.profiles",message:"profiles must be an object",value:B.profiles});else{let u=B.profiles;if(u.autoDetect!==void 0&&typeof u.autoDetect!=="boolean")F.push({path:"typeSchema.profiles.autoDetect",message:"autoDetect must be a boolean",value:u.autoDetect})}return F}}class I6{validator=new w6;async autoload(D=process.cwd()){let F=await this.findConfigFile(D);if(F)return this.loadFromFile(F);return{...LF}}async loadFromFile(D){try{let F;if(D.endsWith(".ts")||D.endsWith(".js")){let C=await import(j6(D));F=C.default||C}else{let E=await iB(D,"utf-8");F=JSON.parse(E)}let B=this.validator.validate(F);if(!B.valid){let E=B.errors.map((C)=>`${C.path}: ${C.message}`).join(`
|
|
1275
|
+
`);await this.fileManager.writeFile("valuesets/index.ts",B),this.logger.info(`Generated valuesets/index.ts with ${this.collectedValueSets.size} value sets`)}async generateMainIndexFile(){if(!this.options.generateIndex)return;let D=[];if(this.tsOptions.includeDocuments)D.push("/**"),D.push(" * FHIR R4 TypeScript Types"),D.push(" * Generated from FHIR StructureDefinitions"),D.push(" * "),D.push(" * @generated This file is auto-generated. Do not edit manually."),D.push(" */"),D.push("");if(D.push('export * from "./utilities.js";'),this.tsOptions.generateValueSets&&this.collectedValueSets.size>0)D.push(""),D.push("// Value Sets"),D.push('export * from "./valuesets/index.js";');let F=D.join(`
|
|
1276
|
+
`);await this.fileManager.writeFile("index.ts",F),this.logger.info(`Generated index.ts with type exports${this.tsOptions.generateValueSets&&this.collectedValueSets.size>0?" and value sets":""}`)}}class UF{schemas=[];options;generators=new Map;progressCallback;cache;pendingOperations=[];typeSchemaGenerator;logger;typeSchemaConfig;constructor(D={}){if(this.options={outputDir:D.outputDir||"./generated",verbose:D.verbose??!1,overwrite:D.overwrite??!0,validate:D.validate??!0,cache:D.cache??!0,typeSchemaConfig:D.typeSchemaConfig},this.typeSchemaConfig=D.typeSchemaConfig,this.logger=D.logger||JD({verbose:this.options.verbose,prefix:"API"}),this.options.cache)this.cache=new mD(this.typeSchemaConfig)}fromPackage(D,F){this.logger.debug(`Loading from FHIR package: ${D}@${F||"latest"}`);let B=this.loadFromPackage(D,F);return this.pendingOperations.push(B),this}fromFiles(...D){this.logger.debug(`Loading from ${D.length} TypeSchema files`);let F=this.loadFromFiles(D);return this.pendingOperations.push(F),this}fromSchemas(D){return this.logger.debug(`Adding ${D.length} TypeSchemas to generation`),this.schemas=[...this.schemas,...D],this}typescript(D={}){let F=`${this.options.outputDir}/types`,B=new RF({outputDir:F,moduleFormat:D.moduleFormat||"esm",generateIndex:D.generateIndex??!0,includeDocuments:D.includeDocuments??!0,namingConvention:D.namingConvention||"PascalCase",includeExtensions:D.includeExtensions??!1,includeProfiles:D.includeProfiles??!1,generateValueSets:D.generateValueSets??!1,includeValueSetHelpers:D.includeValueSetHelpers??!1,valueSetStrengths:D.valueSetStrengths??["required"],logger:this.logger.child("TS"),valueSetMode:D.valueSetMode??"required-only",valueSetDirectory:D.valueSetDirectory??"valuesets",verbose:this.options.verbose,validate:!0,overwrite:this.options.overwrite});return this.generators.set("typescript",B),this.logger.debug(`Configured TypeScript generator (${D.moduleFormat||"esm"})`),this}restClient(D={}){let F=`${this.options.outputDir}/client`,B=new KF({outputDir:F,logger:this.logger.child("REST"),...D});return this.generators.set("restclient",B),this.logger.debug(`Configured REST client generator (${D.clientName||"FHIRClient"})`),this}onProgress(D){return this.progressCallback=D,this}outputTo(D){this.logger.debug(`Setting output directory: ${D}`),this.options.outputDir=D;for(let F of this.generators.values())if(F.setOutputDir)F.setOutputDir(D);return this}verbose(D=!0){return this.options.verbose=D,this}validate(D=!0){return this.options.validate=D,this}ensureTypeScriptForRestClient(){let D=this.generators.has("restclient"),F=this.generators.has("typescript");if(D&&!F)this.logger.debug("Automatically adding TypeScript generator for REST client"),this.typescript({moduleFormat:"esm",generateIndex:!0,includeDocuments:!1,namingConvention:"PascalCase"})}async generate(){this.ensureTypeScriptForRestClient();let D=performance.now(),F={success:!1,outputDir:this.options.outputDir,filesGenerated:[],errors:[],warnings:[],duration:0};this.logger.debug(`Starting generation with ${this.generators.size} generators`);try{if(this.reportProgress("Loading",0,4,"Loading TypeSchema data..."),await this.resolveSchemas(),this.logger.debug(`Resolved ${this.schemas.length} schemas`),this.reportProgress("Validating",1,4,"Validating TypeSchema documents..."),this.options.validate)this.logger.debug("Starting schema validation"),await this.validateSchemas(F),this.logger.debug("Schema validation completed");this.reportProgress("Generating",2,4,"Generating code..."),this.logger.debug(`Executing ${this.generators.size} generators`),await this.executeGenerators(F),this.reportProgress("Complete",4,4,"Generation completed successfully"),F.success=F.errors.length===0,this.logger.debug(`Generation completed: ${F.filesGenerated.length} files`)}catch(B){this.logger.error("Code generation failed",B instanceof Error?B:new Error(String(B))),F.errors.push(B instanceof Error?B.message:String(B)),F.success=!1}finally{F.duration=performance.now()-D}return F}async build(){await this.resolveSchemas();let D={};for(let[F,B]of this.generators.entries())if(B.build)D[F]=await B.build(this.schemas);return D}reset(){return this.schemas=[],this.generators.clear(),this.progressCallback=void 0,this}getSchemas(){return[...this.schemas]}getGenerators(){return Array.from(this.generators.keys())}async loadFromPackage(D,F){let B=new SD({verbose:this.options.verbose,logger:this.logger.child("Schema"),treeshake:this.typeSchemaConfig?.treeshake},this.typeSchemaConfig);this.typeSchemaGenerator=B;let E=await B.generateFromPackage(D,F);if(this.schemas=[...this.schemas,...E],this.cache)this.cache.setMany(E)}async loadFromFiles(D){if(!this.typeSchemaGenerator)this.typeSchemaGenerator=new SD({verbose:this.options.verbose,logger:this.logger.child("Schema"),treeshake:this.typeSchemaConfig?.treeshake},this.typeSchemaConfig);let B=await new _0({format:"auto",validate:this.options.validate}).parseFromFiles(D);if(this.schemas=[...this.schemas,...B],this.cache)this.cache.setMany(B)}async resolveSchemas(){if(this.pendingOperations.length>0)await Promise.all(this.pendingOperations),this.pendingOperations=[]}async validateSchemas(D){return}async executeGenerators(D){let F=this.generators.size,B=0;for(let[E,C]of this.generators.entries()){this.reportProgress("Generating",2+B/F,4,`Generating ${E}...`);try{let u=await C.generate(this.schemas);D.filesGenerated.push(...u.map(($)=>$.path||$.filename))}catch(u){D.errors.push(`${E} generator failed: ${u instanceof Error?u.message:String(u)}`)}B++}}reportProgress(D,F,B,E){if(this.progressCallback)this.progressCallback(D,F,B,E);if(this.options.verbose&&E)this.logger.debug(`[${D}] ${E}`)}}import{existsSync as nB}from"node:fs";import{readFile as iB}from"node:fs/promises";import{resolve as j6}from"node:path";var LF={outputDir:"./generated",verbose:!1,overwrite:!0,validate:!0,cache:!0,restClient:{clientName:"FHIRClient",includeValidation:!1,includeErrorHandling:!0,includeRequestInterceptors:!1,baseUrlOverride:"",enhancedSearch:!1,chainedSearchBuilder:!1,searchAutocomplete:!0,generateValueSetEnums:!0,includeUtilities:!0,generateValidators:!1,useCanonicalManager:!0,defaultTimeout:30000,defaultRetries:0,includeDocumentation:!0,generateExamples:!1},typescript:{moduleFormat:"esm",generateIndex:!0,includeDocuments:!1,namingConvention:"PascalCase",strictMode:!0,includeProfiles:!0,includeExtensions:!1,includeCodeSystems:!1,includeOperations:!1,generateValueSets:!1,valueSetDirectory:"valuesets",valueSetMode:"required-only",valueSetStrengths:["required"],includeValueSetHelpers:!1,fhirVersion:"R4",resourceTypes:[],maxDepth:10,profileOptions:{generateKind:"interface",includeConstraints:!0,includeDocumentation:!0,strictMode:!1,subfolder:"profiles"},generateBuilders:!1,builderOptions:{includeValidation:!0,includeFactoryMethods:!0,includeInterfaces:!0,generateNestedBuilders:!0,includeHelperMethods:!0,supportPartialBuild:!0,includeJSDoc:!0,generateFactories:!0,includeTypeGuards:!0,handleChoiceTypes:!0,generateArrayHelpers:!0},validatorOptions:{includeCardinality:!0,includeTypes:!0,includeConstraints:!0,includeInvariants:!1,validateRequired:!0,allowAdditional:!1,strictValidation:!1,collectMetrics:!1,generateAssertions:!0,generatePartialValidators:!0,optimizePerformance:!0,includeJSDoc:!0,generateCompositeValidators:!0},guardOptions:{includeRuntimeValidation:!0,includeErrorMessages:!0,treeShakeable:!0,targetTSVersion:"5.0",strictGuards:!1,includeNullChecks:!0,verbose:!1}},typeSchema:{enablePersistence:!0,cacheDir:".typeschema-cache",maxAge:86400000,validateCached:!0,forceRegenerate:!1,shareCache:!0,cacheKeyPrefix:"",treeshake:[],singleFile:!1,profiles:{autoDetect:!0}},packages:[],files:[],$schema:""},NF=["atomic-codegen.config.ts","atomic-codegen.config.js","atomic-codegen.config.json",".atomic-codegenrc","atomic-codegen.json",".atomic-codegen.json","codegen.config.json","codegen.json"];class w6{validate(D){let F={valid:!0,errors:[],warnings:[]};if(!D||typeof D!=="object")return F.valid=!1,F.errors.push({path:"root",message:"Configuration must be an object",value:D}),F;let B=D;if(B.outputDir!==void 0&&typeof B.outputDir!=="string")F.errors.push({path:"outputDir",message:"outputDir must be a string",value:B.outputDir});let E=["verbose","overwrite","validate","cache"];for(let C of E)if(B[C]!==void 0&&typeof B[C]!=="boolean")F.errors.push({path:C,message:`${C} must be a boolean`,value:B[C]});if(B.typescript!==void 0){let C=this.validateTypeScriptConfig(B.typescript);F.errors.push(...C)}if(B.typeSchema!==void 0){let C=this.validateTypeSchemaConfig(B.typeSchema);F.errors.push(...C)}if(B.restClient!==void 0){let C=this.validateRestClientConfig(B.restClient);F.errors.push(...C)}if(B.packages!==void 0)if(!Array.isArray(B.packages))F.errors.push({path:"packages",message:"packages must be an array",value:B.packages});else B.packages.forEach((C,u)=>{if(typeof C!=="string")F.errors.push({path:`packages[${u}]`,message:"package name must be a string",value:C})});if(B.files!==void 0)if(!Array.isArray(B.files))F.errors.push({path:"files",message:"files must be an array",value:B.files});else B.files.forEach((C,u)=>{if(typeof C!=="string")F.errors.push({path:`files[${u}]`,message:"file path must be a string",value:C})});if(F.valid=F.errors.length===0,F.valid)F.config=B;return F}validateTypeScriptConfig(D){let F=[];if(typeof D!=="object"||D===null)return F.push({path:"typescript",message:"typescript config must be an object",value:D}),F;let B=D;if(B.moduleFormat!==void 0){if(!["esm","cjs"].includes(B.moduleFormat))F.push({path:"typescript.moduleFormat",message:'moduleFormat must be "esm" or "cjs"',value:B.moduleFormat})}if(B.namingConvention!==void 0){if(!["PascalCase","camelCase"].includes(B.namingConvention))F.push({path:"typescript.namingConvention",message:'namingConvention must be "PascalCase" or "camelCase"',value:B.namingConvention})}let E=["generateIndex","includeDocuments","strictMode","includeProfiles","includeExtensions","includeCodeSystems","includeOperations","generateValueSets","includeValueSetHelpers"];for(let C of E)if(B[C]!==void 0&&typeof B[C]!=="boolean")F.push({path:`typescript.${C}`,message:`${C} must be a boolean`,value:B[C]});if(B.validatorOptions!==void 0){let C=this.validateValidatorOptions(B.validatorOptions);F.push(...C)}if(B.guardOptions!==void 0){let C=this.validateGuardOptions(B.guardOptions);F.push(...C)}if(B.profileOptions!==void 0){let C=this.validateProfileOptions(B.profileOptions);F.push(...C)}return F}validateValidatorOptions(D){let F=[];if(typeof D!=="object"||D===null)return F.push({path:"typescript.validatorOptions",message:"validatorOptions must be an object",value:D}),F;let B=D,E=["includeCardinality","includeTypes","includeConstraints","includeInvariants","validateRequired","allowAdditional","strictValidation","collectMetrics","generateAssertions","generatePartialValidators","optimizePerformance","includeJSDoc","generateCompositeValidators"];for(let C of E)if(B[C]!==void 0&&typeof B[C]!=="boolean")F.push({path:`typescript.validatorOptions.${C}`,message:`${C} must be a boolean`,value:B[C]});return F}validateRestClientConfig(D){let F=[];if(typeof D!=="object"||D===null)return F.push({path:"restClient",message:"restClient config must be an object",value:D}),F;let B=D;if(B.clientName!==void 0&&typeof B.clientName!=="string")F.push({path:"restClient.clientName",message:"clientName must be a string",value:B.clientName});if(B.baseUrlOverride!==void 0&&typeof B.baseUrlOverride!=="string")F.push({path:"restClient.baseUrlOverride",message:"baseUrlOverride must be a string",value:B.baseUrlOverride});if(B.defaultTimeout!==void 0){if(typeof B.defaultTimeout!=="number"||B.defaultTimeout<=0)F.push({path:"restClient.defaultTimeout",message:"defaultTimeout must be a positive number",value:B.defaultTimeout})}if(B.defaultRetries!==void 0){if(typeof B.defaultRetries!=="number"||B.defaultRetries<0)F.push({path:"restClient.defaultRetries",message:"defaultRetries must be a non-negative number",value:B.defaultRetries})}let E=["includeValidation","includeErrorHandling","includeRequestInterceptors","enhancedSearch","chainedSearchBuilder","searchAutocomplete","generateValueSetEnums","includeUtilities","generateValidators","useCanonicalManager","includeDocumentation","generateExamples"];for(let C of E)if(B[C]!==void 0&&typeof B[C]!=="boolean")F.push({path:`restClient.${C}`,message:`${C} must be a boolean`,value:B[C]});return F}validateGuardOptions(D){let F=[];if(typeof D!=="object"||D===null)return F.push({path:"typescript.guardOptions",message:"guardOptions must be an object",value:D}),F;let B=D;if(B.targetTSVersion!==void 0){if(!["3.8","4.0","4.5","5.0"].includes(B.targetTSVersion))F.push({path:"typescript.guardOptions.targetTSVersion",message:'targetTSVersion must be one of: "3.8", "4.0", "4.5", "5.0"',value:B.targetTSVersion})}let E=["includeRuntimeValidation","includeErrorMessages","treeShakeable","strictGuards","includeNullChecks","verbose"];for(let C of E)if(B[C]!==void 0&&typeof B[C]!=="boolean")F.push({path:`typescript.guardOptions.${C}`,message:`${C} must be a boolean`,value:B[C]});return F}validateProfileOptions(D){let F=[];if(typeof D!=="object"||D===null)return F.push({path:"typescript.profileOptions",message:"profileOptions must be an object",value:D}),F;let B=D;if(B.generateKind!==void 0){if(!["interface","type","both"].includes(B.generateKind))F.push({path:"typescript.profileOptions.generateKind",message:'generateKind must be "interface", "type", or "both"',value:B.generateKind})}if(B.subfolder!==void 0&&typeof B.subfolder!=="string")F.push({path:"typescript.profileOptions.subfolder",message:"subfolder must be a string",value:B.subfolder});let E=["includeConstraints","includeDocumentation","strictMode"];for(let C of E)if(B[C]!==void 0&&typeof B[C]!=="boolean")F.push({path:`typescript.profileOptions.${C}`,message:`${C} must be a boolean`,value:B[C]});return F}validateTypeSchemaConfig(D){let F=[];if(typeof D!=="object"||D===null)return F.push({path:"typeSchema",message:"typeSchema config must be an object",value:D}),F;let B=D,E=["enablePersistence","validateCached","forceRegenerate","shareCache"];for(let u of E)if(B[u]!==void 0&&typeof B[u]!=="boolean")F.push({path:`typeSchema.${u}`,message:`${u} must be a boolean`,value:B[u]});let C=["cacheDir","cacheKeyPrefix"];for(let u of C)if(B[u]!==void 0&&typeof B[u]!=="string")F.push({path:`typeSchema.${u}`,message:`${u} must be a string`,value:B[u]});if(B.maxAge!==void 0){if(typeof B.maxAge!=="number"||B.maxAge<=0)F.push({path:"typeSchema.maxAge",message:"maxAge must be a positive number",value:B.maxAge})}if(B.profiles!==void 0)if(typeof B.profiles!=="object"||B.profiles===null)F.push({path:"typeSchema.profiles",message:"profiles must be an object",value:B.profiles});else{let u=B.profiles;if(u.autoDetect!==void 0&&typeof u.autoDetect!=="boolean")F.push({path:"typeSchema.profiles.autoDetect",message:"autoDetect must be a boolean",value:u.autoDetect})}return F}}class I6{validator=new w6;async autoload(D=process.cwd()){let F=await this.findConfigFile(D);if(F)return this.loadFromFile(F);return{...LF}}async loadFromFile(D){try{let F;if(D.endsWith(".ts")||D.endsWith(".js")){let C=await import(j6(D));F=C.default||C}else{let E=await iB(D,"utf-8");F=JSON.parse(E)}let B=this.validator.validate(F);if(!B.valid){let E=B.errors.map((C)=>`${C.path}: ${C.message}`).join(`
|
|
1277
1277
|
`);throw new Error(`Configuration validation failed:
|
|
1278
1278
|
${E}`)}return this.mergeWithDefaults(B.config)}catch(F){if(F instanceof Error)throw new Error(`Failed to load config from ${D}: ${F.message}`);throw F}}async findConfigFile(D){for(let F of NF){let B=j6(D,F);if(nB(B))return B}return null}mergeWithDefaults(D){let F={...LF,...D,typescript:{...LF.typescript,...D.typescript}};if(D.restClient!==void 0)F.restClient={...LF.restClient,...D.restClient};else delete F.restClient;return F}}var tB=new I6;async function jF(D){return tB.autoload(D)}var T6={command:"generate",describe:"Generate code based on configuration file settings",builder:(D)=>D.option("verbose",{alias:"v",type:"boolean",default:!1,description:"Enable verbose output"}).example("$0 generate","Generate code using settings from config file").example("$0 generate --verbose","Generate with verbose output"),handler:async(D)=>{if(D._.length>1){let $=D._.slice(1).join(" ");RD(`Invalid syntax: 'atomic-codegen generate ${$}'
|
|
1279
1279
|
|
package/package.json
CHANGED