@atomic-ehr/codegen 0.0.1-canary.20251106144955.d906520 → 0.0.1-canary.20251106152808.f4530b9
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/cli/index.js +23 -23
- package/dist/index.d.ts +31 -3
- package/dist/index.js +244 -233
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
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
|
|
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
|
|
1468
|
+
return res?.resourceType === "ValueSet";
|
|
1451
1469
|
};
|
|
1452
1470
|
var isCodeSystem = (res) => {
|
|
1453
|
-
return res
|
|
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:
|
|
1593
|
-
version:
|
|
1613
|
+
package: baseFs.package_meta.name,
|
|
1614
|
+
version: baseFs.package_meta.version,
|
|
1594
1615
|
name: baseName,
|
|
1595
|
-
url:
|
|
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(
|
|
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(
|
|
1691
|
+
const url = register.ensureSpecializationCanonicalUrl(element.type);
|
|
1670
1692
|
const fieldFs = register.resolveFs(fhirSchema.package_meta, url);
|
|
1671
|
-
if (!fieldFs)
|
|
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;
|
|
@@ -1711,8 +1736,9 @@ function isNestedElement(element) {
|
|
|
1711
1736
|
return isBackbone || isElement || elementsWithoutType;
|
|
1712
1737
|
}
|
|
1713
1738
|
function mkNestedField(register, fhirSchema, path, element, logger) {
|
|
1739
|
+
const nestedIdentifier = mkNestedIdentifier(register, fhirSchema, path, logger);
|
|
1714
1740
|
return {
|
|
1715
|
-
type:
|
|
1741
|
+
type: nestedIdentifier,
|
|
1716
1742
|
array: element.array || false,
|
|
1717
1743
|
required: isRequired(register, fhirSchema, path),
|
|
1718
1744
|
excluded: isExcluded(register, fhirSchema, path)
|
|
@@ -1868,19 +1894,6 @@ function extractFieldDependencies(fields) {
|
|
|
1868
1894
|
}
|
|
1869
1895
|
return deps;
|
|
1870
1896
|
}
|
|
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
1897
|
function isExtensionSchema(fhirSchema, _identifier) {
|
|
1885
1898
|
if (fhirSchema.base === "Extension" || fhirSchema.base === "http://hl7.org/fhir/StructureDefinition/Extension") {
|
|
1886
1899
|
return true;
|
|
@@ -1907,62 +1920,6 @@ async function transformValueSet(register, valueSet, logger) {
|
|
|
1907
1920
|
compose: !concept ? valueSet.compose : void 0
|
|
1908
1921
|
};
|
|
1909
1922
|
}
|
|
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
1923
|
function extractDependencies(identifier, base, fields, nestedTypes) {
|
|
1967
1924
|
const deps = [];
|
|
1968
1925
|
if (base) deps.push(base);
|
|
@@ -1987,10 +1944,12 @@ function transformFhirSchemaResource(register, fhirSchema, logger) {
|
|
|
1987
1944
|
if (fhirSchema.base && fhirSchema.type !== "Element") {
|
|
1988
1945
|
const baseFs = register.resolveFs(
|
|
1989
1946
|
fhirSchema.package_meta,
|
|
1990
|
-
register.ensureSpecializationCanonicalUrl(fhirSchema.
|
|
1947
|
+
register.ensureSpecializationCanonicalUrl(fhirSchema.base)
|
|
1991
1948
|
);
|
|
1992
1949
|
if (!baseFs) {
|
|
1993
|
-
throw new Error(
|
|
1950
|
+
throw new Error(
|
|
1951
|
+
`Base resource not found '${fhirSchema.base}' for <${fhirSchema.url}> from ${packageMetaToFhir(fhirSchema.package_meta)}`
|
|
1952
|
+
);
|
|
1994
1953
|
}
|
|
1995
1954
|
base = mkIdentifier(baseFs);
|
|
1996
1955
|
}
|
|
@@ -2009,16 +1968,16 @@ function transformFhirSchemaResource(register, fhirSchema, logger) {
|
|
|
2009
1968
|
return [typeSchema, ...bindingSchemas];
|
|
2010
1969
|
}
|
|
2011
1970
|
async function transformFhirSchema(register, fhirSchema, logger) {
|
|
2012
|
-
const
|
|
2013
|
-
mkIdentifier(fhirSchema)
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
1971
|
+
const schemas = transformFhirSchemaResource(register, fhirSchema, logger);
|
|
1972
|
+
if (isExtensionSchema(fhirSchema, mkIdentifier(fhirSchema))) {
|
|
1973
|
+
const schema = schemas[0];
|
|
1974
|
+
if (!schema) throw new Error(`Expected schema to be defined`);
|
|
1975
|
+
schema.metadata = {
|
|
1976
|
+
isExtension: true
|
|
1977
|
+
// Mark as extension for file organization
|
|
1978
|
+
};
|
|
2020
1979
|
}
|
|
2021
|
-
return
|
|
1980
|
+
return schemas;
|
|
2022
1981
|
}
|
|
2023
1982
|
var TypeSchemaCache = class {
|
|
2024
1983
|
cache = /* @__PURE__ */ new Map();
|
|
@@ -2362,7 +2321,7 @@ function createLogger(options = {}) {
|
|
|
2362
2321
|
}
|
|
2363
2322
|
var readPackageJSON = async (workDir, packageMeta) => {
|
|
2364
2323
|
const packageJSONFileName = Path4.join(workDir, "node_modules", packageMeta.name, "package.json");
|
|
2365
|
-
const packageJSON = JSON.parse(await
|
|
2324
|
+
const packageJSON = JSON.parse(await afs3.readFile(packageJSONFileName, "utf8"));
|
|
2366
2325
|
return packageJSON;
|
|
2367
2326
|
};
|
|
2368
2327
|
var readPackageDependencies = async (workDir, packageMeta) => {
|
|
@@ -2376,69 +2335,50 @@ var readPackageDependencies = async (workDir, packageMeta) => {
|
|
|
2376
2335
|
return [];
|
|
2377
2336
|
};
|
|
2378
2337
|
var mkEmptyPkgIndex = (pkg) => {
|
|
2379
|
-
return {
|
|
2338
|
+
return {
|
|
2339
|
+
pkg,
|
|
2340
|
+
canonicalResolution: {},
|
|
2341
|
+
fhirSchemas: {},
|
|
2342
|
+
valueSets: {}
|
|
2343
|
+
};
|
|
2380
2344
|
};
|
|
2381
|
-
var mkPackageAwareResolver = async (manager, pkg, deep
|
|
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
|
-
}
|
|
2345
|
+
var mkPackageAwareResolver = async (manager, pkg, deep, acc, logger) => {
|
|
2388
2346
|
const pkgId = packageMetaToFhir(pkg);
|
|
2389
|
-
|
|
2347
|
+
logger?.info(`${" ".repeat(deep * 2)}+ ${pkgId}`);
|
|
2348
|
+
if (acc[pkgId]) return acc[pkgId];
|
|
2349
|
+
const index = mkEmptyPkgIndex(pkg);
|
|
2390
2350
|
for (const resource of await manager.search({ package: pkg })) {
|
|
2391
2351
|
const rawUrl = resource.url;
|
|
2392
2352
|
if (!rawUrl) continue;
|
|
2393
2353
|
if (!(isStructureDefinition(resource) || isValueSet(resource) || isCodeSystem(resource))) continue;
|
|
2394
2354
|
const url = rawUrl;
|
|
2395
|
-
if (
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
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
|
-
}
|
|
2355
|
+
if (index.canonicalResolution[url]) logger?.dry_warn(`Duplicate canonical URL: ${url} at ${pkgId}.`);
|
|
2356
|
+
index.canonicalResolution[url] = [{ deep, pkg, pkgId, resource }];
|
|
2357
|
+
}
|
|
2358
|
+
const deps = await readPackageDependencies("tmp/fhir", pkg);
|
|
2359
|
+
for (const depPkg of deps) {
|
|
2360
|
+
const { canonicalResolution } = await mkPackageAwareResolver(manager, depPkg, deep + 1, acc, logger);
|
|
2361
|
+
for (const [surl, resolutions] of Object.entries(canonicalResolution)) {
|
|
2362
|
+
const url = surl;
|
|
2363
|
+
index.canonicalResolution[url] = [...index.canonicalResolution[url] || [], ...resolutions];
|
|
2418
2364
|
}
|
|
2419
2365
|
}
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
const resource = resolver[pkgId].nameResolution[name];
|
|
2426
|
-
return resource;
|
|
2366
|
+
for (const resolutionOptions of Object.values(index.canonicalResolution)) {
|
|
2367
|
+
resolutionOptions.sort((a, b) => a.deep - b.deep);
|
|
2368
|
+
}
|
|
2369
|
+
acc[pkgId] = index;
|
|
2370
|
+
return index;
|
|
2427
2371
|
};
|
|
2428
|
-
var packageAgnosticResolveCanonical = (resolver, url,
|
|
2372
|
+
var packageAgnosticResolveCanonical = (resolver, url, _logger) => {
|
|
2429
2373
|
const options = Object.values(resolver).flatMap((pkg) => pkg.canonicalResolution[url]);
|
|
2430
2374
|
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
2375
|
return options[0]?.resource;
|
|
2436
2376
|
};
|
|
2437
|
-
var registerFromManager = async (manager, { logger, fallbackPackageForNameResolution }) => {
|
|
2438
|
-
const packages = await manager.packages();
|
|
2377
|
+
var registerFromManager = async (manager, { logger, fallbackPackageForNameResolution, focusedPackages }) => {
|
|
2378
|
+
const packages = focusedPackages ?? await manager.packages();
|
|
2439
2379
|
const resolver = {};
|
|
2440
2380
|
for (const pkg of packages) {
|
|
2441
|
-
|
|
2381
|
+
await mkPackageAwareResolver(manager, pkg, 0, resolver, logger);
|
|
2442
2382
|
}
|
|
2443
2383
|
for (const { pkg, canonicalResolution } of Object.values(resolver)) {
|
|
2444
2384
|
const pkgId = packageMetaToFhir(pkg);
|
|
@@ -2446,19 +2386,21 @@ var registerFromManager = async (manager, { logger, fallbackPackageForNameResolu
|
|
|
2446
2386
|
let counter = 0;
|
|
2447
2387
|
logger?.info(`FHIR Schema conversion for '${packageMetaToFhir(pkg)}' begins...`);
|
|
2448
2388
|
for (const [_url, options] of Object.entries(canonicalResolution)) {
|
|
2449
|
-
const
|
|
2450
|
-
if (!
|
|
2389
|
+
const resolition = options[0];
|
|
2390
|
+
if (!resolition) throw new Error(`Resource not found`);
|
|
2391
|
+
const resource = resolition.resource;
|
|
2392
|
+
const resourcePkg = resolition.pkg;
|
|
2451
2393
|
if (isStructureDefinition(resource)) {
|
|
2452
|
-
const rfs = enrichFHIRSchema(fhirschema.translate(resource),
|
|
2394
|
+
const rfs = enrichFHIRSchema(fhirschema.translate(resource), resourcePkg);
|
|
2453
2395
|
counter++;
|
|
2454
2396
|
resolver[pkgId].fhirSchemas[rfs.url] = rfs;
|
|
2455
2397
|
}
|
|
2456
2398
|
if (isValueSet(resource)) {
|
|
2457
|
-
const rvs = enrichValueSet(resource,
|
|
2399
|
+
const rvs = enrichValueSet(resource, resourcePkg);
|
|
2458
2400
|
resolver[pkgId].valueSets[rvs.url] = rvs;
|
|
2459
2401
|
}
|
|
2460
2402
|
}
|
|
2461
|
-
logger?.
|
|
2403
|
+
logger?.info(`FHIR Schema conversion for '${packageMetaToFhir(pkg)}' completed: ${counter} successful`);
|
|
2462
2404
|
}
|
|
2463
2405
|
const resolveFs = (pkg, canonicalUrl) => {
|
|
2464
2406
|
return resolver[packageMetaToFhir(pkg)]?.fhirSchemas[canonicalUrl] || fallbackPackageForNameResolution && resolver[packageMetaToFhir(fallbackPackageForNameResolution)]?.fhirSchemas[canonicalUrl];
|
|
@@ -2466,14 +2408,19 @@ var registerFromManager = async (manager, { logger, fallbackPackageForNameResolu
|
|
|
2466
2408
|
const resolveVs = (pkg, canonicalUrl) => {
|
|
2467
2409
|
return resolver[packageMetaToFhir(pkg)]?.valueSets[canonicalUrl] || fallbackPackageForNameResolution && resolver[packageMetaToFhir(fallbackPackageForNameResolution)]?.valueSets[canonicalUrl];
|
|
2468
2410
|
};
|
|
2469
|
-
const ensureSpecializationCanonicalUrl = (
|
|
2411
|
+
const ensureSpecializationCanonicalUrl = (name) => name.match(/^[a-zA-Z0-9]+$/) && `http://hl7.org/fhir/StructureDefinition/${name}` || name;
|
|
2470
2412
|
const resolveFsGenealogy = (pkg, canonicalUrl) => {
|
|
2471
2413
|
let fs4 = resolveFs(pkg, canonicalUrl);
|
|
2472
|
-
if (fs4 === void 0) throw new Error(`Failed to resolve FHIR Schema
|
|
2414
|
+
if (fs4 === void 0) throw new Error(`Failed to resolve FHIR Schema: '${canonicalUrl}'`);
|
|
2473
2415
|
const genealogy = [fs4];
|
|
2474
2416
|
while (fs4?.base) {
|
|
2475
|
-
|
|
2476
|
-
|
|
2417
|
+
const pkg2 = fs4.package_meta;
|
|
2418
|
+
const baseUrl = ensureSpecializationCanonicalUrl(fs4.base);
|
|
2419
|
+
fs4 = resolveFs(pkg2, baseUrl);
|
|
2420
|
+
if (fs4 === void 0)
|
|
2421
|
+
throw new Error(
|
|
2422
|
+
`Failed to resolve FHIR Schema base for '${canonicalUrl}'. Problem: '${baseUrl}' from '${packageMetaToFhir(pkg2)}'`
|
|
2423
|
+
);
|
|
2477
2424
|
genealogy.push(fs4);
|
|
2478
2425
|
}
|
|
2479
2426
|
return genealogy;
|
|
@@ -2501,11 +2448,10 @@ var registerFromManager = async (manager, { logger, fallbackPackageForNameResolu
|
|
|
2501
2448
|
};
|
|
2502
2449
|
return {
|
|
2503
2450
|
...manager,
|
|
2504
|
-
|
|
2451
|
+
testAppendFs(fs4) {
|
|
2505
2452
|
const rfs = enrichFHIRSchema(fs4);
|
|
2506
2453
|
const pkgId = packageMetaToFhir(rfs.package_meta);
|
|
2507
2454
|
if (!resolver[pkgId]) resolver[pkgId] = mkEmptyPkgIndex(rfs.package_meta);
|
|
2508
|
-
resolver[pkgId].nameResolution[rfs.name] = rfs.url;
|
|
2509
2455
|
resolver[pkgId].fhirSchemas[rfs.url] = rfs;
|
|
2510
2456
|
},
|
|
2511
2457
|
resolveFs,
|
|
@@ -2513,16 +2459,17 @@ var registerFromManager = async (manager, { logger, fallbackPackageForNameResolu
|
|
|
2513
2459
|
resolveFsSpecializations,
|
|
2514
2460
|
ensureSpecializationCanonicalUrl,
|
|
2515
2461
|
resolveSd: (_pkg, canonicalUrl) => {
|
|
2516
|
-
const res = packageAgnosticResolveCanonical(resolver, canonicalUrl
|
|
2462
|
+
const res = packageAgnosticResolveCanonical(resolver, canonicalUrl);
|
|
2517
2463
|
if (isStructureDefinition(res)) return res;
|
|
2518
2464
|
return void 0;
|
|
2519
2465
|
},
|
|
2520
2466
|
allFs: () => Object.values(resolver).flatMap((pkgIndex) => Object.values(pkgIndex.fhirSchemas)),
|
|
2521
2467
|
allVs: () => Object.values(resolver).flatMap((pkgIndex) => Object.values(pkgIndex.valueSets)),
|
|
2522
2468
|
resolveVs,
|
|
2523
|
-
resolveAny: (canonicalUrl) => packageAgnosticResolveCanonical(resolver, canonicalUrl
|
|
2469
|
+
resolveAny: (canonicalUrl) => packageAgnosticResolveCanonical(resolver, canonicalUrl),
|
|
2524
2470
|
resolveElementSnapshot,
|
|
2525
|
-
getAllElementKeys
|
|
2471
|
+
getAllElementKeys,
|
|
2472
|
+
resolver
|
|
2526
2473
|
};
|
|
2527
2474
|
};
|
|
2528
2475
|
var resolveFsElementGenealogy = (genealogy, path) => {
|
|
@@ -2567,10 +2514,10 @@ var TypeSchemaGenerator = class {
|
|
|
2567
2514
|
}
|
|
2568
2515
|
}
|
|
2569
2516
|
async registerFromPackageMetas(packageMetas) {
|
|
2570
|
-
const packageNames = packageMetas.map(
|
|
2517
|
+
const packageNames = packageMetas.map(packageMetaToFhir);
|
|
2571
2518
|
this.logger?.step(`Loading FHIR packages: ${packageNames.join(", ")}`);
|
|
2572
2519
|
await this.manager.init();
|
|
2573
|
-
return registerFromManager(this.manager, {});
|
|
2520
|
+
return registerFromManager(this.manager, { focusedPackages: packageMetas });
|
|
2574
2521
|
}
|
|
2575
2522
|
generateFhirSchemas(structureDefinitions) {
|
|
2576
2523
|
this.logger?.progress(`Converting ${structureDefinitions.length} StructureDefinitions to FHIRSchemas`);
|
|
@@ -3013,9 +2960,29 @@ var TypeSchemaParser = class {
|
|
|
3013
2960
|
};
|
|
3014
2961
|
|
|
3015
2962
|
// src/typeschema/index.ts
|
|
2963
|
+
var codeableReferenceInR4 = "Use CodeableReference which is not provided by FHIR R4.";
|
|
2964
|
+
var availabilityInR4 = "Use Availability which is not provided by FHIR R4.";
|
|
2965
|
+
var skipMe = {
|
|
2966
|
+
"hl7.fhir.uv.extensions.r4#1.0.0": {
|
|
2967
|
+
"http://hl7.org/fhir/StructureDefinition/extended-contact-availability": availabilityInR4,
|
|
2968
|
+
"http://hl7.org/fhir/StructureDefinition/immunization-procedure": codeableReferenceInR4,
|
|
2969
|
+
"http://hl7.org/fhir/StructureDefinition/specimen-additive": codeableReferenceInR4,
|
|
2970
|
+
"http://hl7.org/fhir/StructureDefinition/workflow-barrier": codeableReferenceInR4,
|
|
2971
|
+
"http://hl7.org/fhir/StructureDefinition/workflow-protectiveFactor": codeableReferenceInR4,
|
|
2972
|
+
"http://hl7.org/fhir/StructureDefinition/workflow-reason": codeableReferenceInR4
|
|
2973
|
+
},
|
|
2974
|
+
"hl7.fhir.r5.core#5.0.0": {
|
|
2975
|
+
"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."
|
|
2976
|
+
}
|
|
2977
|
+
};
|
|
3016
2978
|
var generateTypeSchemas = async (register, logger) => {
|
|
3017
2979
|
const fhirSchemas = [];
|
|
3018
2980
|
for (const fhirSchema of register.allFs()) {
|
|
2981
|
+
const pkgId = packageMetaToFhir(fhirSchema.package_meta);
|
|
2982
|
+
if (skipMe[pkgId]?.[fhirSchema.url]) {
|
|
2983
|
+
logger?.dry_warn(`Skip ${fhirSchema.url} from ${pkgId}. Reason: ${skipMe[pkgId]?.[fhirSchema.url]}`);
|
|
2984
|
+
continue;
|
|
2985
|
+
}
|
|
3019
2986
|
fhirSchemas.push(...await transformFhirSchema(register, fhirSchema, logger));
|
|
3020
2987
|
}
|
|
3021
2988
|
for (const vsSchema of register.allVs()) {
|
|
@@ -3050,23 +3017,9 @@ var uppercaseFirstLetter = (str) => {
|
|
|
3050
3017
|
var uppercaseFirstLetterOfEach = (strings) => {
|
|
3051
3018
|
return strings.map((str) => uppercaseFirstLetter(str));
|
|
3052
3019
|
};
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
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
|
-
}
|
|
3020
|
+
var typeSchemaInfo = (schema) => {
|
|
3021
|
+
return `<${schema.identifier.url}> from ${schema.identifier.package}#${schema.identifier.version}`;
|
|
3022
|
+
};
|
|
3070
3023
|
var FileSystemWriter = class {
|
|
3071
3024
|
opts;
|
|
3072
3025
|
currentDir;
|
|
@@ -3080,12 +3033,14 @@ var FileSystemWriter = class {
|
|
|
3080
3033
|
return this.opts.logger;
|
|
3081
3034
|
}
|
|
3082
3035
|
cd(path, gen) {
|
|
3036
|
+
const prev = this.currentDir;
|
|
3083
3037
|
this.currentDir = path.startsWith("/") ? Path4.join(this.opts.outputDir, path) : Path4.join(this.currentDir, path);
|
|
3084
3038
|
if (!fs.existsSync(this.currentDir)) {
|
|
3085
3039
|
fs.mkdirSync(this.currentDir, { recursive: true });
|
|
3086
3040
|
}
|
|
3087
3041
|
this.logger()?.debug(`cd '${this.currentDir}'`);
|
|
3088
3042
|
gen();
|
|
3043
|
+
this.currentDir = prev;
|
|
3089
3044
|
}
|
|
3090
3045
|
cat(fn, gen) {
|
|
3091
3046
|
if (this.currentFileDescriptor) throw new Error("Can't open file in file");
|
|
@@ -3098,6 +3053,7 @@ var FileSystemWriter = class {
|
|
|
3098
3053
|
gen();
|
|
3099
3054
|
} finally {
|
|
3100
3055
|
if (this.currentFileDescriptor) {
|
|
3056
|
+
fs.fsyncSync(this.currentFileDescriptor);
|
|
3101
3057
|
fs.closeSync(this.currentFileDescriptor);
|
|
3102
3058
|
}
|
|
3103
3059
|
this.currentFileDescriptor = void 0;
|
|
@@ -3512,19 +3468,21 @@ var CSharp = class extends Writer {
|
|
|
3512
3468
|
fs__default.copyFileSync(sourceFile, destFile);
|
|
3513
3469
|
}
|
|
3514
3470
|
};
|
|
3515
|
-
|
|
3516
|
-
// src/typeschema/utils.ts
|
|
3517
3471
|
var groupByPackages = (typeSchemas) => {
|
|
3518
3472
|
const grouped = {};
|
|
3519
3473
|
for (const ts of typeSchemas) {
|
|
3520
|
-
const
|
|
3521
|
-
if (!grouped[
|
|
3522
|
-
|
|
3523
|
-
}
|
|
3524
|
-
grouped[packageName].push(ts);
|
|
3474
|
+
const pkgName = ts.identifier.package;
|
|
3475
|
+
if (!grouped[pkgName]) grouped[pkgName] = [];
|
|
3476
|
+
grouped[pkgName].push(ts);
|
|
3525
3477
|
}
|
|
3526
|
-
for (const [
|
|
3527
|
-
|
|
3478
|
+
for (const [packageName, typeSchemas2] of Object.entries(grouped)) {
|
|
3479
|
+
const dict = {};
|
|
3480
|
+
for (const ts of typeSchemas2) {
|
|
3481
|
+
dict[JSON.stringify(ts.identifier)] = ts;
|
|
3482
|
+
}
|
|
3483
|
+
const tmp = Object.values(dict);
|
|
3484
|
+
tmp.sort((a, b) => a.identifier.name.localeCompare(b.identifier.name));
|
|
3485
|
+
grouped[packageName] = tmp;
|
|
3528
3486
|
}
|
|
3529
3487
|
return grouped;
|
|
3530
3488
|
};
|
|
@@ -3564,7 +3522,8 @@ var mkTypeSchemaIndex = (schemas, logger) => {
|
|
|
3564
3522
|
if (index[url][schema.identifier.package] && pkg !== "shared") {
|
|
3565
3523
|
const r1 = JSON.stringify(schema.identifier, void 0, 2);
|
|
3566
3524
|
const r2 = JSON.stringify(index[url][pkg]?.identifier, void 0, 2);
|
|
3567
|
-
throw new Error(`Duplicate schema: ${r1} and ${r2}`);
|
|
3525
|
+
if (r1 !== r2) throw new Error(`Duplicate schema: ${r1} and ${r2}`);
|
|
3526
|
+
return;
|
|
3568
3527
|
}
|
|
3569
3528
|
index[url][pkg] = schema;
|
|
3570
3529
|
};
|
|
@@ -3622,7 +3581,10 @@ var mkTypeSchemaIndex = (schemas, logger) => {
|
|
|
3622
3581
|
if (!schema2.fields) continue;
|
|
3623
3582
|
for (const [fieldName, fieldConstraints] of Object.entries(schema2.fields)) {
|
|
3624
3583
|
if (mergedFields[fieldName]) {
|
|
3625
|
-
mergedFields[fieldName] = {
|
|
3584
|
+
mergedFields[fieldName] = {
|
|
3585
|
+
...mergedFields[fieldName],
|
|
3586
|
+
...fieldConstraints
|
|
3587
|
+
};
|
|
3626
3588
|
} else {
|
|
3627
3589
|
mergedFields[fieldName] = { ...fieldConstraints };
|
|
3628
3590
|
}
|
|
@@ -3647,6 +3609,26 @@ var mkTypeSchemaIndex = (schemas, logger) => {
|
|
|
3647
3609
|
return schema.fields?.meta !== void 0;
|
|
3648
3610
|
});
|
|
3649
3611
|
};
|
|
3612
|
+
const exportTree = async (filename) => {
|
|
3613
|
+
const tree = {};
|
|
3614
|
+
for (const [pkgId, shemas] of Object.entries(groupByPackages(schemas))) {
|
|
3615
|
+
tree[pkgId] = { complexTypes: {}, resources: {}, profiles: {} };
|
|
3616
|
+
for (const schema of shemas) {
|
|
3617
|
+
schema.identifier;
|
|
3618
|
+
if (isResourceTypeSchema(schema)) {
|
|
3619
|
+
tree[pkgId].resources[schema.identifier.url] = {};
|
|
3620
|
+
}
|
|
3621
|
+
if (isProfileTypeSchema(schema)) {
|
|
3622
|
+
tree[pkgId].profiles[schema.identifier.url] = {};
|
|
3623
|
+
}
|
|
3624
|
+
if (isComplexTypeTypeSchema(schema)) {
|
|
3625
|
+
tree[pkgId].complexTypes[schema.identifier.url] = {};
|
|
3626
|
+
}
|
|
3627
|
+
}
|
|
3628
|
+
}
|
|
3629
|
+
const raw = filename.endsWith(".yaml") ? YAML.stringify(tree) : JSON.stringify(tree, void 0, 2);
|
|
3630
|
+
await afs3.writeFile(filename, raw);
|
|
3631
|
+
};
|
|
3650
3632
|
return {
|
|
3651
3633
|
_schemaIndex: index,
|
|
3652
3634
|
_relations: relations,
|
|
@@ -3661,7 +3643,8 @@ var mkTypeSchemaIndex = (schemas, logger) => {
|
|
|
3661
3643
|
findLastSpecialization,
|
|
3662
3644
|
findLastSpecializationByIdentifier,
|
|
3663
3645
|
flatProfile,
|
|
3664
|
-
isWithMetaField
|
|
3646
|
+
isWithMetaField,
|
|
3647
|
+
exportTree
|
|
3665
3648
|
};
|
|
3666
3649
|
};
|
|
3667
3650
|
|
|
@@ -5730,15 +5713,8 @@ var tsModuleFileName = (id) => {
|
|
|
5730
5713
|
};
|
|
5731
5714
|
var canonicalToName2 = (canonical, dropFragment = true) => {
|
|
5732
5715
|
if (!canonical) return void 0;
|
|
5733
|
-
|
|
5734
|
-
if (!localName) return void 0;
|
|
5735
|
-
if (dropFragment && localName.includes("#")) {
|
|
5736
|
-
localName = localName.split("#")[0];
|
|
5737
|
-
}
|
|
5716
|
+
const localName = extractNameFromCanonical(canonical, dropFragment);
|
|
5738
5717
|
if (!localName) return void 0;
|
|
5739
|
-
if (/^\d/.test(localName)) {
|
|
5740
|
-
localName = `number_${localName}`;
|
|
5741
|
-
}
|
|
5742
5718
|
return normalizeTsName(localName);
|
|
5743
5719
|
};
|
|
5744
5720
|
var tsResourceName = (id) => {
|
|
@@ -5794,12 +5770,14 @@ var TypeScript = class extends Writer {
|
|
|
5794
5770
|
if (["complex-type", "resource", "logical"].includes(dep.kind)) {
|
|
5795
5771
|
imports.push({
|
|
5796
5772
|
tsPackage: `../${kebabCase(dep.package)}/${pascalCase(dep.name)}`,
|
|
5797
|
-
name: uppercaseFirstLetter(dep.name)
|
|
5773
|
+
name: uppercaseFirstLetter(dep.name),
|
|
5774
|
+
dep
|
|
5798
5775
|
});
|
|
5799
5776
|
} else if (isNestedIdentifier(dep)) {
|
|
5800
5777
|
imports.push({
|
|
5801
5778
|
tsPackage: `../${kebabCase(dep.package)}/${pascalCase(canonicalToName2(dep.url) ?? "")}`,
|
|
5802
|
-
name: tsResourceName(dep)
|
|
5779
|
+
name: tsResourceName(dep),
|
|
5780
|
+
dep
|
|
5803
5781
|
});
|
|
5804
5782
|
} else {
|
|
5805
5783
|
skipped.push(dep);
|
|
@@ -5807,6 +5785,7 @@ var TypeScript = class extends Writer {
|
|
|
5807
5785
|
}
|
|
5808
5786
|
imports.sort((a, b) => a.name.localeCompare(b.name));
|
|
5809
5787
|
for (const dep of imports) {
|
|
5788
|
+
this.debugComment(dep.dep);
|
|
5810
5789
|
this.tsImportType(dep.tsPackage, dep.name);
|
|
5811
5790
|
}
|
|
5812
5791
|
for (const dep of skipped) {
|
|
@@ -5849,7 +5828,9 @@ var TypeScript = class extends Writer {
|
|
|
5849
5828
|
if (isResourceTypeSchema(schema)) {
|
|
5850
5829
|
const possibleResourceTypes = [schema.identifier];
|
|
5851
5830
|
possibleResourceTypes.push(...tsIndex.resourceChildren(schema.identifier));
|
|
5852
|
-
this.lineSM(
|
|
5831
|
+
this.lineSM(
|
|
5832
|
+
`resourceType: ${possibleResourceTypes.sort((a, b) => a.name.localeCompare(b.name)).map((e) => `"${e.name}"`).join(" | ")}`
|
|
5833
|
+
);
|
|
5853
5834
|
this.line();
|
|
5854
5835
|
}
|
|
5855
5836
|
if (!schema.fields) return;
|
|
@@ -5891,6 +5872,7 @@ var TypeScript = class extends Writer {
|
|
|
5891
5872
|
}
|
|
5892
5873
|
}
|
|
5893
5874
|
generateProfileType(tsIndex, flatProfile) {
|
|
5875
|
+
this.debugComment("flatProfile", flatProfile);
|
|
5894
5876
|
const tsName = tsResourceName(flatProfile.identifier);
|
|
5895
5877
|
this.debugComment("identifier", flatProfile.identifier);
|
|
5896
5878
|
this.debugComment("base", flatProfile.base);
|
|
@@ -5928,6 +5910,8 @@ var TypeScript = class extends Writer {
|
|
|
5928
5910
|
tsType = tsResourceName(field.type);
|
|
5929
5911
|
} else if (isPrimitiveIdentifier(field.type)) {
|
|
5930
5912
|
tsType = resolvePrimitiveType(field.type.name);
|
|
5913
|
+
} else if (field.type === void 0) {
|
|
5914
|
+
throw new Error(`Undefined type for '${fieldName}' field at ${typeSchemaInfo(flatProfile)}`);
|
|
5931
5915
|
} else {
|
|
5932
5916
|
tsType = field.type.name;
|
|
5933
5917
|
}
|
|
@@ -6095,6 +6079,9 @@ var writerToGenerator = (writerGen) => {
|
|
|
6095
6079
|
return {
|
|
6096
6080
|
generate: async (schemas) => {
|
|
6097
6081
|
const tsIndex = mkTypeSchemaIndex(schemas);
|
|
6082
|
+
if (writerGen.opts.writeTypeTree) {
|
|
6083
|
+
await tsIndex.exportTree(writerGen.opts.writeTypeTree);
|
|
6084
|
+
}
|
|
6098
6085
|
writerGen.generate(tsIndex);
|
|
6099
6086
|
return getGeneratedFiles();
|
|
6100
6087
|
},
|
|
@@ -6102,8 +6089,12 @@ var writerToGenerator = (writerGen) => {
|
|
|
6102
6089
|
build: async (_schemas) => getGeneratedFiles()
|
|
6103
6090
|
};
|
|
6104
6091
|
};
|
|
6105
|
-
var normalizeFileName = (str) =>
|
|
6106
|
-
|
|
6092
|
+
var normalizeFileName = (str) => {
|
|
6093
|
+
const res = str.replace(/[^a-zA-Z0-9\-_.@#()]/g, "");
|
|
6094
|
+
if (res.length === 0) return "unknown";
|
|
6095
|
+
return res;
|
|
6096
|
+
};
|
|
6097
|
+
var APIBuilder = class {
|
|
6107
6098
|
schemas = [];
|
|
6108
6099
|
options;
|
|
6109
6100
|
generators = /* @__PURE__ */ new Map();
|
|
@@ -6124,7 +6115,8 @@ var APIBuilder = class _APIBuilder {
|
|
|
6124
6115
|
typeSchemaConfig: options.typeSchemaConfig,
|
|
6125
6116
|
manager: options.manager || null,
|
|
6126
6117
|
throwException: options.throwException || false,
|
|
6127
|
-
typeSchemaOutputDir: options.typeSchemaOutputDir
|
|
6118
|
+
typeSchemaOutputDir: options.typeSchemaOutputDir,
|
|
6119
|
+
exportTypeTree: options.exportTypeTree
|
|
6128
6120
|
};
|
|
6129
6121
|
this.typeSchemaConfig = options.typeSchemaConfig;
|
|
6130
6122
|
this.logger = options.logger || createLogger({
|
|
@@ -6186,7 +6178,8 @@ var APIBuilder = class _APIBuilder {
|
|
|
6186
6178
|
outputDir: Path4.join(this.options.outputDir, "/types"),
|
|
6187
6179
|
tabSize: 4,
|
|
6188
6180
|
withDebugComment: false,
|
|
6189
|
-
commentLinePrefix: "//"
|
|
6181
|
+
commentLinePrefix: "//",
|
|
6182
|
+
exportTypeTree: this.options.exportTypeTree
|
|
6190
6183
|
};
|
|
6191
6184
|
const effectiveOpts = { logger: this.logger, ...writerOpts, ...opts };
|
|
6192
6185
|
const generator = writerToGenerator(new TypeScript(effectiveOpts));
|
|
@@ -6245,63 +6238,70 @@ var APIBuilder = class _APIBuilder {
|
|
|
6245
6238
|
this.options.cleanOutput = enabled;
|
|
6246
6239
|
return this;
|
|
6247
6240
|
}
|
|
6241
|
+
writeTypeTree(filename) {
|
|
6242
|
+
this.options.exportTypeTree = filename;
|
|
6243
|
+
return this;
|
|
6244
|
+
}
|
|
6248
6245
|
writeTypeSchemas(target) {
|
|
6249
6246
|
this.options.typeSchemaOutputDir = target;
|
|
6250
6247
|
return this;
|
|
6251
6248
|
}
|
|
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
6249
|
async writeTypeSchemasToSeparateFiles(typeSchemas, outputDir) {
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
const
|
|
6263
|
-
this.logger.info(`Writing TypeSchema files to ${outputDir}...`);
|
|
6250
|
+
await afs3.mkdir(outputDir, { recursive: true });
|
|
6251
|
+
this.logger.info(`Writing TypeSchema files to ${outputDir}/...`);
|
|
6252
|
+
const files = {};
|
|
6264
6253
|
for (const ts of typeSchemas) {
|
|
6265
|
-
const
|
|
6266
|
-
const
|
|
6254
|
+
const pkg = { name: ts.identifier.package, version: ts.identifier.version };
|
|
6255
|
+
const pkgPath = normalizeFileName(packageMetaToFhir(pkg));
|
|
6256
|
+
const name = normalizeFileName(`${ts.identifier.name}(${extractNameFromCanonical(ts.identifier.url)})`);
|
|
6267
6257
|
const json = JSON.stringify(ts, null, 2);
|
|
6268
|
-
const baseName = Path4.join(outputDir,
|
|
6269
|
-
|
|
6270
|
-
if (
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6258
|
+
const baseName = Path4.join(outputDir, pkgPath, name);
|
|
6259
|
+
if (!files[baseName]) files[baseName] = [];
|
|
6260
|
+
if (!files[baseName]?.some((e) => e === json)) {
|
|
6261
|
+
files[baseName].push(json);
|
|
6262
|
+
}
|
|
6263
|
+
}
|
|
6264
|
+
for (const [baseName, jsons] of Object.entries(files)) {
|
|
6265
|
+
await Promise.all(
|
|
6266
|
+
jsons.map(async (json, index) => {
|
|
6267
|
+
let fullName;
|
|
6268
|
+
if (index === 0) {
|
|
6269
|
+
fullName = `${baseName}.typeschema.json`;
|
|
6270
|
+
} else {
|
|
6271
|
+
fullName = `${baseName}-${index}.typeschema.json`;
|
|
6272
|
+
}
|
|
6273
|
+
await afs3.mkdir(Path4.dirname(fullName), { recursive: true });
|
|
6274
|
+
await afs3.writeFile(fullName, json);
|
|
6275
|
+
})
|
|
6276
|
+
);
|
|
6280
6277
|
}
|
|
6281
6278
|
}
|
|
6282
6279
|
async writeTypeSchemasToSingleFile(typeSchemas, outputFile) {
|
|
6280
|
+
this.logger.info(`Writing TypeSchema files to: ${outputFile}`);
|
|
6283
6281
|
if (this.options.cleanOutput && fs.existsSync(outputFile)) fs.rmSync(outputFile);
|
|
6284
|
-
await
|
|
6282
|
+
await afs3.mkdir(Path4.dirname(outputFile), { recursive: true });
|
|
6285
6283
|
this.logger.info(`Writing TypeSchemas to one file ${outputFile}...`);
|
|
6286
6284
|
for (const ts of typeSchemas) {
|
|
6287
6285
|
const json = JSON.stringify(ts, null, 2);
|
|
6288
|
-
await
|
|
6286
|
+
await afs3.appendFile(outputFile, `${json}
|
|
6287
|
+
`);
|
|
6289
6288
|
}
|
|
6290
6289
|
}
|
|
6291
6290
|
async tryWriteTypeSchema(typeSchemas) {
|
|
6292
6291
|
if (!this.options.typeSchemaOutputDir) return;
|
|
6293
6292
|
try {
|
|
6294
|
-
this.
|
|
6295
|
-
if (Path4.extname(this.options.typeSchemaOutputDir) === ".ndjson")
|
|
6293
|
+
if (Path4.extname(this.options.typeSchemaOutputDir) === ".ndjson") {
|
|
6296
6294
|
await this.writeTypeSchemasToSingleFile(typeSchemas, this.options.typeSchemaOutputDir);
|
|
6297
|
-
else
|
|
6298
|
-
|
|
6295
|
+
} else {
|
|
6296
|
+
await this.writeTypeSchemasToSeparateFiles(typeSchemas, this.options.typeSchemaOutputDir);
|
|
6297
|
+
}
|
|
6298
|
+
this.logger.info(`Writing TypeSchema - DONE`);
|
|
6299
6299
|
} catch (error) {
|
|
6300
|
-
if (this.options.throwException) throw error;
|
|
6301
6300
|
this.logger.error(
|
|
6302
6301
|
"Failed to write TypeSchema output",
|
|
6303
6302
|
error instanceof Error ? error : new Error(String(error))
|
|
6304
6303
|
);
|
|
6304
|
+
if (this.options.throwException) throw error;
|
|
6305
6305
|
}
|
|
6306
6306
|
}
|
|
6307
6307
|
async generate() {
|
|
@@ -6316,10 +6316,18 @@ var APIBuilder = class _APIBuilder {
|
|
|
6316
6316
|
};
|
|
6317
6317
|
this.logger.debug(`Starting generation with ${this.generators.size} generators`);
|
|
6318
6318
|
if (this.options.cleanOutput) {
|
|
6319
|
-
this.logger.info(`Cleaning
|
|
6319
|
+
this.logger.info(`Cleaning outputs...`);
|
|
6320
6320
|
try {
|
|
6321
|
+
this.logger.info(`Clean ${this.options.outputDir}`);
|
|
6321
6322
|
fs.rmSync(this.options.outputDir, { recursive: true, force: true });
|
|
6322
|
-
|
|
6323
|
+
if (this.options.typeSchemaOutputDir) {
|
|
6324
|
+
this.logger.info(`Clean ${this.options.typeSchemaOutputDir}`);
|
|
6325
|
+
fs.rmSync(this.options.typeSchemaOutputDir, { recursive: true, force: true });
|
|
6326
|
+
}
|
|
6327
|
+
if (this.options.exportTypeTree) {
|
|
6328
|
+
this.logger.info(`Clean ${this.options.exportTypeTree}`);
|
|
6329
|
+
fs.rmSync(this.options.exportTypeTree, { recursive: true, force: true });
|
|
6330
|
+
}
|
|
6323
6331
|
} catch (error) {
|
|
6324
6332
|
this.logger.warn(
|
|
6325
6333
|
`Error cleaning output directory: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -6333,7 +6341,10 @@ var APIBuilder = class _APIBuilder {
|
|
|
6333
6341
|
workingDir: "tmp/fhir"
|
|
6334
6342
|
});
|
|
6335
6343
|
await manager.init();
|
|
6336
|
-
const register = await registerFromManager(manager, {
|
|
6344
|
+
const register = await registerFromManager(manager, {
|
|
6345
|
+
logger: this.logger,
|
|
6346
|
+
focusedPackages: this.packages.map(npmToPackageMeta)
|
|
6347
|
+
});
|
|
6337
6348
|
const typeSchemas = await generateTypeSchemas(register, this.logger);
|
|
6338
6349
|
await this.tryWriteTypeSchema(typeSchemas);
|
|
6339
6350
|
this.logger.debug(`Executing ${this.generators.size} generators`);
|