@atomic-ehr/codegen 0.0.1-canary.20251106145509.e3b1f82 → 0.0.1-canary.20251107091824.7605d36

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
@@ -1,6 +1,6 @@
1
1
  import * as fs from 'fs';
2
2
  import fs__default, { existsSync, mkdirSync } from 'fs';
3
- import * as afs2 from 'fs/promises';
3
+ import * as afs3 from 'fs/promises';
4
4
  import { readdir, stat, unlink, readFile, writeFile, access, mkdir, rm } from 'fs/promises';
5
5
  import * as Path4 from 'path';
6
6
  import Path4__default, { join, resolve, dirname, relative } from 'path';
@@ -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 pc from 'picocolors';
11
+ import * as YAML from 'yaml';
11
12
 
12
13
  var __defProp = Object.defineProperty;
13
14
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -1397,7 +1398,24 @@ var init_IndexBuilder = __esm({
1397
1398
  });
1398
1399
 
1399
1400
  // src/typeschema/types.ts
1401
+ var extractNameFromCanonical = (canonical, dropFragment = true) => {
1402
+ let localName = canonical.split("/").pop();
1403
+ if (!localName) return void 0;
1404
+ if (dropFragment && localName.includes("#")) {
1405
+ localName = localName.split("#")[0];
1406
+ }
1407
+ if (!localName) return void 0;
1408
+ if (/^\d/.test(localName)) {
1409
+ localName = `number_${localName}`;
1410
+ }
1411
+ return localName;
1412
+ };
1400
1413
  var packageMetaToFhir = (packageMeta) => `${packageMeta.name}#${packageMeta.version}`;
1414
+ var npmToPackageMeta = (fhir) => {
1415
+ const [name, version] = fhir.split("@");
1416
+ if (!name) throw new Error(`Invalid FHIR package meta: ${fhir}`);
1417
+ return { name, version: version ?? "latest" };
1418
+ };
1401
1419
  var packageMetaToNpm = (packageMeta) => `${packageMeta.name}@${packageMeta.version}`;
