@atomic-ehr/codegen 0.0.3 → 0.0.4-canary.20251205081611.2b0c108

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.
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ import { CanonicalManager } from '@atomic-ehr/fhir-canonical-manager';
8
8
  import * as fhirschema from '@atomic-ehr/fhirschema';
9
9
  import { isStructureDefinition } from '@atomic-ehr/fhirschema';
10
10
  import * as YAML from 'yaml';
11
+ import assert from 'assert';
11
12
  import pc from 'picocolors';
12
13
 
13
14
  // src/api/builder.ts
@@ -221,6 +222,9 @@ var isPrimitiveIdentifier = (id) => {
221
222
  var isNestedIdentifier = (id) => {
222
223
  return id?.kind === "nested";
223
224
  };
225
+ var isComplexTypeIdentifier = (id) => {
226
+ return id?.kind === "complex-type";
227
+ };
224
228
  var isProfileIdentifier = (id) => {
225
229
  return id?.kind === "profile";
226
230
  };
@@ -256,12 +260,6 @@ var isChoiceDeclarationField = (field) => {
256
260
  if (!field) return false;
257
261
  return field.choices !== void 0;
258
262
  };
259
- var isValueSet = (res) => {
260
- return res?.resourceType === "ValueSet";
261
- };
262
- var isCodeSystem = (res) => {
263
- return res?.resourceType === "CodeSystem";
264
- };
265
263
  var enrichValueSet = (vs, packageMeta) => {
266
264
  if (!vs.url) throw new Error("ValueSet must have a URL");
267
265
  if (!vs.name) throw new Error("ValueSet must have a name");
@@ -591,6 +589,18 @@ var CSharp = class extends Writer {
591
589
  fs__default.copyFileSync(sourceFile, destFile);
592
590
  }
593
591
  };
592
+
593
+ // src/fhir-types/hl7-fhir-r4-core/CodeSystem.ts
594
+ var isCodeSystem = (resource) => {
595
+ return resource !== null && typeof resource === "object" && resource.resourceType === "CodeSystem";
596
+ };
597
+
598
+ // src/fhir-types/hl7-fhir-r4-core/ValueSet.ts
599
+ var isValueSet = (resource) => {
600
+ return resource !== null && typeof resource === "object" && resource.resourceType === "ValueSet";
601
+ };
602
+
603
+ // src/typeschema/register.ts
594
604
  var readPackageDependencies = async (manager, packageMeta) => {
595
605
  const packageJSON = await manager.packageJson(packageMeta.name);
596
606
  const dependencies = packageJSON.dependencies;
@@ -739,7 +749,22 @@ var registerFromManager = async (manager, { logger, fallbackPackageForNameResolu
739
749
  resolveAny: (canonicalUrl) => packageAgnosticResolveCanonical(resolver, canonicalUrl),
740
750
  resolveElementSnapshot,
741
751
  getAllElementKeys,
742
- resolver
752
+ resolver,
753
+ resolutionTree: () => {
754
+ const res = {};
755
+ for (const [_pkgId, pkgIndex] of Object.entries(resolver)) {
756
+ const pkgName = pkgIndex.pkg.name;
757
+ res[pkgName] = {};
758
+ for (const [surl, resolutions] of Object.entries(pkgIndex.canonicalResolution)) {
759
+ const url = surl;
760
+ res[pkgName][url] = [];
761
+ for (const resolution of resolutions) {
762
+ res[pkgName][url].push({ deep: resolution.deep, pkg: resolution.pkg });
763
+ }
764
+ }
765
+ }
766
+ return res;
767
+ }
743
768
  };
744
769
  };
745
770
  var resolveFsElementGenealogy = (genealogy, path) => {
@@ -1038,7 +1063,16 @@ function extractValueSetConceptsByUrl(register, pkg, valueSetUrl, logger) {
1038
1063
  return extractValueSetConcepts(register, valueSet);
1039
1064
  }
1040
1065
  function extractValueSetConcepts(register, valueSet, _logger) {
1041
- if (valueSet.expansion?.contains) return valueSet.expansion.contains;
1066
+ if (valueSet.expansion?.contains) {
1067
+ return valueSet.expansion.contains.filter((item) => item.code !== void 0).map((item) => {
1068
+ assert(item.code);
1069
+ return {
1070
+ code: item.code,
1071
+ display: item.display,
1072
+ system: item.system
1073
+ };
1074
+ });
1075
+ }
1042
1076
  const concepts = [];
1043
1077
  if (valueSet.compose?.include) {
1044
1078
  for (const include of valueSet.compose.include) {
@@ -1296,7 +1330,7 @@ var treeShakeTypeSchema = (schema, rule, _logger) => {
1296
1330
  schema.dependencies = extractDependencies(schema.identifier, schema.base, schema.fields, schema.nested);
1297
1331
  return schema;
1298
1332
  };
1299
- var treeShake = (tsIndex, treeShake2, logger) => {
1333
+ var treeShake = (tsIndex, treeShake2, { resolutionTree, logger }) => {
1300
1334
  const focusedSchemas = [];
1301
1335
  for (const [pkgId, requires] of Object.entries(treeShake2)) {
1302
1336
  for (const [url, rule] of Object.entries(requires)) {
@@ -1333,7 +1367,7 @@ var treeShake = (tsIndex, treeShake2, logger) => {
1333
1367
  return collectDeps(newSchemas, acc);
1334
1368
  };
1335
1369
  const shaked = collectDeps(focusedSchemas, {});
1336
- return mkTypeSchemaIndex(shaked, logger);
1370
+ return mkTypeSchemaIndex(shaked, { resolutionTree, logger });
1337
1371
  };
1338
1372
  var resourceRelatives = (schemas) => {
1339
1373
  const regularSchemas = schemas.filter((e) => isResourceTypeSchema(e) || isLogicalTypeSchema(e));
@@ -1362,7 +1396,7 @@ var resourceRelatives = (schemas) => {
1362
1396
  }
1363
1397
  return allPairs;
1364
1398
  };
1365
- var mkTypeSchemaIndex = (schemas, logger) => {
1399
+ var mkTypeSchemaIndex = (schemas, { resolutionTree, logger }) => {
1366
1400
  const index = {};
1367
1401
  const append = (schema) => {
1368
1402
  const url = schema.identifier.url;
@@ -1381,7 +1415,15 @@ var mkTypeSchemaIndex = (schemas, logger) => {
1381
1415
  }
1382
1416
  const relations = resourceRelatives(schemas);
1383
1417
  const resolve3 = (id) => index[id.url]?.[id.package];
1384
- const resolveByUrl = (pkgName, url) => index[url]?.[pkgName];
1418
+ const resolveByUrl = (pkgName, url) => {
1419
+ if (resolutionTree) {
1420
+ const resolution = resolutionTree[pkgName]?.[url]?.[0];
1421
+ if (resolution) {
1422
+ return index[url]?.[resolution.pkg.name];
1423
+ }
1424
+ }
1425
+ return index[url]?.[pkgName];
1426
+ };
1385
1427
  const resourceChildren = (id) => {
1386
1428
  return relations.filter((relative) => relative.parent.name === id.name).map((relative) => relative.child);
1387
1429
  };
@@ -1696,6 +1738,9 @@ var tsModuleName = (id) => {
1696
1738
  var tsModuleFileName = (id) => {
1697
1739
  return `${tsModuleName(id)}.ts`;
1698
1740
  };
1741
+ var tsModulePath = (id) => {
1742
+ return `${tsFhirPackageDir(id.package)}/${tsModuleName(id)}`;
1743
+ };
1699
1744
  var canonicalToName2 = (canonical, dropFragment = true) => {
1700
1745
  if (!canonical) return void 0;
1701
1746
  const localName = extractNameFromCanonical(canonical, dropFragment);
@@ -1758,20 +1803,22 @@ var TypeScript = class extends Writer {
1758
1803
  }
1759
1804
  });
1760
1805
  }
1761
- generateDependenciesImports(schema) {
1806
+ generateDependenciesImports(tsIndex, schema) {
1762
1807
  if (schema.dependencies) {
1763
1808
  const imports = [];
1764
1809
  const skipped = [];
1765
1810
  for (const dep of schema.dependencies) {
1766
1811
  if (["complex-type", "resource", "logical"].includes(dep.kind)) {
1767
1812
  imports.push({
1768
- tsPackage: `../${kebabCase(dep.package)}/${pascalCase(dep.name)}`,
1813
+ tsPackage: `../${tsModulePath(dep)}`,
1769
1814
  name: uppercaseFirstLetter(dep.name),
1770
1815
  dep
1771
1816
  });
1772
1817
  } else if (isNestedIdentifier(dep)) {
1818
+ const ndep = { ...dep };
1819
+ ndep.name = canonicalToName2(dep.url);
1773
1820
  imports.push({
1774
- tsPackage: `../${kebabCase(dep.package)}/${pascalCase(canonicalToName2(dep.url) ?? "")}`,
1821
+ tsPackage: `../${tsModulePath(ndep)}`,
1775
1822
  name: tsResourceName(dep),
1776
1823
  dep
1777
1824
  });
@@ -1788,11 +1835,17 @@ var TypeScript = class extends Writer {
1788
1835
  this.debugComment("skip:", dep);
1789
1836
  }
1790
1837
  this.line();
1838
+ if (this.withPrimitiveTypeExtension(schema) && schema.identifier.name !== "Element" && schema.dependencies.find((e) => e.name === "Element") === void 0) {
1839
+ const elementUrl = "http://hl7.org/fhir/StructureDefinition/Element";
1840
+ const element = tsIndex.resolveByUrl(schema.identifier.package, elementUrl);
1841
+ if (!element) throw new Error(`'${elementUrl}' not found for ${schema.identifier.package}.`);
1842
+ this.tsImportType(`../${tsModulePath(element.identifier)}`, "Element");
1843
+ }
1791
1844
  }
1792
1845
  }
1793
1846
  generateComplexTypeReexports(schema) {
1794
- const complexTypeDeps = schema.dependencies?.filter((dep) => ["complex-type"].includes(dep.kind)).map((dep) => ({
1795
- tsPackage: `../${kebabCase(dep.package)}/${pascalCase(dep.name)}`,
1847
+ const complexTypeDeps = schema.dependencies?.filter(isComplexTypeIdentifier).map((dep) => ({
1848
+ tsPackage: `../${tsModulePath(dep)}`,
1796
1849
  name: uppercaseFirstLetter(dep.name)
1797
1850
  }));
1798
1851
  if (complexTypeDeps && complexTypeDeps.length > 0) {
@@ -1802,11 +1855,9 @@ var TypeScript = class extends Writer {
1802
1855
  this.line();
1803
1856
  }
1804
1857
  }
1805
- addFieldExtension(fieldName, field) {
1806
- if (field.type.kind === "primitive-type") {
1807
- const extFieldName = tsFieldName(`_${fieldName}`);
1808
- this.lineSM(`${extFieldName}?: Element`);
1809
- }
1858
+ addFieldExtension(fieldName) {
1859
+ const extFieldName = tsFieldName(`_${fieldName}`);
1860
+ this.lineSM(`${extFieldName}?: Element`);
1810
1861
  }
1811
1862
  generateType(tsIndex, schema) {
1812
1863
  let name;
@@ -1858,12 +1909,23 @@ var TypeScript = class extends Writer {
1858
1909
  const optionalSymbol = field.required ? "" : "?";
1859
1910
  const arraySymbol = field.array ? "[]" : "";
1860
1911
  this.lineSM(`${tsName}${optionalSymbol}: ${tsType}${arraySymbol}`);
1861
- if (["resource", "complex-type"].includes(schema.identifier.kind)) {
1862
- this.addFieldExtension(fieldName, field);
1912
+ if (this.withPrimitiveTypeExtension(schema)) {
1913
+ if (isPrimitiveIdentifier(field.type)) {
1914
+ this.addFieldExtension(fieldName);
1915
+ }
1863
1916
  }
1864
1917
  }
1865
1918
  });
1866
1919
  }
1920
+ withPrimitiveTypeExtension(schema) {
1921
+ if (!this.opts.primitiveTypeExtension) return false;
1922
+ if (!isSpecializationTypeSchema(schema)) return false;
1923
+ for (const field of Object.values(schema.fields ?? {})) {
1924
+ if (isChoiceDeclarationField(field)) continue;
1925
+ if (isPrimitiveIdentifier(field.type)) return true;
1926
+ }
1927
+ return false;
1928
+ }
1867
1929
  generateResourceTypePredicate(schema) {
1868
1930
  if (!isResourceTypeSchema(schema) && !isLogicalTypeSchema(schema)) return;
1869
1931
  const name = tsResourceName(schema.identifier);
@@ -2035,7 +2097,7 @@ var TypeScript = class extends Writer {
2035
2097
  this.cat(`${tsModuleFileName(schema.identifier)}`, () => {
2036
2098
  this.generateDisclaimer();
2037
2099
  if (["complex-type", "resource", "logical"].includes(schema.identifier.kind)) {
2038
- this.generateDependenciesImports(schema);
2100
+ this.generateDependenciesImports(tsIndex, schema);
2039
2101
  this.generateComplexTypeReexports(schema);
2040
2102
  this.generateNestedTypes(tsIndex, schema);
2041
2103
  this.comment("CanonicalURL:", schema.identifier.url);
@@ -2043,7 +2105,7 @@ var TypeScript = class extends Writer {
2043
2105
  this.generateResourceTypePredicate(schema);
2044
2106
  } else if (isProfileTypeSchema(schema)) {
2045
2107
  const flatProfile = tsIndex.flatProfile(schema);
2046
- this.generateDependenciesImports(flatProfile);
2108
+ this.generateDependenciesImports(tsIndex, flatProfile);
2047
2109
  this.comment("CanonicalURL:", schema.identifier.url);
2048
2110
  this.generateProfileType(tsIndex, flatProfile);
2049
2111
  this.generateAttachProfile(flatProfile);
@@ -2212,7 +2274,8 @@ var APIBuilder = class {
2212
2274
  };
2213
2275
  const defaultTsOpts = {
2214
2276
  ...defaultWriterOpts,
2215
- openResourceTypeSet: false
2277
+ openResourceTypeSet: false,
2278
+ primitiveTypeExtension: true
2216
2279
  };
2217
2280
  const opts = {
2218
2281
  ...defaultTsOpts,
@@ -2308,8 +2371,12 @@ var APIBuilder = class {
2308
2371
  });
2309
2372
  const typeSchemas = await generateTypeSchemas(register, this.logger);
2310
2373
  await tryWriteTypeSchema(typeSchemas, this.options, this.logger);
2311
- let tsIndex = mkTypeSchemaIndex(typeSchemas, this.logger);
2312
- if (this.options.treeShake) tsIndex = treeShake(tsIndex, this.options.treeShake, this.logger);
2374
+ const tsIndexOpts = {
2375
+ resolutionTree: register.resolutionTree(),
2376
+ logger: this.logger
2377
+ };
2378
+ let tsIndex = mkTypeSchemaIndex(typeSchemas, tsIndexOpts);
2379
+ if (this.options.treeShake) tsIndex = treeShake(tsIndex, this.options.treeShake, tsIndexOpts);
2313
2380
  if (this.options.exportTypeTree) await tsIndex.exportTree(this.options.exportTypeTree);
2314
2381
  this.logger.debug(`Executing ${this.generators.size} generators`);
2315
2382
  await this.executeGenerators(result, tsIndex);