@atomic-ehr/codegen 0.0.1-canary.20250811235950.67a72a5 → 0.0.1-canary.20250812081907.f886676

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.
@@ -142,6 +142,19 @@ export declare class TypeScriptAPIGenerator {
142
142
  * Get TypeScript type for a TypeSchema identifier
143
143
  */
144
144
  private getType;
145
+ /**
146
+ * Check if a profile identifier represents an extension
147
+ */
148
+ private isExtensionProfile;
149
+ /**
150
+ * Check if a schema extends Extension by looking at its base type
151
+ */
152
+ private isExtensionSchema;
153
+ /**
154
+ * Generate extension name from URL
155
+ * e.g., http://hl7.org/fhir/StructureDefinition/contactpoint-area -> ExtensionContactpointArea
156
+ */
157
+ private generateExtensionName;
145
158
  /**
146
159
  * Get base interface for schema
147
160
  */
@@ -162,6 +175,10 @@ export declare class TypeScriptAPIGenerator {
162
175
  * Calculate the correct import path from current profile to base type
163
176
  */
164
177
  private calculateImportPath;
178
+ /**
179
+ * Track actual interface names for profile index generation
180
+ */
181
+ private trackProfileInterfaceName;
165
182
  /**
166
183
  * Generate TypeScript for a profile schema
167
184
  */
@@ -174,6 +191,34 @@ export declare class TypeScriptAPIGenerator {
174
191
  * Generate TypeScript for a profile field with constraints
175
192
  */
176
193
  private generateProfileField;
194
+ /**
195
+ * Get list of field names that have constraints in a profile
196
+ */
197
+ private getConstrainedFields;
198
+ /**
199
+ * Check if a field has significant constraints that warrant generation
200
+ */
201
+ private hasSignificantConstraints;
202
+ /**
203
+ * Check if a constraint is significant enough to warrant field generation
204
+ */
205
+ private isSignificantConstraint;
206
+ /**
207
+ * Generate a constrained field for a profile with proper typing
208
+ */
209
+ private generateConstrainedProfileField;
210
+ /**
211
+ * Generate a choice instance field (e.g., effectiveDateTime, effectivePeriod)
212
+ */
213
+ private generateChoiceInstanceField;
214
+ /**
215
+ * Generate field from constraint-only definition
216
+ */
217
+ private generateFieldFromConstraint;
218
+ /**
219
+ * Collect imports needed for a constrained field
220
+ */
221
+ private collectImportsForField;
177
222
  /**
178
223
  * Generate an enum type for a field with enumerated values
179
224
  */
@@ -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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"}
package/dist/cli/index.js CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  step,
18
18
  success,
19
19
  warn
20
- } from "../index-m60p8fkc.js";
20
+ } from "../index-4p27vhn8.js";
21
21
 
22
22
  // node_modules/emoji-regex/index.js
23
23
  var require_emoji_regex = __commonJS((exports, module) => {
@@ -5241,11 +5241,17 @@ class TypeScriptAPIGenerator {
5241
5241
  const result = await this.transformSchema(schema);
5242
5242
  if (result) {
5243
5243
  results.push(result);
5244
+ if (schema.identifier.kind === "profile" && result.exports && result.exports.length > 0) {
5245
+ const interfaceName = result.exports[0];
5246
+ this.trackProfileInterfaceName(schema.identifier, result.filename, interfaceName ?? "");
5247
+ }
5244
5248
  }
5245
5249
  }
5246
5250
  return results;
5247
5251
  }
5248
5252
  async generate(schemas) {
5253
+ this.profilesByPackage.clear();
5254
+ this.packageNameMap.clear();
5249
5255
  const filteredSchemas = this.filterSchemas(schemas);
5250
5256
  const results = await this.transformSchemas(filteredSchemas);
5251
5257
  const generatedFiles = [];
@@ -5514,18 +5520,15 @@ ${result.content}` : result.content;
5514
5520
  }
5515
5521
  }
5516
5522
  async generateProfileIndexFiles(generatedFiles) {
5517
- for (const [
5518
- packageName,
5519
- profileNames
5520
- ] of this.profilesByPackage.entries()) {
5521
- const packageIndexContent = this.generatePackageIndex(packageName, profileNames);
5523
+ for (const [packageName, profiles] of this.profilesByPackage.entries()) {
5524
+ const packageIndexContent = this.generatePackageIndex(packageName, profiles);
5522
5525
  const packageIndexPath = join11(this.options.outputDir, "profiles", packageName, "index.ts");
5523
5526
  await writeFile5(packageIndexPath, packageIndexContent, "utf-8");
5524
5527
  generatedFiles.push({
5525
5528
  path: packageIndexPath,
5526
5529
  filename: `profiles/${packageName}/index.ts`,
5527
5530
  content: packageIndexContent,
5528
- exports: profileNames
5531
+ exports: profiles.map((p) => p.interfaceName)
5529
5532
  });
5530
5533
  }
5531
5534
  const mainProfilesIndex = this.generateMainProfilesIndex();
@@ -5538,7 +5541,7 @@ ${result.content}` : result.content;
5538
5541
  exports: Array.from(this.profilesByPackage.keys())
5539
5542
  });
5540
5543
  }
