@atomic-ehr/codegen 0.0.9 → 0.0.10-canary.20260330084405.5054c4a
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/README.md +55 -1
- package/dist/cli/index.js +5 -5
- package/dist/index.d.ts +237 -69
- package/dist/index.js +439 -360
- package/dist/index.js.map +1 -1
- package/package.json +9 -7
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import pc from 'picocolors';
|
|
2
|
-
import
|
|
2
|
+
import assert4 from 'assert';
|
|
3
3
|
import * as fs from 'fs';
|
|
4
4
|
import fs__default from 'fs';
|
|
5
5
|
import * as Path5 from 'path';
|
|
@@ -138,9 +138,6 @@ var uppercaseFirstLetter = (str) => {
|
|
|
138
138
|
var uppercaseFirstLetterOfEach = (strings) => {
|
|
139
139
|
return strings.map((str) => uppercaseFirstLetter(str));
|
|
140
140
|
};
|
|
141
|
-
var typeSchemaInfo = (schema) => {
|
|
142
|
-
return `<${schema.identifier.url}> from ${schema.identifier.package}#${schema.identifier.version}`;
|
|
143
|
-
};
|
|
144
141
|
var FileSystemWriter = class {
|
|
145
142
|
opts;
|
|
146
143
|
currentDir;
|
|
@@ -362,8 +359,11 @@ var hashSchema = (schema) => {
|
|
|
362
359
|
return createHash("sha256").update(json).digest("hex").slice(0, 16);
|
|
363
360
|
};
|
|
364
361
|
var enrichFHIRSchema = (schema, packageMeta2) => {
|
|
362
|
+
const derivation = schema.derivation === "constraint" ? "constraint" : "specialization";
|
|
365
363
|
return {
|
|
366
364
|
...schema,
|
|
365
|
+
derivation,
|
|
366
|
+
kind: schema.kind,
|
|
367
367
|
package_meta: schema.package_meta || packageMeta2,
|
|
368
368
|
name: schema.name,
|
|
369
369
|
url: schema.url,
|
|
@@ -382,15 +382,15 @@ var isPrimitiveIdentifier = (id) => {
|
|
|
382
382
|
var isNestedIdentifier = (id) => {
|
|
383
383
|
return id?.kind === "nested";
|
|
384
384
|
};
|
|
385
|
-
var isProfileIdentifier = (id) => {
|
|
386
|
-
return id?.kind === "profile";
|
|
387
|
-
};
|
|
388
385
|
var concatIdentifiers = (...sources) => {
|
|
389
386
|
const entries = sources.filter((s) => s !== void 0).flatMap((s) => s.map((id) => [id.url, id]));
|
|
390
387
|
if (entries.length === 0) return void 0;
|
|
391
388
|
const deduped = Object.values(Object.fromEntries(entries));
|
|
392
389
|
return deduped.sort((a, b) => a.url.localeCompare(b.url));
|
|
393
390
|
};
|
|
391
|
+
var isNestedTypeSchema = (schema) => {
|
|
392
|
+
return schema !== void 0 && isNestedIdentifier(schema.identifier);
|
|
393
|
+
};
|
|
394
394
|
var isSpecializationTypeSchema = (schema) => {
|
|
395
395
|
return schema?.identifier.kind === "resource" || schema?.identifier.kind === "complex-type" || schema?.identifier.kind === "logical";
|
|
396
396
|
};
|
|
@@ -409,12 +409,17 @@ var isLogicalTypeSchema = (schema) => {
|
|
|
409
409
|
var isProfileTypeSchema = (schema) => {
|
|
410
410
|
return schema?.identifier.kind === "profile";
|
|
411
411
|
};
|
|
412
|
-
|
|
412
|
+
var isBindingSchema = (schema) => {
|
|
413
413
|
return schema?.identifier.kind === "binding";
|
|
414
|
-
}
|
|
415
|
-
|
|
414
|
+
};
|
|
415
|
+
var isValueSetTypeSchema = (schema) => {
|
|
416
416
|
return schema?.identifier.kind === "value-set";
|
|
417
|
-
}
|
|
417
|
+
};
|
|
418
|
+
var extractExtensionDeps = (ext) => [
|
|
419
|
+
...ext.valueFieldTypes ?? [],
|
|
420
|
+
...ext.profile ? [ext.profile] : [],
|
|
421
|
+
...ext.subExtensions?.flatMap((sub) => sub.valueFieldType ? [sub.valueFieldType] : []) ?? []
|
|
422
|
+
];
|
|
418
423
|
var isNotChoiceDeclarationField = (field) => {
|
|
419
424
|
if (!field) return false;
|
|
420
425
|
return field.choices === void 0;
|
|
@@ -832,51 +837,36 @@ var sortAsDeclarationSequence = (schemas) => {
|
|
|
832
837
|
const sorted = topologicalSort(graph);
|
|
833
838
|
return sorted.map((name) => schemas.find((schema) => schema.identifier.name === name)).filter(Boolean);
|
|
834
839
|
};
|
|
835
|
-
var
|
|
836
|
-
const
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
}
|
|
853
|
-
const transitiveCache = /* @__PURE__ */ new Map();
|
|
854
|
-
const getTransitiveChildren = (parentName) => {
|
|
855
|
-
const cached = transitiveCache.get(parentName);
|
|
856
|
-
if (cached) return cached;
|
|
857
|
-
const directChildren = childrenByParent.get(parentName) ?? [];
|
|
858
|
-
const result = [...directChildren];
|
|
859
|
-
for (const child of directChildren) {
|
|
860
|
-
result.push(...getTransitiveChildren(child.name));
|
|
861
|
-
}
|
|
862
|
-
transitiveCache.set(parentName, result);
|
|
840
|
+
var populateTypeFamily = (schemas) => {
|
|
841
|
+
const directChildrenByParent = {};
|
|
842
|
+
for (const schema of schemas) {
|
|
843
|
+
if (!isSpecializationTypeSchema(schema) || !schema.base) continue;
|
|
844
|
+
const parentUrl = schema.base.url;
|
|
845
|
+
if (!directChildrenByParent[parentUrl]) directChildrenByParent[parentUrl] = [];
|
|
846
|
+
directChildrenByParent[parentUrl].push(schema.identifier);
|
|
847
|
+
}
|
|
848
|
+
const transitiveCache = {};
|
|
849
|
+
const getTransitiveChildren = (parentUrl) => {
|
|
850
|
+
if (transitiveCache[parentUrl]) return transitiveCache[parentUrl];
|
|
851
|
+
const direct = directChildrenByParent[parentUrl] ?? [];
|
|
852
|
+
const result = [...direct];
|
|
853
|
+
for (const child of direct) {
|
|
854
|
+
result.push(...getTransitiveChildren(child.url));
|
|
855
|
+
}
|
|
856
|
+
transitiveCache[parentUrl] = result;
|
|
863
857
|
return result;
|
|
864
858
|
};
|
|
865
|
-
const
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
allPairs.push({ parent: pair.parent, child: transitiveChild });
|
|
876
|
-
}
|
|
877
|
-
}
|
|
859
|
+
for (const schema of schemas) {
|
|
860
|
+
if (!isSpecializationTypeSchema(schema)) continue;
|
|
861
|
+
const allChildren = getTransitiveChildren(schema.identifier.url);
|
|
862
|
+
if (allChildren.length === 0) continue;
|
|
863
|
+
const resources = allChildren.filter(isResourceIdentifier);
|
|
864
|
+
const complexTypes = allChildren.filter(isComplexTypeIdentifier);
|
|
865
|
+
const family = {};
|
|
866
|
+
if (resources.length > 0) family.resources = resources;
|
|
867
|
+
if (complexTypes.length > 0) family.complexTypes = complexTypes;
|
|
868
|
+
if (Object.keys(family).length > 0) schema.typeFamily = family;
|
|
878
869
|
}
|
|
879
|
-
return allPairs;
|
|
880
870
|
};
|
|
881
871
|
var mkTypeSchemaIndex = (schemas, {
|
|
882
872
|
register,
|
|
@@ -910,9 +900,12 @@ var mkTypeSchemaIndex = (schemas, {
|
|
|
910
900
|
for (const schema of schemas) {
|
|
911
901
|
append(schema);
|
|
912
902
|
}
|
|
913
|
-
|
|
903
|
+
populateTypeFamily(schemas);
|
|
914
904
|
const resolve6 = (id) => {
|
|
915
|
-
|
|
905
|
+
return index[id.url]?.[id.package];
|
|
906
|
+
};
|
|
907
|
+
const resolveType = (id) => {
|
|
908
|
+
if (isNestedIdentifier(id)) return nestedIndex[id.url]?.[id.package];
|
|
916
909
|
return index[id.url]?.[id.package];
|
|
917
910
|
};
|
|
918
911
|
const resolveByUrl = (pkgName, url) => {
|
|
@@ -924,6 +917,7 @@ var mkTypeSchemaIndex = (schemas, {
|
|
|
924
917
|
}
|
|
925
918
|
}
|
|
926
919
|
if (index[url]?.[pkgName]) return index[url]?.[pkgName];
|
|
920
|
+
if (nestedIndex[url]?.[pkgName]) return nestedIndex[url]?.[pkgName];
|
|
927
921
|
logger?.dryWarn(`Type '${url}' not found in '${pkgName}'`);
|
|
928
922
|
if (index[url]) {
|
|
929
923
|
const anyPkg = Object.keys(index[url])[0];
|
|
@@ -932,11 +926,15 @@ var mkTypeSchemaIndex = (schemas, {
|
|
|
932
926
|
return index[url]?.[anyPkg];
|
|
933
927
|
}
|
|
934
928
|
}
|
|
929
|
+
if (nestedIndex[url]) {
|
|
930
|
+
const anyPkg = Object.keys(nestedIndex[url])[0];
|
|
931
|
+
if (anyPkg) {
|
|
932
|
+
logger?.dryWarn(`Type '${url}' fallback to package ${anyPkg}`);
|
|
933
|
+
return nestedIndex[url]?.[anyPkg];
|
|
934
|
+
}
|
|
935
|
+
}
|
|
935
936
|
return void 0;
|
|
936
937
|
};
|
|
937
|
-
const resourceChildren = (id) => {
|
|
938
|
-
return relations.filter((relative) => relative.parent.name === id.name).map((relative) => relative.child);
|
|
939
|
-
};
|
|
940
938
|
const tryHierarchy = (schema) => {
|
|
941
939
|
const res = [];
|
|
942
940
|
let cur = schema;
|
|
@@ -944,6 +942,7 @@ var mkTypeSchemaIndex = (schemas, {
|
|
|
944
942
|
res.push(cur);
|
|
945
943
|
const base = cur.base;
|
|
946
944
|
if (base === void 0) break;
|
|
945
|
+
if (isNestedIdentifier(base)) break;
|
|
947
946
|
const resolved = resolve6(base);
|
|
948
947
|
if (!resolved) {
|
|
949
948
|
logger?.warn(
|
|
@@ -971,9 +970,35 @@ var mkTypeSchemaIndex = (schemas, {
|
|
|
971
970
|
return nonConstraintSchema;
|
|
972
971
|
};
|
|
973
972
|
const findLastSpecializationByIdentifier = (id) => {
|
|
974
|
-
const
|
|
975
|
-
if (!
|
|
976
|
-
return
|
|
973
|
+
const resolved = resolveType(id);
|
|
974
|
+
if (!resolved) return id;
|
|
975
|
+
if (isNestedTypeSchema(resolved)) return findLastSpecializationByIdentifier(resolved.base);
|
|
976
|
+
return findLastSpecialization(resolved).identifier;
|
|
977
|
+
};
|
|
978
|
+
const narrowMergedChoiceDeclarations = (mergedFields, constraintSchemas) => {
|
|
979
|
+
const result = { ...mergedFields };
|
|
980
|
+
for (const [declName, declField] of Object.entries(result)) {
|
|
981
|
+
if (!isChoiceDeclarationField(declField) || declField.excluded) continue;
|
|
982
|
+
for (const cSchema of constraintSchemas) {
|
|
983
|
+
const sFields = cSchema.fields;
|
|
984
|
+
if (!sFields) continue;
|
|
985
|
+
if (sFields[declName] && isChoiceDeclarationField(sFields[declName])) continue;
|
|
986
|
+
const instancesInSchema = Object.entries(sFields).filter(([_, f]) => isChoiceInstanceField(f) && f.choiceOf === declName).map(([name]) => name);
|
|
987
|
+
if (instancesInSchema.length === 0) continue;
|
|
988
|
+
const allowed = new Set(instancesInSchema);
|
|
989
|
+
result[declName] = { ...declField, choices: declField.choices.filter((c) => allowed.has(c)) };
|
|
990
|
+
break;
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
for (const [declName, declField] of Object.entries(result)) {
|
|
994
|
+
if (!isChoiceDeclarationField(declField)) continue;
|
|
995
|
+
const permitted = new Set(declField.excluded ? [] : declField.choices);
|
|
996
|
+
const prohibited = Object.entries(result).filter(
|
|
997
|
+
(e) => isChoiceInstanceField(e[1]) && e[1].choiceOf === declName
|
|
998
|
+
).filter(([name]) => !permitted.has(name)).map(([name]) => name);
|
|
999
|
+
if (prohibited.length > 0) result[declName] = { ...declField, prohibited };
|
|
1000
|
+
}
|
|
1001
|
+
return result;
|
|
977
1002
|
};
|
|
978
1003
|
const flatProfile = (schema) => {
|
|
979
1004
|
const hierarchySchemas = hierarchy(schema);
|
|
@@ -996,6 +1021,7 @@ var mkTypeSchemaIndex = (schemas, {
|
|
|
996
1021
|
}
|
|
997
1022
|
}
|
|
998
1023
|
}
|
|
1024
|
+
const narrowedFields = narrowMergedChoiceDeclarations(mergedFields, constraintSchemas);
|
|
999
1025
|
const dependencies = Object.values(
|
|
1000
1026
|
Object.fromEntries(
|
|
1001
1027
|
constraintSchemas.flatMap((s) => s.dependencies ?? []).map((dep) => [dep.url, dep])
|
|
@@ -1011,7 +1037,7 @@ var mkTypeSchemaIndex = (schemas, {
|
|
|
1011
1037
|
return {
|
|
1012
1038
|
...schema,
|
|
1013
1039
|
base: nonConstraintSchema.identifier,
|
|
1014
|
-
fields:
|
|
1040
|
+
fields: narrowedFields,
|
|
1015
1041
|
dependencies,
|
|
1016
1042
|
extensions: mergedExtensions.length > 0 ? mergedExtensions : void 0
|
|
1017
1043
|
};
|
|
@@ -1069,7 +1095,6 @@ var mkTypeSchemaIndex = (schemas, {
|
|
|
1069
1095
|
};
|
|
1070
1096
|
return {
|
|
1071
1097
|
_schemaIndex: index,
|
|
1072
|
-
_relations: relations,
|
|
1073
1098
|
schemas,
|
|
1074
1099
|
schemasByPackage: groupByPackages(schemas),
|
|
1075
1100
|
register,
|
|
@@ -1078,8 +1103,8 @@ var mkTypeSchemaIndex = (schemas, {
|
|
|
1078
1103
|
collectLogicalModels: () => schemas.filter(isLogicalTypeSchema),
|
|
1079
1104
|
collectProfiles: () => schemas.filter(isProfileTypeSchema),
|
|
1080
1105
|
resolve: resolve6,
|
|
1106
|
+
resolveType,
|
|
1081
1107
|
resolveByUrl,
|
|
1082
|
-
resourceChildren,
|
|
1083
1108
|
tryHierarchy,
|
|
1084
1109
|
hierarchy,
|
|
1085
1110
|
findLastSpecialization,
|
|
@@ -1373,8 +1398,7 @@ var Python = class extends Writer {
|
|
|
1373
1398
|
return names;
|
|
1374
1399
|
}
|
|
1375
1400
|
shouldImportResourceFamily(resource) {
|
|
1376
|
-
|
|
1377
|
-
return resource.identifier.kind === "resource" && this.tsIndex.resourceChildren(resource.identifier).length > 0;
|
|
1401
|
+
return resource.identifier.kind === "resource" && (resource.typeFamily?.resources?.length ?? 0) > 0;
|
|
1378
1402
|
}
|
|
1379
1403
|
generateExportsDeclaration(packageComplexTypes, allResourceNames) {
|
|
1380
1404
|
this.squareBlock(["__all__", "="], () => {
|
|
@@ -1426,11 +1450,11 @@ var Python = class extends Writer {
|
|
|
1426
1450
|
this.line("pass");
|
|
1427
1451
|
return;
|
|
1428
1452
|
}
|
|
1429
|
-
if (schema
|
|
1453
|
+
if (isResourceTypeSchema(schema)) {
|
|
1430
1454
|
this.generateResourceTypeField(schema);
|
|
1431
1455
|
}
|
|
1432
1456
|
this.generateFields(schema, schema.identifier.name);
|
|
1433
|
-
if (schema
|
|
1457
|
+
if (isResourceTypeSchema(schema)) {
|
|
1434
1458
|
this.generateResourceMethods(schema);
|
|
1435
1459
|
}
|
|
1436
1460
|
}
|
|
@@ -1439,8 +1463,7 @@ var Python = class extends Writer {
|
|
|
1439
1463
|
this.line(`model_config = ConfigDict(validate_by_name=True, serialize_by_alias=True, extra="${extraMode}")`);
|
|
1440
1464
|
}
|
|
1441
1465
|
generateResourceTypeField(schema) {
|
|
1442
|
-
|
|
1443
|
-
const hasChildren = this.tsIndex.resourceChildren(schema.identifier).length > 0;
|
|
1466
|
+
const hasChildren = (schema.typeFamily?.resources?.length ?? 0) > 0;
|
|
1444
1467
|
if (hasChildren) {
|
|
1445
1468
|
this.line(`${this.nameFormatFunction("resourceType")}: str = Field(`);
|
|
1446
1469
|
} else {
|
|
@@ -1602,7 +1625,7 @@ var Python = class extends Writer {
|
|
|
1602
1625
|
this.pyImportFrom(this.pyPackage(identifier), pascalCase(identifier.name));
|
|
1603
1626
|
}
|
|
1604
1627
|
generateResourceFamilies(packageResources) {
|
|
1605
|
-
|
|
1628
|
+
assert4(this.tsIndex !== void 0);
|
|
1606
1629
|
const packages = (
|
|
1607
1630
|
//this.helper.getPackages(packageResources, this.opts.rootPackageName);
|
|
1608
1631
|
Object.keys(groupByPackages(packageResources)).map(
|
|
@@ -1611,7 +1634,7 @@ var Python = class extends Writer {
|
|
|
1611
1634
|
);
|
|
1612
1635
|
const families = {};
|
|
1613
1636
|
for (const resource of this.tsIndex.collectResources()) {
|
|
1614
|
-
const children =
|
|
1637
|
+
const children = (resource.typeFamily?.resources ?? []).map((c) => c.name);
|
|
1615
1638
|
if (children.length > 0) {
|
|
1616
1639
|
const familyName = `${resource.identifier.name}Family`;
|
|
1617
1640
|
families[familyName] = children;
|
|
@@ -1730,22 +1753,20 @@ function getVersionFromUrl(url) {
|
|
|
1730
1753
|
const version = url.split("|")[1];
|
|
1731
1754
|
return version;
|
|
1732
1755
|
}
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
return "resource";
|
|
1740
|
-
}
|
|
1756
|
+
var identifierBase = (fhirSchema) => ({
|
|
1757
|
+
package: fhirSchema.package_meta.name,
|
|
1758
|
+
version: fhirSchema.package_meta.version,
|
|
1759
|
+
name: fhirSchema.name,
|
|
1760
|
+
url: fhirSchema.url
|
|
1761
|
+
});
|
|
1741
1762
|
function mkIdentifier(fhirSchema) {
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
};
|
|
1763
|
+
const fields = identifierBase(fhirSchema);
|
|
1764
|
+
if (fhirSchema.derivation === "constraint") return { kind: "profile", ...fields };
|
|
1765
|
+
if (fhirSchema.kind === "primitive-type") return { kind: "primitive-type", ...fields };
|
|
1766
|
+
if (fhirSchema.kind === "complex-type") return { kind: "complex-type", ...fields };
|
|
1767
|
+
if (fhirSchema.kind === "resource") return { kind: "resource", ...fields };
|
|
1768
|
+
if (fhirSchema.kind === "logical") return { kind: "logical", ...fields };
|
|
1769
|
+
return { kind: "resource", ...fields };
|
|
1749
1770
|
}
|
|
1750
1771
|
var getValueSetName = (url) => {
|
|
1751
1772
|
const urlParts = url.split("/");
|
|
@@ -1797,7 +1818,7 @@ function extractValueSetConceptsByUrl(register, pkg, valueSetUrl, logger) {
|
|
|
1797
1818
|
function extractValueSetConcepts(register, valueSet, _logger) {
|
|
1798
1819
|
if (valueSet.expansion?.contains) {
|
|
1799
1820
|
return valueSet.expansion.contains.filter((item) => item.code !== void 0).map((item) => {
|
|
1800
|
-
|
|
1821
|
+
assert4(item.code);
|
|
1801
1822
|
return {
|
|
1802
1823
|
code: item.code,
|
|
1803
1824
|
display: item.display,
|
|
@@ -2455,12 +2476,29 @@ var collectDiscriminatorValue = (schema, segments, index, result) => {
|
|
|
2455
2476
|
}
|
|
2456
2477
|
collectDiscriminatorValue(element, segments, index + 1, result);
|
|
2457
2478
|
};
|
|
2479
|
+
var computeTypeDiscriminatorMatch = (path, schema, result) => {
|
|
2480
|
+
if (path === "$this") return;
|
|
2481
|
+
const segments = path.split(".");
|
|
2482
|
+
let elem = schema;
|
|
2483
|
+
for (const seg of segments) {
|
|
2484
|
+
elem = elem?.elements?.[seg];
|
|
2485
|
+
if (!elem) return;
|
|
2486
|
+
}
|
|
2487
|
+
const typeName = elem.type;
|
|
2488
|
+
if (!typeName || typeName.includes("/")) return;
|
|
2489
|
+
setNestedValue(result, segments, { resourceType: typeName });
|
|
2490
|
+
};
|
|
2458
2491
|
var computeMatchFromSchema = (discriminators, schema) => {
|
|
2459
|
-
if (!schema
|
|
2492
|
+
if (!schema || !discriminators || discriminators.length === 0) return void 0;
|
|
2460
2493
|
const result = {};
|
|
2461
2494
|
for (const disc of discriminators) {
|
|
2462
|
-
|
|
2463
|
-
|
|
2495
|
+
if (disc.type === "type") {
|
|
2496
|
+
computeTypeDiscriminatorMatch(disc.path, schema, result);
|
|
2497
|
+
} else {
|
|
2498
|
+
if (!schema.elements) continue;
|
|
2499
|
+
const segments = disc.path.split(".");
|
|
2500
|
+
collectDiscriminatorValue(schema, segments, 0, result);
|
|
2501
|
+
}
|
|
2464
2502
|
}
|
|
2465
2503
|
return Object.keys(result).length > 0 ? result : void 0;
|
|
2466
2504
|
};
|
|
@@ -2481,7 +2519,7 @@ var buildSlicing = (element) => {
|
|
|
2481
2519
|
};
|
|
2482
2520
|
}
|
|
2483
2521
|
return {
|
|
2484
|
-
discriminator: slicing.discriminator,
|
|
2522
|
+
discriminator: slicing.discriminator ?? [],
|
|
2485
2523
|
rules: slicing.rules,
|
|
2486
2524
|
ordered: slicing.ordered,
|
|
2487
2525
|
slices: Object.keys(slices).length > 0 ? slices : void 0
|
|
@@ -2579,16 +2617,16 @@ function mkNestedField(register, fhirSchema, path, element) {
|
|
|
2579
2617
|
}
|
|
2580
2618
|
|
|
2581
2619
|
// src/typeschema/core/profile-extensions.ts
|
|
2582
|
-
var
|
|
2620
|
+
var extractExtensionValueFieldTypes = (register, fhirSchema, extensionUrl, logger) => {
|
|
2583
2621
|
const extensionSchema = register.resolveFs(fhirSchema.package_meta, extensionUrl);
|
|
2584
2622
|
if (!extensionSchema?.elements) return void 0;
|
|
2585
|
-
const
|
|
2623
|
+
const valueFieldTypes = [];
|
|
2586
2624
|
for (const [key, element] of Object.entries(extensionSchema.elements)) {
|
|
2587
2625
|
if (element.choiceOf !== "value" && !key.startsWith("value")) continue;
|
|
2588
2626
|
const fieldType = buildFieldType(register, extensionSchema, [key], element, logger);
|
|
2589
|
-
if (fieldType)
|
|
2627
|
+
if (fieldType) valueFieldTypes.push(fieldType);
|
|
2590
2628
|
}
|
|
2591
|
-
return concatIdentifiers(
|
|
2629
|
+
return concatIdentifiers(valueFieldTypes);
|
|
2592
2630
|
};
|
|
2593
2631
|
var extractLegacySubExtensions = (register, extensionSchema, logger) => {
|
|
2594
2632
|
const subExtensions = [];
|
|
@@ -2606,14 +2644,14 @@ var extractLegacySubExtensions = (register, extensionSchema, logger) => {
|
|
|
2606
2644
|
subExtensions.push({
|
|
2607
2645
|
name: sliceName,
|
|
2608
2646
|
url: element.url ?? sliceName,
|
|
2609
|
-
valueType,
|
|
2647
|
+
valueFieldType: valueType,
|
|
2610
2648
|
min: element.min,
|
|
2611
2649
|
max: element.max !== void 0 ? String(element.max) : void 0
|
|
2612
2650
|
});
|
|
2613
2651
|
}
|
|
2614
2652
|
return subExtensions;
|
|
2615
2653
|
};
|
|
2616
|
-
var extractSlicingSubExtensions = (extensionSchema) => {
|
|
2654
|
+
var extractSlicingSubExtensions = (register, extensionSchema, logger) => {
|
|
2617
2655
|
const subExtensions = [];
|
|
2618
2656
|
const extensionElement = extensionSchema.elements?.extension;
|
|
2619
2657
|
const slices = extensionElement?.slicing?.slices;
|
|
@@ -2626,21 +2664,13 @@ var extractSlicingSubExtensions = (extensionSchema) => {
|
|
|
2626
2664
|
for (const [elemKey, elemValue] of Object.entries(schema.elements ?? {})) {
|
|
2627
2665
|
const elem = elemValue;
|
|
2628
2666
|
if (elem.choiceOf !== "value" && !elemKey.startsWith("value")) continue;
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
kind: "complex-type",
|
|
2632
|
-
package: extensionSchema.package_meta.name,
|
|
2633
|
-
version: extensionSchema.package_meta.version,
|
|
2634
|
-
name: elem.type,
|
|
2635
|
-
url: `http://hl7.org/fhir/StructureDefinition/${elem.type}`
|
|
2636
|
-
};
|
|
2637
|
-
break;
|
|
2638
|
-
}
|
|
2667
|
+
valueType = buildFieldType(register, extensionSchema, [elemKey], elem, logger);
|
|
2668
|
+
if (valueType) break;
|
|
2639
2669
|
}
|
|
2640
2670
|
subExtensions.push({
|
|
2641
2671
|
name: sliceName,
|
|
2642
2672
|
url: slice.match?.url ?? sliceName,
|
|
2643
|
-
valueType,
|
|
2673
|
+
valueFieldType: valueType,
|
|
2644
2674
|
min: schema._required ? 1 : schema.min ?? 0,
|
|
2645
2675
|
// biome-ignore lint/style/noNestedTernary : okay here
|
|
2646
2676
|
max: schema.max !== void 0 ? String(schema.max) : schema.array ? "*" : "1"
|
|
@@ -2652,7 +2682,7 @@ var extractSubExtensions = (register, fhirSchema, extensionUrl, logger) => {
|
|
|
2652
2682
|
const extensionSchema = register.resolveFs(fhirSchema.package_meta, extensionUrl);
|
|
2653
2683
|
if (!extensionSchema?.elements) return void 0;
|
|
2654
2684
|
const legacySubs = extractLegacySubExtensions(register, extensionSchema, logger);
|
|
2655
|
-
const slicingSubs = extractSlicingSubExtensions(extensionSchema);
|
|
2685
|
+
const slicingSubs = extractSlicingSubExtensions(register, extensionSchema, logger);
|
|
2656
2686
|
const subExtensions = [...legacySubs, ...slicingSubs];
|
|
2657
2687
|
return subExtensions.length > 0 ? subExtensions : void 0;
|
|
2658
2688
|
};
|
|
@@ -2660,38 +2690,36 @@ var extractProfileExtensions = (register, fhirSchema, logger) => {
|
|
|
2660
2690
|
const extensions = [];
|
|
2661
2691
|
const addExtensionEntry = (path, name, schema) => {
|
|
2662
2692
|
let url = schema.url;
|
|
2663
|
-
let
|
|
2693
|
+
let valueFieldTypes = url ? extractExtensionValueFieldTypes(register, fhirSchema, url, logger) : void 0;
|
|
2664
2694
|
const subExtensions = url ? extractSubExtensions(register, fhirSchema, url, logger) : void 0;
|
|
2665
2695
|
if (!url) {
|
|
2666
2696
|
const sliceSchema = fhirSchema.elements?.extension?.slicing?.slices?.[name]?.schema;
|
|
2667
2697
|
if (sliceSchema) {
|
|
2668
2698
|
url = sliceSchema.elements?.url?.fixed?.value ?? name;
|
|
2669
|
-
for (const [
|
|
2699
|
+
for (const [elemKey, elemValue] of Object.entries(sliceSchema.elements ?? {})) {
|
|
2670
2700
|
const elem = elemValue;
|
|
2671
|
-
if (elem.choiceOf === "value"
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
name: elem.type,
|
|
2678
|
-
url: `http://hl7.org/fhir/StructureDefinition/${elem.type}`
|
|
2679
|
-
}
|
|
2680
|
-
];
|
|
2681
|
-
break;
|
|
2701
|
+
if (elem.choiceOf === "value" || elemKey.startsWith("value")) {
|
|
2702
|
+
const ft = buildFieldType(register, fhirSchema, [elemKey], elem, logger);
|
|
2703
|
+
if (ft) {
|
|
2704
|
+
valueFieldTypes = [ft];
|
|
2705
|
+
break;
|
|
2706
|
+
}
|
|
2682
2707
|
}
|
|
2683
2708
|
}
|
|
2684
2709
|
}
|
|
2685
2710
|
}
|
|
2686
2711
|
const isComplex = subExtensions && subExtensions.length > 0;
|
|
2712
|
+
const extFs = url ? register.resolveFs(fhirSchema.package_meta, url) : void 0;
|
|
2713
|
+
const profile = extFs ? mkIdentifier(extFs) : void 0;
|
|
2687
2714
|
extensions.push({
|
|
2688
2715
|
name,
|
|
2689
2716
|
path: [...path, "extension"].join("."),
|
|
2690
2717
|
url,
|
|
2718
|
+
profile,
|
|
2691
2719
|
min: schema.min,
|
|
2692
2720
|
max: schema.max !== void 0 ? String(schema.max) : void 0,
|
|
2693
2721
|
mustSupport: schema.mustSupport,
|
|
2694
|
-
|
|
2722
|
+
valueFieldTypes,
|
|
2695
2723
|
subExtensions,
|
|
2696
2724
|
isComplex
|
|
2697
2725
|
});
|
|
@@ -2765,22 +2793,28 @@ async function transformValueSet(register, valueSet, logger) {
|
|
|
2765
2793
|
compose: !concept ? valueSet.compose : void 0
|
|
2766
2794
|
};
|
|
2767
2795
|
}
|
|
2768
|
-
|
|
2796
|
+
var collectRawDeps = (base, fields, nestedTypes) => {
|
|
2769
2797
|
const deps = [];
|
|
2770
2798
|
if (base) deps.push(base);
|
|
2771
2799
|
if (fields) deps.push(...extractFieldDependencies(fields));
|
|
2772
2800
|
if (nestedTypes) deps.push(...extractNestedDependencies(nestedTypes));
|
|
2773
|
-
|
|
2801
|
+
return deps;
|
|
2802
|
+
};
|
|
2803
|
+
var extractDependencies = (identifier, base, fields, nestedTypes) => {
|
|
2804
|
+
const deps = collectRawDeps(base, fields, nestedTypes);
|
|
2774
2805
|
const filtered = deps.filter((dep) => {
|
|
2775
2806
|
if (dep.url === identifier.url) return false;
|
|
2776
|
-
if (
|
|
2777
|
-
|
|
2778
|
-
return !localNestedTypeUrls.has(dep.url);
|
|
2807
|
+
if (isNestedIdentifier(dep)) return false;
|
|
2808
|
+
return true;
|
|
2779
2809
|
});
|
|
2780
2810
|
return concatIdentifiers(filtered);
|
|
2781
|
-
}
|
|
2782
|
-
|
|
2783
|
-
const
|
|
2811
|
+
};
|
|
2812
|
+
var extractProfileDependencies = (identifier, base, fields, nestedTypes) => {
|
|
2813
|
+
const deps = collectRawDeps(base, fields, nestedTypes);
|
|
2814
|
+
const filtered = deps.filter((dep) => dep.url !== identifier.url);
|
|
2815
|
+
return concatIdentifiers(filtered);
|
|
2816
|
+
};
|
|
2817
|
+
function transformFhirSchema(register, fhirSchema, logger) {
|
|
2784
2818
|
let base;
|
|
2785
2819
|
if (fhirSchema.base) {
|
|
2786
2820
|
const baseFs = register.resolveFs(
|
|
@@ -2791,31 +2825,60 @@ function transformFhirSchemaResource(register, fhirSchema, logger) {
|
|
|
2791
2825
|
throw new Error(
|
|
2792
2826
|
`Base resource not found '${fhirSchema.base}' for <${fhirSchema.url}> from ${packageMetaToFhir(fhirSchema.package_meta)}`
|
|
2793
2827
|
);
|
|
2794
|
-
|
|
2828
|
+
const baseId = mkIdentifier(baseFs);
|
|
2829
|
+
assert4(!isNestedIdentifier(baseId), `Unexpected nested base for ${fhirSchema.url}`);
|
|
2830
|
+
base = baseId;
|
|
2795
2831
|
}
|
|
2796
2832
|
const fields = mkFields(register, fhirSchema, [], fhirSchema.elements, logger);
|
|
2797
2833
|
const nested = mkNestedTypes(register, fhirSchema, logger);
|
|
2798
|
-
const
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2834
|
+
const bindingSchemas = collectBindingSchemas(register, fhirSchema, logger);
|
|
2835
|
+
if (fhirSchema.derivation === "constraint") {
|
|
2836
|
+
const identifier2 = mkIdentifier(fhirSchema);
|
|
2837
|
+
if (!base) throw new Error(`Profile ${fhirSchema.url} must have a base type`);
|
|
2838
|
+
const extensions = extractProfileExtensions(register, fhirSchema, logger);
|
|
2839
|
+
const extensionDeps = extensions?.flatMap(extractExtensionDeps);
|
|
2840
|
+
const rawDeps = extractProfileDependencies(identifier2, base, fields, nested);
|
|
2841
|
+
return [
|
|
2842
|
+
{
|
|
2843
|
+
identifier: identifier2,
|
|
2844
|
+
base,
|
|
2845
|
+
fields,
|
|
2846
|
+
nested,
|
|
2847
|
+
description: fhirSchema.description,
|
|
2848
|
+
dependencies: concatIdentifiers(rawDeps, extensionDeps),
|
|
2849
|
+
extensions
|
|
2850
|
+
},
|
|
2851
|
+
...bindingSchemas
|
|
2852
|
+
];
|
|
2853
|
+
}
|
|
2854
|
+
if (fhirSchema.kind === "primitive-type") {
|
|
2855
|
+
const identifier2 = mkIdentifier(fhirSchema);
|
|
2856
|
+
assert4(base, `Primitive type ${fhirSchema.url} must have a base type`);
|
|
2857
|
+
return [
|
|
2858
|
+
{
|
|
2859
|
+
identifier: identifier2,
|
|
2860
|
+
description: fhirSchema.description,
|
|
2861
|
+
base,
|
|
2862
|
+
dependencies: extractDependencies(identifier2, base, fields, nested)
|
|
2863
|
+
},
|
|
2864
|
+
...bindingSchemas
|
|
2865
|
+
];
|
|
2866
|
+
}
|
|
2867
|
+
const identifier = mkIdentifier(fhirSchema);
|
|
2868
|
+
const schema = {
|
|
2802
2869
|
identifier,
|
|
2803
2870
|
base,
|
|
2804
2871
|
fields,
|
|
2805
2872
|
nested,
|
|
2806
2873
|
description: fhirSchema.description,
|
|
2807
|
-
dependencies:
|
|
2808
|
-
|
|
2874
|
+
dependencies: extractDependencies(identifier, base, fields, nested),
|
|
2875
|
+
typeFamily: void 0
|
|
2809
2876
|
};
|
|
2810
|
-
|
|
2811
|
-
return [typeSchema, ...bindingSchemas];
|
|
2812
|
-
}
|
|
2813
|
-
async function transformFhirSchema(register, fhirSchema, logger) {
|
|
2814
|
-
return transformFhirSchemaResource(register, fhirSchema, logger);
|
|
2877
|
+
return [schema, ...bindingSchemas];
|
|
2815
2878
|
}
|
|
2816
2879
|
|
|
2817
2880
|
// src/typeschema/index.ts
|
|
2818
|
-
var deduplicateSchemas = (schemasWithSources, logger) => {
|
|
2881
|
+
var deduplicateSchemas = (schemasWithSources, resolveCollisions, logger) => {
|
|
2819
2882
|
const groups = {};
|
|
2820
2883
|
for (const item of schemasWithSources) {
|
|
2821
2884
|
const key = `${item.schema.identifier.url}|${item.schema.identifier.package}`;
|
|
@@ -2830,11 +2893,30 @@ var deduplicateSchemas = (schemasWithSources, logger) => {
|
|
|
2830
2893
|
const sorted = Object.values(versions).sort((a, b) => b.sources.length - a.sources.length);
|
|
2831
2894
|
const best = sorted[0];
|
|
2832
2895
|
if (!best) continue;
|
|
2833
|
-
schemas.push(best.typeSchema);
|
|
2834
2896
|
if (sorted.length > 1) {
|
|
2835
|
-
const pkg = best.typeSchema.identifier.package;
|
|
2836
2897
|
const url = best.typeSchema.identifier.url;
|
|
2837
|
-
|
|
2898
|
+
const pkg = best.typeSchema.identifier.package;
|
|
2899
|
+
const preferredCanonical = resolveCollisions?.[url];
|
|
2900
|
+
if (preferredCanonical) {
|
|
2901
|
+
const allSources = sorted.flatMap((v) => v.sources);
|
|
2902
|
+
const match = sorted.find(
|
|
2903
|
+
(v) => v.sources.some(
|
|
2904
|
+
(s) => s.sourceCanonical === preferredCanonical.canonical && s.sourcePackage === preferredCanonical.package
|
|
2905
|
+
)
|
|
2906
|
+
);
|
|
2907
|
+
if (match) {
|
|
2908
|
+
schemas.push(match.typeSchema);
|
|
2909
|
+
} else {
|
|
2910
|
+
logger?.dryWarn(
|
|
2911
|
+
"#resolveCollisionMiss",
|
|
2912
|
+
`'${url}': preferred source '${preferredCanonical.canonical}' from '${preferredCanonical.package}' not found among variants: ${allSources.map((s) => `${s.sourceCanonical} (${s.sourcePackage})`).join(", ")}`
|
|
2913
|
+
);
|
|
2914
|
+
schemas.push(best.typeSchema);
|
|
2915
|
+
}
|
|
2916
|
+
} else {
|
|
2917
|
+
logger?.dryWarn("#duplicateSchema", `'${url}' from '${pkg}' has ${sorted.length} versions`);
|
|
2918
|
+
schemas.push(best.typeSchema);
|
|
2919
|
+
}
|
|
2838
2920
|
collisions[pkg] ??= {};
|
|
2839
2921
|
collisions[pkg][url] = sorted.flatMap(
|
|
2840
2922
|
(v) => v.sources.map((s) => ({
|
|
@@ -2843,11 +2925,13 @@ var deduplicateSchemas = (schemasWithSources, logger) => {
|
|
|
2843
2925
|
sourceCanonical: s.sourceCanonical
|
|
2844
2926
|
}))
|
|
2845
2927
|
);
|
|
2928
|
+
} else {
|
|
2929
|
+
schemas.push(best.typeSchema);
|
|
2846
2930
|
}
|
|
2847
2931
|
}
|
|
2848
2932
|
return { schemas, collisions };
|
|
2849
2933
|
};
|
|
2850
|
-
var generateTypeSchemas = async (register, logger) => {
|
|
2934
|
+
var generateTypeSchemas = async (register, resolveCollisions, logger) => {
|
|
2851
2935
|
const schemasWithSources = [];
|
|
2852
2936
|
for (const fhirSchema of register.allFs()) {
|
|
2853
2937
|
const pkgId = packageMetaToFhir(fhirSchema.package_meta);
|
|
@@ -2856,7 +2940,7 @@ var generateTypeSchemas = async (register, logger) => {
|
|
|
2856
2940
|
logger?.dryWarn("#skipCanonical", `Skip ${fhirSchema.url} from ${pkgId}. Reason: ${skipCheck.reason}`);
|
|
2857
2941
|
continue;
|
|
2858
2942
|
}
|
|
2859
|
-
for (const schema of
|
|
2943
|
+
for (const schema of transformFhirSchema(register, fhirSchema, logger)) {
|
|
2860
2944
|
schemasWithSources.push({
|
|
2861
2945
|
schema,
|
|
2862
2946
|
sourcePackage: pkgId,
|
|
@@ -2871,7 +2955,7 @@ var generateTypeSchemas = async (register, logger) => {
|
|
|
2871
2955
|
sourceCanonical: vsSchema.url
|
|
2872
2956
|
});
|
|
2873
2957
|
}
|
|
2874
|
-
return deduplicateSchemas(schemasWithSources, logger);
|
|
2958
|
+
return deduplicateSchemas(schemasWithSources, resolveCollisions, logger);
|
|
2875
2959
|
};
|
|
2876
2960
|
|
|
2877
2961
|
// src/typeschema/ir/logic-promotion.ts
|
|
@@ -2884,7 +2968,7 @@ var promoteLogical = (tsIndex, promotes) => {
|
|
|
2884
2968
|
tsIndex.schemas.map((schema) => {
|
|
2885
2969
|
const promo = promoteSets[schema.identifier.package]?.has(schema.identifier.url);
|
|
2886
2970
|
if (!promo) return void 0;
|
|
2887
|
-
if (schema
|
|
2971
|
+
if (!isLogicalTypeSchema(schema))
|
|
2888
2972
|
throw new Error(`Unexpected schema kind: ${JSON.stringify(schema.identifier)}`);
|
|
2889
2973
|
return [identifierToString(schema.identifier), { ...schema.identifier, kind: "resource" }];
|
|
2890
2974
|
}).filter((e) => e !== void 0)
|
|
@@ -2943,14 +3027,14 @@ var mutableSelectFields = (schema, selectFields) => {
|
|
|
2943
3027
|
}
|
|
2944
3028
|
for (const [choiceName, { declaration, instances }] of Object.entries(selectPolimorphic)) {
|
|
2945
3029
|
const choices = instances ?? declaration;
|
|
2946
|
-
|
|
3030
|
+
assert4(choices);
|
|
2947
3031
|
for (const choiceInstanceName of choices) {
|
|
2948
3032
|
const field = schema.fields?.[choiceInstanceName];
|
|
2949
|
-
|
|
3033
|
+
assert4(field);
|
|
2950
3034
|
selectedFields[choiceInstanceName] = field;
|
|
2951
3035
|
}
|
|
2952
3036
|
const decl = schema.fields?.[choiceName];
|
|
2953
|
-
|
|
3037
|
+
assert4(decl);
|
|
2954
3038
|
selectedFields[choiceName] = { ...decl, choices };
|
|
2955
3039
|
}
|
|
2956
3040
|
schema.fields = selectedFields;
|
|
@@ -2967,7 +3051,7 @@ var mutableIgnoreFields = (schema, ignoreFields) => {
|
|
|
2967
3051
|
}
|
|
2968
3052
|
if (isChoiceInstanceField(field)) {
|
|
2969
3053
|
const choiceDeclaration = schema.fields[field.choiceOf];
|
|
2970
|
-
|
|
3054
|
+
assert4(isChoiceDeclarationField(choiceDeclaration));
|
|
2971
3055
|
choiceDeclaration.choices = choiceDeclaration.choices.filter((c) => c !== fieldName);
|
|
2972
3056
|
if (choiceDeclaration.choices.length === 0) {
|
|
2973
3057
|
delete schema.fields[field.choiceOf];
|
|
@@ -2977,6 +3061,15 @@ var mutableIgnoreFields = (schema, ignoreFields) => {
|
|
|
2977
3061
|
}
|
|
2978
3062
|
}
|
|
2979
3063
|
};
|
|
3064
|
+
var mutableIgnoreExtensions = (schema, ignoreExtensions) => {
|
|
3065
|
+
if (!schema.extensions) return;
|
|
3066
|
+
for (const url of ignoreExtensions) {
|
|
3067
|
+
if (!schema.extensions.some((ext) => ext.url === url))
|
|
3068
|
+
throw new Error(`Extension ${url} not found in profile ${schema.identifier.url}`);
|
|
3069
|
+
}
|
|
3070
|
+
schema.extensions = schema.extensions.filter((ext) => !ext.url || !ignoreExtensions.includes(ext.url));
|
|
3071
|
+
if (schema.extensions.length === 0) schema.extensions = void 0;
|
|
3072
|
+
};
|
|
2980
3073
|
var mutableFillReport = (report, tsIndex, shakedIndex) => {
|
|
2981
3074
|
const packages = Object.keys(tsIndex.schemasByPackage);
|
|
2982
3075
|
const shakedPackages = Object.keys(shakedIndex.schemasByPackage);
|
|
@@ -2985,15 +3078,15 @@ var mutableFillReport = (report, tsIndex, shakedIndex) => {
|
|
|
2985
3078
|
for (const [pkgName, shakedSchemas] of Object.entries(shakedIndex.schemasByPackage)) {
|
|
2986
3079
|
if (skippedPackages.includes(pkgName)) continue;
|
|
2987
3080
|
const tsSchemas = tsIndex.schemasByPackage[pkgName];
|
|
2988
|
-
|
|
3081
|
+
assert4(tsSchemas);
|
|
2989
3082
|
report.packages[pkgName] = {
|
|
2990
3083
|
skippedCanonicals: tsSchemas.filter((schema) => !shakedSchemas.includes(schema)).map((schema) => schema.identifier.url).sort(),
|
|
2991
3084
|
canonicals: Object.fromEntries(
|
|
2992
3085
|
shakedSchemas.map((shakedSchema) => {
|
|
2993
3086
|
const schema = tsIndex.resolve(shakedSchema.identifier);
|
|
2994
|
-
|
|
3087
|
+
assert4(schema);
|
|
2995
3088
|
if (!isSpecializationTypeSchema(schema)) return void 0;
|
|
2996
|
-
|
|
3089
|
+
assert4(isSpecializationTypeSchema(shakedSchema));
|
|
2997
3090
|
if (!schema.fields) return void 0;
|
|
2998
3091
|
if (!shakedSchema.fields) {
|
|
2999
3092
|
return [shakedSchema.identifier.url, Object.keys(schema.fields)];
|
|
@@ -3018,6 +3111,9 @@ var treeShakeTypeSchema = (schema, rule, _logger) => {
|
|
|
3018
3111
|
if (rule.selectFields) throw new Error("Cannot use both ignoreFields and selectFields in the same rule");
|
|
3019
3112
|
mutableIgnoreFields(schema, rule.ignoreFields);
|
|
3020
3113
|
}
|
|
3114
|
+
if (isProfileTypeSchema(schema) && rule.ignoreExtensions) {
|
|
3115
|
+
mutableIgnoreExtensions(schema, rule.ignoreExtensions);
|
|
3116
|
+
}
|
|
3021
3117
|
if (schema.nested) {
|
|
3022
3118
|
const usedTypes = /* @__PURE__ */ new Set();
|
|
3023
3119
|
const collectUsedNestedTypes = (s) => {
|
|
@@ -3026,7 +3122,7 @@ var treeShakeTypeSchema = (schema, rule, _logger) => {
|
|
|
3026
3122
|
if (!usedTypes.has(url)) {
|
|
3027
3123
|
usedTypes.add(url);
|
|
3028
3124
|
const nestedTypeDef = schema.nested?.find((f2) => f2.identifier.url === url);
|
|
3029
|
-
|
|
3125
|
+
assert4(nestedTypeDef);
|
|
3030
3126
|
collectUsedNestedTypes(nestedTypeDef);
|
|
3031
3127
|
}
|
|
3032
3128
|
});
|
|
@@ -3034,7 +3130,16 @@ var treeShakeTypeSchema = (schema, rule, _logger) => {
|
|
|
3034
3130
|
collectUsedNestedTypes(schema);
|
|
3035
3131
|
schema.nested = schema.nested.filter((n) => usedTypes.has(n.identifier.url));
|
|
3036
3132
|
}
|
|
3037
|
-
|
|
3133
|
+
if (isProfileTypeSchema(schema)) {
|
|
3134
|
+
const extDeps = schema.extensions?.flatMap(extractExtensionDeps);
|
|
3135
|
+
schema.dependencies = concatIdentifiers(
|
|
3136
|
+
extractProfileDependencies(schema.identifier, schema.base, schema.fields, schema.nested),
|
|
3137
|
+
extDeps
|
|
3138
|
+
);
|
|
3139
|
+
} else {
|
|
3140
|
+
assert4(!isNestedIdentifier(schema.identifier));
|
|
3141
|
+
schema.dependencies = extractDependencies(schema.identifier, schema.base, schema.fields, schema.nested);
|
|
3142
|
+
}
|
|
3038
3143
|
return schema;
|
|
3039
3144
|
};
|
|
3040
3145
|
var treeShake = (tsIndex, treeShake2) => {
|
|
@@ -3042,7 +3147,7 @@ var treeShake = (tsIndex, treeShake2) => {
|
|
|
3042
3147
|
for (const [pkgId, requires] of Object.entries(treeShake2)) {
|
|
3043
3148
|
for (const [url, rule] of Object.entries(requires)) {
|
|
3044
3149
|
const schema = tsIndex.resolveByUrl(pkgId, url);
|
|
3045
|
-
if (!schema) throw new Error(`Schema not found for ${pkgId} ${url}`);
|
|
3150
|
+
if (!schema || isNestedTypeSchema(schema)) throw new Error(`Schema not found for ${pkgId} ${url}`);
|
|
3046
3151
|
const shaked2 = treeShakeTypeSchema(schema, rule);
|
|
3047
3152
|
focusedSchemas.push(shaked2);
|
|
3048
3153
|
}
|
|
@@ -3057,6 +3162,7 @@ var treeShake = (tsIndex, treeShake2) => {
|
|
|
3057
3162
|
if (isSpecializationTypeSchema(schema) || isProfileTypeSchema(schema)) {
|
|
3058
3163
|
if (!schema.dependencies) continue;
|
|
3059
3164
|
schema.dependencies.forEach((dep) => {
|
|
3165
|
+
if (isNestedIdentifier(dep)) return;
|
|
3060
3166
|
const depSchema = tsIndex.resolve(dep);
|
|
3061
3167
|
if (!depSchema)
|
|
3062
3168
|
throw new Error(
|
|
@@ -3065,13 +3171,6 @@ var treeShake = (tsIndex, treeShake2) => {
|
|
|
3065
3171
|
const id = JSON.stringify(depSchema.identifier);
|
|
3066
3172
|
if (!acc[id]) newSchemas.push(depSchema);
|
|
3067
3173
|
});
|
|
3068
|
-
if (schema.nested) {
|
|
3069
|
-
for (const nest of schema.nested) {
|
|
3070
|
-
if (isNestedIdentifier(nest.identifier)) continue;
|
|
3071
|
-
const id = JSON.stringify(nest.identifier);
|
|
3072
|
-
if (!acc[id]) newSchemas.push(nest);
|
|
3073
|
-
}
|
|
3074
|
-
}
|
|
3075
3174
|
}
|
|
3076
3175
|
}
|
|
3077
3176
|
return collectDeps(newSchemas, acc);
|
|
@@ -3149,7 +3248,7 @@ var IntrospectionWriter = class extends FileSystemWriter {
|
|
|
3149
3248
|
for (const [canonical, entries] of Object.entries(canonicals)) {
|
|
3150
3249
|
if (entries.length <= 1) continue;
|
|
3151
3250
|
const firstEntry = entries[0];
|
|
3152
|
-
|
|
3251
|
+
assert4(firstEntry);
|
|
3153
3252
|
const name = normalizeFileName(
|
|
3154
3253
|
`${firstEntry.typeSchema.identifier.name}(${extractNameFromCanonical(canonical)})`
|
|
3155
3254
|
);
|
|
@@ -3289,31 +3388,42 @@ var generatePackageSection = (lines, pkgName, treeShakePkg, promotedCanonicals)
|
|
|
3289
3388
|
lines.push("");
|
|
3290
3389
|
}
|
|
3291
3390
|
};
|
|
3292
|
-
var
|
|
3391
|
+
var groupCollisionVersions = (entries, resolution) => {
|
|
3293
3392
|
const uniqueSchemas = /* @__PURE__ */ new Map();
|
|
3294
3393
|
for (const entry of entries) {
|
|
3295
3394
|
const key = JSON.stringify(entry.typeSchema);
|
|
3296
3395
|
if (!uniqueSchemas.has(key)) uniqueSchemas.set(key, []);
|
|
3297
3396
|
uniqueSchemas.get(key)?.push(entry);
|
|
3298
3397
|
}
|
|
3299
|
-
const
|
|
3300
|
-
const
|
|
3398
|
+
const sorted = [...uniqueSchemas.values()].sort((a, b) => b.length - a.length);
|
|
3399
|
+
const markVersion = (group, i) => {
|
|
3400
|
+
if (resolution)
|
|
3401
|
+
return group.some(
|
|
3402
|
+
(e) => e.sourceCanonical === resolution.canonical && e.sourcePackage === resolution.package
|
|
3403
|
+
) ? "selected" : void 0;
|
|
3404
|
+
return i === 0 ? "auto" : void 0;
|
|
3405
|
+
};
|
|
3406
|
+
return sorted.map((group, i) => ({ entries: group, mark: markVersion(group, i) }));
|
|
3407
|
+
};
|
|
3408
|
+
var versionMarkLabel = { selected: " (selected)", auto: " (auto)" };
|
|
3409
|
+
var generateCollisionVersionLines = (versions) => {
|
|
3301
3410
|
let version = 1;
|
|
3302
|
-
|
|
3303
|
-
const sourceList =
|
|
3411
|
+
return versions.map((v) => {
|
|
3412
|
+
const sourceList = v.entries.map((e) => {
|
|
3304
3413
|
const name = extractNameFromCanonical(e.sourceCanonical) ?? e.sourceCanonical;
|
|
3305
3414
|
return `${name} (${e.sourcePackage})`;
|
|
3306
3415
|
}).join(", ");
|
|
3307
|
-
|
|
3308
|
-
}
|
|
3309
|
-
|
|
3416
|
+
const mark = v.mark ? versionMarkLabel[v.mark] : "";
|
|
3417
|
+
return ` - Version ${version++}${mark}: ${sourceList}`;
|
|
3418
|
+
});
|
|
3310
3419
|
};
|
|
3311
|
-
var generateCollisionsSection = (lines, collisions) => {
|
|
3420
|
+
var generateCollisionsSection = (lines, collisions, resolveCollisions) => {
|
|
3312
3421
|
if (!collisions) return;
|
|
3313
3422
|
lines.push("## Schema Collisions", "");
|
|
3314
3423
|
lines.push("The following canonicals have multiple schema versions with different content.");
|
|
3315
3424
|
lines.push("To inspect collision versions, export TypeSchemas using `.introspection({ typeSchemas: 'path' })`");
|
|
3316
3425
|
lines.push("and check `<pkg>/collisions/<name>/1.json, 2.json, ...` files.", "");
|
|
3426
|
+
const allCollisions = [];
|
|
3317
3427
|
const collisionPackages = Object.keys(collisions).sort();
|
|
3318
3428
|
for (const pkgName of collisionPackages) {
|
|
3319
3429
|
const collisionsPkg = collisions[pkgName];
|
|
@@ -3326,13 +3436,34 @@ var generateCollisionsSection = (lines, collisions) => {
|
|
|
3326
3436
|
if (sortedEntries.length > 0) {
|
|
3327
3437
|
lines.push(`### \`${pkgName}\``, "");
|
|
3328
3438
|
for (const [canonical, entries] of sortedEntries) {
|
|
3329
|
-
const
|
|
3330
|
-
|
|
3439
|
+
const versions = groupCollisionVersions(entries, resolveCollisions?.[canonical]);
|
|
3440
|
+
const versionLines = generateCollisionVersionLines(versions);
|
|
3441
|
+
lines.push(`- \`${canonical}\` (${versions.length} versions)`);
|
|
3331
3442
|
lines.push(...versionLines);
|
|
3443
|
+
if (entries[0]) allCollisions.push({ url: canonical, firstSource: entries[0] });
|
|
3332
3444
|
}
|
|
3333
3445
|
lines.push("");
|
|
3334
3446
|
}
|
|
3335
3447
|
}
|
|
3448
|
+
if (allCollisions.length > 0) {
|
|
3449
|
+
const unresolved = allCollisions.filter((c) => !resolveCollisions?.[c.url]);
|
|
3450
|
+
if (unresolved.length > 0) {
|
|
3451
|
+
lines.push("### Suggested `resolveCollisions` config", "");
|
|
3452
|
+
lines.push("Add to `.typeSchema({ resolveCollisions: { ... } })` to resolve remaining collisions:", "");
|
|
3453
|
+
lines.push("```typescript");
|
|
3454
|
+
lines.push(".typeSchema({");
|
|
3455
|
+
lines.push(" resolveCollisions: {");
|
|
3456
|
+
for (const { url, firstSource } of unresolved) {
|
|
3457
|
+
lines.push(` "${url}": {`);
|
|
3458
|
+
lines.push(` package: "${firstSource.sourcePackage}",`);
|
|
3459
|
+
lines.push(` canonical: "${firstSource.sourceCanonical}",`);
|
|
3460
|
+
lines.push(" },");
|
|
3461
|
+
}
|
|
3462
|
+
lines.push(" },");
|
|
3463
|
+
lines.push("})");
|
|
3464
|
+
lines.push("```", "");
|
|
3465
|
+
}
|
|
3466
|
+
}
|
|
3336
3467
|
};
|
|
3337
3468
|
var generateIrReportReadme = (report) => {
|
|
3338
3469
|
const lines = ["# IR Report", ""];
|
|
@@ -3360,7 +3491,7 @@ var generateIrReportReadme = (report) => {
|
|
|
3360
3491
|
);
|
|
3361
3492
|
}
|
|
3362
3493
|
if (hasCollisions) {
|
|
3363
|
-
generateCollisionsSection(lines, report.collisions);
|
|
3494
|
+
generateCollisionsSection(lines, report.collisions, report.resolveCollisions);
|
|
3364
3495
|
}
|
|
3365
3496
|
return lines.join("\n");
|
|
3366
3497
|
};
|
|
@@ -3654,7 +3785,7 @@ var ViewModelFactory = class {
|
|
|
3654
3785
|
throw new Error(`Unknown type ${typeRef.kind}`);
|
|
3655
3786
|
}
|
|
3656
3787
|
_createForComplexType(typeRef, cache, nestedIn) {
|
|
3657
|
-
const type = this.tsIndex.
|
|
3788
|
+
const type = this.tsIndex.resolveType(typeRef);
|
|
3658
3789
|
if (!type) {
|
|
3659
3790
|
throw new Error(`ComplexType ${typeRef.name} not found`);
|
|
3660
3791
|
}
|
|
@@ -3666,7 +3797,7 @@ var ViewModelFactory = class {
|
|
|
3666
3797
|
return res;
|
|
3667
3798
|
}
|
|
3668
3799
|
_createForResource(typeRef, cache, nestedIn) {
|
|
3669
|
-
const type = this.tsIndex.
|
|
3800
|
+
const type = this.tsIndex.resolveType(typeRef);
|
|
3670
3801
|
if (!type) {
|
|
3671
3802
|
throw new Error(`Resource ${typeRef.name} not found`);
|
|
3672
3803
|
}
|
|
@@ -3678,11 +3809,13 @@ var ViewModelFactory = class {
|
|
|
3678
3809
|
return res;
|
|
3679
3810
|
}
|
|
3680
3811
|
_createChildrenFor(typeRef, cache, nestedIn) {
|
|
3681
|
-
|
|
3682
|
-
|
|
3812
|
+
const schema = this.tsIndex.resolveType(typeRef);
|
|
3813
|
+
if (!schema) return [];
|
|
3814
|
+
if (isComplexTypeTypeSchema(schema)) {
|
|
3815
|
+
return (schema.typeFamily?.complexTypes ?? []).filter(this.filterPred).map((childRef) => this._createFor(childRef, cache, nestedIn));
|
|
3683
3816
|
}
|
|
3684
|
-
if (
|
|
3685
|
-
return
|
|
3817
|
+
if (isResourceTypeSchema(schema)) {
|
|
3818
|
+
return (schema.typeFamily?.resources ?? []).filter(this.filterPred).map((childRef) => this._createFor(childRef, cache, nestedIn));
|
|
3686
3819
|
}
|
|
3687
3820
|
return [];
|
|
3688
3821
|
}
|
|
@@ -3691,7 +3824,7 @@ var ViewModelFactory = class {
|
|
|
3691
3824
|
let parentRef = "base" in base ? base.base : void 0;
|
|
3692
3825
|
while (parentRef) {
|
|
3693
3826
|
parents.push(this._createFor(parentRef, cache, void 0));
|
|
3694
|
-
const parent = this.tsIndex.
|
|
3827
|
+
const parent = this.tsIndex.resolveType(parentRef);
|
|
3695
3828
|
parentRef = parent && "base" in parent ? parent.base : void 0;
|
|
3696
3829
|
}
|
|
3697
3830
|
return parents;
|
|
@@ -4151,7 +4284,8 @@ var rewriteFieldTypeDefs = {
|
|
|
4151
4284
|
Reference: { reference: () => "`${T}/${string}`" },
|
|
4152
4285
|
CodeableConcept: { coding: () => "Coding<T>" }
|
|
4153
4286
|
};
|
|
4154
|
-
var resolveFieldTsType = (schemaName, tsName, field, resolveRef) => {
|
|
4287
|
+
var resolveFieldTsType = (schemaName, tsName, field, resolveRef, genericFieldMap) => {
|
|
4288
|
+
if (genericFieldMap?.[tsName]) return genericFieldMap[tsName];
|
|
4155
4289
|
const rewriteFieldType = rewriteFieldTypeDefs[schemaName]?.[tsName];
|
|
4156
4290
|
if (rewriteFieldType) return rewriteFieldType();
|
|
4157
4291
|
if (field.enum) {
|
|
@@ -4325,7 +4459,7 @@ var generateComplexExtensionSetter = (w, info) => {
|
|
|
4325
4459
|
w.curlyBlock(["public", setMethodName, `(input: ${inputTypeName}): this`], () => {
|
|
4326
4460
|
w.line("const subExtensions: Extension[] = []");
|
|
4327
4461
|
for (const sub of ext.subExtensions ?? []) {
|
|
4328
|
-
const valueField = sub.
|
|
4462
|
+
const valueField = sub.valueFieldType ? tsValueFieldName(sub.valueFieldType) : "value";
|
|
4329
4463
|
if (sub.max === "*") {
|
|
4330
4464
|
w.curlyBlock(["if", `(input.${sub.name})`], () => {
|
|
4331
4465
|
w.curlyBlock(["for", `(const item of input.${sub.name})`], () => {
|
|
@@ -4362,7 +4496,7 @@ var generateComplexExtensionGetter = (w, info) => {
|
|
|
4362
4496
|
const inputType = extProfileHasFlatInput && extProfileInfo ? `${extProfileInfo.className}Flat` : inputTypeName;
|
|
4363
4497
|
generateExtensionGetterOverloads(w, ext, targetPath, getMethodName, inputType, extProfileInfo, () => {
|
|
4364
4498
|
const configItems = (ext.subExtensions ?? []).map((sub) => {
|
|
4365
|
-
const valueField = sub.
|
|
4499
|
+
const valueField = sub.valueFieldType ? tsValueFieldName(sub.valueFieldType) : "value";
|
|
4366
4500
|
const isArray = sub.max === "*";
|
|
4367
4501
|
return `{ name: "${sub.url}", valueField: "${valueField}", isArray: ${isArray} }`;
|
|
4368
4502
|
});
|
|
@@ -4372,7 +4506,7 @@ var generateComplexExtensionGetter = (w, info) => {
|
|
|
4372
4506
|
};
|
|
4373
4507
|
var generateSingleValueExtensionSetter = (w, tsIndex, info) => {
|
|
4374
4508
|
const { ext, setMethodName, targetPath, extProfileInfo } = info;
|
|
4375
|
-
const firstValueType = ext.
|
|
4509
|
+
const firstValueType = ext.valueFieldTypes?.[0];
|
|
4376
4510
|
if (!firstValueType) return;
|
|
4377
4511
|
const valueType = tsTypeFromIdentifier(firstValueType);
|
|
4378
4512
|
const valueField = tsValueFieldName(firstValueType);
|
|
@@ -4408,7 +4542,7 @@ var generateSingleValueExtensionSetter = (w, tsIndex, info) => {
|
|
|
4408
4542
|
};
|
|
4409
4543
|
var generateSingleValueExtensionGetter = (w, info) => {
|
|
4410
4544
|
const { ext, getMethodName, targetPath, extProfileInfo } = info;
|
|
4411
|
-
const firstValueType = ext.
|
|
4545
|
+
const firstValueType = ext.valueFieldTypes?.[0];
|
|
4412
4546
|
if (!firstValueType) return;
|
|
4413
4547
|
const valueType = tsTypeFromIdentifier(firstValueType);
|
|
4414
4548
|
const valueField = tsValueFieldName(firstValueType);
|
|
@@ -4462,7 +4596,7 @@ var generateExtensionMethods = (w, tsIndex, flatProfile, extensionBaseNames) =>
|
|
|
4462
4596
|
generateComplexExtensionSetter(w, info);
|
|
4463
4597
|
w.line();
|
|
4464
4598
|
generateComplexExtensionGetter(w, info);
|
|
4465
|
-
} else if (ext.
|
|
4599
|
+
} else if (ext.valueFieldTypes?.length === 1 && ext.valueFieldTypes[0]) {
|
|
4466
4600
|
generateSingleValueExtensionSetter(w, tsIndex, info);
|
|
4467
4601
|
w.line();
|
|
4468
4602
|
generateSingleValueExtensionGetter(w, info);
|
|
@@ -4480,21 +4614,21 @@ var collectTypesFromExtensions = (tsIndex, flatProfile, addType) => {
|
|
|
4480
4614
|
if (ext.isComplex && ext.subExtensions) {
|
|
4481
4615
|
needsExtensionType = true;
|
|
4482
4616
|
for (const sub of ext.subExtensions) {
|
|
4483
|
-
if (!sub.
|
|
4617
|
+
if (!sub.valueFieldType) continue;
|
|
4484
4618
|
const resolvedType = tsIndex.resolveByUrl(
|
|
4485
4619
|
flatProfile.identifier.package,
|
|
4486
|
-
sub.
|
|
4620
|
+
sub.valueFieldType.url
|
|
4487
4621
|
);
|
|
4488
|
-
addType(resolvedType?.identifier ?? sub.
|
|
4622
|
+
addType(resolvedType?.identifier ?? sub.valueFieldType);
|
|
4489
4623
|
}
|
|
4490
|
-
} else if (ext.
|
|
4624
|
+
} else if (ext.valueFieldTypes && ext.valueFieldTypes.length === 1) {
|
|
4491
4625
|
needsExtensionType = true;
|
|
4492
|
-
if (ext.
|
|
4626
|
+
if (ext.valueFieldTypes[0]) {
|
|
4493
4627
|
const resolvedType = tsIndex.resolveByUrl(
|
|
4494
4628
|
flatProfile.identifier.package,
|
|
4495
|
-
ext.
|
|
4629
|
+
ext.valueFieldTypes[0].url
|
|
4496
4630
|
);
|
|
4497
|
-
addType(resolvedType?.identifier ?? ext.
|
|
4631
|
+
addType(resolvedType?.identifier ?? ext.valueFieldTypes[0]);
|
|
4498
4632
|
}
|
|
4499
4633
|
} else {
|
|
4500
4634
|
needsExtensionType = true;
|
|
@@ -4517,7 +4651,7 @@ var collectTypesFromFlatInput = (tsIndex, flatProfile, addType) => {
|
|
|
4517
4651
|
// src/api/writer-generator/typescript/profile-slices.ts
|
|
4518
4652
|
var collectChoiceBaseNames = (tsIndex, typeId) => {
|
|
4519
4653
|
const names = /* @__PURE__ */ new Set();
|
|
4520
|
-
const schema = tsIndex.
|
|
4654
|
+
const schema = tsIndex.resolveType(typeId);
|
|
4521
4655
|
if (schema && "fields" in schema && schema.fields) {
|
|
4522
4656
|
for (const [name, f] of Object.entries(schema.fields)) {
|
|
4523
4657
|
if (isChoiceDeclarationField(f)) names.add(name);
|
|
@@ -4525,15 +4659,35 @@ var collectChoiceBaseNames = (tsIndex, typeId) => {
|
|
|
4525
4659
|
}
|
|
4526
4660
|
return names;
|
|
4527
4661
|
};
|
|
4662
|
+
var extractResourceTypeFromMatch = (match) => {
|
|
4663
|
+
for (const value of Object.values(match)) {
|
|
4664
|
+
if (typeof value !== "object" || value === null) continue;
|
|
4665
|
+
const obj = value;
|
|
4666
|
+
if (typeof obj.resourceType === "string") return obj.resourceType;
|
|
4667
|
+
const nested = extractResourceTypeFromMatch(obj);
|
|
4668
|
+
if (nested) return nested;
|
|
4669
|
+
}
|
|
4670
|
+
return void 0;
|
|
4671
|
+
};
|
|
4528
4672
|
var collectTypesFromSlices = (tsIndex, flatProfile, addType) => {
|
|
4529
4673
|
const pkgName = flatProfile.identifier.package;
|
|
4530
4674
|
for (const field of Object.values(flatProfile.fields ?? {})) {
|
|
4531
4675
|
if (!isNotChoiceDeclarationField(field) || !field.slicing?.slices || !field.type) continue;
|
|
4676
|
+
const isTypeDisc = field.slicing.discriminator?.some((d) => d.type === "type") ?? false;
|
|
4532
4677
|
for (const slice of Object.values(field.slicing.slices)) {
|
|
4533
4678
|
if (Object.keys(slice.match ?? {}).length > 0) {
|
|
4534
4679
|
addType(field.type);
|
|
4535
4680
|
const cc = slice.elements ? tsIndex.constrainedChoice(pkgName, field.type, slice.elements) : void 0;
|
|
4536
4681
|
if (cc) addType(cc.variantType);
|
|
4682
|
+
if (isTypeDisc && slice.match) {
|
|
4683
|
+
const resourceTypeName = extractResourceTypeFromMatch(slice.match);
|
|
4684
|
+
if (resourceTypeName) {
|
|
4685
|
+
const resourceSchema = tsIndex.schemas.find(
|
|
4686
|
+
(s) => s.identifier.name === resourceTypeName && s.identifier.kind === "resource"
|
|
4687
|
+
);
|
|
4688
|
+
if (resourceSchema) addType(resourceSchema.identifier);
|
|
4689
|
+
}
|
|
4690
|
+
}
|
|
4537
4691
|
}
|
|
4538
4692
|
}
|
|
4539
4693
|
}
|
|
@@ -4548,6 +4702,7 @@ var collectSliceDefs = (tsIndex, flatProfile) => Object.entries(flatProfile.fiel
|
|
|
4548
4702
|
const baseType = tsTypeFromIdentifier(field.type);
|
|
4549
4703
|
const pkgName = flatProfile.identifier.package;
|
|
4550
4704
|
const choiceBaseNames = collectChoiceBaseNames(tsIndex, field.type);
|
|
4705
|
+
const isTypeDisc = field.slicing.discriminator?.some((d) => d.type === "type") ?? false;
|
|
4551
4706
|
return Object.entries(field.slicing.slices).filter(([_, slice]) => Object.keys(slice.match ?? {}).length > 0).map(([sliceName, slice]) => {
|
|
4552
4707
|
const matchFields = Object.keys(slice.match ?? {});
|
|
4553
4708
|
const required = (slice.required ?? []).filter(
|
|
@@ -4555,15 +4710,19 @@ var collectSliceDefs = (tsIndex, flatProfile) => Object.entries(flatProfile.fiel
|
|
|
4555
4710
|
);
|
|
4556
4711
|
const cc = slice.elements ? tsIndex.constrainedChoice(pkgName, field.type, slice.elements) : void 0;
|
|
4557
4712
|
const constrainedChoice = cc && !isPrimitiveIdentifier(cc.variantType) ? cc : void 0;
|
|
4713
|
+
const resourceType = isTypeDisc ? extractResourceTypeFromMatch(slice.match ?? {}) : void 0;
|
|
4714
|
+
const typedBaseType = resourceType ? `${baseType}<${resourceType}>` : baseType;
|
|
4558
4715
|
return {
|
|
4559
4716
|
fieldName,
|
|
4560
4717
|
baseType,
|
|
4718
|
+
typedBaseType,
|
|
4561
4719
|
sliceName,
|
|
4562
4720
|
match: slice.match ?? {},
|
|
4563
4721
|
required,
|
|
4564
4722
|
excluded: slice.excluded ?? [],
|
|
4565
4723
|
array: Boolean(field.array),
|
|
4566
|
-
constrainedChoice
|
|
4724
|
+
constrainedChoice,
|
|
4725
|
+
typeDiscriminator: isTypeDisc
|
|
4567
4726
|
};
|
|
4568
4727
|
});
|
|
4569
4728
|
});
|
|
@@ -4577,7 +4736,7 @@ var generateSliceSetters = (w, sliceDefs, flatProfile, sliceBaseNames) => {
|
|
|
4577
4736
|
const matchRef = `${profileClassName}.${tsSliceStaticName(sliceDef.sliceName)}SliceMatch`;
|
|
4578
4737
|
const tsField = tsFieldName(sliceDef.fieldName);
|
|
4579
4738
|
const fieldAccess = tsGet("this.resource", tsField);
|
|
4580
|
-
const baseType = sliceDef.
|
|
4739
|
+
const baseType = sliceDef.typedBaseType;
|
|
4581
4740
|
const inputOptional = sliceDef.required.length === 0;
|
|
4582
4741
|
const unionType = `${typeName} | ${baseType}`;
|
|
4583
4742
|
const paramSignature = inputOptional ? `(input?: ${unionType}): this` : `(input: ${unionType}): this`;
|
|
@@ -4621,7 +4780,7 @@ var generateSliceGetters = (w, sliceDefs, flatProfile, sliceBaseNames) => {
|
|
|
4621
4780
|
const matchKeys = JSON.stringify(Object.keys(sliceDef.match));
|
|
4622
4781
|
const tsField = tsFieldName(sliceDef.fieldName);
|
|
4623
4782
|
const fieldAccess = tsGet("this.resource", tsField);
|
|
4624
|
-
const baseType = sliceDef.
|
|
4783
|
+
const baseType = sliceDef.typedBaseType;
|
|
4625
4784
|
const defaultReturn = defaultMode === "raw" ? baseType : typeName;
|
|
4626
4785
|
w.lineSM(`public ${getMethodName}(mode: 'flat'): ${typeName} | undefined`);
|
|
4627
4786
|
w.lineSM(`public ${getMethodName}(mode: 'raw'): ${baseType} | undefined`);
|
|
@@ -4641,8 +4800,14 @@ var generateSliceGetters = (w, sliceDefs, flatProfile, sliceBaseNames) => {
|
|
|
4641
4800
|
w.line(`const item = ${fieldAccess}`);
|
|
4642
4801
|
w.line("if (!item || !matchesValue(item, match)) return undefined");
|
|
4643
4802
|
}
|
|
4644
|
-
|
|
4645
|
-
|
|
4803
|
+
if (sliceDef.typeDiscriminator) {
|
|
4804
|
+
w.line(`if (mode === 'raw') return item as ${baseType}`);
|
|
4805
|
+
} else {
|
|
4806
|
+
w.line("if (mode === 'raw') return item");
|
|
4807
|
+
}
|
|
4808
|
+
if (sliceDef.typeDiscriminator) {
|
|
4809
|
+
w.line(`return item as ${typeName}`);
|
|
4810
|
+
} else if (sliceDef.constrainedChoice) {
|
|
4646
4811
|
const cc = sliceDef.constrainedChoice;
|
|
4647
4812
|
w.line(`return unwrapSliceChoice<${typeName}>(item, ${matchKeys}, ${JSON.stringify(cc.variant)})`);
|
|
4648
4813
|
} else {
|
|
@@ -4699,7 +4864,12 @@ var generateValidateMethod = (w, tsIndex, flatProfile) => {
|
|
|
4699
4864
|
const errors = [];
|
|
4700
4865
|
const warnings = [];
|
|
4701
4866
|
for (const [name, field] of Object.entries(fields)) {
|
|
4702
|
-
if (isChoiceInstanceField(field))
|
|
4867
|
+
if (isChoiceInstanceField(field)) {
|
|
4868
|
+
const decl = fields[field.choiceOf];
|
|
4869
|
+
if (decl && isChoiceDeclarationField(decl) && decl.prohibited?.includes(name))
|
|
4870
|
+
errors.push(`...validateExcluded(res, profileName, ${JSON.stringify(name)})`);
|
|
4871
|
+
continue;
|
|
4872
|
+
}
|
|
4703
4873
|
if (isChoiceDeclarationField(field)) {
|
|
4704
4874
|
if (field.required)
|
|
4705
4875
|
errors.push(`...validateChoiceRequired(res, profileName, ${JSON.stringify(field.choices)})`);
|
|
@@ -4812,7 +4982,7 @@ var collectProfileFactoryInfo = (tsIndex, flatProfile) => {
|
|
|
4812
4982
|
};
|
|
4813
4983
|
var collectBaseRequiredParams = (tsIndex, flatProfile, resolveRef, params, coveredNames) => {
|
|
4814
4984
|
const covered = new Set(coveredNames);
|
|
4815
|
-
const baseSchema = tsIndex.
|
|
4985
|
+
const baseSchema = tsIndex.resolveType(flatProfile.base);
|
|
4816
4986
|
if (!baseSchema || !("fields" in baseSchema) || !baseSchema.fields) return;
|
|
4817
4987
|
for (const [name, field] of Object.entries(baseSchema.fields)) {
|
|
4818
4988
|
if (covered.has(name)) continue;
|
|
@@ -4829,78 +4999,20 @@ var generateProfileIndexFile = (w, tsIndex, initialProfiles) => {
|
|
|
4829
4999
|
if (initialProfiles.length === 0) return;
|
|
4830
5000
|
w.cd("profiles", () => {
|
|
4831
5001
|
w.cat("index.ts", () => {
|
|
4832
|
-
const
|
|
5002
|
+
const exports$1 = /* @__PURE__ */ new Map();
|
|
5003
|
+
for (const profile of initialProfiles) {
|
|
4833
5004
|
const className = tsProfileClassName(profile);
|
|
4834
|
-
const resourceName = tsResourceName(profile.identifier);
|
|
4835
|
-
const overrides = detectFieldOverrides(tsIndex, profile);
|
|
4836
|
-
let typeExport;
|
|
4837
|
-
if (overrides.size > 0) typeExport = resourceName;
|
|
4838
|
-
return [profile, className, typeExport];
|
|
4839
|
-
});
|
|
4840
|
-
if (profiles.length === 0) return;
|
|
4841
|
-
const classExports = /* @__PURE__ */ new Map();
|
|
4842
|
-
const typeExports = /* @__PURE__ */ new Map();
|
|
4843
|
-
for (const [profile, className, typeName] of profiles) {
|
|
4844
5005
|
const moduleName = tsProfileModuleName(tsIndex, profile);
|
|
4845
|
-
if (!
|
|
4846
|
-
|
|
4847
|
-
}
|
|
4848
|
-
if (typeName && !typeExports.has(typeName) && !classExports.has(typeName)) {
|
|
4849
|
-
typeExports.set(typeName, `export type { ${typeName} } from "./${moduleName}"`);
|
|
5006
|
+
if (!exports$1.has(className)) {
|
|
5007
|
+
exports$1.set(className, `export { ${className} } from "./${moduleName}"`);
|
|
4850
5008
|
}
|
|
4851
5009
|
}
|
|
4852
|
-
const
|
|
4853
|
-
for (const exp of allExports) {
|
|
5010
|
+
for (const exp of [...exports$1.values()].sort()) {
|
|
4854
5011
|
w.lineSM(exp);
|
|
4855
5012
|
}
|
|
4856
5013
|
});
|
|
4857
5014
|
});
|
|
4858
5015
|
};
|
|
4859
|
-
var tsTypeForProfileField = (tsIndex, flatProfile, fieldName, field) => {
|
|
4860
|
-
if (!isNotChoiceDeclarationField(field)) {
|
|
4861
|
-
throw new Error(`Choice declaration fields not supported for '${fieldName}'`);
|
|
4862
|
-
}
|
|
4863
|
-
let tsType;
|
|
4864
|
-
if (field.enum) {
|
|
4865
|
-
if (field.type?.name === "Coding") {
|
|
4866
|
-
tsType = `Coding<${tsEnumType(field.enum)}>`;
|
|
4867
|
-
} else if (field.type?.name === "CodeableConcept") {
|
|
4868
|
-
tsType = `CodeableConcept<${tsEnumType(field.enum)}>`;
|
|
4869
|
-
} else {
|
|
4870
|
-
tsType = tsEnumType(field.enum);
|
|
4871
|
-
}
|
|
4872
|
-
} else if (field.reference && field.reference.length > 0) {
|
|
4873
|
-
const specialization = tsIndex.findLastSpecialization(flatProfile);
|
|
4874
|
-
if (!isSpecializationTypeSchema(specialization))
|
|
4875
|
-
throw new Error(`Invalid specialization for ${flatProfile.identifier}`);
|
|
4876
|
-
const sField = specialization.fields?.[fieldName];
|
|
4877
|
-
if (sField === void 0 || isChoiceDeclarationField(sField) || sField.reference === void 0)
|
|
4878
|
-
throw new Error(`Invalid field declaration for ${fieldName}`);
|
|
4879
|
-
const sRefs = sField.reference.map((e) => e.name);
|
|
4880
|
-
const references = field.reference.map((ref) => {
|
|
4881
|
-
const resRef = tsIndex.findLastSpecializationByIdentifier(ref);
|
|
4882
|
-
if (resRef.name !== ref.name) {
|
|
4883
|
-
return `"${resRef.name}" /*${ref.name}*/`;
|
|
4884
|
-
}
|
|
4885
|
-
return `'${ref.name}'`;
|
|
4886
|
-
}).join(" | ");
|
|
4887
|
-
if (sRefs.length === 1 && sRefs[0] === "Resource" && references !== '"Resource"') {
|
|
4888
|
-
const cleanRefs = references.replace(/\/\*[^*]*\*\//g, "").trim();
|
|
4889
|
-
tsType = `Reference<"Resource" /* ${cleanRefs} */ >`;
|
|
4890
|
-
} else {
|
|
4891
|
-
tsType = `Reference<${references}>`;
|
|
4892
|
-
}
|
|
4893
|
-
} else if (isPrimitiveIdentifier(field.type)) {
|
|
4894
|
-
tsType = resolvePrimitiveType(field.type.name);
|
|
4895
|
-
} else if (isNestedIdentifier(field.type)) {
|
|
4896
|
-
tsType = tsResourceName(field.type);
|
|
4897
|
-
} else if (field.type === void 0) {
|
|
4898
|
-
throw new Error(`Undefined type for '${fieldName}' field at ${typeSchemaInfo(flatProfile)}`);
|
|
4899
|
-
} else {
|
|
4900
|
-
tsType = field.type.name;
|
|
4901
|
-
}
|
|
4902
|
-
return tsType;
|
|
4903
|
-
};
|
|
4904
5016
|
var generateProfileHelpersImport = (w, tsIndex, flatProfile, sliceDefs, factoryInfo) => {
|
|
4905
5017
|
const extensions = flatProfile.extensions ?? [];
|
|
4906
5018
|
const hasMeta = tsIndex.isWithMetaField(flatProfile);
|
|
@@ -4914,7 +5026,7 @@ var generateProfileHelpersImport = (w, tsIndex, flatProfile, sliceDefs, factoryI
|
|
|
4914
5026
|
imports.push("applySliceMatch", "matchesValue", "setArraySlice", "getArraySlice", "ensureSliceDefaults");
|
|
4915
5027
|
if (extensions.some((ext) => ext.path.split(".").some((s) => s !== "extension"))) imports.push("ensurePath");
|
|
4916
5028
|
if (extensions.some((ext) => ext.isComplex && ext.subExtensions)) imports.push("extractComplexExtension");
|
|
4917
|
-
if (sliceDefs.
|
|
5029
|
+
if (sliceDefs.some((s) => !s.typeDiscriminator)) imports.push("stripMatchKeys");
|
|
4918
5030
|
if (sliceDefs.some((s) => s.constrainedChoice)) imports.push("wrapSliceChoice", "unwrapSliceChoice");
|
|
4919
5031
|
if (extensions.some((ext) => ext.url)) imports.push("isExtension", "getExtensionValue", "pushExtension");
|
|
4920
5032
|
if (Object.keys(flatProfile.fields ?? {}).length > 0)
|
|
@@ -4933,7 +5045,7 @@ var generateProfileHelpersImport = (w, tsIndex, flatProfile, sliceDefs, factoryI
|
|
|
4933
5045
|
w.line();
|
|
4934
5046
|
}
|
|
4935
5047
|
};
|
|
4936
|
-
var generateProfileImports = (w, tsIndex, flatProfile
|
|
5048
|
+
var generateProfileImports = (w, tsIndex, flatProfile) => {
|
|
4937
5049
|
const usedTypes = /* @__PURE__ */ new Map();
|
|
4938
5050
|
const getModulePath = (typeId) => {
|
|
4939
5051
|
if (isNestedIdentifier(typeId)) {
|
|
@@ -4952,7 +5064,6 @@ var generateProfileImports = (w, tsIndex, flatProfile, overrides) => {
|
|
|
4952
5064
|
addType(flatProfile.base);
|
|
4953
5065
|
collectTypesFromSlices(tsIndex, flatProfile, addType);
|
|
4954
5066
|
const needsExtensionType = collectTypesFromExtensions(tsIndex, flatProfile, addType);
|
|
4955
|
-
for (const { typeId } of overrides.values()) addType(typeId);
|
|
4956
5067
|
collectTypesFromFlatInput(tsIndex, flatProfile, addType);
|
|
4957
5068
|
const factoryInfo = collectProfileFactoryInfo(tsIndex, flatProfile);
|
|
4958
5069
|
for (const param of factoryInfo.params) addType(param.typeId);
|
|
@@ -5198,7 +5309,7 @@ var generateInlineExtensionInputTypes = (w, tsIndex, flatProfile) => {
|
|
|
5198
5309
|
const typeName = tsExtensionFlatTypeName(tsProfileName, ext.name);
|
|
5199
5310
|
w.curlyBlock(["export", "type", typeName, "="], () => {
|
|
5200
5311
|
for (const sub of ext.subExtensions ?? []) {
|
|
5201
|
-
const tsType = sub.
|
|
5312
|
+
const tsType = sub.valueFieldType ? tsTypeFromIdentifier(sub.valueFieldType) : "unknown";
|
|
5202
5313
|
const isArray = sub.max === "*";
|
|
5203
5314
|
const isRequired2 = sub.min !== void 0 && sub.min > 0;
|
|
5204
5315
|
w.lineSM(`${sub.name}${isRequired2 ? "" : "?"}: ${tsType}${isArray ? "[]" : ""}`);
|
|
@@ -5212,7 +5323,7 @@ var generateSliceInputTypes = (w, flatProfile, sliceDefs) => {
|
|
|
5212
5323
|
const tsProfileName = tsResourceName(flatProfile.identifier);
|
|
5213
5324
|
for (const sliceDef of sliceDefs) {
|
|
5214
5325
|
const typeName = tsSliceFlatTypeName(tsProfileName, sliceDef.fieldName, sliceDef.sliceName);
|
|
5215
|
-
const matchFields = Object.keys(sliceDef.match);
|
|
5326
|
+
const matchFields = sliceDef.typeDiscriminator ? [] : Object.keys(sliceDef.match);
|
|
5216
5327
|
const allExcluded = [.../* @__PURE__ */ new Set([...sliceDef.excluded, ...matchFields])];
|
|
5217
5328
|
if (sliceDef.constrainedChoice) {
|
|
5218
5329
|
const cc = sliceDef.constrainedChoice;
|
|
@@ -5223,12 +5334,13 @@ var generateSliceInputTypes = (w, flatProfile, sliceDefs) => {
|
|
|
5223
5334
|
}
|
|
5224
5335
|
const excludedNames = allExcluded.map((name) => JSON.stringify(name));
|
|
5225
5336
|
const requiredNames = sliceDef.required.map((name) => JSON.stringify(name));
|
|
5226
|
-
|
|
5337
|
+
const baseType = sliceDef.typedBaseType;
|
|
5338
|
+
let typeExpr = baseType;
|
|
5227
5339
|
if (excludedNames.length > 0) {
|
|
5228
5340
|
typeExpr = `Omit<${typeExpr}, ${excludedNames.join(" | ")}>`;
|
|
5229
5341
|
}
|
|
5230
5342
|
if (requiredNames.length > 0) {
|
|
5231
|
-
typeExpr = `${typeExpr} & Required<Pick<${
|
|
5343
|
+
typeExpr = `${typeExpr} & Required<Pick<${baseType}, ${requiredNames.join(" | ")}>>`;
|
|
5232
5344
|
}
|
|
5233
5345
|
if (sliceDef.constrainedChoice) {
|
|
5234
5346
|
typeExpr = `${typeExpr} & ${tsTypeFromIdentifier(sliceDef.constrainedChoice.variantType)}`;
|
|
@@ -5343,57 +5455,6 @@ var generateProfileClass = (w, tsIndex, flatProfile) => {
|
|
|
5343
5455
|
});
|
|
5344
5456
|
w.line();
|
|
5345
5457
|
};
|
|
5346
|
-
var detectFieldOverrides = (tsIndex, flatProfile) => {
|
|
5347
|
-
const overrides = /* @__PURE__ */ new Map();
|
|
5348
|
-
const specialization = tsIndex.findLastSpecialization(flatProfile);
|
|
5349
|
-
if (!isSpecializationTypeSchema(specialization)) return overrides;
|
|
5350
|
-
const referenceUrl = "http://hl7.org/fhir/StructureDefinition/Reference";
|
|
5351
|
-
const referenceSchema = tsIndex.resolveByUrl(flatProfile.identifier.package, referenceUrl);
|
|
5352
|
-
for (const [fieldName, pField] of Object.entries(flatProfile.fields ?? {})) {
|
|
5353
|
-
if (!isNotChoiceDeclarationField(pField)) continue;
|
|
5354
|
-
const sField = specialization.fields?.[fieldName];
|
|
5355
|
-
if (!sField || isChoiceDeclarationField(sField)) continue;
|
|
5356
|
-
if (pField.reference && sField.reference && pField.reference.length < sField.reference.length) {
|
|
5357
|
-
if (!referenceSchema) continue;
|
|
5358
|
-
const references = pField.reference.map((ref) => {
|
|
5359
|
-
const resRef = tsIndex.findLastSpecializationByIdentifier(ref);
|
|
5360
|
-
if (resRef.name !== ref.name) {
|
|
5361
|
-
return `"${resRef.name}"`;
|
|
5362
|
-
}
|
|
5363
|
-
return `"${ref.name}"`;
|
|
5364
|
-
}).join(" | ");
|
|
5365
|
-
overrides.set(fieldName, {
|
|
5366
|
-
profileType: `Reference<${references}>`,
|
|
5367
|
-
required: pField.required ?? false,
|
|
5368
|
-
array: pField.array ?? false,
|
|
5369
|
-
typeId: referenceSchema.identifier
|
|
5370
|
-
});
|
|
5371
|
-
} else if (pField.required && !sField.required) {
|
|
5372
|
-
const tsType = tsTypeForProfileField(tsIndex, flatProfile, fieldName, pField);
|
|
5373
|
-
overrides.set(fieldName, {
|
|
5374
|
-
profileType: tsType,
|
|
5375
|
-
required: true,
|
|
5376
|
-
array: pField.array ?? false,
|
|
5377
|
-
typeId: pField.type
|
|
5378
|
-
});
|
|
5379
|
-
}
|
|
5380
|
-
}
|
|
5381
|
-
return overrides;
|
|
5382
|
-
};
|
|
5383
|
-
var generateProfileOverrideInterface = (w, flatProfile, overrides) => {
|
|
5384
|
-
if (overrides.size === 0) return;
|
|
5385
|
-
const tsProfileName = tsResourceName(flatProfile.identifier);
|
|
5386
|
-
const tsBaseResourceName = tsResourceName(flatProfile.base);
|
|
5387
|
-
w.curlyBlock(["export", "interface", tsProfileName, "extends", tsBaseResourceName], () => {
|
|
5388
|
-
for (const [fieldName, override] of overrides) {
|
|
5389
|
-
const tsField = tsFieldName(fieldName);
|
|
5390
|
-
const optionalSymbol = override.required ? "" : "?";
|
|
5391
|
-
const arraySymbol = override.array ? "[]" : "";
|
|
5392
|
-
w.lineSM(`${tsField}${optionalSymbol}: ${override.profileType}${arraySymbol}`);
|
|
5393
|
-
}
|
|
5394
|
-
});
|
|
5395
|
-
w.line();
|
|
5396
|
-
};
|
|
5397
5458
|
|
|
5398
5459
|
// src/api/writer-generator/typescript/writer.ts
|
|
5399
5460
|
var resolveTsAssets = (fn) => {
|
|
@@ -5488,14 +5549,6 @@ var TypeScript = class extends Writer {
|
|
|
5488
5549
|
name: tsResourceName(dep),
|
|
5489
5550
|
dep
|
|
5490
5551
|
});
|
|
5491
|
-
} else if (isNestedIdentifier(dep)) {
|
|
5492
|
-
const ndep = { ...dep };
|
|
5493
|
-
ndep.name = tsNameFromCanonical(dep.url);
|
|
5494
|
-
imports.push({
|
|
5495
|
-
tsPackage: `${importPrefix}${tsModulePath(ndep)}`,
|
|
5496
|
-
name: tsResourceName(dep),
|
|
5497
|
-
dep
|
|
5498
|
-
});
|
|
5499
5552
|
} else {
|
|
5500
5553
|
skipped.push(dep);
|
|
5501
5554
|
}
|
|
@@ -5537,11 +5590,32 @@ var TypeScript = class extends Writer {
|
|
|
5537
5590
|
const genericTypes = ["Reference", "Coding", "CodeableConcept"];
|
|
5538
5591
|
if (genericTypes.includes(schema.identifier.name)) {
|
|
5539
5592
|
name = `${schema.identifier.name}<T extends string = string>`;
|
|
5540
|
-
} else if (schema.identifier.kind === "nested") {
|
|
5541
|
-
name = tsResourceName(schema.identifier);
|
|
5542
5593
|
} else {
|
|
5543
5594
|
name = tsResourceName(schema.identifier);
|
|
5544
5595
|
}
|
|
5596
|
+
const typeFamilyFields = [];
|
|
5597
|
+
for (const [fieldName, field] of Object.entries(schema.fields ?? {})) {
|
|
5598
|
+
if (isChoiceDeclarationField(field) || !field.type) continue;
|
|
5599
|
+
const fieldTypeSchema = tsIndex.resolveType(field.type);
|
|
5600
|
+
if (isSpecializationTypeSchema(fieldTypeSchema) && (fieldTypeSchema.typeFamily?.resources?.length ?? 0) > 0) {
|
|
5601
|
+
typeFamilyFields.push({ fieldName: tsFieldName(fieldName), familyTypeName: field.type.name });
|
|
5602
|
+
}
|
|
5603
|
+
}
|
|
5604
|
+
const genericFieldMap = {};
|
|
5605
|
+
if (!genericTypes.includes(schema.identifier.name) && typeFamilyFields.length > 0) {
|
|
5606
|
+
const [first, ...rest] = typeFamilyFields;
|
|
5607
|
+
if (first && rest.length === 0) {
|
|
5608
|
+
genericFieldMap[first.fieldName] = "T";
|
|
5609
|
+
name += `<T extends ${first.familyTypeName} = ${first.familyTypeName}>`;
|
|
5610
|
+
} else {
|
|
5611
|
+
const params = typeFamilyFields.map((tf) => {
|
|
5612
|
+
const paramName = `T${uppercaseFirstLetter(tf.fieldName)}`;
|
|
5613
|
+
genericFieldMap[tf.fieldName] = paramName;
|
|
5614
|
+
return `${paramName} extends ${tf.familyTypeName} = ${tf.familyTypeName}`;
|
|
5615
|
+
});
|
|
5616
|
+
name += `<${params.join(", ")}>`;
|
|
5617
|
+
}
|
|
5618
|
+
}
|
|
5545
5619
|
let extendsClause;
|
|
5546
5620
|
if (schema.base) extendsClause = `extends ${tsNameFromCanonical(schema.base.url)}`;
|
|
5547
5621
|
this.debugComment(schema.identifier);
|
|
@@ -5551,8 +5625,7 @@ var TypeScript = class extends Writer {
|
|
|
5551
5625
|
}
|
|
5552
5626
|
this.curlyBlock(["export", "interface", name, extendsClause], () => {
|
|
5553
5627
|
if (isResourceTypeSchema(schema)) {
|
|
5554
|
-
const possibleResourceTypes = [schema.identifier];
|
|
5555
|
-
possibleResourceTypes.push(...tsIndex.resourceChildren(schema.identifier));
|
|
5628
|
+
const possibleResourceTypes = [schema.identifier, ...schema.typeFamily?.resources ?? []];
|
|
5556
5629
|
const openSetSuffix = this.opts.openResourceTypeSet && possibleResourceTypes.length > 1 ? " | string" : "";
|
|
5557
5630
|
this.lineSM(
|
|
5558
5631
|
`resourceType: ${possibleResourceTypes.sort((a, b) => a.name.localeCompare(b.name)).map((e) => `"${e.name}"`).join(" | ")}${openSetSuffix}`
|
|
@@ -5566,7 +5639,7 @@ var TypeScript = class extends Writer {
|
|
|
5566
5639
|
if (!field.type) continue;
|
|
5567
5640
|
this.debugComment(fieldName, ":", field);
|
|
5568
5641
|
const tsName = tsFieldName(fieldName);
|
|
5569
|
-
const tsType = resolveFieldTsType(schema.identifier.name, tsName, field);
|
|
5642
|
+
const tsType = resolveFieldTsType(schema.identifier.name, tsName, field, void 0, genericFieldMap);
|
|
5570
5643
|
const optionalSymbol = field.required ? "" : "?";
|
|
5571
5644
|
const arraySymbol = field.array ? "[]" : "";
|
|
5572
5645
|
this.lineSM(`${tsName}${optionalSymbol}: ${tsType}${arraySymbol}`);
|
|
@@ -5610,13 +5683,11 @@ var TypeScript = class extends Writer {
|
|
|
5610
5683
|
this.cat(`${tsProfileModuleFileName(tsIndex, schema)}`, () => {
|
|
5611
5684
|
this.generateDisclaimer();
|
|
5612
5685
|
const flatProfile = tsIndex.flatProfile(schema);
|
|
5613
|
-
|
|
5614
|
-
generateProfileImports(this, tsIndex, flatProfile, overrides);
|
|
5615
|
-
generateProfileOverrideInterface(this, flatProfile, overrides);
|
|
5686
|
+
generateProfileImports(this, tsIndex, flatProfile);
|
|
5616
5687
|
generateProfileClass(this, tsIndex, flatProfile);
|
|
5617
5688
|
});
|
|
5618
5689
|
});
|
|
5619
|
-
} else if (
|
|
5690
|
+
} else if (isSpecializationTypeSchema(schema)) {
|
|
5620
5691
|
this.cat(`${tsModuleFileName(schema.identifier)}`, () => {
|
|
5621
5692
|
this.generateDisclaimer();
|
|
5622
5693
|
this.generateDependenciesImports(tsIndex, schema);
|
|
@@ -5707,8 +5778,6 @@ var APIBuilder = class {
|
|
|
5707
5778
|
outputDir: "./generated",
|
|
5708
5779
|
cleanOutput: true,
|
|
5709
5780
|
throwException: false,
|
|
5710
|
-
treeShake: void 0,
|
|
5711
|
-
promoteLogical: void 0,
|
|
5712
5781
|
registry: void 0,
|
|
5713
5782
|
dropCanonicalManagerCache: false
|
|
5714
5783
|
};
|
|
@@ -5885,13 +5954,18 @@ var APIBuilder = class {
|
|
|
5885
5954
|
return this;
|
|
5886
5955
|
}
|
|
5887
5956
|
typeSchema(cfg) {
|
|
5957
|
+
this.options.typeSchema ??= {};
|
|
5888
5958
|
if (cfg.treeShake) {
|
|
5889
|
-
|
|
5890
|
-
this.options.treeShake = cfg.treeShake;
|
|
5959
|
+
assert4(this.options.typeSchema.treeShake === void 0, "treeShake option is already set");
|
|
5960
|
+
this.options.typeSchema.treeShake = cfg.treeShake;
|
|
5891
5961
|
}
|
|
5892
5962
|
if (cfg.promoteLogical) {
|
|
5893
|
-
|
|
5894
|
-
this.options.promoteLogical = cfg.promoteLogical;
|
|
5963
|
+
assert4(this.options.typeSchema.promoteLogical === void 0, "promoteLogical option is already set");
|
|
5964
|
+
this.options.typeSchema.promoteLogical = cfg.promoteLogical;
|
|
5965
|
+
}
|
|
5966
|
+
if (cfg.resolveCollisions) {
|
|
5967
|
+
assert4(this.options.typeSchema.resolveCollisions === void 0, "resolveCollisions option is already set");
|
|
5968
|
+
this.options.typeSchema.resolveCollisions = cfg.resolveCollisions;
|
|
5895
5969
|
}
|
|
5896
5970
|
this.irReport({});
|
|
5897
5971
|
return this;
|
|
@@ -5948,15 +6022,20 @@ var APIBuilder = class {
|
|
|
5948
6022
|
});
|
|
5949
6023
|
}
|
|
5950
6024
|
const tsLogger = this.logger.fork("ts");
|
|
5951
|
-
const { schemas: typeSchemas, collisions } = await generateTypeSchemas(
|
|
5952
|
-
const tsIndexOpts = {
|
|
6025
|
+
const { schemas: typeSchemas, collisions } = await generateTypeSchemas(
|
|
5953
6026
|
register,
|
|
5954
|
-
|
|
5955
|
-
|
|
6027
|
+
this.options.typeSchema?.resolveCollisions,
|
|
6028
|
+
tsLogger
|
|
6029
|
+
);
|
|
6030
|
+
const irReport = {
|
|
6031
|
+
resolveCollisions: this.options.typeSchema?.resolveCollisions,
|
|
6032
|
+
collisions
|
|
5956
6033
|
};
|
|
6034
|
+
const tsIndexOpts = { register, irReport, logger: tsLogger };
|
|
5957
6035
|
let tsIndex = mkTypeSchemaIndex(typeSchemas, tsIndexOpts);
|
|
5958
|
-
if (this.options.treeShake) tsIndex = treeShake(tsIndex, this.options.treeShake);
|
|
5959
|
-
if (this.options.promoteLogical)
|
|
6036
|
+
if (this.options.typeSchema?.treeShake) tsIndex = treeShake(tsIndex, this.options.typeSchema.treeShake);
|
|
6037
|
+
if (this.options.typeSchema?.promoteLogical)
|
|
6038
|
+
tsIndex = promoteLogical(tsIndex, this.options.typeSchema.promoteLogical);
|
|
5960
6039
|
tsLogger.printTagSummary();
|
|
5961
6040
|
this.logger.debug(`Executing ${this.generators.length} generators`);
|
|
5962
6041
|
await this.executeGenerators(result, tsIndex);
|