1402
1420
  var enrichFHIRSchema = (schema, packageMeta) => {
1403
1421
  if (!packageMeta) {
@@ -1447,10 +1465,10 @@ var isChoiceDeclarationField = (field) => {
1447
1465
  return field.choices !== void 0;
1448
1466
  };
1449
1467
  var isValueSet = (res) => {
1450
- return res.resourceType === "ValueSet";
1468
+ return res?.resourceType === "ValueSet";
1451
1469
  };
1452
1470
  var isCodeSystem = (res) => {
1453
- return res.resourceType === "CodeSystem";
1471
+ return res?.resourceType === "CodeSystem";
1454
1472
  };
1455
1473
  var enrichValueSet = (vs, packageMeta) => {
1456
1474
  if (!vs.url) throw new Error("ValueSet must have a URL");
@@ -1587,12 +1605,15 @@ function mkNestedTypes(register, fhirSchema, logger) {
1587
1605
  } else {
1588
1606
  baseName = element.type;
1589
1607
  }
1608
+ const baseUrl = register.ensureSpecializationCanonicalUrl(baseName);
1609
+ const baseFs = register.resolveFs(fhirSchema.package_meta, baseUrl);
1610
+ if (!baseFs) throw new Error(`Could not resolve base type ${baseName}`);
1590
1611
  const base = {
1591
1612
  kind: "complex-type",
1592
- package: fhirSchema.package_meta.name,
1593
- version: fhirSchema.package_meta.version,
1613
+ package: baseFs.package_meta.name,
1614
+ version: baseFs.package_meta.version,
1594
1615
  name: baseName,
1595
- url: register.ensureSpecializationCanonicalUrl(fhirSchema.package_meta, baseName)
1616
+ url: baseUrl
1596
1617
  };
1597
1618
  const fields = transformNestedElements(register, fhirSchema, path, element.elements, logger);
1598
1619
  const nestedType = {
@@ -1656,8 +1677,9 @@ function isExcluded(register, fhirSchema, path) {
1656
1677
  var buildReferences = (register, fhirSchema, element) => {
1657
1678
  if (!element.refers) return void 0;
1658
1679
  return element.refers.map((ref) => {
1659
- const curl = register.ensureSpecializationCanonicalUrl(fhirSchema.package_meta, ref);
1680
+ const curl = register.ensureSpecializationCanonicalUrl(ref);
1660
1681
  const fs4 = register.resolveFs(fhirSchema.package_meta, curl);
1682
+ if (!fs4) throw new Error(`Failed to resolve fs for ${curl}`);
1661
1683
  return mkIdentifier(fs4);
1662
1684
  });
1663
1685
  };
@@ -1666,9 +1688,12 @@ function buildFieldType(register, fhirSchema, path, element, logger) {
1666
1688
  const refPath = element.elementReference.slice(1).filter((_, i) => i % 2 === 1);
1667
1689
  return mkNestedIdentifier(register, fhirSchema, refPath, logger);
1668
1690
  } else if (element.type) {
1669
- const url = register.ensureSpecializationCanonicalUrl(fhirSchema.package_meta, element.type);
1691
+ const url = register.ensureSpecializationCanonicalUrl(element.type);
1670
1692
  const fieldFs = register.resolveFs(fhirSchema.package_meta, url);
1671
- if (!fieldFs) throw new Error(`Could not resolve field type: '${element.type}'`);
1693
+ if (!fieldFs)
1694
+ throw new Error(
1695
+ `Could not resolve field type: '${element.type}' (from '${fhirSchema.url}' in '${packageMetaToFhir(fhirSchema.package_meta)}')`
1696
+ );
1672
1697
  return mkIdentifier(fieldFs);
1673
1698
  } else if (element.choices) {
1674
1699
  return void 0;
@@ -1690,8 +1715,10 @@ var mkField = (register, fhirSchema, path, element, logger) => {
1690
1715
  enumValues = buildEnum(register, fhirSchema, element, logger);
1691
1716
  }
1692
1717
  }
1718
+ const fieldType = buildFieldType(register, fhirSchema, path, element, logger);
1719
+ if (!fieldType) logger?.warn(`Field type not found for ${path.join(".")}`);
1693
1720
  return {
1694
- type: buildFieldType(register, fhirSchema, path, element, logger),
1721
+ type: fieldType,
1695
1722
  required: isRequired(register, fhirSchema, path),
1696
1723
  excluded: isExcluded(register, fhirSchema, path),
1697
1724
  reference: buildReferences(register, fhirSchema, element),
@@ -1711,8 +1738,9 @@ function isNestedElement(element) {
1711
1738
  return isBackbone || isElement || elementsWithoutType;
1712
1739
  }
1713
1740
  function mkNestedField(register, fhirSchema, path, element, logger) {
1741
+ const nestedIdentifier = mkNestedIdentifier(register, fhirSchema, path, logger);
1714
1742
  return {
1715
- type: mkNestedIdentifier(register, fhirSchema, path, logger),
1743
+ type: nestedIdentifier,
1716
1744
  array: element.array || false,
1717
1745
  required: isRequired(register, fhirSchema, path),
1718
1746
  excluded: isExcluded(register, fhirSchema, path)
@@ -1868,19 +1896,6 @@ function extractFieldDependencies(fields) {
1868
1896
  }
1869
1897
  return deps;
1870
1898
  }
1871
- function deduplicateDependencies(deps) {
1872
- const seen = /* @__PURE__ */ new Set();
1873
- const unique = [];
1874
- for (const dep of deps) {
1875
- const key = dep.url;
1876
- if (!seen.has(key)) {
1877
- seen.add(key);
1878
- unique.push(dep);
1879
- }
1880
- }
1881
- unique.sort((a, b) => a.name.localeCompare(b.name));
1882
- return unique;
1883
- }
1884
1899
  function isExtensionSchema(fhirSchema, _identifier) {
1885
1900
  if (fhirSchema.base === "Extension" || fhirSchema.base === "http://hl7.org/fhir/StructureDefinition/Extension") {
1886
1901
  return true;
@@ -1907,62 +1922,6 @@ async function transformValueSet(register, valueSet, logger) {
1907
1922
  compose: !concept ? valueSet.compose : void 0
1908
1923
  };
1909
1924
  }
1910
- async function transformExtension(fhirSchema, register, logger) {
1911
- try {
1912
- const identifier = mkIdentifier(fhirSchema);
1913
- let base;
1914
- if (fhirSchema.base && fhirSchema.base !== "Extension") {
1915
- const baseUrl = fhirSchema.base.includes("/") ? fhirSchema.base : `http://hl7.org/fhir/StructureDefinition/${fhirSchema.base}`;
1916
- const baseName = fhirSchema.base.split("/").pop() || fhirSchema.base;
1917
- base = {
1918
- kind: "complex-type",
1919
- package: "hl7.fhir.r4.core",
1920
- version: "4.0.1",
1921
- name: baseName,
1922
- url: baseUrl
1923
- };
1924
- } else {
1925
- base = {
1926
- kind: "complex-type",
1927
- package: "hl7.fhir.r4.core",
1928
- version: "4.0.1",
1929
- name: "Extension",
1930
- url: "http://hl7.org/fhir/StructureDefinition/Extension"
1931
- };
1932
- }
1933
- const extensionSchema = {
1934
- identifier,
1935
- base,
1936
- description: fhirSchema.description,
1937
- dependencies: [],
1938
- metadata: {
1939
- isExtension: true
1940
- // Mark as extension for file organization
1941
- }
1942
- };
1943
- if (base) {
1944
- extensionSchema.dependencies.push(base);
1945
- }
1946
- if (fhirSchema.elements) {
1947
- const fields = mkFields(register, fhirSchema, [], fhirSchema.elements, logger);
1948
- if (fields && Object.keys(fields).length > 0) {
1949
- extensionSchema.fields = fields;
1950
- extensionSchema.dependencies.push(...extractFieldDependencies(fields));
1951
- }
1952
- }
1953
- const nestedTypes = mkNestedTypes(register, fhirSchema, logger);
1954
- if (nestedTypes && nestedTypes.length > 0) {
1955
- extensionSchema.nested = nestedTypes;
1956
- extensionSchema.dependencies.push(...extractNestedDependencies(nestedTypes));
1957
- }
1958
- extensionSchema.dependencies = deduplicateDependencies(extensionSchema.dependencies);
1959
- extensionSchema.dependencies = extensionSchema.dependencies.filter((dep) => dep.url !== identifier.url);
1960
- return extensionSchema;
1961
- } catch (error) {
1962
- console.warn(`Failed to transform extension ${fhirSchema.name}: ${error}`);
1963
- return null;
1964
- }
1965
- }
1966
1925
  function extractDependencies(identifier, base, fields, nestedTypes) {
1967
1926
  const deps = [];
1968
1927
  if (base) deps.push(base);
@@ -1987,10 +1946,12 @@ function transformFhirSchemaResource(register, fhirSchema, logger) {
1987
1946
  if (fhirSchema.base && fhirSchema.type !== "Element") {
1988
1947
  const baseFs = register.resolveFs(
1989
1948
  fhirSchema.package_meta,
1990
- register.ensureSpecializationCanonicalUrl(fhirSchema.package_meta, fhirSchema.base)
1949
+ register.ensureSpecializationCanonicalUrl(fhirSchema.base)
1991
1950
  );
1992
1951
  if (!baseFs) {
1993
- throw new Error(`Base resource not found '${fhirSchema.base}' for '${fhirSchema.url}'`);
1952
+ throw new Error(
1953
+ `Base resource not found '${fhirSchema.base}' for <${fhirSchema.url}> from ${packageMetaToFhir(fhirSchema.package_meta)}`
1954
+ );
1994
1955
  }
1995
1956
  base = mkIdentifier(baseFs);
1996
1957
  }
@@ -2009,16 +1970,16 @@ function transformFhirSchemaResource(register, fhirSchema, logger) {
2009
1970
  return [typeSchema, ...bindingSchemas];
2010
1971
  }
2011
1972
  async function transformFhirSchema(register, fhirSchema, logger) {
2012
- const results = [];
2013
- mkIdentifier(fhirSchema);
2014
- if (isExtensionSchema(fhirSchema)) {
2015
- const extensionSchema = await transformExtension(fhirSchema, register, logger);
2016
- if (extensionSchema) {
2017
- results.push(extensionSchema);
2018
- }
2019
- return results;
1973
+ const schemas = transformFhirSchemaResource(register, fhirSchema, logger);
1974
+ if (isExtensionSchema(fhirSchema, mkIdentifier(fhirSchema))) {
1975
+ const schema = schemas[0];
1976
+ if (!schema) throw new Error(`Expected schema to be defined`);
1977
+ schema.metadata = {
1978
+ isExtension: true
1979
+ // Mark as extension for file organization
1980
+ };
2020
1981
  }
2021
- return transformFhirSchemaResource(register, fhirSchema, logger);
1982
+ return schemas;
2022
1983
  }
2023
1984
  var TypeSchemaCache = class {
2024
1985
  cache = /* @__PURE__ */ new Map();
@@ -2362,7 +2323,7 @@ function createLogger(options = {}) {
2362
2323
  }
2363
2324
  var readPackageJSON = async (workDir, packageMeta) => {
2364
2325
  const packageJSONFileName = Path4.join(workDir, "node_modules", packageMeta.name, "package.json");
2365
- const packageJSON = JSON.parse(await afs2.readFile(packageJSONFileName, "utf8"));
2326
+ const packageJSON = JSON.parse(await afs3.readFile(packageJSONFileName, "utf8"));
2366
2327
  return packageJSON;
2367
2328
  };
2368
2329
  var readPackageDependencies = async (workDir, packageMeta) => {
@@ -2376,69 +2337,50 @@ var readPackageDependencies = async (workDir, packageMeta) => {
2376
2337
  return [];
2377
2338
  };
2378
2339
  var mkEmptyPkgIndex = (pkg) => {
2379
- return { pkg, nameResolution: {}, canonicalResolution: {}, fhirSchemas: {}, valueSets: {} };
2340
+ return {
2341
+ pkg,
2342
+ canonicalResolution: {},
2343
+ fhirSchemas: {},
2344
+ valueSets: {}
2345
+ };
2380
2346
  };
2381
- var mkPackageAwareResolver = async (manager, pkg, deep = 0, _logger) => {
2382
- const options = {};
2383
- const deps = await readPackageDependencies("tmp/fhir", pkg);
2384
- for (const dep of deps) {
2385
- const depOptions = mkPackageAwareResolver(manager, dep, deep);
2386
- Object.assign(options, depOptions);
2387
- }
2347
+ var mkPackageAwareResolver = async (manager, pkg, deep, acc, logger) => {
2388
2348
  const pkgId = packageMetaToFhir(pkg);
2389
- if (!options[pkgId]) options[pkgId] = mkEmptyPkgIndex(pkg);
2349
+ logger?.info(`${" ".repeat(deep * 2)}+ ${pkgId}`);
2350
+ if (acc[pkgId]) return acc[pkgId];
2351
+ const index = mkEmptyPkgIndex(pkg);
2390
2352
  for (const resource of await manager.search({ package: pkg })) {
2391
2353
  const rawUrl = resource.url;
2392
2354
  if (!rawUrl) continue;
2393
2355
  if (!(isStructureDefinition(resource) || isValueSet(resource) || isCodeSystem(resource))) continue;
2394
2356
  const url = rawUrl;
2395
- if (!options[pkgId].canonicalResolution[url]) {
2396
- options[pkgId].canonicalResolution[url] = [];
2397
- for (const [depPkgId, { canonicalResolution }] of Object.entries(options)) {
2398
- if (pkgId === depPkgId) continue;
2399
- if (!canonicalResolution[url]) continue;
2400
- for (const deepRes of canonicalResolution[url]) {
2401
- options[pkgId].canonicalResolution[url].push({
2402
- deep: deepRes.deep + 1,
2403
- resource: deepRes.resource,
2404
- packageMeta: deepRes.packageMeta
2405
- });
2406
- }
2407
- }
2408
- }
2409
- options[pkgId].canonicalResolution[url].push({ deep, packageMeta: pkg, resource });
2410
- options[pkgId].canonicalResolution[url].sort((a, b) => a.deep - b.deep);
2411
- const name = resource.name;
2412
- if (name && isStructureDefinition(resource) && (resource.derivation === "specialization" || resource.derivation === void 0)) {
2413
- if (!options[pkgId].nameResolution[name]) {
2414
- options[pkgId].nameResolution[name] = resource.url;
2415
- } else {
2416
- throw new Error(`Duplicate name ${name} in package ${pkgId}`);
2417
- }
2357
+ if (index.canonicalResolution[url]) logger?.dry_warn(`Duplicate canonical URL: ${url} at ${pkgId}.`);
2358
+ index.canonicalResolution[url] = [{ deep, pkg, pkgId, resource }];
2359
+ }
2360
+ const deps = await readPackageDependencies("tmp/fhir", pkg);
2361
+ for (const depPkg of deps) {
2362
+ const { canonicalResolution } = await mkPackageAwareResolver(manager, depPkg, deep + 1, acc, logger);
2363
+ for (const [surl, resolutions] of Object.entries(canonicalResolution)) {
2364
+ const url = surl;
2365
+ index.canonicalResolution[url] = [...index.canonicalResolution[url] || [], ...resolutions];
2418
2366
  }
2419
2367
  }
2420
- return options;
2421
- };
2422
- var packageAwareResolveName = (resolver, pkg, name) => {
2423
- const pkgId = packageMetaToFhir(pkg);
2424
- if (!resolver[pkgId]) throw new Error(`Package ${pkgId} not found`);
2425
- const resource = resolver[pkgId].nameResolution[name];
2426
- return resource;
2368
+ for (const resolutionOptions of Object.values(index.canonicalResolution)) {
2369
+ resolutionOptions.sort((a, b) => a.deep - b.deep);
2370
+ }
2371
+ acc[pkgId] = index;
2372
+ return index;
2427
2373
  };
2428
- var packageAgnosticResolveCanonical = (resolver, url, logger) => {
2374
+ var packageAgnosticResolveCanonical = (resolver, url, _logger) => {
2429
2375
  const options = Object.values(resolver).flatMap((pkg) => pkg.canonicalResolution[url]);
2430
2376
  if (!options) throw new Error(`No canonical resolution found for ${url} in any package`);
2431
- if (options.length > 1)
2432
- logger?.dry_warn(
2433
- `Multiple canonical resolutions found for ${url} in: ${JSON.stringify(options, void 0, 2)}`
2434
- );
2435
2377
  return options[0]?.resource;
2436
2378
  };
2437
- var registerFromManager = async (manager, { logger, fallbackPackageForNameResolution }) => {
2438
- const packages = await manager.packages();
2379
+ var registerFromManager = async (manager, { logger, fallbackPackageForNameResolution, focusedPackages }) => {
2380
+ const packages = focusedPackages ?? await manager.packages();
2439
2381
  const resolver = {};
2440
2382
  for (const pkg of packages) {
2441
- Object.assign(resolver, await mkPackageAwareResolver(manager, pkg));
2383
+ await mkPackageAwareResolver(manager, pkg, 0, resolver, logger);
2442
2384
  }
2443
2385
  for (const { pkg, canonicalResolution } of Object.values(resolver)) {
2444
2386
  const pkgId = packageMetaToFhir(pkg);
@@ -2446,19 +2388,21 @@ var registerFromManager = async (manager, { logger, fallbackPackageForNameResolu
2446
2388
  let counter = 0;
2447
2389
  logger?.info(`FHIR Schema conversion for '${packageMetaToFhir(pkg)}' begins...`);
2448
2390
  for (const [_url, options] of Object.entries(canonicalResolution)) {
2449
- const resource = options[0]?.resource;
2450
- if (!resource) throw new Error(`Resource not found`);
2391
+ const resolition = options[0];
2392
+ if (!resolition) throw new Error(`Resource not found`);
2393
+ const resource = resolition.resource;
2394
+ const resourcePkg = resolition.pkg;
2451
2395
  if (isStructureDefinition(resource)) {
2452
- const rfs = enrichFHIRSchema(fhirschema.translate(resource), pkg);
2396
+ const rfs = enrichFHIRSchema(fhirschema.translate(resource), resourcePkg);
2453
2397
  counter++;
2454
2398
  resolver[pkgId].fhirSchemas[rfs.url] = rfs;
2455
2399
  }
2456
2400
  if (isValueSet(resource)) {
2457
- const rvs = enrichValueSet(resource, pkg);
2401
+ const rvs = enrichValueSet(resource, resourcePkg);
2458
2402
  resolver[pkgId].valueSets[rvs.url] = rvs;
2459
2403
  }
2460
2404
  }
2461
- logger?.success(`FHIR Schema conversion for '${packageMetaToFhir(pkg)}' completed: ${counter} successful`);
2405
+ logger?.info(`FHIR Schema conversion for '${packageMetaToFhir(pkg)}' completed: ${counter} successful`);
2462
2406
  }
2463
2407
  const resolveFs = (pkg, canonicalUrl) => {
2464
2408
  return resolver[packageMetaToFhir(pkg)]?.fhirSchemas[canonicalUrl] || fallbackPackageForNameResolution && resolver[packageMetaToFhir(fallbackPackageForNameResolution)]?.fhirSchemas[canonicalUrl];
@@ -2466,14 +2410,19 @@ var registerFromManager = async (manager, { logger, fallbackPackageForNameResolu
2466
2410
  const resolveVs = (pkg, canonicalUrl) => {
2467
2411
  return resolver[packageMetaToFhir(pkg)]?.valueSets[canonicalUrl] || fallbackPackageForNameResolution && resolver[packageMetaToFhir(fallbackPackageForNameResolution)]?.valueSets[canonicalUrl];
2468
2412
  };
2469
- const ensureSpecializationCanonicalUrl = (pkg, name) => packageAwareResolveName(resolver, pkg, name) || fallbackPackageForNameResolution && packageAwareResolveName(resolver, fallbackPackageForNameResolution, name) || name;
2413
+ const ensureSpecializationCanonicalUrl = (name) => name.match(/^[a-zA-Z0-9]+$/) && `http://hl7.org/fhir/StructureDefinition/${name}` || name;
2470
2414
  const resolveFsGenealogy = (pkg, canonicalUrl) => {
2471
2415
  let fs4 = resolveFs(pkg, canonicalUrl);
2472
- if (fs4 === void 0) throw new Error(`Failed to resolve FHIR Schema genealogy for '${canonicalUrl}'`);
2416
+ if (fs4 === void 0) throw new Error(`Failed to resolve FHIR Schema: '${canonicalUrl}'`);
2473
2417
  const genealogy = [fs4];
2474
2418
  while (fs4?.base) {
2475
- fs4 = resolveFs(fs4.package_meta, fs4.base) || resolveFs(fs4.package_meta, ensureSpecializationCanonicalUrl(fs4.package_meta, fs4.base));
2476
- if (fs4 === void 0) throw new Error(`Failed to resolve FHIR Schema genealogy for '${canonicalUrl}'`);
2419
+ const pkg2 = fs4.package_meta;
2420
+ const baseUrl = ensureSpecializationCanonicalUrl(fs4.base);
2421
+ fs4 = resolveFs(pkg2, baseUrl);
2422
+ if (fs4 === void 0)
2423
+ throw new Error(
2424
+ `Failed to resolve FHIR Schema base for '${canonicalUrl}'. Problem: '${baseUrl}' from '${packageMetaToFhir(pkg2)}'`
2425
+ );
2477
2426
  genealogy.push(fs4);
2478
2427
  }
2479
2428
  return genealogy;
@@ -2501,11 +2450,10 @@ var registerFromManager = async (manager, { logger, fallbackPackageForNameResolu
2501
2450
  };
2502
2451
  return {
2503
2452
  ...manager,
2504
- unsafeAppendFs(fs4) {
2453
+ testAppendFs(fs4) {
2505
2454
  const rfs = enrichFHIRSchema(fs4);
2506
2455
  const pkgId = packageMetaToFhir(rfs.package_meta);
2507
2456
  if (!resolver[pkgId]) resolver[pkgId] = mkEmptyPkgIndex(rfs.package_meta);
2508
- resolver[pkgId].nameResolution[rfs.name] = rfs.url;
2509
2457
  resolver[pkgId].fhirSchemas[rfs.url] = rfs;
2510
2458
  },
2511
2459
  resolveFs,
@@ -2513,16 +2461,17 @@ var registerFromManager = async (manager, { logger, fallbackPackageForNameResolu
2513
2461
  resolveFsSpecializations,
2514
2462
  ensureSpecializationCanonicalUrl,
2515
2463
  resolveSd: (_pkg, canonicalUrl) => {
2516
- const res = packageAgnosticResolveCanonical(resolver, canonicalUrl, logger);
2464
+ const res = packageAgnosticResolveCanonical(resolver, canonicalUrl);
2517
2465
  if (isStructureDefinition(res)) return res;
2518
2466
  return void 0;
2519
2467
  },
2520
2468
  allFs: () => Object.values(resolver).flatMap((pkgIndex) => Object.values(pkgIndex.fhirSchemas)),
2521
2469
  allVs: () => Object.values(resolver).flatMap((pkgIndex) => Object.values(pkgIndex.valueSets)),
2522
2470
  resolveVs,
2523
- resolveAny: (canonicalUrl) => packageAgnosticResolveCanonical(resolver, canonicalUrl, logger),
2471
+ resolveAny: (canonicalUrl) => packageAgnosticResolveCanonical(resolver, canonicalUrl),
2524
2472
  resolveElementSnapshot,
2525
- getAllElementKeys
2473
+ getAllElementKeys,
2474
+ resolver
2526
2475
  };
2527
2476
  };
2528
2477
  var resolveFsElementGenealogy = (genealogy, path) => {
@@ -2567,10 +2516,10 @@ var TypeSchemaGenerator = class {
2567
2516
  }
2568
2517
  }
2569
2518
  async registerFromPackageMetas(packageMetas) {
2570
- const packageNames = packageMetas.map((meta) => `${meta.name}${meta.version}`);
2519
+ const packageNames = packageMetas.map(packageMetaToFhir);
2571
2520
  this.logger?.step(`Loading FHIR packages: ${packageNames.join(", ")}`);
2572
2521
  await this.manager.init();
2573
- return registerFromManager(this.manager, {});
2522
+ return registerFromManager(this.manager, { focusedPackages: packageMetas });
2574
2523
  }
2575
2524
  generateFhirSchemas(structureDefinitions) {
2576
2525
  this.logger?.progress(`Converting ${structureDefinitions.length} StructureDefinitions to FHIRSchemas`);
@@ -3013,9 +2962,29 @@ var TypeSchemaParser = class {
3013
2962
  };
3014
2963
 
3015
2964
  // src/typeschema/index.ts
2965
+ var codeableReferenceInR4 = "Use CodeableReference which is not provided by FHIR R4.";
2966
+ var availabilityInR4 = "Use Availability which is not provided by FHIR R4.";
2967
+ var skipMe = {
2968
+ "hl7.fhir.uv.extensions.r4#1.0.0": {
2969
+ "http://hl7.org/fhir/StructureDefinition/extended-contact-availability": availabilityInR4,
2970
+ "http://hl7.org/fhir/StructureDefinition/immunization-procedure": codeableReferenceInR4,
2971
+ "http://hl7.org/fhir/StructureDefinition/specimen-additive": codeableReferenceInR4,
2972
+ "http://hl7.org/fhir/StructureDefinition/workflow-barrier": codeableReferenceInR4,
2973
+ "http://hl7.org/fhir/StructureDefinition/workflow-protectiveFactor": codeableReferenceInR4,
2974
+ "http://hl7.org/fhir/StructureDefinition/workflow-reason": codeableReferenceInR4
2975
+ },
2976
+ "hl7.fhir.r5.core#5.0.0": {
2977
+ "http://hl7.org/fhir/StructureDefinition/shareablecodesystem": "FIXME: CodeSystem.concept.concept defined by ElementReference. FHIR Schema generator output broken value in it, so we just skip it for now."
2978
+ }
2979
+ };
3016
2980
  var generateTypeSchemas = async (register, logger) => {
3017
2981
  const fhirSchemas = [];
3018
2982
  for (const fhirSchema of register.allFs()) {
2983
+ const pkgId = packageMetaToFhir(fhirSchema.package_meta);
2984
+ if (skipMe[pkgId]?.[fhirSchema.url]) {
2985
+ logger?.dry_warn(`Skip ${fhirSchema.url} from ${pkgId}. Reason: ${skipMe[pkgId]?.[fhirSchema.url]}`);
2986
+ continue;
2987
+ }
3019
2988
  fhirSchemas.push(...await transformFhirSchema(register, fhirSchema, logger));
3020
2989
  }
3021
2990
  for (const vsSchema of register.allVs()) {
@@ -3050,23 +3019,9 @@ var uppercaseFirstLetter = (str) => {
3050
3019
  var uppercaseFirstLetterOfEach = (strings) => {
3051
3020
  return strings.map((str) => uppercaseFirstLetter(str));
3052
3021
  };
3053
- function deepEqual(obj1, obj2) {
3054
- if (obj1 === obj2) return true;
3055
- if (obj1 === null || obj2 === null || typeof obj1 !== "object" || typeof obj2 !== "object") {
3056
- return false;
3057
- }
3058
- if (Array.isArray(obj1) && Array.isArray(obj2)) {
3059
- if (obj1.length !== obj2.length) return false;
3060
- return obj1.every((item, index) => deepEqual(item, obj2[index]));
3061
- }
3062
- if (Array.isArray(obj1) || Array.isArray(obj2)) {
3063
- return false;
3064
- }
3065
- const keys1 = Object.keys(obj1);
3066
- const keys2 = Object.keys(obj2);
3067
- if (keys1.length !== keys2.length) return false;
3068
- return keys1.every((key) => keys2.includes(key) && deepEqual(obj1[key], obj2[key]));
3069
- }
3022
+ var typeSchemaInfo = (schema) => {
3023
+ return `<${schema.identifier.url}> from ${schema.identifier.package}#${schema.identifier.version}`;
3024
+ };
3070
3025
  var FileSystemWriter = class {
3071
3026
  opts;
3072
3027
  currentDir;
@@ -3080,12 +3035,14 @@ var FileSystemWriter = class {
3080
3035
  return this.opts.logger;
3081
3036
  }
3082
3037
  cd(path, gen) {
3038
+ const prev = this.currentDir;
3083
3039
  this.currentDir = path.startsWith("/") ? Path4.join(this.opts.outputDir, path) : Path4.join(this.currentDir, path);
3084
3040
  if (!fs.existsSync(this.currentDir)) {
3085
3041
  fs.mkdirSync(this.currentDir, { recursive: true });
3086
3042
  }
3087
3043
  this.logger()?.debug(`cd '${this.currentDir}'`);
3088
3044
  gen();
3045
+ this.currentDir = prev;
3089
3046
  }
3090
3047
  cat(fn, gen) {
3091
3048
  if (this.currentFileDescriptor) throw new Error("Can't open file in file");
@@ -3098,6 +3055,7 @@ var FileSystemWriter = class {
3098
3055
  gen();
3099
3056
  } finally {
3100
3057
  if (this.currentFileDescriptor) {
3058
+ fs.fsyncSync(this.currentFileDescriptor);
3101
3059
  fs.closeSync(this.currentFileDescriptor);
3102
3060
  }
3103
3061
  this.currentFileDescriptor = void 0;
@@ -3512,19 +3470,21 @@ var CSharp = class extends Writer {
3512
3470
  fs__default.copyFileSync(sourceFile, destFile);
3513
3471
  }
3514
3472
  };
3515
-
3516
- // src/typeschema/utils.ts
3517
3473
  var groupByPackages = (typeSchemas) => {
3518
3474
  const grouped = {};
3519
3475
  for (const ts of typeSchemas) {
3520
- const packageName = ts.identifier.package;
3521
- if (!grouped[packageName]) {
3522
- grouped[packageName] = [];
3523
- }
3524
- grouped[packageName].push(ts);
3476
+ const pkgName = ts.identifier.package;
3477
+ if (!grouped[pkgName]) grouped[pkgName] = [];
3478
+ grouped[pkgName].push(ts);
3525
3479
  }
3526
- for (const [_packageName, typeSchemas2] of Object.entries(grouped)) {
3527
- typeSchemas2.sort((a, b) => a.identifier.name.localeCompare(b.identifier.name));
3480
+ for (const [packageName, typeSchemas2] of Object.entries(grouped)) {
3481
+ const dict = {};
3482
+ for (const ts of typeSchemas2) {
3483
+ dict[JSON.stringify(ts.identifier)] = ts;
3484
+ }
3485
+ const tmp = Object.values(dict);
3486
+ tmp.sort((a, b) => a.identifier.name.localeCompare(b.identifier.name));
3487
+ grouped[packageName] = tmp;
3528
3488
  }
3529
3489
  return grouped;
3530
3490
  };
@@ -3564,7 +3524,8 @@ var mkTypeSchemaIndex = (schemas, logger) => {
3564
3524
  if (index[url][schema.identifier.package] && pkg !== "shared") {
3565
3525
  const r1 = JSON.stringify(schema.identifier, void 0, 2);
3566
3526
  const r2 = JSON.stringify(index[url][pkg]?.identifier, void 0, 2);
3567
- throw new Error(`Duplicate schema: ${r1} and ${r2}`);
3527
+ if (r1 !== r2) throw new Error(`Duplicate schema: ${r1} and ${r2}`);
3528
+ return;
3568
3529
  }
3569
3530
  index[url][pkg] = schema;
3570
3531
  };
@@ -3622,7 +3583,10 @@ var mkTypeSchemaIndex = (schemas, logger) => {
3622
3583
  if (!schema2.fields) continue;
3623
3584
  for (const [fieldName, fieldConstraints] of Object.entries(schema2.fields)) {
3624
3585
  if (mergedFields[fieldName]) {
3625
- mergedFields[fieldName] = { ...mergedFields[fieldName], ...fieldConstraints };
3586
+ mergedFields[fieldName] = {
3587
+ ...mergedFields[fieldName],
3588
+ ...fieldConstraints
3589
+ };
3626
3590
  } else {
3627
3591
  mergedFields[fieldName] = { ...fieldConstraints };
3628
3592
  }
@@ -3647,6 +3611,26 @@ var mkTypeSchemaIndex = (schemas, logger) => {
3647
3611
  return schema.fields?.meta !== void 0;
3648
3612
  });
3649
3613
  };
3614
+ const exportTree = async (filename) => {
3615
+ const tree = {};
3616
+ for (const [pkgId, shemas] of Object.entries(groupByPackages(schemas))) {
3617
+ tree[pkgId] = { complexTypes: {}, resources: {}, profiles: {} };
3618
+ for (const schema of shemas) {
3619
+ schema.identifier;
3620
+ if (isResourceTypeSchema(schema)) {
3621
+ tree[pkgId].resources[schema.identifier.url] = {};
3622
+ }
3623
+ if (isProfileTypeSchema(schema)) {
3624
+ tree[pkgId].profiles[schema.identifier.url] = {};
3625
+ }
3626
+ if (isComplexTypeTypeSchema(schema)) {
3627
+ tree[pkgId].complexTypes[schema.identifier.url] = {};
3628
+ }
3629
+ }
3630
+ }
3631
+ const raw = filename.endsWith(".yaml") ? YAML.stringify(tree) : JSON.stringify(tree, void 0, 2);
3632
+ await afs3.writeFile(filename, raw);
3633
+ };
3650
3634
  return {
3651
3635
  _schemaIndex: index,
3652
3636
  _relations: relations,
@@ -3661,7 +3645,8 @@ var mkTypeSchemaIndex = (schemas, logger) => {
3661
3645
  findLastSpecialization,
3662
3646
  findLastSpecializationByIdentifier,
3663
3647
  flatProfile,
3664
- isWithMetaField
3648
+ isWithMetaField,
3649
+ exportTree
3665
3650
  };
3666
3651
  };
3667
3652
 
@@ -4179,7 +4164,7 @@ var BaseGenerator = class {
4179
4164
  * This is the main method that orchestrates the entire generation process
4180
4165
  * @param schemas - Array of TypeSchema documents
4181
4166
  */
4182
- async generate(schemas) {
4167
+ async generate({ schemas }) {
4183
4168
  return this.errorBoundary.withErrorBoundary(
4184
4169
  async () => {
4185
4170
  this.generationStartTime = performance.now();
@@ -4219,7 +4204,7 @@ var BaseGenerator = class {
4219
4204
  return result;
4220
4205
  };
4221
4206
  try {
4222
- const result = await this.generate(schemas);
4207
+ const result = await this.generate({ schemas, index: null });
4223
4208
  result.forEach((file) => {
4224
4209
  const mockResult = mockWriteResults.get(file.filename);
4225
4210
  if (mockResult) {
@@ -5527,10 +5512,10 @@ ${nestedInterfaces}`;
5527
5512
  /**
5528
5513
  * Override generate to clean directory first
5529
5514
  */
5530
- async generate(schemas) {
5515
+ async generate(input) {
5531
5516
  await this.fileManager.cleanDirectory();
5532
5517
  this.logger.debug("Cleaned output directory before generation");
5533
- return super.generate(schemas);
5518
+ return super.generate(input);
5534
5519
  }
5535
5520
  /**
5536
5521
  * Run post-generation hooks - generate utility files
@@ -5730,15 +5715,8 @@ var tsModuleFileName = (id) => {
5730
5715
  };
5731
5716
  var canonicalToName2 = (canonical, dropFragment = true) => {
5732
5717
  if (!canonical) return void 0;
5733
- let localName = canonical.split("/").pop();
5718
+ const localName = extractNameFromCanonical(canonical, dropFragment);
5734
5719
  if (!localName) return void 0;
5735
- if (dropFragment && localName.includes("#")) {
5736
- localName = localName.split("#")[0];
5737
- }
5738
- if (!localName) return void 0;
5739
- if (/^\d/.test(localName)) {
5740
- localName = `number_${localName}`;
5741
- }
5742
5720
  return normalizeTsName(localName);
5743
5721
  };
5744
5722
  var tsResourceName = (id) => {
@@ -5794,12 +5772,14 @@ var TypeScript = class extends Writer {
5794
5772
  if (["complex-type", "resource", "logical"].includes(dep.kind)) {
5795
5773
  imports.push({
5796
5774
  tsPackage: `../${kebabCase(dep.package)}/${pascalCase(dep.name)}`,
5797
- name: uppercaseFirstLetter(dep.name)
5775
+ name: uppercaseFirstLetter(dep.name),
5776
+ dep
5798
5777
  });
5799
5778
  } else if (isNestedIdentifier(dep)) {
5800
5779
  imports.push({
5801
5780
  tsPackage: `../${kebabCase(dep.package)}/${pascalCase(canonicalToName2(dep.url) ?? "")}`,
5802
- name: tsResourceName(dep)
5781
+ name: tsResourceName(dep),
5782
+ dep
5803
5783
  });
5804
5784
  } else {
5805
5785
  skipped.push(dep);
@@ -5807,6 +5787,7 @@ var TypeScript = class extends Writer {
5807
5787
  }
5808
5788
  imports.sort((a, b) => a.name.localeCompare(b.name));
5809
5789
  for (const dep of imports) {
5790
+ this.debugComment(dep.dep);
5810
5791
  this.tsImportType(dep.tsPackage, dep.name);
5811
5792
  }
5812
5793
  for (const dep of skipped) {
@@ -5849,7 +5830,9 @@ var TypeScript = class extends Writer {
5849
5830
  if (isResourceTypeSchema(schema)) {
5850
5831
  const possibleResourceTypes = [schema.identifier];
5851
5832
  possibleResourceTypes.push(...tsIndex.resourceChildren(schema.identifier));
5852
- this.lineSM(`resourceType: ${possibleResourceTypes.map((e) => `"${e.name}"`).join(" | ")}`);
5833
+ this.lineSM(
5834
+ `resourceType: ${possibleResourceTypes.sort((a, b) => a.name.localeCompare(b.name)).map((e) => `"${e.name}"`).join(" | ")}`
5835
+ );
5853
5836
  this.line();
5854
5837
  }
5855
5838
  if (!schema.fields) return;
@@ -5891,6 +5874,7 @@ var TypeScript = class extends Writer {
5891
5874
  }
5892
5875
  }
5893
5876
  generateProfileType(tsIndex, flatProfile) {
5877
+ this.debugComment("flatProfile", flatProfile);
5894
5878
  const tsName = tsResourceName(flatProfile.identifier);
5895
5879
  this.debugComment("identifier", flatProfile.identifier);
5896
5880
  this.debugComment("base", flatProfile.base);
@@ -5928,6 +5912,8 @@ var TypeScript = class extends Writer {
5928
5912
  tsType = tsResourceName(field.type);
5929
5913
  } else if (isPrimitiveIdentifier(field.type)) {
5930
5914
  tsType = resolvePrimitiveType(field.type.name);
5915
+ } else if (field.type === void 0) {
5916
+ throw new Error(`Undefined type for '${fieldName}' field at ${typeSchemaInfo(flatProfile)}`);
5931
5917
  } else {
5932
5918
  tsType = field.type.name;
5933
5919
  }
@@ -6093,17 +6079,20 @@ var writerToGenerator = (writerGen) => {
6093
6079
  });
6094
6080
  };
6095
6081
  return {
6096
- generate: async (schemas) => {
6097
- const tsIndex = mkTypeSchemaIndex(schemas);
6082
+ generate: async ({ index: tsIndex }) => {
6098
6083
  writerGen.generate(tsIndex);
6099
6084
  return getGeneratedFiles();
6100
6085
  },
6101
6086
  setOutputDir: (outputDir) => writerGen.opts.outputDir = outputDir,
6102
- build: async (_schemas) => getGeneratedFiles()
6087
+ build: async (_input) => getGeneratedFiles()
6103
6088
  };
6104
6089
  };
6105
- var normalizeFileName = (str) => str.replace(/[^a-zA-Z0-9]/g, "");
6106
- var APIBuilder = class _APIBuilder {
6090
+ var normalizeFileName = (str) => {
6091
+ const res = str.replace(/[^a-zA-Z0-9\-_.@#()]/g, "");
6092
+ if (res.length === 0) return "unknown";
6093
+ return res;
6094
+ };
6095
+ var APIBuilder = class {
6107
6096
  schemas = [];
6108
6097
  options;
6109
6098
  generators = /* @__PURE__ */ new Map();
@@ -6124,7 +6113,8 @@ var APIBuilder = class _APIBuilder {
6124
6113
  typeSchemaConfig: options.typeSchemaConfig,
6125
6114
  manager: options.manager || null,
6126
6115
  throwException: options.throwException || false,
6127
- typeSchemaOutputDir: options.typeSchemaOutputDir
6116
+ typeSchemaOutputDir: options.typeSchemaOutputDir,
6117
+ exportTypeTree: options.exportTypeTree
6128
6118
  };
6129
6119
  this.typeSchemaConfig = options.typeSchemaConfig;
6130
6120
  this.logger = options.logger || createLogger({
@@ -6139,24 +6129,18 @@ var APIBuilder = class _APIBuilder {
6139
6129
  this.packages.push(packageMetaToNpm({ name: packageName, version: version || "latest" }));
6140
6130
  return this;
6141
6131
  }
6142
- /**
6143
- * Load TypeSchema from files
6144
- */
6145
6132
  fromFiles(...filePaths) {
6146
6133
  this.logger.debug(`Loading from ${filePaths.length} TypeSchema files`);
6147
6134
  const operation = this.loadFromFiles(filePaths);
6148
6135
  this.pendingOperations.push(operation);
6149
6136
  return this;
6150
6137
  }
6151
- /**
6152
- * Load TypeSchema from TypeSchema objects
6153
- */
6154
6138
  fromSchemas(schemas) {
6155
6139
  this.logger.debug(`Adding ${schemas.length} TypeSchemas to generation`);
6156
6140
  this.schemas = [...this.schemas, ...schemas];
6157
6141
  return this;
6158
6142
  }
6159
- typescript(options = {}) {
6143
+ typescriptDepricated(options = {}) {
6160
6144
  const typesOutputDir = `${this.options.outputDir}/types`;
6161
6145
  const generator = new TypeScriptGenerator({
6162
6146
  outputDir: typesOutputDir,
@@ -6181,12 +6165,13 @@ var APIBuilder = class _APIBuilder {
6181
6165
  this.logger.debug(`Configured TypeScript generator (${options.moduleFormat || "esm"})`);
6182
6166
  return this;
6183
6167
  }
6184
- typescript2(opts) {
6168
+ typescript(opts) {
6185
6169
  const writerOpts = {
6186
6170
  outputDir: Path4.join(this.options.outputDir, "/types"),
6187
6171
  tabSize: 4,
6188
6172
  withDebugComment: false,
6189
- commentLinePrefix: "//"
6173
+ commentLinePrefix: "//",
6174
+ exportTypeTree: this.options.exportTypeTree
6190
6175
  };
6191
6176
  const effectiveOpts = { logger: this.logger, ...writerOpts, ...opts };
6192
6177
  const generator = writerToGenerator(new TypeScript(effectiveOpts));
@@ -6245,63 +6230,70 @@ var APIBuilder = class _APIBuilder {
6245
6230
  this.options.cleanOutput = enabled;
6246
6231
  return this;
6247
6232
  }
6233
+ writeTypeTree(filename) {
6234
+ this.options.exportTypeTree = filename;
6235
+ return this;
6236
+ }
6248
6237
  writeTypeSchemas(target) {
6249
6238
  this.options.typeSchemaOutputDir = target;
6250
6239
  return this;
6251
6240
  }
6252
- static async isIdenticalTo(path, tsJSON) {
6253
- if (!await afs2.exists(path)) return false;
6254
- const json = await afs2.readFile(path);
6255
- const ts1 = JSON.parse(json.toString());
6256
- const ts2 = JSON.parse(tsJSON);
6257
- return deepEqual(ts1, ts2);
6258
- }
6259
6241
  async writeTypeSchemasToSeparateFiles(typeSchemas, outputDir) {
6260
- if (this.options.cleanOutput) fs.rmSync(outputDir, { recursive: true, force: true });
6261
- await afs2.mkdir(outputDir, { recursive: true });
6262
- const usedNames = {};
6263
- this.logger.info(`Writing TypeSchema files to ${outputDir}...`);
6242
+ await afs3.mkdir(outputDir, { recursive: true });
6243
+ this.logger.info(`Writing TypeSchema files to ${outputDir}/...`);
6244
+ const files = {};
6264
6245
  for (const ts of typeSchemas) {
6265
- const package_name = camelCase(ts.identifier.package.replaceAll("/", "-"));
6266
- const name = normalizeFileName(ts.identifier.name.toString());
6246
+ const pkg = { name: ts.identifier.package, version: ts.identifier.version };
6247
+ const pkgPath = normalizeFileName(packageMetaToFhir(pkg));
6248
+ const name = normalizeFileName(`${ts.identifier.name}(${extractNameFromCanonical(ts.identifier.url)})`);
6267
6249
  const json = JSON.stringify(ts, null, 2);
6268
- const baseName = Path4.join(outputDir, package_name, name);
6269
- let fullName;
6270
- if (usedNames[baseName] !== void 0) {
6271
- usedNames[baseName]++;
6272
- fullName = `${baseName}-${usedNames[baseName]}.typeschema.json`;
6273
- } else {
6274
- usedNames[baseName] = 0;
6275
- fullName = `${baseName}.typeschema.json`;
6276
- }
6277
- if (await _APIBuilder.isIdenticalTo(fullName, json)) continue;
6278
- await afs2.mkdir(Path4.dirname(fullName), { recursive: true });
6279
- await afs2.writeFile(fullName, json);
6250
+ const baseName = Path4.join(outputDir, pkgPath, name);
6251
+ if (!files[baseName]) files[baseName] = [];
6252
+ if (!files[baseName]?.some((e) => e === json)) {
6253
+ files[baseName].push(json);
6254
+ }
6255
+ }
6256
+ for (const [baseName, jsons] of Object.entries(files)) {
6257
+ await Promise.all(
6258
+ jsons.map(async (json, index) => {
6259
+ let fullName;
6260
+ if (index === 0) {
6261
+ fullName = `${baseName}.typeschema.json`;
6262
+ } else {
6263
+ fullName = `${baseName}-${index}.typeschema.json`;
6264
+ }
6265
+ await afs3.mkdir(Path4.dirname(fullName), { recursive: true });
6266
+ await afs3.writeFile(fullName, json);
6267
+ })
6268
+ );
6280
6269
  }
6281
6270
  }
6282
6271
  async writeTypeSchemasToSingleFile(typeSchemas, outputFile) {
6272
+ this.logger.info(`Writing TypeSchema files to: ${outputFile}`);
6283
6273
  if (this.options.cleanOutput && fs.existsSync(outputFile)) fs.rmSync(outputFile);
6284
- await afs2.mkdir(Path4.dirname(outputFile), { recursive: true });
6274
+ await afs3.mkdir(Path4.dirname(outputFile), { recursive: true });
6285
6275
  this.logger.info(`Writing TypeSchemas to one file ${outputFile}...`);
6286
6276
  for (const ts of typeSchemas) {
6287
6277
  const json = JSON.stringify(ts, null, 2);
6288
- await afs2.appendFile(outputFile, json + "\n");
6278
+ await afs3.appendFile(outputFile, `${json}
6279
+ `);
6289
6280
  }
6290
6281
  }
6291
6282
  async tryWriteTypeSchema(typeSchemas) {
6292
6283
  if (!this.options.typeSchemaOutputDir) return;
6293
6284
  try {
6294
- this.logger.info(`Starting writing TypeSchema files.`);
6295
- if (Path4.extname(this.options.typeSchemaOutputDir) === ".ndjson")
6285
+ if (Path4.extname(this.options.typeSchemaOutputDir) === ".ndjson") {
6296
6286
  await this.writeTypeSchemasToSingleFile(typeSchemas, this.options.typeSchemaOutputDir);
6297
- else await this.writeTypeSchemasToSeparateFiles(typeSchemas, this.options.typeSchemaOutputDir);
6298
- this.logger.info(`Finished writing TypeSchema files.`);
6287
+ } else {
6288
+ await this.writeTypeSchemasToSeparateFiles(typeSchemas, this.options.typeSchemaOutputDir);
6289
+ }
6290
+ this.logger.info(`Writing TypeSchema - DONE`);
6299
6291
  } catch (error) {
6300
- if (this.options.throwException) throw error;
6301
6292
  this.logger.error(
6302
6293
  "Failed to write TypeSchema output",
6303
6294
  error instanceof Error ? error : new Error(String(error))
6304
6295
  );
6296
+ if (this.options.throwException) throw error;
6305
6297
  }
6306
6298
  }
6307
6299
  async generate() {
@@ -6316,10 +6308,18 @@ var APIBuilder = class _APIBuilder {
6316
6308
  };
6317
6309
  this.logger.debug(`Starting generation with ${this.generators.size} generators`);
6318
6310
  if (this.options.cleanOutput) {
6319
- this.logger.info(`Cleaning output directory: ${this.options.outputDir}`);
6311
+ this.logger.info(`Cleaning outputs...`);
6320
6312
  try {
6313
+ this.logger.info(`Clean ${this.options.outputDir}`);
6321
6314
  fs.rmSync(this.options.outputDir, { recursive: true, force: true });
6322
- fs.mkdirSync(this.options.outputDir, { recursive: true });
6315
+ if (this.options.typeSchemaOutputDir) {
6316
+ this.logger.info(`Clean ${this.options.typeSchemaOutputDir}`);
6317
+ fs.rmSync(this.options.typeSchemaOutputDir, { recursive: true, force: true });
6318
+ }
6319
+ if (this.options.exportTypeTree) {
6320
+ this.logger.info(`Clean ${this.options.exportTypeTree}`);
6321
+ fs.rmSync(this.options.exportTypeTree, { recursive: true, force: true });
6322
+ }
6323
6323
  } catch (error) {
6324
6324
  this.logger.warn(
6325
6325
  `Error cleaning output directory: ${error instanceof Error ? error.message : String(error)}`
@@ -6333,11 +6333,16 @@ var APIBuilder = class _APIBuilder {
6333
6333
  workingDir: "tmp/fhir"
6334
6334
  });
6335
6335
  await manager.init();
6336
- const register = await registerFromManager(manager, { logger: this.logger });
6336
+ const register = await registerFromManager(manager, {
6337
+ logger: this.logger,
6338
+ focusedPackages: this.packages.map(npmToPackageMeta)
6339
+ });
6337
6340
  const typeSchemas = await generateTypeSchemas(register, this.logger);
6338
6341
  await this.tryWriteTypeSchema(typeSchemas);
6342
+ const tsIndex = mkTypeSchemaIndex(typeSchemas);
6343
+ if (this.options.exportTypeTree) await tsIndex.exportTree(this.options.exportTypeTree);
6339
6344
  this.logger.debug(`Executing ${this.generators.size} generators`);
6340
- await this.executeGenerators(result, typeSchemas);
6345
+ await this.executeGenerators(result, { schemas: typeSchemas, index: tsIndex });
6341
6346
  this.logger.info("Generation completed successfully");
6342
6347
  result.success = result.errors.length === 0;
6343
6348
  this.logger.debug(`Generation completed: ${result.filesGenerated.length} files`);
@@ -6404,11 +6409,11 @@ var APIBuilder = class _APIBuilder {
6404
6409
  this.cache.setMany(schemas);
6405
6410
  }
6406
6411
  }
6407
- async executeGenerators(result, typeSchemas) {
6412
+ async executeGenerators(result, input) {
6408
6413
  for (const [type, generator] of this.generators.entries()) {
6409
6414
  this.logger.info(`Generating ${type}...`);
6410
6415
  try {
6411
- const files = await generator.generate(typeSchemas);
6416
+ const files = await generator.generate(input);
6412
6417
  result.filesGenerated.push(...files.map((f) => f.path || f.filename));
6413
6418
  this.logger.info(`Generating ${type} finished successfully`);
6414
6419
  } catch (error) {
@@ -6441,7 +6446,7 @@ function createAPIFromConfig(config) {
6441
6446
  builder.fromFiles(...config.files);
6442
6447
  }
6443
6448
  if (config.typescript) {
6444
- builder.typescript(config.typescript);
6449
+ builder.typescriptDepricated(config.typescript);
6445
6450
  }
6446
6451
  return builder;
6447
6452
  }
@@ -6449,13 +6454,13 @@ async function generateTypesFromPackage(packageName, outputDir, options = {}) {
6449
6454
  return createAPI({
6450
6455
  outputDir,
6451
6456
  verbose: options.verbose
6452
- }).fromPackage(packageName, options.version).typescript().generate();
6457
+ }).fromPackage(packageName, options.version).typescriptDepricated().generate();
6453
6458
  }
6454
6459
  async function generateTypesFromFiles(inputFiles, outputDir, options = {}) {
6455
6460
  return createAPI({
6456
6461
  outputDir,
6457
6462
  verbose: options.verbose
6458
- }).fromFiles(...inputFiles).typescript().generate();
6463
+ }).fromFiles(...inputFiles).typescriptDepricated().generate();
6459
6464
  }
6460
6465
  var DEFAULT_CONFIG = {
6461
6466
  outputDir: "./generated",