5541
- generatePackageIndex(packageName, profileNames) {
5544
+ generatePackageIndex(packageName, profiles) {
5542
5545
  const lines = [];
5543
5546
  lines.push("/**");
5544
5547
  lines.push(` * ${packageName} Profiles Index`);
@@ -5546,14 +5549,14 @@ ${result.content}` : result.content;
5546
5549
  lines.push(" * Auto-generated exports for all profile types in this package.");
5547
5550
  lines.push(" */");
5548
5551
  lines.push("");
5549
- if (profileNames.length === 0) {
5552
+ if (profiles.length === 0) {
5550
5553
  lines.push("// No profiles in this package");
5551
5554
  lines.push("export {};");
5552
5555
  return lines.join(`
5553
5556
  `);
5554
5557
  }
5555
- for (const profileName of profileNames) {
5556
- lines.push(`export type { ${profileName} } from './${profileName}';`);
5558
+ for (const profile of profiles) {
5559
+ lines.push(`export type { ${profile.interfaceName} } from './${profile.filename}';`);
5557
5560
  }
5558
5561
  return lines.join(`
5559
5562
  `);
@@ -5624,7 +5627,43 @@ ${result.content}` : result.content;
5624
5627
  if (primitiveType) {
5625
5628
  return { isPrimitive: true, value: primitiveType };
5626
5629
  }
5627
- return { isPrimitive: false, value: this.formatTypeName(identifier.name) };
5630
+ let typeName = identifier.name;
5631
+ if (identifier.kind === "profile") {
5632
+ if (this.isExtensionProfile(identifier)) {
5633
+ typeName = this.generateExtensionName(identifier);
5634
+ } else if (identifier.url && identifier.url.includes("vitalsigns") && !typeName.includes("Observation")) {
5635
+ typeName = `observation-${typeName}`;
5636
+ }
5637
+ }
5638
+ return { isPrimitive: false, value: this.formatTypeName(typeName) };
5639
+ }
5640
+ isExtensionProfile(identifier) {
5641
+ if (identifier.url) {
5642
+ const isKnownProfile = identifier.url.includes("/vitalsigns") || identifier.url.includes("/bmi") || identifier.url.includes("/bodyheight") || identifier.url.includes("/bodyweight") || identifier.url.includes("/bodytemp") || identifier.url.includes("/headcircum") || identifier.url.includes("/heartrate") || identifier.url.includes("/oxygensat") || identifier.url.includes("/resprate") || identifier.url.includes("/bp") || identifier.url.includes("/vitalspanel");
5643
+ return identifier.url.includes("/StructureDefinition/") && !isKnownProfile;
5644
+ }
5645
+ return false;
5646
+ }
5647
+ isExtensionSchema(schema) {
5648
+ if (schema.identifier.kind === "profile") {
5649
+ const profileSchema = schema;
5650
+ if (profileSchema.base && profileSchema.base.name === "Extension") {
5651
+ return true;
5652
+ }
5653
+ }
5654
+ return false;
5655
+ }
5656
+ generateExtensionName(identifier) {
5657
+ if (!identifier.url) {
5658
+ return `Extension${this.formatTypeName(identifier.name)}`;
5659
+ }
5660
+ const urlParts = identifier.url.split("/");
5661
+ const extensionName = urlParts[urlParts.length - 1];
5662
+ if (!extensionName) {
5663
+ return `Extension${this.formatTypeName(identifier.name)}`;
5664
+ }
5665
+ const formattedName = extensionName.split(/[-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join("");
5666
+ return `Extension${formattedName}`;
5628
5667
  }
5629
5668
  getBaseInterface(schema) {
5630
5669
  if ((isTypeSchemaForResourceComplexTypeLogical(schema) || schema.identifier.kind === "profile") && schema.base) {
@@ -5647,7 +5686,6 @@ ${result.content}` : result.content;
5647
5686
  this.profilesByPackage.set(sanitizedPackageName, []);
5648
5687
  this.packageNameMap.set(sanitizedPackageName, originalPackageName);
5649
5688
  }
5650
- this.profilesByPackage.get(sanitizedPackageName).push(name);
5651
5689
  return `${subfolder}/${name}.ts`;
5652
5690
  }
5653
5691
  return `${name}.ts`;
@@ -5663,18 +5701,39 @@ ${result.content}` : result.content;
5663
5701
  const currentPackage = this.sanitizePackageName(currentSchema.identifier.package);
5664
5702
  const basePackage = this.sanitizePackageName(baseIdentifier.package);
5665
5703
  if (currentPackage === basePackage) {
5666
- return `./${this.formatTypeName(baseIdentifier.name)}`;
5704
+ const baseTypeInfo = this.getType(baseIdentifier);
5705
+ return `./${baseTypeInfo.value}`;
5667
5706
  } else {
5668
- return `../${basePackage}/${this.formatTypeName(baseIdentifier.name)}`;
5707
+ const baseTypeInfo = this.getType(baseIdentifier);
5708
+ return `../${basePackage}/${baseTypeInfo.value}`;
5669
5709
  }
5670
5710
  } else {
5671
5711
  return `../../${this.formatTypeName(baseIdentifier.name)}`;
5672
5712
  }
5673
5713
  }
5714
+ trackProfileInterfaceName(identifier, filename, interfaceName) {
5715
+ if (identifier.kind === "profile" && identifier.package) {
5716
+ const originalPackageName = identifier.package;
5717
+ const sanitizedPackageName = this.sanitizePackageName(originalPackageName);
5718
+ if (!this.profilesByPackage.has(sanitizedPackageName)) {
5719
+ this.profilesByPackage.set(sanitizedPackageName, []);
5720
+ this.packageNameMap.set(sanitizedPackageName, originalPackageName);
5721
+ }
5722
+ const baseFilename = filename.split("/").pop()?.replace(/\.ts$/, "") || filename;
5723
+ this.profilesByPackage.get(sanitizedPackageName).push({
5724
+ filename: baseFilename,
5725
+ interfaceName
5726
+ });
5727
+ }
5728
+ }
5674
5729
  async generateProfile(schema) {
5675
5730
  this.imports.clear();
5676
5731
  this.exports.clear();
5677
- this.currentSchemaName = this.formatTypeName(schema.identifier.name);
5732
+ if (this.isExtensionSchema(schema)) {
5733
+ this.currentSchemaName = this.generateExtensionName(schema.identifier);
5734
+ } else {
5735
+ this.currentSchemaName = this.formatTypeName(schema.identifier.name);
5736
+ }
5678
5737
  this.profileTypes.add(this.currentSchemaName);
5679
5738
  const content = this.generateTypeScriptForProfile(schema);
5680
5739
  const imports = new Map(this.imports);
@@ -5689,11 +5748,16 @@ ${result.content}` : result.content;
5689
5748
  }
5690
5749
  generateTypeScriptForProfile(schema) {
5691
5750
  const lines = [];
5692
- const interfaceName = this.formatTypeName(schema.identifier.name);
5751
+ const interfaceName = this.currentSchemaName || this.formatTypeName(schema.identifier.name);
5752
+ const isExtension = this.isExtensionSchema(schema);
5693
5753
  if (schema.description) {
5694
5754
  lines.push("/**");
5695
5755
  lines.push(` * ${schema.description}`);
5696
- lines.push(` * @profile ${schema.identifier.url}`);
5756
+ if (isExtension) {
5757
+ lines.push(` * @extension ${schema.identifier.url}`);
5758
+ } else {
5759
+ lines.push(` * @profile ${schema.identifier.url}`);
5760
+ }
5697
5761
  lines.push(" */");
5698
5762
  }
5699
5763
  this.exports.add(interfaceName);
@@ -5705,7 +5769,34 @@ ${result.content}` : result.content;
5705
5769
  } else {
5706
5770
  lines.push(`export interface ${interfaceName} {`);
5707
5771
  }
5708
- if (isTypeSchemaForResourceComplexTypeLogical(schema) || schema.identifier.kind === "profile") {
5772
+ if (schema.identifier.kind === "profile") {
5773
+ const constrainedFields = this.getConstrainedFields(schema);
5774
+ for (const fieldName of constrainedFields) {
5775
+ this.collectImportsForField(fieldName, schema);
5776
+ }
5777
+ if (constrainedFields.length > 0) {
5778
+ const baseType = baseInterface?.value || "{}";
5779
+ let fieldsToOmit = constrainedFields;
5780
+ if (isExtension && !fieldsToOmit.includes("url")) {
5781
+ fieldsToOmit = [...constrainedFields, "url"];
5782
+ }
5783
+ const omittedFields = fieldsToOmit.map((field) => `'${field}'`).join(" | ");
5784
+ lines[lines.length - 1] = `export interface ${interfaceName} extends Omit<${baseType}, ${omittedFields}> {`;
5785
+ if (isExtension) {
5786
+ lines.push(` url: '${schema.identifier.url}';`);
5787
+ }
5788
+ for (const fieldName of constrainedFields) {
5789
+ const fieldLine = this.generateConstrainedProfileField(fieldName, schema);
5790
+ if (fieldLine) {
5791
+ lines.push(` ${fieldLine}`);
5792
+ }
5793
+ }
5794
+ } else if (isExtension) {
5795
+ const baseType = baseInterface?.value || "Extension";
5796
+ lines[lines.length - 1] = `export interface ${interfaceName} extends Omit<${baseType}, 'url'> {`;
5797
+ lines.push(` url: '${schema.identifier.url}';`);
5798
+ }
5799
+ } else if (isTypeSchemaForResourceComplexTypeLogical(schema)) {
5709
5800
  if (schema.constraints && Object.keys(schema.constraints).length > 0) {
5710
5801
  for (const [path9, constraint] of Object.entries(schema.constraints)) {
5711
5802
  const fieldName = path9.includes(".") ? path9.split(".").pop() : path9;
@@ -5722,15 +5813,13 @@ ${result.content}` : result.content;
5722
5813
  }
5723
5814
  }
5724
5815
  }
5725
- lines.push("}");
5726
- if (schema.nested) {
5727
- for (const nested of schema.nested) {
5728
- lines.push("");
5729
- lines.push(this.generateNested(this.currentSchemaName ?? "", nested));
5730
- }
5816
+ }
5817
+ lines.push("}");
5818
+ if (schema.nested) {
5819
+ for (const nested of schema.nested) {
5820
+ lines.push("");
5821
+ lines.push(this.generateNested(this.currentSchemaName ?? "", nested));
5731
5822
  }
5732
- } else {
5733
- lines.push("}");
5734
5823
  }
5735
5824
  return lines.join(`
5736
5825
  `);
@@ -5786,6 +5875,199 @@ ${result.content}` : result.content;
5786
5875
  const arrayType = array ? "[]" : "";
5787
5876
  return `${fieldName}${optional}: ${typeString}${arrayType};`;
5788
5877
  }
5878
+ getConstrainedFields(schema) {
5879
+ const constrainedFields = [];
5880
+ const choiceBaseFields = new Set;
5881
+ if (schema.fields) {
5882
+ const fields = schema.fields;
5883
+ for (const [fieldName, field] of Object.entries(fields)) {
5884
+ if (field.choices && Array.isArray(field.choices)) {
5885
+ choiceBaseFields.add(fieldName);
5886
+ }
5887
+ if (field.choiceOf) {
5888
+ choiceBaseFields.add(field.choiceOf);
5889
+ constrainedFields.push(fieldName);
5890
+ } else if (this.hasSignificantConstraints(field, fieldName, schema)) {
5891
+ constrainedFields.push(fieldName);
5892
+ }
5893
+ }
5894
+ }
5895
+ if (schema.constraints) {
5896
+ const constraints = schema.constraints;
5897
+ for (const [path9, constraint] of Object.entries(constraints)) {
5898
+ const fieldName = path9.includes(".") ? path9.split(".").pop() : path9;
5899
+ if (fieldName && !constrainedFields.includes(fieldName)) {
5900
+ if (this.isSignificantConstraint(constraint)) {
5901
+ constrainedFields.push(fieldName);
5902
+ }
5903
+ }
5904
+ }
5905
+ }
5906
+ for (const choiceBaseField of choiceBaseFields) {
5907
+ if (!constrainedFields.includes(choiceBaseField)) {
5908
+ constrainedFields.push(choiceBaseField);
5909
+ }
5910
+ }
5911
+ return constrainedFields;
5912
+ }
5913
+ hasSignificantConstraints(field, fieldName, schema) {
5914
+ if (field.binding && field.binding.strength && field.binding.valueSet) {
5915
+ return true;
5916
+ }
5917
+ if (field.min !== undefined && field.min > 0) {
5918
+ return true;
5919
+ }
5920
+ if (field.type && Array.isArray(field.type) && field.type.length > 0) {
5921
+ return true;
5922
+ }
5923
+ if (field.choices && Array.isArray(field.choices)) {
5924
+ return true;
5925
+ }
5926
+ if (field.values && Array.isArray(field.values)) {
5927
+ return true;
5928
+ }
5929
+ return false;
5930
+ }
5931
+ isSignificantConstraint(constraint) {
5932
+ if (constraint.min !== undefined && constraint.min > 0) {
5933
+ return true;
5934
+ }
5935
+ if (constraint.type && Array.isArray(constraint.type)) {
5936
+ return true;
5937
+ }
5938
+ if (constraint.binding) {
5939
+ return true;
5940
+ }
5941
+ return false;
5942
+ }
5943
+ generateConstrainedProfileField(fieldName, schema) {
5944
+ const field = schema.fields?.[fieldName];
5945
+ if (!field) {
5946
+ const constraint2 = schema.constraints?.[fieldName];
5947
+ if (constraint2) {
5948
+ return this.generateFieldFromConstraint(fieldName, constraint2, schema);
5949
+ }
5950
+ return null;
5951
+ }
5952
+ if (field.choices && Array.isArray(field.choices)) {
5953
+ return null;
5954
+ }
5955
+ if (field.choiceOf) {
5956
+ return this.generateChoiceInstanceField(fieldName, field, schema);
5957
+ }
5958
+ let required = field.required || false;
5959
+ if (field.min !== undefined && field.min > 0) {
5960
+ required = true;
5961
+ }
5962
+ const constraint = schema.constraints?.[fieldName];
5963
+ if (constraint && constraint.min !== undefined && constraint.min > 0) {
5964
+ required = true;
5965
+ }
5966
+ let typeString = "any";
5967
+ if (field.type) {
5968
+ const typeInfo = this.getType(field.type);
5969
+ typeString = typeInfo.value;
5970
+ }
5971
+ if (field.enum && Array.isArray(field.enum)) {
5972
+ const enumValues = field.enum.map((v) => `'${v}'`).join(" | ");
5973
+ typeString = enumValues;
5974
+ } else if (field.values && Array.isArray(field.values)) {
5975
+ const enumValues = field.values.map((v) => `'${v}'`).join(" | ");
5976
+ typeString = enumValues;
5977
+ }
5978
+ if (field.binding && field.binding.strength === "required" && field.binding.valueSet) {}
5979
+ if (field.type && Array.isArray(field.type)) {
5980
+ const referenceTypes = field.type.filter((t) => t.code === "Reference" && t.targetProfile).map((t) => {
5981
+ const profile = t.targetProfile.split("/").pop();
5982
+ return `'${profile}'`;
5983
+ });
5984
+ if (referenceTypes.length > 0) {
5985
+ typeString = `Reference<${referenceTypes.join(" | ")}>`;
5986
+ }
5987
+ }
5988
+ let array = field.array || false;
5989
+ if (field.max === "*" || constraint && constraint.max === "*") {
5990
+ array = true;
5991
+ }
5992
+ const optional = !required ? "?" : "";
5993
+ const arrayType = array ? "[]" : "";
5994
+ return `${fieldName}${optional}: ${typeString}${arrayType};`;
5995
+ }
5996
+ generateChoiceInstanceField(fieldName, field, schema) {
5997
+ let required = field.required || false;
5998
+ if (field.min !== undefined && field.min > 0) {
5999
+ required = true;
6000
+ }
6001
+ const constraint = schema.constraints?.[fieldName];
6002
+ if (constraint && constraint.min !== undefined && constraint.min > 0) {
6003
+ required = true;
6004
+ }
6005
+ let typeString = "any";
6006
+ if (field.type) {
6007
+ const typeInfo = this.getType(field.type);
6008
+ typeString = typeInfo.value;
6009
+ if (!typeInfo.isPrimitive) {
6010
+ const importPath = this.calculateImportPath(schema, field.type);
6011
+ this.imports.set(typeInfo.value, importPath);
6012
+ }
6013
+ }
6014
+ if (field.enum && Array.isArray(field.enum)) {
6015
+ const enumValues = field.enum.map((v) => `'${v}'`).join(" | ");
6016
+ typeString = enumValues;
6017
+ }
6018
+ if (field.reference && Array.isArray(field.reference)) {
6019
+ typeString = this.buildReferenceType(field.reference);
6020
+ }
6021
+ let array = field.array || false;
6022
+ if (field.max === "*" || constraint && constraint.max === "*") {
6023
+ array = true;
6024
+ }
6025
+ const optional = !required ? "?" : "";
6026
+ const arrayType = array ? "[]" : "";
6027
+ return `${fieldName}${optional}: ${typeString}${arrayType};`;
6028
+ }
6029
+ generateFieldFromConstraint(fieldName, constraint, schema) {
6030
+ let typeString = "any";
6031
+ const required = constraint.min !== undefined && constraint.min > 0;
6032
+ const array = constraint.max === "*";
6033
+ if (constraint.type && Array.isArray(constraint.type)) {
6034
+ const types4 = constraint.type.map((t) => {
6035
+ if (t.code === "Reference" && t.targetProfile) {
6036
+ const profile = t.targetProfile.split("/").pop();
6037
+ return `Reference<'${profile}'>`;
6038
+ }
6039
+ return t.code || t;
6040
+ });
6041
+ typeString = types4.length === 1 ? types4[0] : `(${types4.join(" | ")})`;
6042
+ }
6043
+ const optional = !required ? "?" : "";
6044
+ const arrayType = array ? "[]" : "";
6045
+ return `${fieldName}${optional}: ${typeString}${arrayType};`;
6046
+ }
6047
+ collectImportsForField(fieldName, schema) {
6048
+ const field = schema.fields?.[fieldName];
6049
+ if (!field)
6050
+ return;
6051
+ if (field.type && !field.type.isPrimitive) {
6052
+ const typeInfo = this.getType(field.type);
6053
+ if (!typeInfo.isPrimitive) {
6054
+ const importPath = this.calculateImportPath(schema, field.type);
6055
+ this.imports.set(typeInfo.value, importPath);
6056
+ }
6057
+ }
6058
+ if (field.choices && Array.isArray(field.choices)) {
6059
+ field.choices.forEach((choice) => {
6060
+ const choiceField = schema.fields?.[choice];
6061
+ if (choiceField && choiceField.type) {
6062
+ const typeInfo = this.getType(choiceField.type);
6063
+ if (!typeInfo.isPrimitive) {
6064
+ const importPath = this.calculateImportPath(schema, choiceField.type);
6065
+ this.imports.set(typeInfo.value, importPath);
6066
+ }
6067
+ }
6068
+ });
6069
+ }
6070
+ }
5789
6071
  generateEnumType(fieldName, enumValues, baseName) {
5790
6072
  const prefix = baseName || this.currentSchemaName || "";
5791
6073
  const enumTypeName = `${prefix}${this.toPascalCase(fieldName)}Values`;
package/dist/index.js CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  generateTypesFromPackage,
17
17
  isConfig,
18
18
  loadConfig
19
- } from "./index-m60p8fkc.js";
19
+ } from "./index-4p27vhn8.js";
20
20
  export {
21
21
  loadConfig,
22
22
  isConfig,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atomic-ehr/codegen",
3
- "version": "0.0.1-canary.20250811235950.67a72a5",
3
+ "version": "0.0.1-canary.20250812081907.f886676",
4
4
  "description": "Code generation tools for FHIR resources and TypeSchema definitions",
5
5
  "keywords": [
6
6
  "fhir",