@atomic-ehr/codegen 0.0.6 → 0.0.7-canary.20260224101452.ccac84d
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 +7 -7
- package/dist/index.d.ts +13 -7
- package/dist/index.js +910 -689
- package/dist/index.js.map +1 -1
- package/package.json +10 -7
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import Path5__default from 'path';
|
|
|
7
7
|
import { CanonicalManager } from '@atomic-ehr/fhir-canonical-manager';
|
|
8
8
|
import { fileURLToPath } from 'url';
|
|
9
9
|
import * as fsPromises from 'fs/promises';
|
|
10
|
+
import { createHash } from 'crypto';
|
|
10
11
|
import * as YAML from 'yaml';
|
|
11
12
|
import YAML__default from 'yaml';
|
|
12
13
|
import * as fhirschema from '@atomic-ehr/fhirschema';
|
|
@@ -106,7 +107,7 @@ var CodegenLogger = class _CodegenLogger {
|
|
|
106
107
|
warn(message) {
|
|
107
108
|
this.tryWriteToConsole(2 /* WARN */, this.formatMessage("!", message, pc.yellow));
|
|
108
109
|
}
|
|
109
|
-
|
|
110
|
+
dryWarn(message) {
|
|
110
111
|
if (!this.dryWarnSet.has(message)) {
|
|
111
112
|
this.warn(message);
|
|
112
113
|
this.dryWarnSet.add(message);
|
|
@@ -258,6 +259,10 @@ var FileSystemWriter = class {
|
|
|
258
259
|
if (this.currentFile) throw new Error("Can't open file when another file is open");
|
|
259
260
|
if (fn.includes("/")) throw new Error(`Change file path separatly: ${fn}`);
|
|
260
261
|
const relPath = Path5.normalize(`${this.currentDir}/${fn}`);
|
|
262
|
+
if (this.writtenFilesBuffer[relPath]) {
|
|
263
|
+
this.logger()?.warn(`File will be rewritten '${relPath}'`);
|
|
264
|
+
this.logger()?.debug(`File content: ${this.writtenFilesBuffer[relPath].tokens.join("")}`);
|
|
265
|
+
}
|
|
261
266
|
try {
|
|
262
267
|
const descriptor = this.onDiskOpenFile(relPath);
|
|
263
268
|
this.logger()?.debug(`cat > '${relPath}'`);
|
|
@@ -402,8 +407,6 @@ var Writer = class extends FileSystemWriter {
|
|
|
402
407
|
this.line(`]${endTokens?.filter(Boolean).join(" ") ?? ""}`);
|
|
403
408
|
}
|
|
404
409
|
};
|
|
405
|
-
|
|
406
|
-
// src/typeschema/types.ts
|
|
407
410
|
var extractNameFromCanonical = (canonical, dropFragment = true) => {
|
|
408
411
|
let localName = canonical.split("/").pop();
|
|
409
412
|
if (!localName) return void 0;
|
|
@@ -424,10 +427,11 @@ var packageMeta = (schema) => {
|
|
|
424
427
|
};
|
|
425
428
|
var packageMetaToFhir = (packageMeta2) => `${packageMeta2.name}#${packageMeta2.version}`;
|
|
426
429
|
var packageMetaToNpm = (packageMeta2) => `${packageMeta2.name}@${packageMeta2.version}`;
|
|
430
|
+
var hashSchema = (schema) => {
|
|
431
|
+
const json = JSON.stringify(schema);
|
|
432
|
+
return createHash("sha256").update(json).digest("hex").slice(0, 16);
|
|
433
|
+
};
|
|
427
434
|
var enrichFHIRSchema = (schema, packageMeta2) => {
|
|
428
|
-
if (!packageMeta2) {
|
|
429
|
-
packageMeta2 = { name: "undefined", version: "undefined" };
|
|
430
|
-
}
|
|
431
435
|
return {
|
|
432
436
|
...schema,
|
|
433
437
|
package_meta: schema.package_meta || packageMeta2,
|
|
@@ -681,7 +685,7 @@ var CSharp = class extends Writer {
|
|
|
681
685
|
}
|
|
682
686
|
determineFieldType(fieldName, field, packageName) {
|
|
683
687
|
let typeName = this.getBaseTypeName(field);
|
|
684
|
-
if ("enum" in field && field.enum) {
|
|
688
|
+
if ("enum" in field && field.enum && !field.enum.isOpen) {
|
|
685
689
|
typeName = this.registerAndGetEnumType(fieldName, field, packageName);
|
|
686
690
|
}
|
|
687
691
|
typeName = prefixReservedTypeName(typeName);
|
|
@@ -704,7 +708,7 @@ var CSharp = class extends Writer {
|
|
|
704
708
|
const enumName = formatName(field.binding?.name ?? fieldName);
|
|
705
709
|
const enumTypeName = `${enumName}Enum`;
|
|
706
710
|
if (!this.enums[packageName]) this.enums[packageName] = {};
|
|
707
|
-
if (field.enum) this.enums[packageName][enumTypeName] = field.enum;
|
|
711
|
+
if (field.enum) this.enums[packageName][enumTypeName] = field.enum.values;
|
|
708
712
|
return enumTypeName;
|
|
709
713
|
}
|
|
710
714
|
includeHelperMethods() {
|
|
@@ -1480,8 +1484,8 @@ var Python = class extends Writer {
|
|
|
1480
1484
|
}
|
|
1481
1485
|
determineFieldType(field) {
|
|
1482
1486
|
let fieldType = field ? this.getBaseFieldType(field) : "";
|
|
1483
|
-
if ("enum" in field && field.enum) {
|
|
1484
|
-
const s = field.enum.map((e) => `"${e}"`).join(", ");
|
|
1487
|
+
if ("enum" in field && field.enum && !field.enum.isOpen) {
|
|
1488
|
+
const s = field.enum.values.map((e) => `"${e}"`).join(", ");
|
|
1485
1489
|
fieldType = `Literal[${s}]`;
|
|
1486
1490
|
}
|
|
1487
1491
|
if (field.array) {
|
|
@@ -1758,7 +1762,8 @@ function mkValueSetIdentifierByUrl(register, pkg, fullValueSetUrl) {
|
|
|
1758
1762
|
url: valueSetUrl
|
|
1759
1763
|
};
|
|
1760
1764
|
}
|
|
1761
|
-
function mkBindingIdentifier(fhirSchema, path,
|
|
1765
|
+
function mkBindingIdentifier(fhirSchema, path, element) {
|
|
1766
|
+
const bindingName = element.binding?.bindingName;
|
|
1762
1767
|
const pathStr = path.join(".");
|
|
1763
1768
|
const [pkg, name, url] = bindingName ? [{ name: "shared", version: "1.0.0" }, bindingName, `urn:fhir:binding:${bindingName}`] : [fhirSchema.package_meta, `${fhirSchema.name}.${pathStr}_binding`, `${fhirSchema.url}#${pathStr}_binding`];
|
|
1764
1769
|
return {
|
|
@@ -1770,6 +1775,146 @@ function mkBindingIdentifier(fhirSchema, path, bindingName) {
|
|
|
1770
1775
|
};
|
|
1771
1776
|
}
|
|
1772
1777
|
|
|
1778
|
+
// src/typeschema/core/binding.ts
|
|
1779
|
+
function extractValueSetConceptsByUrl(register, pkg, valueSetUrl, logger) {
|
|
1780
|
+
const cleanUrl = dropVersionFromUrl(valueSetUrl) || valueSetUrl;
|
|
1781
|
+
const valueSet = register.resolveVs(pkg, cleanUrl);
|
|
1782
|
+
if (!valueSet) return void 0;
|
|
1783
|
+
return extractValueSetConcepts(register, valueSet);
|
|
1784
|
+
}
|
|
1785
|
+
function extractValueSetConcepts(register, valueSet, _logger) {
|
|
1786
|
+
if (valueSet.expansion?.contains) {
|
|
1787
|
+
return valueSet.expansion.contains.filter((item) => item.code !== void 0).map((item) => {
|
|
1788
|
+
assert3(item.code);
|
|
1789
|
+
return {
|
|
1790
|
+
code: item.code,
|
|
1791
|
+
display: item.display,
|
|
1792
|
+
system: item.system
|
|
1793
|
+
};
|
|
1794
|
+
});
|
|
1795
|
+
}
|
|
1796
|
+
const concepts = [];
|
|
1797
|
+
if (valueSet.compose?.include) {
|
|
1798
|
+
for (const include of valueSet.compose.include) {
|
|
1799
|
+
if (include.concept) {
|
|
1800
|
+
for (const concept of include.concept) {
|
|
1801
|
+
concepts.push({
|
|
1802
|
+
system: include.system,
|
|
1803
|
+
code: concept.code,
|
|
1804
|
+
display: concept.display
|
|
1805
|
+
});
|
|
1806
|
+
}
|
|
1807
|
+
} else if (include.system && !include.filter) {
|
|
1808
|
+
try {
|
|
1809
|
+
const codeSystem = register.resolveAny(include.system);
|
|
1810
|
+
if (codeSystem?.concept) {
|
|
1811
|
+
const extractConcepts = (conceptList, system) => {
|
|
1812
|
+
for (const concept of conceptList) {
|
|
1813
|
+
concepts.push({
|
|
1814
|
+
system,
|
|
1815
|
+
code: concept.code,
|
|
1816
|
+
display: concept.display
|
|
1817
|
+
});
|
|
1818
|
+
if (concept.concept) {
|
|
1819
|
+
extractConcepts(concept.concept, system);
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
};
|
|
1823
|
+
extractConcepts(codeSystem.concept, include.system);
|
|
1824
|
+
}
|
|
1825
|
+
} catch {
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
return concepts.length > 0 ? concepts : void 0;
|
|
1831
|
+
}
|
|
1832
|
+
var MAX_ENUM_LENGTH = 100;
|
|
1833
|
+
var BINDABLE_TYPES = /* @__PURE__ */ new Set([
|
|
1834
|
+
"code",
|
|
1835
|
+
"Coding",
|
|
1836
|
+
"CodeableConcept",
|
|
1837
|
+
"CodeableReference",
|
|
1838
|
+
"Quantity",
|
|
1839
|
+
"string",
|
|
1840
|
+
"uri",
|
|
1841
|
+
"Duration"
|
|
1842
|
+
]);
|
|
1843
|
+
function buildEnum(register, fhirSchema, element, logger) {
|
|
1844
|
+
if (!element.binding) return void 0;
|
|
1845
|
+
const strength = element.binding.strength;
|
|
1846
|
+
const valueSetUrl = element.binding.valueSet;
|
|
1847
|
+
if (!valueSetUrl) return void 0;
|
|
1848
|
+
if (!BINDABLE_TYPES.has(element.type ?? "")) {
|
|
1849
|
+
logger?.dryWarn(`eld-11: Binding on non-bindable type '${element.type}' (valueSet: ${valueSetUrl})`);
|
|
1850
|
+
return void 0;
|
|
1851
|
+
}
|
|
1852
|
+
const shouldGenerateEnum = strength === "required" || strength === "extensible" || strength === "preferred";
|
|
1853
|
+
if (!shouldGenerateEnum) return void 0;
|
|
1854
|
+
const concepts = extractValueSetConceptsByUrl(register, fhirSchema.package_meta, valueSetUrl);
|
|
1855
|
+
if (!concepts || concepts.length === 0) return void 0;
|
|
1856
|
+
const codes = concepts.map((c) => c.code).filter((code) => code && typeof code === "string" && code.trim().length > 0);
|
|
1857
|
+
if (codes.length > MAX_ENUM_LENGTH) {
|
|
1858
|
+
logger?.dryWarn(
|
|
1859
|
+
`Value set ${valueSetUrl} has ${codes.length} which is more than ${MAX_ENUM_LENGTH} codes, which may cause issues with code generation.`
|
|
1860
|
+
);
|
|
1861
|
+
return void 0;
|
|
1862
|
+
}
|
|
1863
|
+
if (codes.length === 0) return void 0;
|
|
1864
|
+
return { isOpen: strength !== "required", values: codes };
|
|
1865
|
+
}
|
|
1866
|
+
function generateBindingSchema(register, fhirSchema, path, element, logger) {
|
|
1867
|
+
if (!element.binding?.valueSet) return void 0;
|
|
1868
|
+
const identifier = mkBindingIdentifier(fhirSchema, path, element);
|
|
1869
|
+
const valueSetIdentifier = mkValueSetIdentifierByUrl(
|
|
1870
|
+
register,
|
|
1871
|
+
fhirSchema.package_meta,
|
|
1872
|
+
element.binding.valueSet
|
|
1873
|
+
);
|
|
1874
|
+
const enumResult = buildEnum(register, fhirSchema, element, logger);
|
|
1875
|
+
return {
|
|
1876
|
+
identifier,
|
|
1877
|
+
valueset: valueSetIdentifier,
|
|
1878
|
+
strength: element.binding.strength,
|
|
1879
|
+
enum: enumResult,
|
|
1880
|
+
dependencies: [valueSetIdentifier]
|
|
1881
|
+
};
|
|
1882
|
+
}
|
|
1883
|
+
function collectBindingSchemas(register, fhirSchema, logger) {
|
|
1884
|
+
const processedPaths = /* @__PURE__ */ new Set();
|
|
1885
|
+
if (!fhirSchema.elements) return [];
|
|
1886
|
+
const bindings = [];
|
|
1887
|
+
function collectBindings(elements, parentPath) {
|
|
1888
|
+
for (const [key, element] of Object.entries(elements)) {
|
|
1889
|
+
const path = [...parentPath, key];
|
|
1890
|
+
const pathKey = path.join(".");
|
|
1891
|
+
const elemSnapshot = register.resolveElementSnapshot(fhirSchema, path);
|
|
1892
|
+
if (processedPaths.has(pathKey)) continue;
|
|
1893
|
+
processedPaths.add(pathKey);
|
|
1894
|
+
if (elemSnapshot.binding) {
|
|
1895
|
+
const binding = generateBindingSchema(register, fhirSchema, path, elemSnapshot, logger);
|
|
1896
|
+
if (binding) {
|
|
1897
|
+
bindings.push(binding);
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
if (element.elements) {
|
|
1901
|
+
collectBindings(element.elements, path);
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
collectBindings(fhirSchema.elements, []);
|
|
1906
|
+
bindings.sort((a, b) => a.identifier.name.localeCompare(b.identifier.name));
|
|
1907
|
+
const uniqueBindings = [];
|
|
1908
|
+
const seenUrls = /* @__PURE__ */ new Set();
|
|
1909
|
+
for (const binding of bindings) {
|
|
1910
|
+
if (!seenUrls.has(binding.identifier.url)) {
|
|
1911
|
+
seenUrls.add(binding.identifier.url);
|
|
1912
|
+
uniqueBindings.push(binding);
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
return uniqueBindings;
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1773
1918
|
// src/typeschema/core/nested-types.ts
|
|
1774
1919
|
function mkNestedIdentifier(register, fhirSchema, path, logger) {
|
|
1775
1920
|
const nestedTypeOrigins = {};
|
|
@@ -1972,24 +2117,24 @@ function buildFieldType(register, fhirSchema, path, element, logger) {
|
|
|
1972
2117
|
} else if (fhirSchema.derivation === "constraint") {
|
|
1973
2118
|
return void 0;
|
|
1974
2119
|
} else {
|
|
1975
|
-
logger?.
|
|
1976
|
-
`Can't recognize element type: <${fhirSchema.url}>.${path.join(".")} (pkg: '${packageMetaToFhir(fhirSchema.package_meta)}'):
|
|
2120
|
+
logger?.dryWarn(
|
|
2121
|
+
`Can't recognize element type: <${fhirSchema.url}>.${path.join(".")} (pkg: '${packageMetaToFhir(fhirSchema.package_meta)}'): missing type info`
|
|
1977
2122
|
);
|
|
1978
|
-
|
|
2123
|
+
return void 0;
|
|
1979
2124
|
}
|
|
1980
2125
|
}
|
|
1981
2126
|
var mkField = (register, fhirSchema, path, element, logger) => {
|
|
1982
2127
|
let binding;
|
|
1983
|
-
let
|
|
2128
|
+
let enumResult;
|
|
1984
2129
|
if (element.binding) {
|
|
1985
|
-
binding = mkBindingIdentifier(fhirSchema, path, element
|
|
1986
|
-
if (
|
|
1987
|
-
|
|
2130
|
+
binding = mkBindingIdentifier(fhirSchema, path, element);
|
|
2131
|
+
if (BINDABLE_TYPES.has(element.type ?? "")) {
|
|
2132
|
+
enumResult = buildEnum(register, fhirSchema, element, logger);
|
|
1988
2133
|
}
|
|
1989
2134
|
}
|
|
1990
2135
|
const fieldType = buildFieldType(register, fhirSchema, path, element, logger);
|
|
1991
2136
|
if (!fieldType)
|
|
1992
|
-
logger?.
|
|
2137
|
+
logger?.dryWarn(`Field type not found for '${fhirSchema.url}#${path.join(".")}' (${fhirSchema.derivation})`);
|
|
1993
2138
|
return {
|
|
1994
2139
|
type: fieldType,
|
|
1995
2140
|
required: isRequired(register, fhirSchema, path),
|
|
@@ -2002,13 +2147,18 @@ var mkField = (register, fhirSchema, path, element, logger) => {
|
|
|
2002
2147
|
choices: element.choices,
|
|
2003
2148
|
choiceOf: element.choiceOf,
|
|
2004
2149
|
binding,
|
|
2005
|
-
enum:
|
|
2150
|
+
enum: enumResult
|
|
2006
2151
|
};
|
|
2007
2152
|
};
|
|
2008
2153
|
function isNestedElement(element) {
|
|
2009
2154
|
const isBackbone = element.type === "BackboneElement";
|
|
2010
2155
|
const isElement = element.type === "Element" && element.elements !== void 0 && Object.keys(element.elements).length > 0;
|
|
2011
|
-
const elementsWithoutType =
|
|
2156
|
+
const elementsWithoutType = (
|
|
2157
|
+
// FIXME: understand and make a decision.
|
|
2158
|
+
// Problem example: http://hl7.org/cda/stds/core/StructureDefinition/SubstanceAdministration -> consumable
|
|
2159
|
+
// Don't generate nested type for that field, but defetly expect it.
|
|
2160
|
+
element.type === void 0 && element.choiceOf === void 0 && element.elements !== void 0 && Object.keys(element.elements).length > 0
|
|
2161
|
+
);
|
|
2012
2162
|
return isBackbone || isElement || elementsWithoutType;
|
|
2013
2163
|
}
|
|
2014
2164
|
function mkNestedField(register, fhirSchema, path, element, logger) {
|
|
@@ -2022,138 +2172,6 @@ function mkNestedField(register, fhirSchema, path, element, logger) {
|
|
|
2022
2172
|
};
|
|
2023
2173
|
}
|
|
2024
2174
|
|
|
2025
|
-
// src/typeschema/core/binding.ts
|
|
2026
|
-
function extractValueSetConceptsByUrl(register, pkg, valueSetUrl, logger) {
|
|
2027
|
-
const cleanUrl = dropVersionFromUrl(valueSetUrl) || valueSetUrl;
|
|
2028
|
-
const valueSet = register.resolveVs(pkg, cleanUrl);
|
|
2029
|
-
if (!valueSet) return void 0;
|
|
2030
|
-
return extractValueSetConcepts(register, valueSet);
|
|
2031
|
-
}
|
|
2032
|
-
function extractValueSetConcepts(register, valueSet, _logger) {
|
|
2033
|
-
if (valueSet.expansion?.contains) {
|
|
2034
|
-
return valueSet.expansion.contains.filter((item) => item.code !== void 0).map((item) => {
|
|
2035
|
-
assert3(item.code);
|
|
2036
|
-
return {
|
|
2037
|
-
code: item.code,
|
|
2038
|
-
display: item.display,
|
|
2039
|
-
system: item.system
|
|
2040
|
-
};
|
|
2041
|
-
});
|
|
2042
|
-
}
|
|
2043
|
-
const concepts = [];
|
|
2044
|
-
if (valueSet.compose?.include) {
|
|
2045
|
-
for (const include of valueSet.compose.include) {
|
|
2046
|
-
if (include.concept) {
|
|
2047
|
-
for (const concept of include.concept) {
|
|
2048
|
-
concepts.push({
|
|
2049
|
-
system: include.system,
|
|
2050
|
-
code: concept.code,
|
|
2051
|
-
display: concept.display
|
|
2052
|
-
});
|
|
2053
|
-
}
|
|
2054
|
-
} else if (include.system && !include.filter) {
|
|
2055
|
-
try {
|
|
2056
|
-
const codeSystem = register.resolveAny(include.system);
|
|
2057
|
-
if (codeSystem?.concept) {
|
|
2058
|
-
const extractConcepts = (conceptList, system) => {
|
|
2059
|
-
for (const concept of conceptList) {
|
|
2060
|
-
concepts.push({
|
|
2061
|
-
system,
|
|
2062
|
-
code: concept.code,
|
|
2063
|
-
display: concept.display
|
|
2064
|
-
});
|
|
2065
|
-
if (concept.concept) {
|
|
2066
|
-
extractConcepts(concept.concept, system);
|
|
2067
|
-
}
|
|
2068
|
-
}
|
|
2069
|
-
};
|
|
2070
|
-
extractConcepts(codeSystem.concept, include.system);
|
|
2071
|
-
}
|
|
2072
|
-
} catch {
|
|
2073
|
-
}
|
|
2074
|
-
}
|
|
2075
|
-
}
|
|
2076
|
-
}
|
|
2077
|
-
return concepts.length > 0 ? concepts : void 0;
|
|
2078
|
-
}
|
|
2079
|
-
var MAX_ENUM_LENGTH = 100;
|
|
2080
|
-
function buildEnum(register, fhirSchema, element, logger) {
|
|
2081
|
-
if (!element.binding) return void 0;
|
|
2082
|
-
const strength = element.binding.strength;
|
|
2083
|
-
const valueSetUrl = element.binding.valueSet;
|
|
2084
|
-
if (!valueSetUrl) return void 0;
|
|
2085
|
-
const shouldGenerateEnum = strength === "required" || strength === "extensible" && (element.type === "code" || element.type === "Coding") || strength === "preferred" && (element.type === "code" || element.type === "Coding");
|
|
2086
|
-
if (!shouldGenerateEnum) return void 0;
|
|
2087
|
-
const concepts = extractValueSetConceptsByUrl(register, fhirSchema.package_meta, valueSetUrl);
|
|
2088
|
-
if (!concepts || concepts.length === 0) return void 0;
|
|
2089
|
-
const codes = concepts.map((c) => c.code).filter((code) => code && typeof code === "string" && code.trim().length > 0);
|
|
2090
|
-
if (codes.length > MAX_ENUM_LENGTH) {
|
|
2091
|
-
logger?.dry_warn(
|
|
2092
|
-
`Value set ${valueSetUrl} has ${codes.length} which is more than ${MAX_ENUM_LENGTH} codes, which may cause issues with code generation.`
|
|
2093
|
-
);
|
|
2094
|
-
return void 0;
|
|
2095
|
-
}
|
|
2096
|
-
return codes.length > 0 ? codes : void 0;
|
|
2097
|
-
}
|
|
2098
|
-
function generateBindingSchema(register, fhirSchema, path, element, logger) {
|
|
2099
|
-
if (!element.binding?.valueSet) return void 0;
|
|
2100
|
-
const identifier = mkBindingIdentifier(fhirSchema, path, element.binding.bindingName);
|
|
2101
|
-
const fieldType = buildFieldType(register, fhirSchema, path, element, logger);
|
|
2102
|
-
const valueSetIdentifier = mkValueSetIdentifierByUrl(
|
|
2103
|
-
register,
|
|
2104
|
-
fhirSchema.package_meta,
|
|
2105
|
-
element.binding.valueSet
|
|
2106
|
-
);
|
|
2107
|
-
const dependencies = [];
|
|
2108
|
-
if (fieldType) {
|
|
2109
|
-
dependencies.push(fieldType);
|
|
2110
|
-
}
|
|
2111
|
-
dependencies.push(valueSetIdentifier);
|
|
2112
|
-
const enumValues = buildEnum(register, fhirSchema, element, logger);
|
|
2113
|
-
return {
|
|
2114
|
-
identifier,
|
|
2115
|
-
type: fieldType,
|
|
2116
|
-
valueset: valueSetIdentifier,
|
|
2117
|
-
strength: element.binding.strength,
|
|
2118
|
-
enum: enumValues,
|
|
2119
|
-
dependencies
|
|
2120
|
-
};
|
|
2121
|
-
}
|
|
2122
|
-
function collectBindingSchemas(register, fhirSchema, logger) {
|
|
2123
|
-
const processedPaths = /* @__PURE__ */ new Set();
|
|
2124
|
-
if (!fhirSchema.elements) return [];
|
|
2125
|
-
const bindings = [];
|
|
2126
|
-
function collectBindings(elements, parentPath) {
|
|
2127
|
-
for (const [key, element] of Object.entries(elements)) {
|
|
2128
|
-
const path = [...parentPath, key];
|
|
2129
|
-
const pathKey = path.join(".");
|
|
2130
|
-
const elemSnapshot = register.resolveElementSnapshot(fhirSchema, path);
|
|
2131
|
-
if (processedPaths.has(pathKey)) continue;
|
|
2132
|
-
processedPaths.add(pathKey);
|
|
2133
|
-
if (elemSnapshot.binding) {
|
|
2134
|
-
const binding = generateBindingSchema(register, fhirSchema, path, elemSnapshot, logger);
|
|
2135
|
-
if (binding) {
|
|
2136
|
-
bindings.push(binding);
|
|
2137
|
-
}
|
|
2138
|
-
}
|
|
2139
|
-
if (element.elements) {
|
|
2140
|
-
collectBindings(element.elements, path);
|
|
2141
|
-
}
|
|
2142
|
-
}
|
|
2143
|
-
}
|
|
2144
|
-
collectBindings(fhirSchema.elements, []);
|
|
2145
|
-
bindings.sort((a, b) => a.identifier.name.localeCompare(b.identifier.name));
|
|
2146
|
-
const uniqueBindings = [];
|
|
2147
|
-
const seenUrls = /* @__PURE__ */ new Set();
|
|
2148
|
-
for (const binding of bindings) {
|
|
2149
|
-
if (!seenUrls.has(binding.identifier.url)) {
|
|
2150
|
-
seenUrls.add(binding.identifier.url);
|
|
2151
|
-
uniqueBindings.push(binding);
|
|
2152
|
-
}
|
|
2153
|
-
}
|
|
2154
|
-
return uniqueBindings;
|
|
2155
|
-
}
|
|
2156
|
-
|
|
2157
2175
|
// src/typeschema/core/transformer.ts
|
|
2158
2176
|
function mkFields(register, fhirSchema, parentPath, elements, logger) {
|
|
2159
2177
|
if (!elements) return void 0;
|
|
@@ -2188,21 +2206,6 @@ function extractFieldDependencies(fields) {
|
|
|
2188
2206
|
}
|
|
2189
2207
|
return deps;
|
|
2190
2208
|
}
|
|
2191
|
-
function isExtensionSchema(fhirSchema, _identifier) {
|
|
2192
|
-
if (fhirSchema.base === "Extension" || fhirSchema.base === "http://hl7.org/fhir/StructureDefinition/Extension") {
|
|
2193
|
-
return true;
|
|
2194
|
-
}
|
|
2195
|
-
if (fhirSchema.url?.includes("/extension/") || fhirSchema.url?.includes("-extension")) {
|
|
2196
|
-
return true;
|
|
2197
|
-
}
|
|
2198
|
-
if (fhirSchema.name?.toLowerCase().includes("extension")) {
|
|
2199
|
-
return true;
|
|
2200
|
-
}
|
|
2201
|
-
if (fhirSchema.type === "Extension") {
|
|
2202
|
-
return true;
|
|
2203
|
-
}
|
|
2204
|
-
return false;
|
|
2205
|
-
}
|
|
2206
2209
|
async function transformValueSet(register, valueSet, logger) {
|
|
2207
2210
|
if (!valueSet.url) throw new Error("ValueSet URL is required");
|
|
2208
2211
|
const identifier = mkValueSetIdentifierByUrl(register, valueSet.package_meta, valueSet.url);
|
|
@@ -2284,15 +2287,13 @@ function extractExtensionValueTypes(register, fhirSchema, extensionUrl, logger)
|
|
|
2284
2287
|
const uniq = new Map(valueTypes.map((type) => [type.url, type]));
|
|
2285
2288
|
return Array.from(uniq.values());
|
|
2286
2289
|
}
|
|
2287
|
-
|
|
2288
|
-
const extensionSchema = register.resolveFs(fhirSchema.package_meta, extensionUrl);
|
|
2289
|
-
if (!extensionSchema?.elements) return void 0;
|
|
2290
|
+
var extractLegacySubExtensions = (register, extensionSchema, logger) => {
|
|
2290
2291
|
const subExtensions = [];
|
|
2292
|
+
if (!extensionSchema.elements) return subExtensions;
|
|
2291
2293
|
for (const [key, element] of Object.entries(extensionSchema.elements)) {
|
|
2292
2294
|
if (!key.startsWith("extension:")) continue;
|
|
2293
2295
|
const sliceName = key.split(":")[1];
|
|
2294
2296
|
if (!sliceName) continue;
|
|
2295
|
-
const sliceUrl = element.url ?? sliceName;
|
|
2296
2297
|
let valueType;
|
|
2297
2298
|
for (const [elemKey, elemValue] of Object.entries(element.elements ?? {})) {
|
|
2298
2299
|
if (elemValue.choiceOf !== "value" && !elemKey.startsWith("value")) continue;
|
|
@@ -2301,48 +2302,57 @@ function extractSubExtensions(register, fhirSchema, extensionUrl, logger) {
|
|
|
2301
2302
|
}
|
|
2302
2303
|
subExtensions.push({
|
|
2303
2304
|
name: sliceName,
|
|
2304
|
-
url:
|
|
2305
|
+
url: element.url ?? sliceName,
|
|
2305
2306
|
valueType,
|
|
2306
2307
|
min: element.min,
|
|
2307
2308
|
max: element.max !== void 0 ? String(element.max) : void 0
|
|
2308
2309
|
});
|
|
2309
2310
|
}
|
|
2310
|
-
|
|
2311
|
+
return subExtensions;
|
|
2312
|
+
};
|
|
2313
|
+
var extractSlicingSubExtensions = (extensionSchema) => {
|
|
2314
|
+
const subExtensions = [];
|
|
2315
|
+
const extensionElement = extensionSchema.elements?.extension;
|
|
2311
2316
|
const slices = extensionElement?.slicing?.slices;
|
|
2312
|
-
if (slices
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
const
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
};
|
|
2331
|
-
break;
|
|
2332
|
-
}
|
|
2317
|
+
if (!slices || typeof slices !== "object") return subExtensions;
|
|
2318
|
+
for (const [sliceName, sliceData] of Object.entries(slices)) {
|
|
2319
|
+
const slice = sliceData;
|
|
2320
|
+
const schema = slice.schema;
|
|
2321
|
+
if (!schema) continue;
|
|
2322
|
+
let valueType;
|
|
2323
|
+
for (const [elemKey, elemValue] of Object.entries(schema.elements ?? {})) {
|
|
2324
|
+
const elem = elemValue;
|
|
2325
|
+
if (elem.choiceOf !== "value" && !elemKey.startsWith("value")) continue;
|
|
2326
|
+
if (elem.type) {
|
|
2327
|
+
valueType = {
|
|
2328
|
+
kind: "complex-type",
|
|
2329
|
+
package: extensionSchema.package_meta.name,
|
|
2330
|
+
version: extensionSchema.package_meta.version,
|
|
2331
|
+
name: elem.type,
|
|
2332
|
+
url: `http://hl7.org/fhir/StructureDefinition/${elem.type}`
|
|
2333
|
+
};
|
|
2334
|
+
break;
|
|
2333
2335
|
}
|
|
2334
|
-
subExtensions.push({
|
|
2335
|
-
name: sliceName,
|
|
2336
|
-
url: sliceUrl,
|
|
2337
|
-
valueType,
|
|
2338
|
-
min: schema._required ? 1 : schema.min ?? 0,
|
|
2339
|
-
// biome-ignore lint/style/noNestedTernary : okay here
|
|
2340
|
-
max: schema.max !== void 0 ? String(schema.max) : schema.array ? "*" : "1"
|
|
2341
|
-
});
|
|
2342
2336
|
}
|
|
2337
|
+
subExtensions.push({
|
|
2338
|
+
name: sliceName,
|
|
2339
|
+
url: slice.match?.url ?? sliceName,
|
|
2340
|
+
valueType,
|
|
2341
|
+
min: schema._required ? 1 : schema.min ?? 0,
|
|
2342
|
+
// biome-ignore lint/style/noNestedTernary : okay here
|
|
2343
|
+
max: schema.max !== void 0 ? String(schema.max) : schema.array ? "*" : "1"
|
|
2344
|
+
});
|
|
2343
2345
|
}
|
|
2346
|
+
return subExtensions;
|
|
2347
|
+
};
|
|
2348
|
+
var extractSubExtensions = (register, fhirSchema, extensionUrl, logger) => {
|
|
2349
|
+
const extensionSchema = register.resolveFs(fhirSchema.package_meta, extensionUrl);
|
|
2350
|
+
if (!extensionSchema?.elements) return void 0;
|
|
2351
|
+
const legacySubs = extractLegacySubExtensions(register, extensionSchema, logger);
|
|
2352
|
+
const slicingSubs = extractSlicingSubExtensions(extensionSchema);
|
|
2353
|
+
const subExtensions = [...legacySubs, ...slicingSubs];
|
|
2344
2354
|
return subExtensions.length > 0 ? subExtensions : void 0;
|
|
2345
|
-
}
|
|
2355
|
+
};
|
|
2346
2356
|
function extractProfileExtensions(register, fhirSchema, logger) {
|
|
2347
2357
|
const extensions = [];
|
|
2348
2358
|
const addExtensionEntry = (path, name, schema) => {
|
|
@@ -2387,268 +2397,67 @@ function extractProfileExtensions(register, fhirSchema, logger) {
|
|
|
2387
2397
|
return extensions;
|
|
2388
2398
|
}
|
|
2389
2399
|
async function transformFhirSchema(register, fhirSchema, logger) {
|
|
2390
|
-
|
|
2391
|
-
if (isExtensionSchema(fhirSchema, mkIdentifier(fhirSchema))) {
|
|
2392
|
-
const schema = schemas[0];
|
|
2393
|
-
if (!schema) throw new Error(`Expected schema to be defined`);
|
|
2394
|
-
schema.metadata = {
|
|
2395
|
-
isExtension: true
|
|
2396
|
-
// Mark as extension for file organization
|
|
2397
|
-
};
|
|
2398
|
-
}
|
|
2399
|
-
return schemas;
|
|
2400
|
+
return transformFhirSchemaResource(register, fhirSchema, logger);
|
|
2400
2401
|
}
|
|
2401
2402
|
|
|
2402
|
-
// src/
|
|
2403
|
-
var
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
const
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
};
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
};
|
|
2431
|
-
var mkPackageAwareResolver = async (manager, pkg, deep, acc, logger) => {
|
|
2432
|
-
const pkgId = packageMetaToFhir(pkg);
|
|
2433
|
-
logger?.info(`${" ".repeat(deep * 2)}+ ${pkgId}`);
|
|
2434
|
-
if (acc[pkgId]) return acc[pkgId];
|
|
2435
|
-
const index = mkEmptyPkgIndex(pkg);
|
|
2436
|
-
for (const resource of await manager.search({ package: pkg })) {
|
|
2437
|
-
const rawUrl = resource.url;
|
|
2438
|
-
if (!rawUrl) continue;
|
|
2439
|
-
if (!(isStructureDefinition(resource) || isValueSet(resource) || isCodeSystem(resource))) continue;
|
|
2440
|
-
const url = rawUrl;
|
|
2441
|
-
if (index.canonicalResolution[url]) logger?.dry_warn(`Duplicate canonical URL: ${url} at ${pkgId}.`);
|
|
2442
|
-
index.canonicalResolution[url] = [{ deep, pkg, pkgId, resource }];
|
|
2443
|
-
}
|
|
2444
|
-
const deps = await readPackageDependencies(manager, pkg);
|
|
2445
|
-
for (const depPkg of deps) {
|
|
2446
|
-
const { canonicalResolution } = await mkPackageAwareResolver(manager, depPkg, deep + 1, acc, logger);
|
|
2447
|
-
for (const [surl, resolutions] of Object.entries(canonicalResolution)) {
|
|
2448
|
-
const url = surl;
|
|
2449
|
-
index.canonicalResolution[url] = [...index.canonicalResolution[url] || [], ...resolutions];
|
|
2450
|
-
}
|
|
2451
|
-
}
|
|
2452
|
-
for (const resolutionOptions of Object.values(index.canonicalResolution)) {
|
|
2453
|
-
resolutionOptions.sort((a, b) => a.deep - b.deep);
|
|
2454
|
-
}
|
|
2455
|
-
acc[pkgId] = index;
|
|
2456
|
-
return index;
|
|
2457
|
-
};
|
|
2458
|
-
var enrichResolver = (resolver, logger) => {
|
|
2459
|
-
for (const { pkg, canonicalResolution } of Object.values(resolver)) {
|
|
2460
|
-
const pkgId = packageMetaToFhir(pkg);
|
|
2461
|
-
if (!resolver[pkgId]) throw new Error(`Package ${pkgId} not found`);
|
|
2462
|
-
for (const [_url, options] of Object.entries(canonicalResolution)) {
|
|
2463
|
-
const resolition = options[0];
|
|
2464
|
-
if (!resolition) throw new Error(`Resource not found`);
|
|
2465
|
-
const resource = resolition.resource;
|
|
2466
|
-
const resourcePkg = resolition.pkg;
|
|
2467
|
-
if (isStructureDefinition(resource)) {
|
|
2468
|
-
const fs7 = fhirschema.translate(resource);
|
|
2469
|
-
const rfs = enrichFHIRSchema(fs7, resourcePkg);
|
|
2470
|
-
resolver[pkgId].fhirSchemas[rfs.url] = rfs;
|
|
2471
|
-
}
|
|
2472
|
-
if (isValueSet(resource)) {
|
|
2473
|
-
const rvs = enrichValueSet(resource, resourcePkg);
|
|
2474
|
-
resolver[pkgId].valueSets[rvs.url] = rvs;
|
|
2475
|
-
}
|
|
2476
|
-
}
|
|
2477
|
-
}
|
|
2478
|
-
};
|
|
2479
|
-
var packageAgnosticResolveCanonical = (resolver, url, _logger) => {
|
|
2480
|
-
const options = Object.values(resolver).flatMap((pkg) => pkg.canonicalResolution[url]);
|
|
2481
|
-
if (!options) throw new Error(`No canonical resolution found for ${url} in any package`);
|
|
2482
|
-
return options[0]?.resource;
|
|
2483
|
-
};
|
|
2484
|
-
var registerFromManager = async (manager, { logger, fallbackPackageForNameResolution, focusedPackages }) => {
|
|
2485
|
-
const packages = focusedPackages ?? await manager.packages();
|
|
2486
|
-
const resolver = {};
|
|
2487
|
-
for (const pkg of packages) {
|
|
2488
|
-
await mkPackageAwareResolver(manager, pkg, 0, resolver, logger);
|
|
2489
|
-
}
|
|
2490
|
-
enrichResolver(resolver);
|
|
2491
|
-
const resolveFs = (pkg, canonicalUrl) => {
|
|
2492
|
-
return resolver[packageMetaToFhir(pkg)]?.fhirSchemas[canonicalUrl] || fallbackPackageForNameResolution && resolver[packageMetaToFhir(fallbackPackageForNameResolution)]?.fhirSchemas[canonicalUrl];
|
|
2493
|
-
};
|
|
2494
|
-
const resolveVs = (pkg, canonicalUrl) => {
|
|
2495
|
-
return resolver[packageMetaToFhir(pkg)]?.valueSets[canonicalUrl] || fallbackPackageForNameResolution && resolver[packageMetaToFhir(fallbackPackageForNameResolution)]?.valueSets[canonicalUrl];
|
|
2496
|
-
};
|
|
2497
|
-
const ensureSpecializationCanonicalUrl = (name) => {
|
|
2498
|
-
if (name.includes("|")) name = name.split("|")[0];
|
|
2499
|
-
if (name.match(/^[a-zA-Z0-9]+$/)) {
|
|
2500
|
-
return `http://hl7.org/fhir/StructureDefinition/${name}`;
|
|
2501
|
-
}
|
|
2502
|
-
return name;
|
|
2503
|
-
};
|
|
2504
|
-
const resolveFsGenealogy = (pkg, canonicalUrl) => {
|
|
2505
|
-
let fs7 = resolveFs(pkg, canonicalUrl);
|
|
2506
|
-
if (fs7 === void 0) throw new Error(`Failed to resolve FHIR Schema: '${canonicalUrl}'`);
|
|
2507
|
-
const genealogy = [fs7];
|
|
2508
|
-
while (fs7?.base) {
|
|
2509
|
-
const pkg2 = fs7.package_meta;
|
|
2510
|
-
const baseUrl = ensureSpecializationCanonicalUrl(fs7.base);
|
|
2511
|
-
fs7 = resolveFs(pkg2, baseUrl);
|
|
2512
|
-
if (fs7 === void 0)
|
|
2513
|
-
throw new Error(
|
|
2514
|
-
`Failed to resolve FHIR Schema base for '${canonicalUrl}'. Problem: '${baseUrl}' from '${packageMetaToFhir(pkg2)}'`
|
|
2515
|
-
);
|
|
2516
|
-
genealogy.push(fs7);
|
|
2517
|
-
}
|
|
2518
|
-
return genealogy;
|
|
2519
|
-
};
|
|
2520
|
-
const resolveFsSpecializations = (pkg, canonicalUrl) => {
|
|
2521
|
-
return resolveFsGenealogy(pkg, canonicalUrl).filter((fs7) => fs7.derivation === "specialization");
|
|
2522
|
-
};
|
|
2523
|
-
const resolveElementSnapshot = (fhirSchema, path) => {
|
|
2524
|
-
const geneology = resolveFsGenealogy(fhirSchema.package_meta, fhirSchema.url);
|
|
2525
|
-
const elemGeneology = resolveFsElementGenealogy(geneology, path);
|
|
2526
|
-
const elemSnapshot = fsElementSnapshot(elemGeneology);
|
|
2527
|
-
return elemSnapshot;
|
|
2528
|
-
};
|
|
2529
|
-
const getAllElementKeys = (elems) => {
|
|
2530
|
-
const keys = /* @__PURE__ */ new Set();
|
|
2531
|
-
for (const [key, elem] of Object.entries(elems)) {
|
|
2532
|
-
keys.add(key);
|
|
2533
|
-
for (const choiceKey of elem?.choices || []) {
|
|
2534
|
-
if (!elems[choiceKey]) {
|
|
2535
|
-
keys.add(choiceKey);
|
|
2536
|
-
}
|
|
2537
|
-
}
|
|
2538
|
-
}
|
|
2539
|
-
return Array.from(keys);
|
|
2540
|
-
};
|
|
2541
|
-
let cachedResolutionTree;
|
|
2542
|
-
return {
|
|
2543
|
-
testAppendFs(fs7) {
|
|
2544
|
-
const rfs = enrichFHIRSchema(fs7);
|
|
2545
|
-
const pkgId = packageMetaToFhir(rfs.package_meta);
|
|
2546
|
-
if (!resolver[pkgId]) resolver[pkgId] = mkEmptyPkgIndex(rfs.package_meta);
|
|
2547
|
-
resolver[pkgId].fhirSchemas[rfs.url] = rfs;
|
|
2548
|
-
cachedResolutionTree = void 0;
|
|
2549
|
-
},
|
|
2550
|
-
resolveFs,
|
|
2551
|
-
resolveFsGenealogy,
|
|
2552
|
-
resolveFsSpecializations,
|
|
2553
|
-
ensureSpecializationCanonicalUrl,
|
|
2554
|
-
resolveSd: (pkg, canonicalUrl) => {
|
|
2555
|
-
const res = resolver[packageMetaToFhir(pkg)]?.canonicalResolution[canonicalUrl]?.[0]?.resource;
|
|
2556
|
-
if (isStructureDefinition(res)) return res;
|
|
2557
|
-
return void 0;
|
|
2558
|
-
},
|
|
2559
|
-
allSd: () => Object.values(resolver).flatMap(
|
|
2560
|
-
(pkgIndex) => Object.values(pkgIndex.canonicalResolution).flatMap(
|
|
2561
|
-
(resolutions) => resolutions.map((r) => {
|
|
2562
|
-
const sd = r.resource;
|
|
2563
|
-
if (!sd.package_name) {
|
|
2564
|
-
return {
|
|
2565
|
-
...sd,
|
|
2566
|
-
package_name: pkgIndex.pkg.name,
|
|
2567
|
-
package_version: pkgIndex.pkg.version
|
|
2568
|
-
};
|
|
2569
|
-
}
|
|
2570
|
-
return sd;
|
|
2571
|
-
})
|
|
2572
|
-
)
|
|
2573
|
-
).filter((r) => isStructureDefinition(r)).sort((sd1, sd2) => sd1.url.localeCompare(sd2.url)),
|
|
2574
|
-
patchSd: (fn) => {
|
|
2575
|
-
Object.values(resolver).flatMap(
|
|
2576
|
-
(pkgIndex) => Object.values(pkgIndex.canonicalResolution).forEach((resolutions) => {
|
|
2577
|
-
resolutions.forEach((e) => {
|
|
2578
|
-
if (isStructureDefinition(e.resource)) {
|
|
2579
|
-
const sd = e.resource;
|
|
2580
|
-
const newSd = fn(pkgIndex.pkg, sd);
|
|
2581
|
-
if (sd.url !== newSd.url)
|
|
2582
|
-
throw new Error(`Patch update StructureDefinition URL: ${sd.url} !== ${newSd.url}`);
|
|
2583
|
-
e.resource = newSd;
|
|
2584
|
-
}
|
|
2585
|
-
});
|
|
2586
|
-
})
|
|
2403
|
+
// src/typeschema/index.ts
|
|
2404
|
+
var deduplicateSchemas = (schemasWithSources, logger) => {
|
|
2405
|
+
const groups = {};
|
|
2406
|
+
for (const item of schemasWithSources) {
|
|
2407
|
+
const key = `${item.schema.identifier.url}|${item.schema.identifier.package}`;
|
|
2408
|
+
const hash = hashSchema(item.schema);
|
|
2409
|
+
groups[key] ??= {};
|
|
2410
|
+
groups[key][hash] ??= { typeSchema: item.schema, sources: [] };
|
|
2411
|
+
groups[key][hash].sources.push(item);
|
|
2412
|
+
}
|
|
2413
|
+
const schemas = [];
|
|
2414
|
+
const collisions = {};
|
|
2415
|
+
for (const versions of Object.values(groups)) {
|
|
2416
|
+
const sorted = Object.values(versions).sort((a, b) => b.sources.length - a.sources.length);
|
|
2417
|
+
const best = sorted[0];
|
|
2418
|
+
if (!best) continue;
|
|
2419
|
+
schemas.push(best.typeSchema);
|
|
2420
|
+
if (sorted.length > 1) {
|
|
2421
|
+
const pkg = best.typeSchema.identifier.package;
|
|
2422
|
+
const url = best.typeSchema.identifier.url;
|
|
2423
|
+
logger?.dryWarn(`'${url}' from '${pkg}'' has ${sorted.length} versions`);
|
|
2424
|
+
collisions[pkg] ??= {};
|
|
2425
|
+
collisions[pkg][url] = sorted.flatMap(
|
|
2426
|
+
(v) => v.sources.map((s) => ({
|
|
2427
|
+
typeSchema: v.typeSchema,
|
|
2428
|
+
sourcePackage: s.sourcePackage,
|
|
2429
|
+
sourceCanonical: s.sourceCanonical
|
|
2430
|
+
}))
|
|
2587
2431
|
);
|
|
2588
|
-
enrichResolver(resolver);
|
|
2589
|
-
cachedResolutionTree = void 0;
|
|
2590
|
-
},
|
|
2591
|
-
allFs: () => Object.values(resolver).flatMap((pkgIndex) => Object.values(pkgIndex.fhirSchemas)),
|
|
2592
|
-
allVs: () => Object.values(resolver).flatMap((pkgIndex) => Object.values(pkgIndex.valueSets)),
|
|
2593
|
-
resolveVs,
|
|
2594
|
-
resolveAny: (canonicalUrl) => packageAgnosticResolveCanonical(resolver, canonicalUrl),
|
|
2595
|
-
resolveElementSnapshot,
|
|
2596
|
-
getAllElementKeys,
|
|
2597
|
-
resolver,
|
|
2598
|
-
resolutionTree: () => {
|
|
2599
|
-
if (cachedResolutionTree) return cachedResolutionTree;
|
|
2600
|
-
const res = {};
|
|
2601
|
-
for (const [_pkgId, pkgIndex] of Object.entries(resolver)) {
|
|
2602
|
-
const pkgName = pkgIndex.pkg.name;
|
|
2603
|
-
res[pkgName] = {};
|
|
2604
|
-
for (const [surl, resolutions] of Object.entries(pkgIndex.canonicalResolution)) {
|
|
2605
|
-
const url = surl;
|
|
2606
|
-
res[pkgName][url] = [];
|
|
2607
|
-
for (const resolution of resolutions) {
|
|
2608
|
-
res[pkgName][url].push({ deep: resolution.deep, pkg: resolution.pkg });
|
|
2609
|
-
}
|
|
2610
|
-
}
|
|
2611
|
-
}
|
|
2612
|
-
cachedResolutionTree = res;
|
|
2613
|
-
return res;
|
|
2614
2432
|
}
|
|
2615
|
-
}
|
|
2616
|
-
};
|
|
2617
|
-
var resolveFsElementGenealogy = (genealogy, path) => {
|
|
2618
|
-
const [top, ...rest] = path;
|
|
2619
|
-
if (top === void 0) return [];
|
|
2620
|
-
return genealogy.map((fs7) => {
|
|
2621
|
-
if (!fs7.elements) return void 0;
|
|
2622
|
-
let elem = fs7.elements?.[top];
|
|
2623
|
-
for (const k of rest) {
|
|
2624
|
-
elem = elem?.elements?.[k];
|
|
2625
|
-
}
|
|
2626
|
-
return elem;
|
|
2627
|
-
}).filter((elem) => elem !== void 0);
|
|
2433
|
+
}
|
|
2434
|
+
return { schemas, collisions };
|
|
2628
2435
|
};
|
|
2629
|
-
function fsElementSnapshot(genealogy) {
|
|
2630
|
-
const revGenealogy = genealogy.reverse();
|
|
2631
|
-
const snapshot = Object.assign({}, ...revGenealogy);
|
|
2632
|
-
snapshot.elements = void 0;
|
|
2633
|
-
return snapshot;
|
|
2634
|
-
}
|
|
2635
|
-
|
|
2636
|
-
// src/typeschema/index.ts
|
|
2637
2436
|
var generateTypeSchemas = async (register, logger) => {
|
|
2638
|
-
const
|
|
2437
|
+
const schemasWithSources = [];
|
|
2639
2438
|
for (const fhirSchema of register.allFs()) {
|
|
2640
2439
|
const pkgId = packageMetaToFhir(fhirSchema.package_meta);
|
|
2641
2440
|
const skipCheck = shouldSkipCanonical(fhirSchema.package_meta, fhirSchema.url);
|
|
2642
2441
|
if (skipCheck.shouldSkip) {
|
|
2643
|
-
logger?.
|
|
2442
|
+
logger?.dryWarn(`Skip ${fhirSchema.url} from ${pkgId}. Reason: ${skipCheck.reason}`);
|
|
2644
2443
|
continue;
|
|
2645
2444
|
}
|
|
2646
|
-
|
|
2445
|
+
for (const schema of await transformFhirSchema(register, fhirSchema, logger)) {
|
|
2446
|
+
schemasWithSources.push({
|
|
2447
|
+
schema,
|
|
2448
|
+
sourcePackage: pkgId,
|
|
2449
|
+
sourceCanonical: fhirSchema.url
|
|
2450
|
+
});
|
|
2451
|
+
}
|
|
2647
2452
|
}
|
|
2648
2453
|
for (const vsSchema of register.allVs()) {
|
|
2649
|
-
|
|
2454
|
+
schemasWithSources.push({
|
|
2455
|
+
schema: await transformValueSet(register, vsSchema),
|
|
2456
|
+
sourcePackage: packageMetaToFhir(vsSchema.package_meta),
|
|
2457
|
+
sourceCanonical: vsSchema.url
|
|
2458
|
+
});
|
|
2650
2459
|
}
|
|
2651
|
-
return
|
|
2460
|
+
return deduplicateSchemas(schemasWithSources, logger);
|
|
2652
2461
|
};
|
|
2653
2462
|
|
|
2654
2463
|
// src/typeschema/ir/logic-promotion.ts
|
|
@@ -2829,38 +2638,316 @@ var treeShake = (tsIndex, treeShake2) => {
|
|
|
2829
2638
|
for (const schema of schemas) {
|
|
2830
2639
|
acc[JSON.stringify(schema.identifier)] = schema;
|
|
2831
2640
|
}
|
|
2832
|
-
const newSchemas = [];
|
|
2833
|
-
for (const schema of schemas) {
|
|
2834
|
-
if (isSpecializationTypeSchema(schema) || isProfileTypeSchema(schema)) {
|
|
2835
|
-
if (!schema.dependencies) continue;
|
|
2836
|
-
schema.dependencies.forEach((dep) => {
|
|
2837
|
-
const depSchema = tsIndex.resolve(dep);
|
|
2838
|
-
if (!depSchema)
|
|
2839
|
-
throw new Error(
|
|
2840
|
-
`Dependent schema ${JSON.stringify(dep)} not found for ${JSON.stringify(schema.identifier)}`
|
|
2841
|
-
);
|
|
2842
|
-
const id = JSON.stringify(depSchema.identifier);
|
|
2843
|
-
if (!acc[id]) newSchemas.push(depSchema);
|
|
2844
|
-
});
|
|
2845
|
-
if (schema.nested) {
|
|
2846
|
-
for (const nest of schema.nested) {
|
|
2847
|
-
if (isNestedIdentifier(nest.identifier)) continue;
|
|
2848
|
-
const id = JSON.stringify(nest.identifier);
|
|
2849
|
-
if (!acc[id]) newSchemas.push(nest);
|
|
2641
|
+
const newSchemas = [];
|
|
2642
|
+
for (const schema of schemas) {
|
|
2643
|
+
if (isSpecializationTypeSchema(schema) || isProfileTypeSchema(schema)) {
|
|
2644
|
+
if (!schema.dependencies) continue;
|
|
2645
|
+
schema.dependencies.forEach((dep) => {
|
|
2646
|
+
const depSchema = tsIndex.resolve(dep);
|
|
2647
|
+
if (!depSchema)
|
|
2648
|
+
throw new Error(
|
|
2649
|
+
`Dependent schema ${JSON.stringify(dep)} not found for ${JSON.stringify(schema.identifier)}`
|
|
2650
|
+
);
|
|
2651
|
+
const id = JSON.stringify(depSchema.identifier);
|
|
2652
|
+
if (!acc[id]) newSchemas.push(depSchema);
|
|
2653
|
+
});
|
|
2654
|
+
if (schema.nested) {
|
|
2655
|
+
for (const nest of schema.nested) {
|
|
2656
|
+
if (isNestedIdentifier(nest.identifier)) continue;
|
|
2657
|
+
const id = JSON.stringify(nest.identifier);
|
|
2658
|
+
if (!acc[id]) newSchemas.push(nest);
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
return collectDeps(newSchemas, acc);
|
|
2664
|
+
};
|
|
2665
|
+
const shaked = collectDeps(focusedSchemas, {});
|
|
2666
|
+
const shakedIndex = tsIndex.replaceSchemas(shaked);
|
|
2667
|
+
const treeShakeReport = { skippedPackages: [], packages: {} };
|
|
2668
|
+
const irReport = shakedIndex.irReport();
|
|
2669
|
+
irReport.treeShake = treeShakeReport;
|
|
2670
|
+
mutableFillReport(treeShakeReport, tsIndex, shakedIndex);
|
|
2671
|
+
return shakedIndex;
|
|
2672
|
+
};
|
|
2673
|
+
|
|
2674
|
+
// src/fhir-types/hl7-fhir-r4-core/CodeSystem.ts
|
|
2675
|
+
var isCodeSystem = (resource) => {
|
|
2676
|
+
return resource !== null && typeof resource === "object" && resource.resourceType === "CodeSystem";
|
|
2677
|
+
};
|
|
2678
|
+
|
|
2679
|
+
// src/fhir-types/hl7-fhir-r4-core/ValueSet.ts
|
|
2680
|
+
var isValueSet = (resource) => {
|
|
2681
|
+
return resource !== null && typeof resource === "object" && resource.resourceType === "ValueSet";
|
|
2682
|
+
};
|
|
2683
|
+
|
|
2684
|
+
// src/typeschema/register.ts
|
|
2685
|
+
var readPackageDependencies = async (manager, packageMeta2) => {
|
|
2686
|
+
const packageJSON = await manager.packageJson(packageMeta2.name);
|
|
2687
|
+
if (!packageJSON) return [];
|
|
2688
|
+
const dependencies = packageJSON.dependencies;
|
|
2689
|
+
if (dependencies !== void 0) {
|
|
2690
|
+
return Object.entries(dependencies).map(([name, version]) => {
|
|
2691
|
+
return { name, version };
|
|
2692
|
+
});
|
|
2693
|
+
}
|
|
2694
|
+
return [];
|
|
2695
|
+
};
|
|
2696
|
+
var mkEmptyPkgIndex = (pkg) => {
|
|
2697
|
+
return {
|
|
2698
|
+
pkg,
|
|
2699
|
+
canonicalResolution: {},
|
|
2700
|
+
fhirSchemas: {},
|
|
2701
|
+
valueSets: {}
|
|
2702
|
+
};
|
|
2703
|
+
};
|
|
2704
|
+
var mkPackageAwareResolver = async (manager, pkg, deep, acc, logger) => {
|
|
2705
|
+
const pkgId = packageMetaToFhir(pkg);
|
|
2706
|
+
logger?.info(`${" ".repeat(deep * 2)}+ ${pkgId}`);
|
|
2707
|
+
if (acc[pkgId]) return acc[pkgId];
|
|
2708
|
+
const index = mkEmptyPkgIndex(pkg);
|
|
2709
|
+
for (const resource of await manager.search({ package: pkg })) {
|
|
2710
|
+
const rawUrl = resource.url;
|
|
2711
|
+
if (!rawUrl) continue;
|
|
2712
|
+
if (!(isStructureDefinition(resource) || isValueSet(resource) || isCodeSystem(resource))) continue;
|
|
2713
|
+
const url = rawUrl;
|
|
2714
|
+
if (index.canonicalResolution[url]) logger?.dryWarn(`Duplicate canonical URL: ${url} at ${pkgId}.`);
|
|
2715
|
+
index.canonicalResolution[url] = [{ deep, pkg, pkgId, resource }];
|
|
2716
|
+
}
|
|
2717
|
+
const deps = await readPackageDependencies(manager, pkg);
|
|
2718
|
+
for (const depPkg of deps) {
|
|
2719
|
+
const { canonicalResolution } = await mkPackageAwareResolver(manager, depPkg, deep + 1, acc, logger);
|
|
2720
|
+
for (const [surl, resolutions] of Object.entries(canonicalResolution)) {
|
|
2721
|
+
const url = surl;
|
|
2722
|
+
index.canonicalResolution[url] = [...index.canonicalResolution[url] || [], ...resolutions];
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
for (const resolutionOptions of Object.values(index.canonicalResolution)) {
|
|
2726
|
+
resolutionOptions.sort((a, b) => a.deep - b.deep);
|
|
2727
|
+
}
|
|
2728
|
+
acc[pkgId] = index;
|
|
2729
|
+
return index;
|
|
2730
|
+
};
|
|
2731
|
+
var enrichResolver = (resolver, logger) => {
|
|
2732
|
+
for (const { pkg, canonicalResolution } of Object.values(resolver)) {
|
|
2733
|
+
const pkgId = packageMetaToFhir(pkg);
|
|
2734
|
+
if (!resolver[pkgId]) throw new Error(`Package ${pkgId} not found`);
|
|
2735
|
+
for (const [_url, options] of Object.entries(canonicalResolution)) {
|
|
2736
|
+
const resolition = options[0];
|
|
2737
|
+
if (!resolition) throw new Error(`Resource not found`);
|
|
2738
|
+
const resource = resolition.resource;
|
|
2739
|
+
const resourcePkg = resolition.pkg;
|
|
2740
|
+
if (isStructureDefinition(resource)) {
|
|
2741
|
+
const fs7 = fhirschema.translate(resource);
|
|
2742
|
+
const rfs = enrichFHIRSchema(fs7, resourcePkg);
|
|
2743
|
+
resolver[pkgId].fhirSchemas[rfs.url] = rfs;
|
|
2744
|
+
}
|
|
2745
|
+
if (isValueSet(resource)) {
|
|
2746
|
+
const rvs = enrichValueSet(resource, resourcePkg);
|
|
2747
|
+
resolver[pkgId].valueSets[rvs.url] = rvs;
|
|
2748
|
+
}
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2751
|
+
};
|
|
2752
|
+
var packageAgnosticResolveCanonical = (resolver, url, _logger) => {
|
|
2753
|
+
const options = Object.values(resolver).flatMap((pkg) => pkg.canonicalResolution[url]);
|
|
2754
|
+
if (!options) throw new Error(`No canonical resolution found for ${url} in any package`);
|
|
2755
|
+
return options[0]?.resource;
|
|
2756
|
+
};
|
|
2757
|
+
var registerFromManager = async (manager, { logger, focusedPackages }) => {
|
|
2758
|
+
const packages = focusedPackages ?? await manager.packages();
|
|
2759
|
+
const resolver = {};
|
|
2760
|
+
for (const pkg of packages) {
|
|
2761
|
+
await mkPackageAwareResolver(manager, pkg, 0, resolver, logger);
|
|
2762
|
+
}
|
|
2763
|
+
enrichResolver(resolver);
|
|
2764
|
+
const resolveFs = (pkg, canonicalUrl) => {
|
|
2765
|
+
const pkgIndex = resolver[packageMetaToFhir(pkg)];
|
|
2766
|
+
if (pkgIndex) {
|
|
2767
|
+
const resolution = pkgIndex.canonicalResolution[canonicalUrl]?.[0];
|
|
2768
|
+
if (resolution) {
|
|
2769
|
+
return resolver[resolution.pkgId]?.fhirSchemas[canonicalUrl];
|
|
2770
|
+
}
|
|
2771
|
+
}
|
|
2772
|
+
for (const idx of Object.values(resolver)) {
|
|
2773
|
+
const fs7 = idx.fhirSchemas[canonicalUrl];
|
|
2774
|
+
if (fs7 && fs7.package_meta.name === pkg.name) return fs7;
|
|
2775
|
+
}
|
|
2776
|
+
for (const idx of Object.values(resolver)) {
|
|
2777
|
+
const fs7 = idx.fhirSchemas[canonicalUrl];
|
|
2778
|
+
if (fs7) return fs7;
|
|
2779
|
+
}
|
|
2780
|
+
return void 0;
|
|
2781
|
+
};
|
|
2782
|
+
const resolveVs = (pkg, canonicalUrl) => {
|
|
2783
|
+
const pkgIndex = resolver[packageMetaToFhir(pkg)];
|
|
2784
|
+
if (pkgIndex) {
|
|
2785
|
+
const resolution = pkgIndex.canonicalResolution[canonicalUrl]?.[0];
|
|
2786
|
+
if (resolution) {
|
|
2787
|
+
return resolver[resolution.pkgId]?.valueSets[canonicalUrl];
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2790
|
+
for (const idx of Object.values(resolver)) {
|
|
2791
|
+
const vs = idx.valueSets[canonicalUrl];
|
|
2792
|
+
if (vs && vs.package_meta.name === pkg.name) return vs;
|
|
2793
|
+
}
|
|
2794
|
+
for (const idx of Object.values(resolver)) {
|
|
2795
|
+
const vs = idx.valueSets[canonicalUrl];
|
|
2796
|
+
if (vs) return vs;
|
|
2797
|
+
}
|
|
2798
|
+
return void 0;
|
|
2799
|
+
};
|
|
2800
|
+
const ensureSpecializationCanonicalUrl = (name) => {
|
|
2801
|
+
if (name.includes("|")) name = name.split("|")[0];
|
|
2802
|
+
if (name.match(/^[a-zA-Z0-9]+$/)) {
|
|
2803
|
+
return `http://hl7.org/fhir/StructureDefinition/${name}`;
|
|
2804
|
+
}
|
|
2805
|
+
return name;
|
|
2806
|
+
};
|
|
2807
|
+
const resolveFsGenealogy = (pkg, canonicalUrl) => {
|
|
2808
|
+
let fs7 = resolveFs(pkg, canonicalUrl);
|
|
2809
|
+
if (fs7 === void 0) throw new Error(`Failed to resolve FHIR Schema: '${canonicalUrl}'`);
|
|
2810
|
+
const genealogy = [fs7];
|
|
2811
|
+
while (fs7?.base) {
|
|
2812
|
+
const pkg2 = fs7.package_meta;
|
|
2813
|
+
const baseUrl = ensureSpecializationCanonicalUrl(fs7.base);
|
|
2814
|
+
fs7 = resolveFs(pkg2, baseUrl);
|
|
2815
|
+
if (fs7 === void 0)
|
|
2816
|
+
throw new Error(
|
|
2817
|
+
`Failed to resolve FHIR Schema base for '${canonicalUrl}'. Problem: '${baseUrl}' from '${packageMetaToFhir(pkg2)}'`
|
|
2818
|
+
);
|
|
2819
|
+
genealogy.push(fs7);
|
|
2820
|
+
}
|
|
2821
|
+
return genealogy;
|
|
2822
|
+
};
|
|
2823
|
+
const resolveFsSpecializations = (pkg, canonicalUrl) => {
|
|
2824
|
+
return resolveFsGenealogy(pkg, canonicalUrl).filter((fs7) => fs7.derivation === "specialization");
|
|
2825
|
+
};
|
|
2826
|
+
const resolveElementSnapshot = (fhirSchema, path) => {
|
|
2827
|
+
const geneology = resolveFsGenealogy(fhirSchema.package_meta, fhirSchema.url);
|
|
2828
|
+
const elemGeneology = resolveFsElementGenealogy(geneology, path);
|
|
2829
|
+
const elemSnapshot = fsElementSnapshot(elemGeneology);
|
|
2830
|
+
return elemSnapshot;
|
|
2831
|
+
};
|
|
2832
|
+
const getAllElementKeys = (elems) => {
|
|
2833
|
+
const keys = /* @__PURE__ */ new Set();
|
|
2834
|
+
for (const [key, elem] of Object.entries(elems)) {
|
|
2835
|
+
keys.add(key);
|
|
2836
|
+
for (const choiceKey of elem?.choices || []) {
|
|
2837
|
+
if (!elems[choiceKey]) {
|
|
2838
|
+
keys.add(choiceKey);
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2841
|
+
}
|
|
2842
|
+
return Array.from(keys);
|
|
2843
|
+
};
|
|
2844
|
+
let cachedResolutionTree;
|
|
2845
|
+
return {
|
|
2846
|
+
testAppendFs(rfs) {
|
|
2847
|
+
const pkgId = packageMetaToFhir(rfs.package_meta);
|
|
2848
|
+
if (!resolver[pkgId]) resolver[pkgId] = mkEmptyPkgIndex(rfs.package_meta);
|
|
2849
|
+
resolver[pkgId].fhirSchemas[rfs.url] = rfs;
|
|
2850
|
+
cachedResolutionTree = void 0;
|
|
2851
|
+
},
|
|
2852
|
+
resolveFs,
|
|
2853
|
+
resolveFsGenealogy,
|
|
2854
|
+
resolveFsSpecializations,
|
|
2855
|
+
ensureSpecializationCanonicalUrl,
|
|
2856
|
+
resolveSd: (pkg, canonicalUrl) => {
|
|
2857
|
+
const res = resolver[packageMetaToFhir(pkg)]?.canonicalResolution[canonicalUrl]?.[0]?.resource;
|
|
2858
|
+
if (isStructureDefinition(res)) return res;
|
|
2859
|
+
return void 0;
|
|
2860
|
+
},
|
|
2861
|
+
allSd: () => Object.values(resolver).flatMap(
|
|
2862
|
+
(pkgIndex) => Object.values(pkgIndex.canonicalResolution).flatMap(
|
|
2863
|
+
(resolutions) => resolutions.map((r) => {
|
|
2864
|
+
const sd = r.resource;
|
|
2865
|
+
if (!sd.package_name) {
|
|
2866
|
+
return {
|
|
2867
|
+
...sd,
|
|
2868
|
+
package_name: pkgIndex.pkg.name,
|
|
2869
|
+
package_version: pkgIndex.pkg.version
|
|
2870
|
+
};
|
|
2871
|
+
}
|
|
2872
|
+
return sd;
|
|
2873
|
+
})
|
|
2874
|
+
)
|
|
2875
|
+
).filter((r) => isStructureDefinition(r)).sort((sd1, sd2) => sd1.url.localeCompare(sd2.url)),
|
|
2876
|
+
patchSd: (fn) => {
|
|
2877
|
+
Object.values(resolver).flatMap(
|
|
2878
|
+
(pkgIndex) => Object.values(pkgIndex.canonicalResolution).forEach((resolutions) => {
|
|
2879
|
+
resolutions.forEach((e) => {
|
|
2880
|
+
if (isStructureDefinition(e.resource)) {
|
|
2881
|
+
const sd = e.resource;
|
|
2882
|
+
const newSd = fn(pkgIndex.pkg, sd);
|
|
2883
|
+
if (sd.url !== newSd.url)
|
|
2884
|
+
throw new Error(`Patch update StructureDefinition URL: ${sd.url} !== ${newSd.url}`);
|
|
2885
|
+
e.resource = newSd;
|
|
2886
|
+
}
|
|
2887
|
+
});
|
|
2888
|
+
})
|
|
2889
|
+
);
|
|
2890
|
+
enrichResolver(resolver);
|
|
2891
|
+
cachedResolutionTree = void 0;
|
|
2892
|
+
},
|
|
2893
|
+
allFs: () => Object.values(resolver).flatMap((pkgIndex) => Object.values(pkgIndex.fhirSchemas)),
|
|
2894
|
+
allVs: () => Object.values(resolver).flatMap((pkgIndex) => Object.values(pkgIndex.valueSets)),
|
|
2895
|
+
resolveVs,
|
|
2896
|
+
resolveAny: (canonicalUrl) => packageAgnosticResolveCanonical(resolver, canonicalUrl),
|
|
2897
|
+
resolveElementSnapshot,
|
|
2898
|
+
getAllElementKeys,
|
|
2899
|
+
resolver,
|
|
2900
|
+
resolutionTree: () => {
|
|
2901
|
+
if (cachedResolutionTree) return cachedResolutionTree;
|
|
2902
|
+
const res = {};
|
|
2903
|
+
for (const [_pkgId, pkgIndex] of Object.entries(resolver)) {
|
|
2904
|
+
const pkgName = pkgIndex.pkg.name;
|
|
2905
|
+
res[pkgName] = {};
|
|
2906
|
+
for (const [surl, resolutions] of Object.entries(pkgIndex.canonicalResolution)) {
|
|
2907
|
+
const url = surl;
|
|
2908
|
+
res[pkgName][url] = [];
|
|
2909
|
+
for (const resolution of resolutions) {
|
|
2910
|
+
res[pkgName][url].push({ deep: resolution.deep, pkg: resolution.pkg });
|
|
2850
2911
|
}
|
|
2851
2912
|
}
|
|
2852
2913
|
}
|
|
2914
|
+
cachedResolutionTree = res;
|
|
2915
|
+
return res;
|
|
2853
2916
|
}
|
|
2854
|
-
return collectDeps(newSchemas, acc);
|
|
2855
2917
|
};
|
|
2856
|
-
const shaked = collectDeps(focusedSchemas, {});
|
|
2857
|
-
const shakedIndex = tsIndex.replaceSchemas(shaked);
|
|
2858
|
-
const treeShakeReport = { skippedPackages: [], packages: {} };
|
|
2859
|
-
const irReport = shakedIndex.irReport();
|
|
2860
|
-
irReport.treeShake = treeShakeReport;
|
|
2861
|
-
mutableFillReport(treeShakeReport, tsIndex, shakedIndex);
|
|
2862
|
-
return shakedIndex;
|
|
2863
2918
|
};
|
|
2919
|
+
var registerFromPackageMetas = async (packageMetas, conf) => {
|
|
2920
|
+
const packageNames = packageMetas.map(packageMetaToNpm);
|
|
2921
|
+
conf?.logger?.step(`Loading FHIR packages: ${packageNames.join(", ")}`);
|
|
2922
|
+
const manager = CanonicalManager({
|
|
2923
|
+
packages: packageNames,
|
|
2924
|
+
workingDir: "tmp/fhir",
|
|
2925
|
+
registry: conf.registry || void 0
|
|
2926
|
+
});
|
|
2927
|
+
await manager.init();
|
|
2928
|
+
return await registerFromManager(manager, {
|
|
2929
|
+
...conf,
|
|
2930
|
+
focusedPackages: packageMetas
|
|
2931
|
+
});
|
|
2932
|
+
};
|
|
2933
|
+
var resolveFsElementGenealogy = (genealogy, path) => {
|
|
2934
|
+
const [top, ...rest] = path;
|
|
2935
|
+
if (top === void 0) return [];
|
|
2936
|
+
return genealogy.map((fs7) => {
|
|
2937
|
+
if (!fs7.elements) return void 0;
|
|
2938
|
+
let elem = fs7.elements?.[top];
|
|
2939
|
+
for (const k of rest) {
|
|
2940
|
+
elem = elem?.elements?.[k];
|
|
2941
|
+
}
|
|
2942
|
+
return elem;
|
|
2943
|
+
}).filter((elem) => elem !== void 0);
|
|
2944
|
+
};
|
|
2945
|
+
function fsElementSnapshot(genealogy) {
|
|
2946
|
+
const revGenealogy = genealogy.reverse();
|
|
2947
|
+
const snapshot = Object.assign({}, ...revGenealogy);
|
|
2948
|
+
snapshot.elements = void 0;
|
|
2949
|
+
return snapshot;
|
|
2950
|
+
}
|
|
2864
2951
|
var normalizeFileName = (str) => {
|
|
2865
2952
|
const res = str.replace(/[^a-zA-Z0-9\-_.@#()]/g, "");
|
|
2866
2953
|
if (res.length === 0) return "unknown";
|
|
@@ -2902,23 +2989,60 @@ var IntrospectionWriter = class extends FileSystemWriter {
|
|
|
2902
2989
|
this.logger()?.info(`IntrospectionWriter: Type tree written to ${this.opts.typeTree}`);
|
|
2903
2990
|
}
|
|
2904
2991
|
if (this.opts.typeSchemas) {
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
if (Path5.extname(outputPath) === ".ndjson") {
|
|
2908
|
-
this.writeNdjson(typeSchemas, outputPath, typeSchemaToJson);
|
|
2992
|
+
if (Path5.extname(this.opts.typeSchemas) === ".ndjson") {
|
|
2993
|
+
this.writeNdjson(tsIndex.schemas, this.opts.typeSchemas, typeSchemaToJson);
|
|
2909
2994
|
} else {
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2995
|
+
const items = tsIndex.schemas.map((ts) => typeSchemaToJson(ts, true));
|
|
2996
|
+
const seenFilenames = /* @__PURE__ */ new Set();
|
|
2997
|
+
const dedupedItems = items.filter((item) => {
|
|
2998
|
+
if (seenFilenames.has(item.filename)) return false;
|
|
2999
|
+
seenFilenames.add(item.filename);
|
|
3000
|
+
return true;
|
|
3001
|
+
});
|
|
3002
|
+
this.cd(this.opts.typeSchemas, () => {
|
|
3003
|
+
for (const { filename, genContent } of dedupedItems) {
|
|
3004
|
+
const fileName = `${filename}.json`;
|
|
3005
|
+
this.cd(Path5.dirname(fileName), () => {
|
|
3006
|
+
this.cat(Path5.basename(fileName), () => {
|
|
3007
|
+
this.write(genContent());
|
|
3008
|
+
});
|
|
3009
|
+
});
|
|
3010
|
+
}
|
|
3011
|
+
for (const [pkg, canonicals] of Object.entries(tsIndex.irReport().collisions ?? {})) {
|
|
3012
|
+
this.cd(`${normalizeFileName(pkg)}`, () => {
|
|
3013
|
+
for (const [canonical, entries] of Object.entries(canonicals)) {
|
|
3014
|
+
if (entries.length <= 1) continue;
|
|
3015
|
+
const firstEntry = entries[0];
|
|
3016
|
+
assert3(firstEntry);
|
|
3017
|
+
const name = normalizeFileName(
|
|
3018
|
+
`${firstEntry.typeSchema.identifier.name}(${extractNameFromCanonical(canonical)})`
|
|
3019
|
+
);
|
|
3020
|
+
this.cd(Path5.join("collisions", name), () => {
|
|
3021
|
+
for (let i = 0; i < entries.length; i++) {
|
|
3022
|
+
const entry = entries[i];
|
|
3023
|
+
this.cat(`${i + 1}.json`, () => {
|
|
3024
|
+
this.write(JSON.stringify(entry, null, 2));
|
|
3025
|
+
});
|
|
3026
|
+
}
|
|
3027
|
+
});
|
|
3028
|
+
}
|
|
3029
|
+
});
|
|
3030
|
+
}
|
|
3031
|
+
});
|
|
2914
3032
|
}
|
|
2915
3033
|
this.logger()?.info(
|
|
2916
|
-
`IntrospectionWriter: ${
|
|
3034
|
+
`IntrospectionWriter: ${tsIndex.schemas.length} TypeSchema written to ${this.opts.typeSchemas}`
|
|
2917
3035
|
);
|
|
2918
3036
|
}
|
|
2919
3037
|
if (this.opts.fhirSchemas && tsIndex.register) {
|
|
2920
3038
|
const outputPath = this.opts.fhirSchemas;
|
|
2921
|
-
const
|
|
3039
|
+
const allFs = tsIndex.register.allFs();
|
|
3040
|
+
const seenUrls = /* @__PURE__ */ new Set();
|
|
3041
|
+
const fhirSchemas = allFs.filter((fs7) => {
|
|
3042
|
+
if (seenUrls.has(fs7.url)) return false;
|
|
3043
|
+
seenUrls.add(fs7.url);
|
|
3044
|
+
return true;
|
|
3045
|
+
});
|
|
2922
3046
|
if (Path5.extname(outputPath) === ".ndjson") {
|
|
2923
3047
|
this.writeNdjson(fhirSchemas, outputPath, fhirSchemaToJson);
|
|
2924
3048
|
} else {
|
|
@@ -2931,7 +3055,13 @@ var IntrospectionWriter = class extends FileSystemWriter {
|
|
|
2931
3055
|
}
|
|
2932
3056
|
if (this.opts.structureDefinitions && tsIndex.register) {
|
|
2933
3057
|
const outputPath = this.opts.structureDefinitions;
|
|
2934
|
-
const
|
|
3058
|
+
const allSd = tsIndex.register.allSd();
|
|
3059
|
+
const seenUrls = /* @__PURE__ */ new Set();
|
|
3060
|
+
const structureDefinitions = allSd.filter((sd) => {
|
|
3061
|
+
if (seenUrls.has(sd.url)) return false;
|
|
3062
|
+
seenUrls.add(sd.url);
|
|
3063
|
+
return true;
|
|
3064
|
+
});
|
|
2935
3065
|
if (Path5.extname(outputPath) === ".ndjson") {
|
|
2936
3066
|
this.writeNdjson(structureDefinitions, outputPath, structureDefinitionToJson);
|
|
2937
3067
|
} else {
|
|
@@ -2984,58 +3114,118 @@ var IntrospectionWriter = class extends FileSystemWriter {
|
|
|
2984
3114
|
};
|
|
2985
3115
|
|
|
2986
3116
|
// src/typeschema/ir/report.ts
|
|
2987
|
-
var
|
|
2988
|
-
|
|
2989
|
-
const
|
|
2990
|
-
|
|
2991
|
-
...Object.keys(report.logicalPromotion?.packages ?? {})
|
|
2992
|
-
]);
|
|
2993
|
-
if (allPackages.size === 0) {
|
|
2994
|
-
lines.push("No IR modifications applied.");
|
|
2995
|
-
return lines.join("\n");
|
|
3117
|
+
var generateSkippedPackagesSection = (lines, skippedPackages) => {
|
|
3118
|
+
lines.push("## Skipped Packages", "");
|
|
3119
|
+
for (const pkg of skippedPackages) {
|
|
3120
|
+
lines.push(`- ${pkg}`);
|
|
2996
3121
|
}
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3122
|
+
lines.push("");
|
|
3123
|
+
};
|
|
3124
|
+
var generatePackageSection = (lines, pkgName, treeShakePkg, promotedCanonicals) => {
|
|
3125
|
+
lines.push(`## Package: \`${pkgName}\``, "");
|
|
3126
|
+
if (promotedCanonicals?.length) {
|
|
3127
|
+
lines.push("### Promoted Logical Models", "");
|
|
3128
|
+
for (const canonical of promotedCanonicals) {
|
|
3129
|
+
lines.push(`- \`${canonical}\``);
|
|
3001
3130
|
}
|
|
3002
3131
|
lines.push("");
|
|
3003
3132
|
}
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3133
|
+
if (!treeShakePkg) return;
|
|
3134
|
+
const canonicalsWithChanges = Object.entries(treeShakePkg.canonicals).filter(
|
|
3135
|
+
([_, data]) => data.skippedFields.length > 0
|
|
3136
|
+
);
|
|
3137
|
+
if (canonicalsWithChanges.length > 0) {
|
|
3138
|
+
lines.push("### Modified Canonicals", "");
|
|
3139
|
+
for (const [canonical, data] of canonicalsWithChanges) {
|
|
3140
|
+
lines.push(`#### \`${canonical}\``, "");
|
|
3141
|
+
lines.push("Skipped fields:", "");
|
|
3142
|
+
for (const field of data.skippedFields) {
|
|
3143
|
+
lines.push(`- \`${field}\``);
|
|
3012
3144
|
}
|
|
3013
3145
|
lines.push("");
|
|
3014
3146
|
}
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3147
|
+
}
|
|
3148
|
+
if (treeShakePkg.skippedCanonicals.length > 0) {
|
|
3149
|
+
lines.push("### Skipped Canonicals", "");
|
|
3150
|
+
for (const canonical of treeShakePkg.skippedCanonicals) {
|
|
3151
|
+
lines.push(`- \`${canonical}\``);
|
|
3152
|
+
}
|
|
3153
|
+
lines.push("");
|
|
3154
|
+
}
|
|
3155
|
+
};
|
|
3156
|
+
var generateCollisionVersionLines = (entries) => {
|
|
3157
|
+
const uniqueSchemas = /* @__PURE__ */ new Map();
|
|
3158
|
+
for (const entry of entries) {
|
|
3159
|
+
const key = JSON.stringify(entry.typeSchema);
|
|
3160
|
+
if (!uniqueSchemas.has(key)) uniqueSchemas.set(key, []);
|
|
3161
|
+
uniqueSchemas.get(key)?.push(entry);
|
|
3162
|
+
}
|
|
3163
|
+
const versionLines = [];
|
|
3164
|
+
const sortedVersions = [...uniqueSchemas.values()].sort((a, b) => b.length - a.length);
|
|
3165
|
+
let version = 1;
|
|
3166
|
+
for (const schemaEntries of sortedVersions) {
|
|
3167
|
+
const sourceList = schemaEntries.map((e) => {
|
|
3168
|
+
const name = extractNameFromCanonical(e.sourceCanonical) ?? e.sourceCanonical;
|
|
3169
|
+
return `${name} (${e.sourcePackage})`;
|
|
3170
|
+
}).join(", ");
|
|
3171
|
+
versionLines.push(` - Version ${version++}: ${sourceList}`);
|
|
3172
|
+
}
|
|
3173
|
+
return versionLines;
|
|
3174
|
+
};
|
|
3175
|
+
var generateCollisionsSection = (lines, collisions) => {
|
|
3176
|
+
if (!collisions) return;
|
|
3177
|
+
lines.push("## Schema Collisions", "");
|
|
3178
|
+
lines.push("The following canonicals have multiple schema versions with different content.");
|
|
3179
|
+
lines.push("To inspect collision versions, export TypeSchemas using `.introspection({ typeSchemas: 'path' })`");
|
|
3180
|
+
lines.push("and check `<pkg>/collisions/<name>/1.json, 2.json, ...` files.", "");
|
|
3181
|
+
const collisionPackages = Object.keys(collisions).sort();
|
|
3182
|
+
for (const pkgName of collisionPackages) {
|
|
3183
|
+
const collisionsPkg = collisions[pkgName];
|
|
3184
|
+
if (!collisionsPkg) throw new Error(`Missing collisions for package ${pkgName}`);
|
|
3185
|
+
const sortedEntries = Object.entries(collisionsPkg).sort(([a], [b]) => {
|
|
3186
|
+
const nameA = a.split("/").pop() ?? a;
|
|
3187
|
+
const nameB = b.split("/").pop() ?? b;
|
|
3188
|
+
return nameA.localeCompare(nameB);
|
|
3189
|
+
});
|
|
3190
|
+
if (sortedEntries.length > 0) {
|
|
3191
|
+
lines.push(`### \`${pkgName}\``, "");
|
|
3192
|
+
for (const [canonical, entries] of sortedEntries) {
|
|
3193
|
+
const versionLines = generateCollisionVersionLines(entries);
|
|
3194
|
+
lines.push(`- \`${canonical}\` (${versionLines.length} versions)`);
|
|
3195
|
+
lines.push(...versionLines);
|
|
3036
3196
|
}
|
|
3197
|
+
lines.push("");
|
|
3037
3198
|
}
|
|
3038
3199
|
}
|
|
3200
|
+
};
|
|
3201
|
+
var generateIrReportReadme = (report) => {
|
|
3202
|
+
const lines = ["# IR Report", ""];
|
|
3203
|
+
const irPackages = [
|
|
3204
|
+
.../* @__PURE__ */ new Set([
|
|
3205
|
+
...Object.keys(report.treeShake?.packages ?? {}),
|
|
3206
|
+
...Object.keys(report.logicalPromotion?.packages ?? {})
|
|
3207
|
+
])
|
|
3208
|
+
].sort();
|
|
3209
|
+
const hasIrChanges = irPackages.length > 0 || (report.treeShake?.skippedPackages.length ?? 0) > 0;
|
|
3210
|
+
const hasCollisions = Object.keys(report.collisions ?? {}).length > 0;
|
|
3211
|
+
if (!hasIrChanges && !hasCollisions) {
|
|
3212
|
+
lines.push("No IR modifications applied.");
|
|
3213
|
+
return lines.join("\n");
|
|
3214
|
+
}
|
|
3215
|
+
if (report.treeShake?.skippedPackages.length) {
|
|
3216
|
+
generateSkippedPackagesSection(lines, report.treeShake.skippedPackages);
|
|
3217
|
+
}
|
|
3218
|
+
for (const pkgName of irPackages) {
|
|
3219
|
+
generatePackageSection(
|
|
3220
|
+
lines,
|
|
3221
|
+
pkgName,
|
|
3222
|
+
report.treeShake?.packages[pkgName],
|
|
3223
|
+
report.logicalPromotion?.packages[pkgName]?.promotedCanonicals
|
|
3224
|
+
);
|
|
3225
|
+
}
|
|
3226
|
+
if (hasCollisions) {
|
|
3227
|
+
generateCollisionsSection(lines, report.collisions);
|
|
3228
|
+
}
|
|
3039
3229
|
return lines.join("\n");
|
|
3040
3230
|
};
|
|
3041
3231
|
|
|
@@ -3407,25 +3597,27 @@ var ViewModelFactory = class {
|
|
|
3407
3597
|
hasFields: fields.length > 0,
|
|
3408
3598
|
hasNestedComplexTypes: nestedComplexTypes.length > 0,
|
|
3409
3599
|
hasNestedEnums: nestedEnums.length > 0,
|
|
3410
|
-
fields: fields.filter(
|
|
3600
|
+
fields: fields.filter(
|
|
3601
|
+
(entry) => isNotChoiceDeclarationField(entry[1])
|
|
3602
|
+
).sort((a, b) => a[0].localeCompare(b[0])).map(([fieldName, field]) => {
|
|
3411
3603
|
return {
|
|
3412
3604
|
owner: name,
|
|
3413
|
-
schema:
|
|
3605
|
+
schema: field,
|
|
3414
3606
|
name: fieldName,
|
|
3415
3607
|
saveName: this.nameGenerator.generateField(fieldName),
|
|
3416
|
-
typeName: this.nameGenerator.generateFieldType(
|
|
3417
|
-
isArray:
|
|
3418
|
-
isRequired:
|
|
3419
|
-
isEnum: !!
|
|
3420
|
-
isSizeConstrained:
|
|
3421
|
-
min:
|
|
3422
|
-
max:
|
|
3423
|
-
isResource: this._createIsResource(
|
|
3424
|
-
isComplexType: this._createIsComplexType(
|
|
3425
|
-
isPrimitive: this._createIsPrimitiveType(
|
|
3426
|
-
isCode:
|
|
3427
|
-
isIdentifier:
|
|
3428
|
-
isReference:
|
|
3608
|
+
typeName: this.nameGenerator.generateFieldType(field),
|
|
3609
|
+
isArray: field.array ?? false,
|
|
3610
|
+
isRequired: field.required ?? false,
|
|
3611
|
+
isEnum: !!field.enum && !field.enum.isOpen,
|
|
3612
|
+
isSizeConstrained: field.min !== void 0 || field.max !== void 0,
|
|
3613
|
+
min: field.min,
|
|
3614
|
+
max: field.max,
|
|
3615
|
+
isResource: this._createIsResource(field.type),
|
|
3616
|
+
isComplexType: this._createIsComplexType(field.type),
|
|
3617
|
+
isPrimitive: this._createIsPrimitiveType(field.type),
|
|
3618
|
+
isCode: field.type?.name === "code",
|
|
3619
|
+
isIdentifier: field.type?.name === "Identifier",
|
|
3620
|
+
isReference: field.type?.name === "Reference"
|
|
3429
3621
|
};
|
|
3430
3622
|
})
|
|
3431
3623
|
};
|
|
@@ -3501,11 +3693,11 @@ var ViewModelFactory = class {
|
|
|
3501
3693
|
_collectNestedEnums(fields) {
|
|
3502
3694
|
const nestedEnumValues = {};
|
|
3503
3695
|
fields.forEach(([fieldName, fieldSchema]) => {
|
|
3504
|
-
if ("enum" in fieldSchema && fieldSchema.enum) {
|
|
3696
|
+
if ("enum" in fieldSchema && fieldSchema.enum && !fieldSchema.enum.isOpen) {
|
|
3505
3697
|
const name = ("binding" in fieldSchema && fieldSchema.binding?.name) ?? fieldName;
|
|
3506
3698
|
if (typeof name === "string") {
|
|
3507
3699
|
nestedEnumValues[name] = nestedEnumValues[name] ?? /* @__PURE__ */ new Set();
|
|
3508
|
-
fieldSchema.enum
|
|
3700
|
+
fieldSchema.enum.values.forEach(nestedEnumValues[name].add.bind(nestedEnumValues[name]));
|
|
3509
3701
|
}
|
|
3510
3702
|
}
|
|
3511
3703
|
});
|
|
@@ -3734,13 +3926,22 @@ var tsFhirPackageDir = (name) => {
|
|
|
3734
3926
|
var tsModuleName = (id) => {
|
|
3735
3927
|
return uppercaseFirstLetter(normalizeTsName(id.name));
|
|
3736
3928
|
};
|
|
3929
|
+
var tsProfileModuleName = (tsIndex, schema) => {
|
|
3930
|
+
const resourceSchema = tsIndex.findLastSpecialization(schema);
|
|
3931
|
+
const resourceName = uppercaseFirstLetter(normalizeTsName(resourceSchema.identifier.name));
|
|
3932
|
+
const profileName = extractNameFromCanonical(schema.identifier.url);
|
|
3933
|
+
if (profileName) {
|
|
3934
|
+
return `${resourceName}_${normalizeTsName(profileName)}`;
|
|
3935
|
+
}
|
|
3936
|
+
return `${resourceName}_${normalizeTsName(schema.identifier.name)}`;
|
|
3937
|
+
};
|
|
3737
3938
|
var tsModuleFileName = (id) => {
|
|
3738
3939
|
return `${tsModuleName(id)}.ts`;
|
|
3739
3940
|
};
|
|
3941
|
+
var tsProfileModuleFileName = (tsIndex, schema) => {
|
|
3942
|
+
return `${tsProfileModuleName(tsIndex, schema)}.ts`;
|
|
3943
|
+
};
|
|
3740
3944
|
var tsModulePath = (id) => {
|
|
3741
|
-
if (isProfileIdentifier(id)) {
|
|
3742
|
-
return `${tsFhirPackageDir(id.package)}/profiles/${tsModuleName(id)}`;
|
|
3743
|
-
}
|
|
3744
3945
|
return `${tsFhirPackageDir(id.package)}/${tsModuleName(id)}`;
|
|
3745
3946
|
};
|
|
3746
3947
|
var canonicalToName3 = (canonical, dropFragment = true) => {
|
|
@@ -3752,9 +3953,9 @@ var canonicalToName3 = (canonical, dropFragment = true) => {
|
|
|
3752
3953
|
var tsResourceName = (id) => {
|
|
3753
3954
|
if (id.kind === "nested") {
|
|
3754
3955
|
const url = id.url;
|
|
3755
|
-
const
|
|
3756
|
-
if (!
|
|
3757
|
-
const [resourceName, fragment] =
|
|
3956
|
+
const localName = extractNameFromCanonical(url, false);
|
|
3957
|
+
if (!localName) return "";
|
|
3958
|
+
const [resourceName, fragment] = localName.split("#");
|
|
3758
3959
|
const name = uppercaseFirstLetterOfEach((fragment ?? "").split(".")).join("");
|
|
3759
3960
|
return normalizeTsName([resourceName, name].join(""));
|
|
3760
3961
|
}
|
|
@@ -3768,14 +3969,37 @@ var tsFieldName = (n) => {
|
|
|
3768
3969
|
};
|
|
3769
3970
|
var normalizeTsName = (n) => {
|
|
3770
3971
|
if (tsKeywords.has(n)) n = `${n}_`;
|
|
3771
|
-
return n.replace(/\[x\]/g, "_x_").replace(/[-
|
|
3972
|
+
return n.replace(/\[x\]/g, "_x_").replace(/[- :.]/g, "_");
|
|
3772
3973
|
};
|
|
3773
3974
|
var tsGet = (object, tsFieldName2) => {
|
|
3774
3975
|
if (tsFieldName2.startsWith('"')) return `${object}[${tsFieldName2}]`;
|
|
3775
3976
|
return `${object}.${tsFieldName2}`;
|
|
3776
3977
|
};
|
|
3777
|
-
var tsEnumType = (
|
|
3778
|
-
|
|
3978
|
+
var tsEnumType = (enumDef) => {
|
|
3979
|
+
const values = enumDef.values.map((e) => `"${e}"`).join(" | ");
|
|
3980
|
+
return enumDef.isOpen ? `(${values} | string)` : `(${values})`;
|
|
3981
|
+
};
|
|
3982
|
+
var rewriteFieldTypeDefs = {
|
|
3983
|
+
Coding: { code: () => "T" },
|
|
3984
|
+
// biome-ignore lint: that is exactly string what we want
|
|
3985
|
+
Reference: { reference: () => "`${T}/${string}`" },
|
|
3986
|
+
CodeableConcept: { coding: () => "Coding<T>" }
|
|
3987
|
+
};
|
|
3988
|
+
var resolveFieldTsType = (schemaName, tsName, field) => {
|
|
3989
|
+
const rewriteFieldType = rewriteFieldTypeDefs[schemaName]?.[tsName];
|
|
3990
|
+
if (rewriteFieldType) return rewriteFieldType();
|
|
3991
|
+
if (field.enum) {
|
|
3992
|
+
if (field.type.name === "Coding") return `Coding<${tsEnumType(field.enum)}>`;
|
|
3993
|
+
if (field.type.name === "CodeableConcept") return `CodeableConcept<${tsEnumType(field.enum)}>`;
|
|
3994
|
+
return tsEnumType(field.enum);
|
|
3995
|
+
}
|
|
3996
|
+
if (field.reference && field.reference.length > 0) {
|
|
3997
|
+
const references = field.reference.map((ref) => `"${ref.name}"`).join(" | ");
|
|
3998
|
+
return `Reference<${references}>`;
|
|
3999
|
+
}
|
|
4000
|
+
if (isPrimitiveIdentifier(field.type)) return resolvePrimitiveType(field.type.name);
|
|
4001
|
+
if (isNestedIdentifier(field.type)) return tsResourceName(field.type);
|
|
4002
|
+
return field.type.name;
|
|
3779
4003
|
};
|
|
3780
4004
|
var tsTypeFromIdentifier = (id) => {
|
|
3781
4005
|
if (isNestedIdentifier(id)) return tsResourceName(id);
|
|
@@ -3784,8 +4008,12 @@ var tsTypeFromIdentifier = (id) => {
|
|
|
3784
4008
|
if (primitiveType !== void 0) return primitiveType;
|
|
3785
4009
|
return id.name;
|
|
3786
4010
|
};
|
|
3787
|
-
var tsProfileClassName = (
|
|
3788
|
-
|
|
4011
|
+
var tsProfileClassName = (schema) => {
|
|
4012
|
+
const profileName = extractNameFromCanonical(schema.identifier.url);
|
|
4013
|
+
if (profileName) {
|
|
4014
|
+
return `${normalizeTsName(profileName)}Profile`;
|
|
4015
|
+
}
|
|
4016
|
+
return `${normalizeTsName(schema.identifier.name)}Profile`;
|
|
3789
4017
|
};
|
|
3790
4018
|
var tsSliceInputTypeName = (profileName, fieldName, sliceName) => {
|
|
3791
4019
|
return `${uppercaseFirstLetter(profileName)}_${uppercaseFirstLetter(normalizeTsName(fieldName))}_${uppercaseFirstLetter(normalizeTsName(sliceName))}SliceInput`;
|
|
@@ -3821,21 +4049,33 @@ var TypeScript = class extends Writer {
|
|
|
3821
4049
|
tsImportType(tsPackageName, ...entities) {
|
|
3822
4050
|
this.lineSM(`import type { ${entities.join(", ")} } from "${tsPackageName}"`);
|
|
3823
4051
|
}
|
|
3824
|
-
generateProfileIndexFile(
|
|
3825
|
-
if (
|
|
4052
|
+
generateProfileIndexFile(tsIndex, initialProfiles) {
|
|
4053
|
+
if (initialProfiles.length === 0) return;
|
|
3826
4054
|
this.cd("profiles", () => {
|
|
3827
4055
|
this.cat("index.ts", () => {
|
|
3828
|
-
const
|
|
3829
|
-
|
|
3830
|
-
const
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
|
|
4056
|
+
const profiles = initialProfiles.map((profile) => {
|
|
4057
|
+
const className = tsProfileClassName(profile);
|
|
4058
|
+
const resourceName = tsResourceName(profile.identifier);
|
|
4059
|
+
const overrides = this.detectFieldOverrides(tsIndex, profile);
|
|
4060
|
+
let typeExport;
|
|
4061
|
+
if (overrides.size > 0) typeExport = resourceName;
|
|
4062
|
+
return [profile, className, typeExport];
|
|
3834
4063
|
});
|
|
3835
|
-
if (
|
|
3836
|
-
|
|
3837
|
-
|
|
3838
|
-
|
|
4064
|
+
if (profiles.length === 0) return;
|
|
4065
|
+
const classExports = /* @__PURE__ */ new Map();
|
|
4066
|
+
const typeExports = /* @__PURE__ */ new Map();
|
|
4067
|
+
for (const [profile, className, typeName] of profiles) {
|
|
4068
|
+
const moduleName = tsProfileModuleName(tsIndex, profile);
|
|
4069
|
+
if (!classExports.has(className)) {
|
|
4070
|
+
classExports.set(className, `export { ${className} } from "./${moduleName}"`);
|
|
4071
|
+
}
|
|
4072
|
+
if (typeName && !typeExports.has(typeName)) {
|
|
4073
|
+
typeExports.set(typeName, `export type { ${typeName} } from "./${moduleName}"`);
|
|
4074
|
+
}
|
|
4075
|
+
}
|
|
4076
|
+
const allExports = [...classExports.values(), ...typeExports.values()].sort();
|
|
4077
|
+
for (const exp of allExports) {
|
|
4078
|
+
this.lineSM(exp);
|
|
3839
4079
|
}
|
|
3840
4080
|
});
|
|
3841
4081
|
});
|
|
@@ -3929,14 +4169,16 @@ var TypeScript = class extends Writer {
|
|
|
3929
4169
|
this.line();
|
|
3930
4170
|
}
|
|
3931
4171
|
}
|
|
3932
|
-
addFieldExtension(fieldName) {
|
|
4172
|
+
addFieldExtension(fieldName, isArray) {
|
|
3933
4173
|
const extFieldName = tsFieldName(`_${fieldName}`);
|
|
3934
|
-
|
|
4174
|
+
const typeExpr = isArray ? "(Element | null)[]" : "Element";
|
|
4175
|
+
this.lineSM(`${extFieldName}?: ${typeExpr}`);
|
|
3935
4176
|
}
|
|
3936
4177
|
generateType(tsIndex, schema) {
|
|
3937
4178
|
let name;
|
|
3938
|
-
|
|
3939
|
-
|
|
4179
|
+
const genericTypes = ["Reference", "Coding", "CodeableConcept"];
|
|
4180
|
+
if (genericTypes.includes(schema.identifier.name)) {
|
|
4181
|
+
name = `${schema.identifier.name}<T extends string = string>`;
|
|
3940
4182
|
} else if (schema.identifier.kind === "nested") {
|
|
3941
4183
|
name = tsResourceName(schema.identifier);
|
|
3942
4184
|
} else {
|
|
@@ -3963,29 +4205,16 @@ var TypeScript = class extends Writer {
|
|
|
3963
4205
|
const fields = Object.entries(schema.fields).sort((a, b) => a[0].localeCompare(b[0]));
|
|
3964
4206
|
for (const [fieldName, field] of fields) {
|
|
3965
4207
|
if (isChoiceDeclarationField(field)) continue;
|
|
4208
|
+
if (!field.type) continue;
|
|
3966
4209
|
this.debugComment(fieldName, ":", field);
|
|
3967
4210
|
const tsName = tsFieldName(fieldName);
|
|
3968
|
-
|
|
3969
|
-
if (field.enum) {
|
|
3970
|
-
tsType = tsEnumType(field.enum);
|
|
3971
|
-
} else if (schema.identifier.name === "Reference" && tsName === "reference") {
|
|
3972
|
-
tsType = "`${T}/${string}`";
|
|
3973
|
-
} else if (field.reference && field.reference.length > 0) {
|
|
3974
|
-
const references = field.reference.map((ref) => `"${ref.name}"`).join(" | ");
|
|
3975
|
-
tsType = `Reference<${references}>`;
|
|
3976
|
-
} else if (isPrimitiveIdentifier(field.type)) {
|
|
3977
|
-
tsType = resolvePrimitiveType(field.type.name);
|
|
3978
|
-
} else if (isNestedIdentifier(field.type)) {
|
|
3979
|
-
tsType = tsResourceName(field.type);
|
|
3980
|
-
} else {
|
|
3981
|
-
tsType = field.type.name;
|
|
3982
|
-
}
|
|
4211
|
+
const tsType = resolveFieldTsType(schema.identifier.name, tsName, field);
|
|
3983
4212
|
const optionalSymbol = field.required ? "" : "?";
|
|
3984
4213
|
const arraySymbol = field.array ? "[]" : "";
|
|
3985
4214
|
this.lineSM(`${tsName}${optionalSymbol}: ${tsType}${arraySymbol}`);
|
|
3986
4215
|
if (this.withPrimitiveTypeExtension(schema)) {
|
|
3987
4216
|
if (isPrimitiveIdentifier(field.type)) {
|
|
3988
|
-
this.addFieldExtension(fieldName);
|
|
4217
|
+
this.addFieldExtension(fieldName, field.array ?? false);
|
|
3989
4218
|
}
|
|
3990
4219
|
}
|
|
3991
4220
|
}
|
|
@@ -4021,10 +4250,16 @@ var TypeScript = class extends Writer {
|
|
|
4021
4250
|
if (!isNotChoiceDeclarationField(field)) {
|
|
4022
4251
|
throw new Error(`Choice declaration fields not supported for '${fieldName}'`);
|
|
4023
4252
|
}
|
|
4253
|
+
let tsType;
|
|
4024
4254
|
if (field.enum) {
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4255
|
+
if (field.type?.name === "Coding") {
|
|
4256
|
+
tsType = `Coding<${tsEnumType(field.enum)}>`;
|
|
4257
|
+
} else if (field.type?.name === "CodeableConcept") {
|
|
4258
|
+
tsType = `CodeableConcept<${tsEnumType(field.enum)}>`;
|
|
4259
|
+
} else {
|
|
4260
|
+
tsType = tsEnumType(field.enum);
|
|
4261
|
+
}
|
|
4262
|
+
} else if (field.reference && field.reference.length > 0) {
|
|
4028
4263
|
const specialization = tsIndex.findLastSpecialization(flatProfile);
|
|
4029
4264
|
if (!isSpecializationTypeSchema(specialization))
|
|
4030
4265
|
throw new Error(`Invalid specialization for ${flatProfile.identifier}`);
|
|
@@ -4041,20 +4276,20 @@ var TypeScript = class extends Writer {
|
|
|
4041
4276
|
}).join(" | ");
|
|
4042
4277
|
if (sRefs.length === 1 && sRefs[0] === "Resource" && references !== '"Resource"') {
|
|
4043
4278
|
const cleanRefs = references.replace(/\/\*[^*]*\*\//g, "").trim();
|
|
4044
|
-
|
|
4279
|
+
tsType = `Reference<"Resource" /* ${cleanRefs} */ >`;
|
|
4280
|
+
} else {
|
|
4281
|
+
tsType = `Reference<${references}>`;
|
|
4045
4282
|
}
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
if (isNestedIdentifier(field.type)) {
|
|
4049
|
-
|
|
4050
|
-
}
|
|
4051
|
-
if (isPrimitiveIdentifier(field.type)) {
|
|
4052
|
-
return resolvePrimitiveType(field.type.name);
|
|
4053
|
-
}
|
|
4054
|
-
if (field.type === void 0) {
|
|
4283
|
+
} else if (isPrimitiveIdentifier(field.type)) {
|
|
4284
|
+
tsType = resolvePrimitiveType(field.type.name);
|
|
4285
|
+
} else if (isNestedIdentifier(field.type)) {
|
|
4286
|
+
tsType = tsResourceName(field.type);
|
|
4287
|
+
} else if (field.type === void 0) {
|
|
4055
4288
|
throw new Error(`Undefined type for '${fieldName}' field at ${typeSchemaInfo(flatProfile)}`);
|
|
4289
|
+
} else {
|
|
4290
|
+
tsType = field.type.name;
|
|
4056
4291
|
}
|
|
4057
|
-
return
|
|
4292
|
+
return tsType;
|
|
4058
4293
|
}
|
|
4059
4294
|
generateProfileType(tsIndex, flatProfile) {
|
|
4060
4295
|
this.debugComment("flatProfile", flatProfile);
|
|
@@ -4358,104 +4593,95 @@ var TypeScript = class extends Writer {
|
|
|
4358
4593
|
this.lineSM(`import { ${imports.join(", ")} } from "../../profile-helpers"`);
|
|
4359
4594
|
}
|
|
4360
4595
|
}
|
|
4361
|
-
|
|
4362
|
-
const
|
|
4363
|
-
const getModulePath = (typeId) => {
|
|
4364
|
-
if (isNestedIdentifier(typeId)) {
|
|
4365
|
-
const url = typeId.url;
|
|
4366
|
-
const path = canonicalToName3(url, true);
|
|
4367
|
-
if (path) {
|
|
4368
|
-
return `../../${tsFhirPackageDir(typeId.package)}/${pascalCase(path)}`;
|
|
4369
|
-
}
|
|
4370
|
-
}
|
|
4371
|
-
return `../../${tsModulePath(typeId)}`;
|
|
4372
|
-
};
|
|
4373
|
-
const addType = (typeId) => {
|
|
4374
|
-
if (typeId.kind === "primitive-type") return;
|
|
4375
|
-
const tsName = tsResourceName(typeId);
|
|
4376
|
-
if (!usedTypes.has(tsName)) {
|
|
4377
|
-
usedTypes.set(tsName, {
|
|
4378
|
-
importPath: getModulePath(typeId),
|
|
4379
|
-
tsName
|
|
4380
|
-
});
|
|
4381
|
-
}
|
|
4382
|
-
};
|
|
4383
|
-
addType(flatProfile.base);
|
|
4384
|
-
const fields = flatProfile.fields ?? {};
|
|
4385
|
-
for (const [_fieldName, field] of Object.entries(fields)) {
|
|
4596
|
+
collectTypesFromSlices(flatProfile, addType) {
|
|
4597
|
+
for (const field of Object.values(flatProfile.fields ?? {})) {
|
|
4386
4598
|
if (!isNotChoiceDeclarationField(field) || !field.slicing?.slices || !field.type) continue;
|
|
4387
|
-
for (const
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4599
|
+
for (const slice of Object.values(field.slicing.slices)) {
|
|
4600
|
+
if (Object.keys(slice.match ?? {}).length > 0) {
|
|
4601
|
+
addType(field.type);
|
|
4602
|
+
}
|
|
4391
4603
|
}
|
|
4392
4604
|
}
|
|
4393
|
-
|
|
4605
|
+
}
|
|
4606
|
+
collectTypesFromExtensions(tsIndex, flatProfile, addType) {
|
|
4394
4607
|
let needsExtensionType = false;
|
|
4395
|
-
for (const ext of extensions) {
|
|
4608
|
+
for (const ext of flatProfile.extensions ?? []) {
|
|
4396
4609
|
if (ext.isComplex && ext.subExtensions) {
|
|
4397
4610
|
needsExtensionType = true;
|
|
4398
4611
|
for (const sub of ext.subExtensions) {
|
|
4399
|
-
if (sub.valueType)
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
addType(resolvedType.identifier);
|
|
4406
|
-
} else {
|
|
4407
|
-
addType(sub.valueType);
|
|
4408
|
-
}
|
|
4409
|
-
}
|
|
4612
|
+
if (!sub.valueType) continue;
|
|
4613
|
+
const resolvedType = tsIndex.resolveByUrl(
|
|
4614
|
+
flatProfile.identifier.package,
|
|
4615
|
+
sub.valueType.url
|
|
4616
|
+
);
|
|
4617
|
+
addType(resolvedType?.identifier ?? sub.valueType);
|
|
4410
4618
|
}
|
|
4411
4619
|
} else if (ext.valueTypes && ext.valueTypes.length === 1) {
|
|
4412
4620
|
needsExtensionType = true;
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4621
|
+
if (ext.valueTypes[0]) {
|
|
4622
|
+
const resolvedType = tsIndex.resolveByUrl(
|
|
4623
|
+
flatProfile.identifier.package,
|
|
4624
|
+
ext.valueTypes[0].url
|
|
4625
|
+
);
|
|
4626
|
+
addType(resolvedType?.identifier ?? ext.valueTypes[0]);
|
|
4416
4627
|
}
|
|
4417
4628
|
} else {
|
|
4418
4629
|
needsExtensionType = true;
|
|
4419
4630
|
}
|
|
4420
4631
|
}
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
if (extensionSchema) {
|
|
4425
|
-
addType(extensionSchema.identifier);
|
|
4426
|
-
}
|
|
4427
|
-
}
|
|
4632
|
+
return needsExtensionType;
|
|
4633
|
+
}
|
|
4634
|
+
collectTypesFromFieldOverrides(tsIndex, flatProfile, addType) {
|
|
4428
4635
|
const referenceUrl = "http://hl7.org/fhir/StructureDefinition/Reference";
|
|
4429
4636
|
const referenceSchema = tsIndex.resolveByUrl(flatProfile.identifier.package, referenceUrl);
|
|
4430
4637
|
const specialization = tsIndex.findLastSpecialization(flatProfile);
|
|
4431
|
-
if (isSpecializationTypeSchema(specialization))
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4638
|
+
if (!isSpecializationTypeSchema(specialization)) return;
|
|
4639
|
+
for (const [fieldName, pField] of Object.entries(flatProfile.fields ?? {})) {
|
|
4640
|
+
if (!isNotChoiceDeclarationField(pField)) continue;
|
|
4641
|
+
const sField = specialization.fields?.[fieldName];
|
|
4642
|
+
if (!sField || isChoiceDeclarationField(sField)) continue;
|
|
4643
|
+
if (pField.reference && sField.reference && pField.reference.length < sField.reference.length) {
|
|
4644
|
+
if (referenceSchema) addType(referenceSchema.identifier);
|
|
4645
|
+
} else if (pField.required && !sField.required && pField.type) {
|
|
4646
|
+
addType(pField.type);
|
|
4647
|
+
}
|
|
4648
|
+
}
|
|
4649
|
+
}
|
|
4650
|
+
generateProfileImports(tsIndex, flatProfile) {
|
|
4651
|
+
const usedTypes = /* @__PURE__ */ new Map();
|
|
4652
|
+
const getModulePath = (typeId) => {
|
|
4653
|
+
if (isNestedIdentifier(typeId)) {
|
|
4654
|
+
const path = canonicalToName3(typeId.url, true);
|
|
4655
|
+
if (path) return `../../${tsFhirPackageDir(typeId.package)}/${pascalCase(path)}`;
|
|
4656
|
+
}
|
|
4657
|
+
return `../../${tsModulePath(typeId)}`;
|
|
4658
|
+
};
|
|
4659
|
+
const addType = (typeId) => {
|
|
4660
|
+
if (typeId.kind === "primitive-type") return;
|
|
4661
|
+
const tsName = tsResourceName(typeId);
|
|
4662
|
+
if (!usedTypes.has(tsName)) {
|
|
4663
|
+
usedTypes.set(tsName, { importPath: getModulePath(typeId), tsName });
|
|
4445
4664
|
}
|
|
4665
|
+
};
|
|
4666
|
+
addType(flatProfile.base);
|
|
4667
|
+
this.collectTypesFromSlices(flatProfile, addType);
|
|
4668
|
+
const needsExtensionType = this.collectTypesFromExtensions(tsIndex, flatProfile, addType);
|
|
4669
|
+
this.collectTypesFromFieldOverrides(tsIndex, flatProfile, addType);
|
|
4670
|
+
if (needsExtensionType) {
|
|
4671
|
+
const extensionUrl = "http://hl7.org/fhir/StructureDefinition/Extension";
|
|
4672
|
+
const extensionSchema = tsIndex.resolveByUrl(flatProfile.identifier.package, extensionUrl);
|
|
4673
|
+
if (extensionSchema) addType(extensionSchema.identifier);
|
|
4446
4674
|
}
|
|
4447
4675
|
const sortedImports = Array.from(usedTypes.values()).sort((a, b) => a.tsName.localeCompare(b.tsName));
|
|
4448
4676
|
for (const { importPath, tsName } of sortedImports) {
|
|
4449
4677
|
this.tsImportType(importPath, tsName);
|
|
4450
4678
|
}
|
|
4451
|
-
if (sortedImports.length > 0)
|
|
4452
|
-
this.line();
|
|
4453
|
-
}
|
|
4679
|
+
if (sortedImports.length > 0) this.line();
|
|
4454
4680
|
}
|
|
4455
4681
|
generateProfileClass(tsIndex, flatProfile) {
|
|
4456
4682
|
const tsBaseResourceName = tsTypeFromIdentifier(flatProfile.base);
|
|
4457
4683
|
const tsProfileName = tsResourceName(flatProfile.identifier);
|
|
4458
|
-
const profileClassName = tsProfileClassName(flatProfile
|
|
4684
|
+
const profileClassName = tsProfileClassName(flatProfile);
|
|
4459
4685
|
const polymorphicBaseNames = /* @__PURE__ */ new Set([
|
|
4460
4686
|
"value",
|
|
4461
4687
|
"effective",
|
|
@@ -4887,7 +5113,7 @@ var TypeScript = class extends Writer {
|
|
|
4887
5113
|
generateResourceModule(tsIndex, schema) {
|
|
4888
5114
|
if (isProfileTypeSchema(schema)) {
|
|
4889
5115
|
this.cd("profiles", () => {
|
|
4890
|
-
this.cat(`${
|
|
5116
|
+
this.cat(`${tsProfileModuleFileName(tsIndex, schema)}`, () => {
|
|
4891
5117
|
this.generateDisclaimer();
|
|
4892
5118
|
const flatProfile = tsIndex.flatProfile(schema);
|
|
4893
5119
|
this.generateProfileImports(tsIndex, flatProfile);
|
|
@@ -4937,7 +5163,7 @@ var TypeScript = class extends Writer {
|
|
|
4937
5163
|
for (const schema of packageSchemas) {
|
|
4938
5164
|
this.generateResourceModule(tsIndex, schema);
|
|
4939
5165
|
}
|
|
4940
|
-
this.generateProfileIndexFile(packageSchemas.filter(isProfileTypeSchema));
|
|
5166
|
+
this.generateProfileIndexFile(tsIndex, packageSchemas.filter(isProfileTypeSchema));
|
|
4941
5167
|
this.generateFhirPackageIndexFile(packageSchemas);
|
|
4942
5168
|
});
|
|
4943
5169
|
}
|
|
@@ -4994,7 +5220,8 @@ var APIBuilder = class {
|
|
|
4994
5220
|
treeShake: void 0,
|
|
4995
5221
|
promoteLogical: void 0,
|
|
4996
5222
|
registry: void 0,
|
|
4997
|
-
logLevel: parseLogLevel("INFO")
|
|
5223
|
+
logLevel: parseLogLevel("INFO"),
|
|
5224
|
+
dropCanonicalManagerCache: false
|
|
4998
5225
|
};
|
|
4999
5226
|
const opts = {
|
|
5000
5227
|
...defaultOpts,
|
|
@@ -5016,7 +5243,8 @@ var APIBuilder = class {
|
|
|
5016
5243
|
this.manager = userOpts.manager ?? CanonicalManager({
|
|
5017
5244
|
packages: [],
|
|
5018
5245
|
workingDir: ".codegen-cache/canonical-manager-cache",
|
|
5019
|
-
registry: userOpts.registry
|
|
5246
|
+
registry: userOpts.registry,
|
|
5247
|
+
dropCache: userOpts.dropCanonicalManagerCache
|
|
5020
5248
|
});
|
|
5021
5249
|
this.logger = userOpts.logger ?? createLogger({ prefix: "API", level: opts.logLevel });
|
|
5022
5250
|
this.options = opts;
|
|
@@ -5030,14 +5258,6 @@ var APIBuilder = class {
|
|
|
5030
5258
|
this.managerInput.npmPackages.push(packageRef);
|
|
5031
5259
|
return this;
|
|
5032
5260
|
}
|
|
5033
|
-
/**
|
|
5034
|
-
* Set a custom FHIR package registry URL
|
|
5035
|
-
* @param url The registry URL (default: https://fs.get-ig.org/pkgs/)
|
|
5036
|
-
*/
|
|
5037
|
-
registry(url) {
|
|
5038
|
-
this.options.registry = url;
|
|
5039
|
-
return this;
|
|
5040
|
-
}
|
|
5041
5261
|
localStructureDefinitions(config) {
|
|
5042
5262
|
this.logger.info(`Registering local StructureDefinitions for ${config.package.name}@${config.package.version}`);
|
|
5043
5263
|
this.managerInput.localSDs.push({
|
|
@@ -5241,10 +5461,11 @@ var APIBuilder = class {
|
|
|
5241
5461
|
focusedPackages: packageMetas
|
|
5242
5462
|
});
|
|
5243
5463
|
}
|
|
5244
|
-
const typeSchemas = await generateTypeSchemas(register, this.logger);
|
|
5464
|
+
const { schemas: typeSchemas, collisions } = await generateTypeSchemas(register, this.logger);
|
|
5245
5465
|
const tsIndexOpts = {
|
|
5246
5466
|
register,
|
|
5247
|
-
logger: this.logger
|
|
5467
|
+
logger: this.logger,
|
|
5468
|
+
irReport: Object.keys(collisions).length > 0 ? { collisions } : {}
|
|
5248
5469
|
};
|
|
5249
5470
|
let tsIndex = mkTypeSchemaIndex(typeSchemas, tsIndexOpts);
|
|
5250
5471
|
if (this.options.treeShake) tsIndex = treeShake(tsIndex, this.options.treeShake);
|
|
@@ -5298,6 +5519,6 @@ var APIBuilder = class {
|
|
|
5298
5519
|
}
|
|
5299
5520
|
};
|
|
5300
5521
|
|
|
5301
|
-
export { APIBuilder, LogLevel, prettyReport };
|
|
5522
|
+
export { APIBuilder, LogLevel, prettyReport, registerFromPackageMetas };
|
|
5302
5523
|
//# sourceMappingURL=index.js.map
|
|
5303
5524
|
//# sourceMappingURL=index.js.map
|