@atomic-ehr/codegen 0.0.17 → 0.0.18-canary.20260727072946.f724a66
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/LICENSE +1 -1
- package/README.md +28 -1
- package/assets/api/writer-generator/python/profile_helpers.py +52 -18
- package/assets/api/writer-generator/typescript/profile-helpers.ts +11 -0
- package/dist/cli/index.js +8 -8
- package/dist/index.d.ts +14 -2
- package/dist/index.js +420 -196
- package/dist/index.js.map +1 -1
- package/package.json +9 -8
package/dist/index.js
CHANGED
|
@@ -383,6 +383,9 @@ var isPrimitiveIdentifier = (id) => {
|
|
|
383
383
|
var isNestedIdentifier = (id) => {
|
|
384
384
|
return id?.kind === "nested";
|
|
385
385
|
};
|
|
386
|
+
var isProfileIdentifier = (id) => {
|
|
387
|
+
return id?.kind === "profile";
|
|
388
|
+
};
|
|
386
389
|
var isSnapshotProfileIdentifier = (id) => {
|
|
387
390
|
return id?.kind === "profile-snapshot";
|
|
388
391
|
};
|
|
@@ -426,6 +429,7 @@ var isValueSetTypeSchema = (schema) => {
|
|
|
426
429
|
var isSnapshotProfileTypeSchema = (s) => {
|
|
427
430
|
return s?.identifier.kind === "profile-snapshot";
|
|
428
431
|
};
|
|
432
|
+
var isTypeDiscriminated = (slicing) => slicing?.discriminator?.some((d) => d.type === "type") ?? false;
|
|
429
433
|
var extractExtensionDeps = (ext) => [
|
|
430
434
|
...ext.valueFieldTypes ?? [],
|
|
431
435
|
...ext.profile ? [ext.profile] : [],
|
|
@@ -892,6 +896,18 @@ var pyTypeFromIdentifier = (id) => {
|
|
|
892
896
|
if (prim !== void 0) return prim;
|
|
893
897
|
return deriveResourceName(id);
|
|
894
898
|
};
|
|
899
|
+
var pyReferenceTypeParam = (field, tsIndex) => {
|
|
900
|
+
if (!field.reference || field.reference.resource.length === 0) return void 0;
|
|
901
|
+
const isFamilyType = (ref) => {
|
|
902
|
+
const schema = tsIndex.resolveType(ref);
|
|
903
|
+
if (!schema || !("typeFamily" in schema)) return false;
|
|
904
|
+
return (schema.typeFamily?.resources?.length ?? 0) > 0;
|
|
905
|
+
};
|
|
906
|
+
const resolved = field.reference.resource.map((ref) => tsIndex.findLastSpecializationByIdentifier(ref));
|
|
907
|
+
if (resolved.some(isFamilyType)) return void 0;
|
|
908
|
+
const names = [...new Set(resolved.map((ref) => ref.name))];
|
|
909
|
+
return `Literal[${names.map((n) => JSON.stringify(n)).join(", ")}]`;
|
|
910
|
+
};
|
|
895
911
|
var groupByPackages = (typeSchemas) => {
|
|
896
912
|
const grouped = {};
|
|
897
913
|
for (const ts of typeSchemas) {
|
|
@@ -1083,6 +1099,54 @@ var populateGeneric = (schemas, resolveType) => {
|
|
|
1083
1099
|
schema.dependencies = concatIdentifiers(schema.dependencies, constraints) ?? schema.dependencies;
|
|
1084
1100
|
}
|
|
1085
1101
|
};
|
|
1102
|
+
var choiceInstances = (fields, declName) => Object.entries(fields).filter(
|
|
1103
|
+
(e) => isChoiceInstanceField(e[1]) && e[1].choiceOf === declName
|
|
1104
|
+
);
|
|
1105
|
+
var choiceUniverse = (fields, baseFields, declName, declField) => {
|
|
1106
|
+
const baseDecl = baseFields[declName];
|
|
1107
|
+
const baseChoices = isChoiceDeclarationField(baseDecl) ? baseDecl.choices : [];
|
|
1108
|
+
return [
|
|
1109
|
+
.../* @__PURE__ */ new Set([...baseChoices, ...declField.choices, ...choiceInstances(fields, declName).map(([name]) => name)])
|
|
1110
|
+
];
|
|
1111
|
+
};
|
|
1112
|
+
var declaredChoiceVariants = (fields, declName) => {
|
|
1113
|
+
const declaration = fields[declName];
|
|
1114
|
+
const fromDeclaration = isChoiceDeclarationField(declaration) && !declaration.excluded ? declaration.choices : [];
|
|
1115
|
+
const fromInstances = choiceInstances(fields, declName).filter(([, field]) => !field.excluded).map(([name]) => name);
|
|
1116
|
+
return [.../* @__PURE__ */ new Set([...fromDeclaration, ...fromInstances])];
|
|
1117
|
+
};
|
|
1118
|
+
var resolvePermittedChoiceVariants = (universe, baseDeclaration, constraintSchemas, declName, logger) => {
|
|
1119
|
+
let permitted = new Set(isChoiceDeclarationField(baseDeclaration) ? baseDeclaration.choices : universe);
|
|
1120
|
+
for (const schema of constraintSchemas.slice().reverse()) {
|
|
1121
|
+
const fields = schema.fields;
|
|
1122
|
+
if (!fields) continue;
|
|
1123
|
+
const reintroduced = declaredChoiceVariants(fields, declName).filter((name) => !permitted.has(name));
|
|
1124
|
+
if (reintroduced.length > 0)
|
|
1125
|
+
logger?.dryWarn(
|
|
1126
|
+
"#nonMonotonicChoice",
|
|
1127
|
+
`Profile '${schema.identifier.name}' declares choice variant(s) ${reintroduced.join(", ")} of '${declName}' that an ancestor prohibits; they stay prohibited`
|
|
1128
|
+
);
|
|
1129
|
+
permitted = applyChoiceConstraints(permitted, fields, declName);
|
|
1130
|
+
}
|
|
1131
|
+
return permitted;
|
|
1132
|
+
};
|
|
1133
|
+
var applyChoiceConstraints = (permitted, fields, declName) => {
|
|
1134
|
+
const result = new Set(permitted);
|
|
1135
|
+
const instances = choiceInstances(fields, declName);
|
|
1136
|
+
for (const [name, field] of instances) {
|
|
1137
|
+
if (field.excluded) result.delete(name);
|
|
1138
|
+
}
|
|
1139
|
+
const declaration = fields[declName];
|
|
1140
|
+
if (isChoiceDeclarationField(declaration)) {
|
|
1141
|
+
if (declaration.excluded) return /* @__PURE__ */ new Set();
|
|
1142
|
+
const declared2 = new Set(declaration.choices);
|
|
1143
|
+
return new Set([...result].filter((name) => declared2.has(name)));
|
|
1144
|
+
}
|
|
1145
|
+
const declared = instances.filter(([, field]) => !field.excluded).map(([name]) => name);
|
|
1146
|
+
if (declared.length === 0) return result;
|
|
1147
|
+
const declaredSet = new Set(declared);
|
|
1148
|
+
return new Set([...result].filter((name) => declaredSet.has(name)));
|
|
1149
|
+
};
|
|
1086
1150
|
var mkTypeSchemaIndex = (schemas, {
|
|
1087
1151
|
register,
|
|
1088
1152
|
logger,
|
|
@@ -1196,28 +1260,29 @@ var mkTypeSchemaIndex = (schemas, {
|
|
|
1196
1260
|
if (isNestedTypeSchema(resolved)) return findLastSpecializationByIdentifier(resolved.base);
|
|
1197
1261
|
return findLastSpecialization(resolved).identifier;
|
|
1198
1262
|
};
|
|
1199
|
-
const narrowMergedChoiceDeclarations = (mergedFields, constraintSchemas) => {
|
|
1263
|
+
const narrowMergedChoiceDeclarations = (mergedFields, constraintSchemas, baseFields = {}) => {
|
|
1200
1264
|
const result = { ...mergedFields };
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
const sFields = cSchema.fields;
|
|
1205
|
-
if (!sFields) continue;
|
|
1206
|
-
if (sFields[declName] && isChoiceDeclarationField(sFields[declName])) continue;
|
|
1207
|
-
const instancesInSchema = Object.entries(sFields).filter(([_, f]) => isChoiceInstanceField(f) && f.choiceOf === declName).map(([name]) => name);
|
|
1208
|
-
if (instancesInSchema.length === 0) continue;
|
|
1209
|
-
const allowed = new Set(instancesInSchema);
|
|
1210
|
-
result[declName] = { ...declField, choices: declField.choices.filter((c) => allowed.has(c)) };
|
|
1211
|
-
break;
|
|
1212
|
-
}
|
|
1213
|
-
}
|
|
1214
|
-
for (const [declName, declField] of Object.entries(result)) {
|
|
1265
|
+
const declNames = /* @__PURE__ */ new Set([...Object.keys(result), ...Object.keys(baseFields)]);
|
|
1266
|
+
for (const declName of declNames) {
|
|
1267
|
+
const declField = result[declName] ?? baseFields[declName];
|
|
1215
1268
|
if (!isChoiceDeclarationField(declField)) continue;
|
|
1216
|
-
const
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1269
|
+
const restated = result[declName] !== void 0;
|
|
1270
|
+
if (!restated && choiceInstances(result, declName).length === 0) continue;
|
|
1271
|
+
const universe = choiceUniverse(result, baseFields, declName, declField);
|
|
1272
|
+
const permitted = resolvePermittedChoiceVariants(
|
|
1273
|
+
universe,
|
|
1274
|
+
baseFields[declName],
|
|
1275
|
+
constraintSchemas,
|
|
1276
|
+
declName,
|
|
1277
|
+
logger
|
|
1278
|
+
);
|
|
1279
|
+
const prohibited = universe.filter((name) => !permitted.has(name));
|
|
1280
|
+
if (!restated && prohibited.length === 0) continue;
|
|
1281
|
+
result[declName] = {
|
|
1282
|
+
...declField,
|
|
1283
|
+
choices: universe.filter((name) => permitted.has(name)),
|
|
1284
|
+
...prohibited.length > 0 ? { prohibited } : {}
|
|
1285
|
+
};
|
|
1221
1286
|
}
|
|
1222
1287
|
return result;
|
|
1223
1288
|
};
|
|
@@ -1228,8 +1293,10 @@ var mkTypeSchemaIndex = (schemas, {
|
|
|
1228
1293
|
if (!nonConstraintSchema)
|
|
1229
1294
|
throw new Error(`No non-constraint schema found in hierarchy for ${schema.identifier.name}`);
|
|
1230
1295
|
const mergedFields = {};
|
|
1296
|
+
const mergedSlicing = {};
|
|
1231
1297
|
for (const anySchema of constraintSchemas.slice().reverse()) {
|
|
1232
1298
|
const schema2 = anySchema;
|
|
1299
|
+
if (schema2.slicing) Object.assign(mergedSlicing, schema2.slicing);
|
|
1233
1300
|
if (!schema2.fields) continue;
|
|
1234
1301
|
for (const [fieldName, fieldConstraints] of Object.entries(schema2.fields)) {
|
|
1235
1302
|
const merged = mergedFields[fieldName] ? { ...mergedFields[fieldName], ...fieldConstraints } : { ...fieldConstraints };
|
|
@@ -1239,7 +1306,11 @@ var mkTypeSchemaIndex = (schemas, {
|
|
|
1239
1306
|
mergedFields[fieldName] = merged;
|
|
1240
1307
|
}
|
|
1241
1308
|
}
|
|
1242
|
-
const narrowedFields = narrowMergedChoiceDeclarations(
|
|
1309
|
+
const narrowedFields = narrowMergedChoiceDeclarations(
|
|
1310
|
+
mergedFields,
|
|
1311
|
+
constraintSchemas,
|
|
1312
|
+
nonConstraintSchema.fields
|
|
1313
|
+
);
|
|
1243
1314
|
const dependencies = Object.values(
|
|
1244
1315
|
Object.fromEntries(
|
|
1245
1316
|
constraintSchemas.flatMap((s) => s.dependencies ?? []).map((dep) => [dep.url, dep])
|
|
@@ -1256,6 +1327,7 @@ var mkTypeSchemaIndex = (schemas, {
|
|
|
1256
1327
|
...schema,
|
|
1257
1328
|
base: nonConstraintSchema.identifier,
|
|
1258
1329
|
fields: narrowedFields,
|
|
1330
|
+
slicing: Object.keys(mergedSlicing).length > 0 ? mergedSlicing : void 0,
|
|
1259
1331
|
dependencies,
|
|
1260
1332
|
extensions: mergedExtensions.length > 0 ? mergedExtensions : void 0
|
|
1261
1333
|
};
|
|
@@ -1281,6 +1353,7 @@ var mkTypeSchemaIndex = (schemas, {
|
|
|
1281
1353
|
base: flat.base,
|
|
1282
1354
|
description: flat.description,
|
|
1283
1355
|
fields: flatFields,
|
|
1356
|
+
slicing: flat.slicing,
|
|
1284
1357
|
inheritedRequiredFields: inheritedRequiredFields.length > 0 ? inheritedRequiredFields : void 0,
|
|
1285
1358
|
extensions: flat.extensions,
|
|
1286
1359
|
dependencies: flat.dependencies,
|
|
@@ -1625,10 +1698,10 @@ var generateGenericExtensionSetter = (w, ext, className, baseName, targetPath, e
|
|
|
1625
1698
|
};
|
|
1626
1699
|
|
|
1627
1700
|
// src/api/writer-generator/python/profile-slices.ts
|
|
1628
|
-
var collectRequiredSliceNames = (field) => {
|
|
1629
|
-
if (!field.array || !
|
|
1630
|
-
if (
|
|
1631
|
-
const names = Object.entries(
|
|
1701
|
+
var collectRequiredSliceNames = (field, fieldSlicing) => {
|
|
1702
|
+
if (!field.array || !fieldSlicing?.slices) return void 0;
|
|
1703
|
+
if (isTypeDiscriminated(fieldSlicing)) return void 0;
|
|
1704
|
+
const names = Object.entries(fieldSlicing.slices).filter(([_, s]) => s.min !== void 0 && s.min >= 1 && s.match && Object.keys(s.match).length > 0).map(([name]) => name);
|
|
1632
1705
|
return names.length > 0 ? names : void 0;
|
|
1633
1706
|
};
|
|
1634
1707
|
var generateStaticSliceFields = (w, sliceDefs) => {
|
|
@@ -1660,8 +1733,8 @@ var normalizeMatchForPython = (tsIndex, match, schema) => {
|
|
|
1660
1733
|
}
|
|
1661
1734
|
return result;
|
|
1662
1735
|
};
|
|
1663
|
-
var extractTypeDiscriminatorResource = (
|
|
1664
|
-
if (!
|
|
1736
|
+
var extractTypeDiscriminatorResource = (isTypeDiscriminated2, rawMatch) => {
|
|
1737
|
+
if (!isTypeDiscriminated2 || !rawMatch) return void 0;
|
|
1665
1738
|
for (const val of Object.values(rawMatch)) {
|
|
1666
1739
|
if (val !== null && typeof val === "object" && !Array.isArray(val)) {
|
|
1667
1740
|
const rt = val.resourceType;
|
|
@@ -1672,8 +1745,9 @@ var extractTypeDiscriminatorResource = (isTypeDiscriminated, rawMatch) => {
|
|
|
1672
1745
|
};
|
|
1673
1746
|
var collectSliceDefs = (tsIndex, flatProfile) => {
|
|
1674
1747
|
const pkgName = flatProfile.identifier.package;
|
|
1675
|
-
return Object.entries(flatProfile.
|
|
1676
|
-
|
|
1748
|
+
return Object.entries(flatProfile.slicing ?? {}).flatMap(([fieldName, fieldSlicing]) => {
|
|
1749
|
+
const field = flatProfile.fields[fieldName];
|
|
1750
|
+
if (!isNotChoiceDeclarationField(field) || !fieldSlicing.slices || !field.type) return [];
|
|
1677
1751
|
const choiceBaseNames = /* @__PURE__ */ new Set();
|
|
1678
1752
|
const baseSchema = tsIndex.resolveType(field.type);
|
|
1679
1753
|
if (baseSchema && "fields" in baseSchema && baseSchema.fields) {
|
|
@@ -1681,16 +1755,16 @@ var collectSliceDefs = (tsIndex, flatProfile) => {
|
|
|
1681
1755
|
if (isChoiceDeclarationField(f)) choiceBaseNames.add(n);
|
|
1682
1756
|
}
|
|
1683
1757
|
}
|
|
1684
|
-
return Object.entries(
|
|
1758
|
+
return Object.entries(fieldSlicing.slices).filter(([_, slice]) => Object.keys(slice.match ?? {}).length > 0).map(([sliceName, slice]) => {
|
|
1685
1759
|
const matchFields = Object.keys(slice.match ?? {});
|
|
1686
1760
|
const required = (slice.required ?? []).filter(
|
|
1687
1761
|
(name) => !matchFields.includes(name) && !choiceBaseNames.has(name)
|
|
1688
1762
|
);
|
|
1689
1763
|
const cc = slice.elements ? tsIndex.constrainedChoice(pkgName, field.type, slice.elements) : void 0;
|
|
1690
1764
|
const constrainedChoice = cc && !isPrimitiveIdentifier(cc.variantType) ? cc : void 0;
|
|
1691
|
-
const
|
|
1765
|
+
const typeDiscriminated = isTypeDiscriminated(fieldSlicing);
|
|
1692
1766
|
const typeDiscriminatorResource = extractTypeDiscriminatorResource(
|
|
1693
|
-
|
|
1767
|
+
typeDiscriminated,
|
|
1694
1768
|
slice.match
|
|
1695
1769
|
);
|
|
1696
1770
|
return {
|
|
@@ -1703,7 +1777,7 @@ var collectSliceDefs = (tsIndex, flatProfile) => {
|
|
|
1703
1777
|
constrainedChoice,
|
|
1704
1778
|
elementTypeName: field.type && !isPrimitiveIdentifier(field.type) ? pyTypeFromIdentifier(field.type) : void 0,
|
|
1705
1779
|
elementTypeId: field.type && !isPrimitiveIdentifier(field.type) ? field.type : void 0,
|
|
1706
|
-
isTypeDiscriminated,
|
|
1780
|
+
isTypeDiscriminated: typeDiscriminated,
|
|
1707
1781
|
typeDiscriminatorResource,
|
|
1708
1782
|
nameCandidates: slice.nameCandidates
|
|
1709
1783
|
};
|
|
@@ -1840,25 +1914,46 @@ var generateSliceSetters = (w, className, sliceDefs, sliceBaseNames) => {
|
|
|
1840
1914
|
};
|
|
1841
1915
|
|
|
1842
1916
|
// src/api/writer-generator/python/profile-factory.ts
|
|
1843
|
-
var fieldPyType = (field, resolveRef) => {
|
|
1917
|
+
var fieldPyType = (field, resolveRef, tsIndex) => {
|
|
1844
1918
|
const resolved = resolveRef ? resolveRef(field.type) : field.type;
|
|
1845
|
-
|
|
1919
|
+
let base = pyTypeFromIdentifier(resolved);
|
|
1846
1920
|
if (base === "str" && field.enum && !field.enum.isOpen && field.enum.values.length > 0) {
|
|
1847
1921
|
const literal = `Literal[${field.enum.values.map((v) => JSON.stringify(v)).join(", ")}]`;
|
|
1848
1922
|
return field.array ? `list[${literal}]` : literal;
|
|
1849
1923
|
}
|
|
1924
|
+
if (base === "Reference" && tsIndex) {
|
|
1925
|
+
const typeParam = pyReferenceTypeParam(field, tsIndex);
|
|
1926
|
+
if (typeParam) base = `Reference[${typeParam}]`;
|
|
1927
|
+
}
|
|
1850
1928
|
return field.array ? `list[${base}]` : base;
|
|
1851
1929
|
};
|
|
1852
|
-
var
|
|
1930
|
+
var pyReferenceComment = (field) => {
|
|
1931
|
+
const urls = (field.reference?.profiles ?? []).map((profile) => profile.url);
|
|
1932
|
+
return urls.length > 0 ? ` # ${urls.join(", ")}` : void 0;
|
|
1933
|
+
};
|
|
1934
|
+
var tryPromoteChoice = (field, fields, params, promotedChoices, tsIndex) => {
|
|
1853
1935
|
if (!isChoiceDeclarationField(field) || !field.required || field.choices.length !== 1) return;
|
|
1854
1936
|
const choiceName = field.choices[0];
|
|
1855
1937
|
if (!choiceName) return;
|
|
1856
1938
|
const choiceField = fields[choiceName];
|
|
1857
1939
|
if (!choiceField || !isChoiceInstanceField(choiceField)) return;
|
|
1858
|
-
const pyType =
|
|
1859
|
-
params.push({
|
|
1940
|
+
const pyType = pyChoiceInstanceType(choiceField, tsIndex);
|
|
1941
|
+
params.push({
|
|
1942
|
+
name: choiceName,
|
|
1943
|
+
pyType,
|
|
1944
|
+
typeId: choiceField.type,
|
|
1945
|
+
refComment: pyReferenceComment(choiceField)
|
|
1946
|
+
});
|
|
1860
1947
|
promotedChoices.add(choiceName);
|
|
1861
1948
|
};
|
|
1949
|
+
var pyChoiceInstanceType = (field, tsIndex) => {
|
|
1950
|
+
let base = pyTypeFromIdentifier(field.type);
|
|
1951
|
+
if (base === "Reference") {
|
|
1952
|
+
const typeParam = pyReferenceTypeParam(field, tsIndex);
|
|
1953
|
+
if (typeParam) base = `Reference[${typeParam}]`;
|
|
1954
|
+
}
|
|
1955
|
+
return base + (field.array ? "[]" : "");
|
|
1956
|
+
};
|
|
1862
1957
|
var collectBaseRequiredParams = (tsIndex, flatProfile, resolveRef, params, coveredNames) => {
|
|
1863
1958
|
const covered = new Set(coveredNames);
|
|
1864
1959
|
const baseSchema = tsIndex.resolveType(flatProfile.base);
|
|
@@ -1869,8 +1964,8 @@ var collectBaseRequiredParams = (tsIndex, flatProfile, resolveRef, params, cover
|
|
|
1869
1964
|
if (isChoiceInstanceField(field)) continue;
|
|
1870
1965
|
if (isChoiceDeclarationField(field)) continue;
|
|
1871
1966
|
if (isNotChoiceDeclarationField(field) && field.type) {
|
|
1872
|
-
const pyType = fieldPyType(field, resolveRef);
|
|
1873
|
-
params.push({ name, pyType, typeId: field.type });
|
|
1967
|
+
const pyType = fieldPyType(field, resolveRef, tsIndex);
|
|
1968
|
+
params.push({ name, pyType, typeId: field.type, refComment: pyReferenceComment(field) });
|
|
1874
1969
|
}
|
|
1875
1970
|
}
|
|
1876
1971
|
};
|
|
@@ -1899,32 +1994,32 @@ var collectProfileFactoryInfo = (tsIndex, flatProfile) => {
|
|
|
1899
1994
|
continue;
|
|
1900
1995
|
}
|
|
1901
1996
|
if (isChoiceDeclarationField(field)) {
|
|
1902
|
-
tryPromoteChoice(field, fields, params, promotedChoices);
|
|
1997
|
+
tryPromoteChoice(field, fields, params, promotedChoices, tsIndex);
|
|
1903
1998
|
continue;
|
|
1904
1999
|
}
|
|
1905
2000
|
if (field.valueConstraint) {
|
|
1906
2001
|
const value = JSON.stringify(field.valueConstraint.value);
|
|
1907
2002
|
autoFields.push({ name, value: field.array ? `[${value}]` : value });
|
|
1908
2003
|
if (isNotChoiceDeclarationField(field) && field.type) {
|
|
1909
|
-
const pyType = fieldPyType(field, resolveRef);
|
|
1910
|
-
autoAccessors.push({ name, pyType, typeId: field.type });
|
|
2004
|
+
const pyType = fieldPyType(field, resolveRef, tsIndex);
|
|
2005
|
+
autoAccessors.push({ name, pyType, typeId: field.type, refComment: pyReferenceComment(field) });
|
|
1911
2006
|
}
|
|
1912
2007
|
continue;
|
|
1913
2008
|
}
|
|
1914
2009
|
if (isNotChoiceDeclarationField(field)) {
|
|
1915
|
-
const sliceNames = collectRequiredSliceNames(field);
|
|
2010
|
+
const sliceNames = collectRequiredSliceNames(field, flatProfile.slicing?.[name]);
|
|
1916
2011
|
if (sliceNames) {
|
|
1917
2012
|
if (field.type) {
|
|
1918
|
-
const pyType = fieldPyType(field, resolveRef);
|
|
2013
|
+
const pyType = fieldPyType(field, resolveRef, tsIndex);
|
|
1919
2014
|
sliceAutoFields.push({ name, pyType, typeId: field.type, sliceNames });
|
|
1920
|
-
autoAccessors.push({ name, pyType, typeId: field.type });
|
|
2015
|
+
autoAccessors.push({ name, pyType, typeId: field.type, refComment: pyReferenceComment(field) });
|
|
1921
2016
|
}
|
|
1922
2017
|
continue;
|
|
1923
2018
|
}
|
|
1924
2019
|
}
|
|
1925
2020
|
if (field.required) {
|
|
1926
|
-
const pyType = fieldPyType(field, resolveRef);
|
|
1927
|
-
params.push({ name, pyType, typeId: field.type });
|
|
2021
|
+
const pyType = fieldPyType(field, resolveRef, tsIndex);
|
|
2022
|
+
params.push({ name, pyType, typeId: field.type, refComment: pyReferenceComment(field) });
|
|
1928
2023
|
}
|
|
1929
2024
|
}
|
|
1930
2025
|
collectBaseRequiredParams(tsIndex, flatProfile, resolveRef, params, [
|
|
@@ -1936,9 +2031,15 @@ var collectProfileFactoryInfo = (tsIndex, flatProfile) => {
|
|
|
1936
2031
|
const choiceAccessors = [];
|
|
1937
2032
|
for (const [name, field] of pendingChoiceInstances) {
|
|
1938
2033
|
if (promotedChoices.has(name)) continue;
|
|
1939
|
-
const pyType =
|
|
2034
|
+
const pyType = pyChoiceInstanceType(field, tsIndex);
|
|
1940
2035
|
const choiceSiblings = (choiceGroups.get(name) ?? []).filter((s) => s !== name && !promotedChoices.has(s));
|
|
1941
|
-
choiceAccessors.push({
|
|
2036
|
+
choiceAccessors.push({
|
|
2037
|
+
name,
|
|
2038
|
+
pyType,
|
|
2039
|
+
typeId: field.type,
|
|
2040
|
+
choiceSiblings,
|
|
2041
|
+
refComment: pyReferenceComment(field)
|
|
2042
|
+
});
|
|
1942
2043
|
}
|
|
1943
2044
|
return { autoFields, sliceAutoFields, params, accessors: [...autoAccessors, ...choiceAccessors] };
|
|
1944
2045
|
};
|
|
@@ -2021,12 +2122,12 @@ var generateFieldAccessors = (w, className, factoryInfo, extSliceMethodBaseNames
|
|
|
2021
2122
|
for (const p of factoryInfo.params) {
|
|
2022
2123
|
const fieldName = pyFieldName(p.name, fmt);
|
|
2023
2124
|
const methodSuffix = pySnakeName(p.name);
|
|
2024
|
-
w.line(`def get_${methodSuffix}(self) -> ${p.pyType} | None
|
|
2125
|
+
w.line(`def get_${methodSuffix}(self) -> ${p.pyType} | None:${p.refComment ?? ""}`);
|
|
2025
2126
|
w.indentBlock(() => {
|
|
2026
2127
|
w.line(`return cast('${p.pyType} | None', getattr(self._resource, ${JSON.stringify(fieldName)}, None))`);
|
|
2027
2128
|
});
|
|
2028
2129
|
w.line();
|
|
2029
|
-
w.line(`def set_${methodSuffix}(self, value: ${p.pyType}) -> "${className}"
|
|
2130
|
+
w.line(`def set_${methodSuffix}(self, value: ${p.pyType}) -> "${className}":${p.refComment ?? ""}`);
|
|
2030
2131
|
w.indentBlock(() => {
|
|
2031
2132
|
w.line(`setattr(self._resource, ${JSON.stringify(fieldName)}, value)`);
|
|
2032
2133
|
w.line("return self");
|
|
@@ -2037,12 +2138,12 @@ var generateFieldAccessors = (w, className, factoryInfo, extSliceMethodBaseNames
|
|
|
2037
2138
|
const methodSuffix = pySnakeName(a.name);
|
|
2038
2139
|
if (extSliceMethodBaseNames.has(methodSuffix)) continue;
|
|
2039
2140
|
const fieldName = pyFieldName(a.name, fmt);
|
|
2040
|
-
w.line(`def get_${methodSuffix}(self) -> ${a.pyType} | None
|
|
2141
|
+
w.line(`def get_${methodSuffix}(self) -> ${a.pyType} | None:${a.refComment ?? ""}`);
|
|
2041
2142
|
w.indentBlock(() => {
|
|
2042
2143
|
w.line(`return cast('${a.pyType} | None', getattr(self._resource, ${JSON.stringify(fieldName)}, None))`);
|
|
2043
2144
|
});
|
|
2044
2145
|
w.line();
|
|
2045
|
-
w.line(`def set_${methodSuffix}(self, value: ${a.pyType}) -> "${className}"
|
|
2146
|
+
w.line(`def set_${methodSuffix}(self, value: ${a.pyType}) -> "${className}":${a.refComment ?? ""}`);
|
|
2046
2147
|
w.indentBlock(() => {
|
|
2047
2148
|
if (a.choiceSiblings?.length) {
|
|
2048
2149
|
for (const sibling of a.choiceSiblings) {
|
|
@@ -2057,94 +2158,125 @@ var generateFieldAccessors = (w, className, factoryInfo, extSliceMethodBaseNames
|
|
|
2057
2158
|
};
|
|
2058
2159
|
|
|
2059
2160
|
// src/api/writer-generator/python/profile-validation.ts
|
|
2060
|
-
var
|
|
2161
|
+
var pushListValidation = (lines, target, fn, args, items) => {
|
|
2162
|
+
const argList = ["self._resource", "profile_name", ...args].join(", ");
|
|
2163
|
+
lines.push(
|
|
2164
|
+
`${target}.extend(`,
|
|
2165
|
+
` ${fn}(${argList}, [`,
|
|
2166
|
+
` ${items.map((i) => JSON.stringify(i)).join(",")}`,
|
|
2167
|
+
"]))"
|
|
2168
|
+
);
|
|
2169
|
+
};
|
|
2170
|
+
var collectValidateBody = (flatProfile, tsIndex, errorLines, warningLines, formatName2) => {
|
|
2061
2171
|
const helpers = /* @__PURE__ */ new Set();
|
|
2062
2172
|
const fields = flatProfile.fields;
|
|
2063
2173
|
for (const [name, field] of Object.entries(fields)) {
|
|
2064
2174
|
const pyName = pyFieldName(name, formatName2);
|
|
2065
|
-
if (isChoiceInstanceField(field))
|
|
2066
|
-
collectProhibitedChoiceValidation(fields, name, pyName, helpers, errorLines);
|
|
2067
|
-
continue;
|
|
2068
|
-
}
|
|
2175
|
+
if (isChoiceInstanceField(field)) continue;
|
|
2069
2176
|
if (isChoiceDeclarationField(field)) {
|
|
2070
2177
|
if (field.required) {
|
|
2071
2178
|
helpers.add("validate_choice_required");
|
|
2072
2179
|
const pyChoices = field.choices.map((c) => pyFieldName(c, formatName2));
|
|
2073
|
-
errorLines
|
|
2074
|
-
|
|
2075
|
-
|
|
2180
|
+
pushListValidation(errorLines, "errors", "validate_choice_required", [], pyChoices);
|
|
2181
|
+
}
|
|
2182
|
+
if (field.prohibited?.length) {
|
|
2183
|
+
helpers.add("validate_choice_prohibited");
|
|
2184
|
+
const pyProhibited = field.prohibited.map((c) => pyFieldName(c, formatName2));
|
|
2185
|
+
pushListValidation(errorLines, "errors", "validate_choice_prohibited", [], pyProhibited);
|
|
2076
2186
|
}
|
|
2077
2187
|
continue;
|
|
2078
2188
|
}
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2189
|
+
collectRegularFieldValidation(
|
|
2190
|
+
field,
|
|
2191
|
+
flatProfile.slicing?.[name],
|
|
2192
|
+
pyName,
|
|
2193
|
+
helpers,
|
|
2194
|
+
errorLines,
|
|
2195
|
+
warningLines,
|
|
2196
|
+
tsIndex,
|
|
2197
|
+
formatName2
|
|
2198
|
+
);
|
|
2199
|
+
}
|
|
2200
|
+
for (const inheritedName of flatProfile.inheritedRequiredFields ?? []) {
|
|
2201
|
+
helpers.add("validate_required");
|
|
2202
|
+
errorLines.push(
|
|
2203
|
+
`errors.extend(validate_required(self._resource, profile_name, ${JSON.stringify(pyFieldName(inheritedName, formatName2))}))`
|
|
2204
|
+
);
|
|
2205
|
+
}
|
|
2206
|
+
return helpers;
|
|
2207
|
+
};
|
|
2208
|
+
var collectRegularFieldValidation = (field, fieldSlicing, pyName, helpers, errorLines, warningLines, tsIndex, formatName2) => {
|
|
2209
|
+
if (field.excluded) {
|
|
2210
|
+
helpers.add("validate_excluded");
|
|
2211
|
+
errorLines.push(`errors.extend(validate_excluded(self._resource, profile_name, ${JSON.stringify(pyName)}))`);
|
|
2212
|
+
return;
|
|
2213
|
+
}
|
|
2214
|
+
if (field.required) {
|
|
2215
|
+
helpers.add("validate_required");
|
|
2216
|
+
errorLines.push(`errors.extend(validate_required(self._resource, profile_name, ${JSON.stringify(pyName)}))`);
|
|
2217
|
+
}
|
|
2218
|
+
if (field.valueConstraint) {
|
|
2219
|
+
helpers.add("validate_fixed_value");
|
|
2220
|
+
const value = JSON.stringify(field.valueConstraint.value);
|
|
2221
|
+
errorLines.push(
|
|
2222
|
+
`errors.extend(validate_fixed_value(self._resource, profile_name, ${JSON.stringify(pyName)}, ${value}))`
|
|
2223
|
+
);
|
|
2224
|
+
}
|
|
2225
|
+
if (isNotChoiceDeclarationField(field)) {
|
|
2226
|
+
if (field.enum) {
|
|
2227
|
+
helpers.add("validate_enum");
|
|
2228
|
+
const target = field.enum.isOpen ? warningLines : errorLines;
|
|
2229
|
+
const listName = field.enum.isOpen ? "warnings" : "errors";
|
|
2230
|
+
pushListValidation(target, listName, "validate_enum", [JSON.stringify(pyName)], field.enum.values);
|
|
2231
|
+
}
|
|
2232
|
+
if (field.mustSupport && !field.required) {
|
|
2233
|
+
helpers.add("validate_must_support");
|
|
2234
|
+
warningLines.push(
|
|
2235
|
+
`warnings.extend(validate_must_support(self._resource, profile_name, ${JSON.stringify(pyName)}))`
|
|
2090
2236
|
);
|
|
2091
2237
|
}
|
|
2092
|
-
if (field.
|
|
2093
|
-
helpers.add("
|
|
2094
|
-
const
|
|
2095
|
-
errorLines.
|
|
2096
|
-
`errors.extend(validate_fixed_value(self._resource, profile_name, ${JSON.stringify(pyName)}, ${value}))`
|
|
2097
|
-
);
|
|
2238
|
+
if (field.reference && field.reference.resource.length > 0) {
|
|
2239
|
+
helpers.add("validate_reference");
|
|
2240
|
+
const allowed = field.reference.resource.map((ref) => tsIndex.findLastSpecializationByIdentifier(ref).name);
|
|
2241
|
+
pushListValidation(errorLines, "errors", "validate_reference", [JSON.stringify(pyName)], allowed);
|
|
2098
2242
|
}
|
|
2099
|
-
if (
|
|
2100
|
-
|
|
2101
|
-
helpers.add("validate_enum");
|
|
2102
|
-
const target = field.enum.isOpen ? warningLines : errorLines;
|
|
2103
|
-
const listName = field.enum.isOpen ? "warnings" : "errors";
|
|
2104
|
-
target.push(
|
|
2105
|
-
`${listName}.extend(validate_enum(self._resource, profile_name, ${JSON.stringify(pyName)}, ${JSON.stringify(field.enum.values)}))`
|
|
2106
|
-
);
|
|
2107
|
-
}
|
|
2108
|
-
if (field.mustSupport && !field.required) {
|
|
2109
|
-
helpers.add("validate_must_support");
|
|
2110
|
-
warningLines.push(
|
|
2111
|
-
`warnings.extend(validate_must_support(self._resource, profile_name, ${JSON.stringify(pyName)}))`
|
|
2112
|
-
);
|
|
2113
|
-
}
|
|
2114
|
-
if (field.reference && field.reference.length > 0) {
|
|
2115
|
-
helpers.add("validate_reference");
|
|
2116
|
-
const allowed = field.reference.map((ref) => resolveRef(ref).name);
|
|
2117
|
-
errorLines.push(
|
|
2118
|
-
`errors.extend(validate_reference(self._resource, profile_name, ${JSON.stringify(pyName)}, ${JSON.stringify(allowed)}))`
|
|
2119
|
-
);
|
|
2120
|
-
}
|
|
2121
|
-
if (field.slicing?.slices) {
|
|
2122
|
-
collectSliceCardinalityValidation(field, pyName, helpers, errorLines);
|
|
2123
|
-
}
|
|
2243
|
+
if (fieldSlicing?.slices) {
|
|
2244
|
+
collectSliceValidation(field, fieldSlicing, pyName, helpers, errorLines, tsIndex, formatName2);
|
|
2124
2245
|
}
|
|
2125
2246
|
}
|
|
2126
|
-
return helpers;
|
|
2127
2247
|
};
|
|
2128
|
-
var
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
const decl = fields[field.choiceOf];
|
|
2132
|
-
if (!decl || !isChoiceDeclarationField(decl) || !decl.prohibited?.includes(name)) return;
|
|
2133
|
-
helpers.add("validate_excluded");
|
|
2134
|
-
errorLines.push(`errors.extend(validate_excluded(self._resource, profile_name, ${JSON.stringify(pyName)}))`);
|
|
2135
|
-
};
|
|
2136
|
-
var collectSliceCardinalityValidation = (field, name, helpers, errorLines) => {
|
|
2137
|
-
if (!field.slicing?.slices) return;
|
|
2138
|
-
for (const [sliceName, slice] of Object.entries(field.slicing.slices)) {
|
|
2139
|
-
if (slice.min === void 0 && slice.max === void 0) continue;
|
|
2248
|
+
var collectSliceValidation = (field, fieldSlicing, name, helpers, errorLines, tsIndex, formatName2) => {
|
|
2249
|
+
if (!fieldSlicing.slices) return;
|
|
2250
|
+
for (const [sliceName, slice] of Object.entries(fieldSlicing.slices)) {
|
|
2140
2251
|
const match = slice.match ?? {};
|
|
2141
2252
|
if (Object.keys(match).length === 0) continue;
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2253
|
+
if (slice.min !== void 0 || slice.max !== void 0) {
|
|
2254
|
+
const min = slice.min ?? 0;
|
|
2255
|
+
const max = slice.max ?? 0;
|
|
2256
|
+
helpers.add("validate_slice_cardinality");
|
|
2257
|
+
errorLines.push(
|
|
2258
|
+
`errors.extend(validate_slice_cardinality(self._resource, profile_name, ${JSON.stringify(name)}, ${JSON.stringify(match)}, ${JSON.stringify(sliceName)}, ${min}, ${max}))`
|
|
2259
|
+
);
|
|
2260
|
+
}
|
|
2261
|
+
const sliceRequiredFields = [];
|
|
2262
|
+
const matchKeys = new Set(Object.keys(match));
|
|
2263
|
+
for (const rf of slice.required ?? []) {
|
|
2264
|
+
if (!matchKeys.has(rf)) sliceRequiredFields.push(pyFieldName(rf, formatName2));
|
|
2265
|
+
}
|
|
2266
|
+
if (field.type && slice.elements) {
|
|
2267
|
+
const cc = tsIndex.constrainedChoice(field.type.package, field.type, slice.elements);
|
|
2268
|
+
if (cc) sliceRequiredFields.push(pyFieldName(cc.variant, formatName2));
|
|
2269
|
+
}
|
|
2270
|
+
if (sliceRequiredFields.length > 0) {
|
|
2271
|
+
helpers.add("validate_slice_fields");
|
|
2272
|
+
pushListValidation(
|
|
2273
|
+
errorLines,
|
|
2274
|
+
"errors",
|
|
2275
|
+
"validate_slice_fields",
|
|
2276
|
+
[JSON.stringify(name), JSON.stringify(match), JSON.stringify(sliceName)],
|
|
2277
|
+
sliceRequiredFields
|
|
2278
|
+
);
|
|
2279
|
+
}
|
|
2148
2280
|
}
|
|
2149
2281
|
};
|
|
2150
2282
|
|
|
@@ -2387,13 +2519,7 @@ var generateProfileModule = (w, tsIndex, flatProfile) => {
|
|
|
2387
2519
|
const resolvedNames = resolveProfileMethodBaseNames(extensions, sliceDefs);
|
|
2388
2520
|
const errorLines = [];
|
|
2389
2521
|
const warningLines = [];
|
|
2390
|
-
const validationHelpers = collectValidateBody(
|
|
2391
|
-
flatProfile,
|
|
2392
|
-
tsIndex.findLastSpecializationByIdentifier,
|
|
2393
|
-
errorLines,
|
|
2394
|
-
warningLines,
|
|
2395
|
-
w.nameFormatFunction
|
|
2396
|
-
);
|
|
2522
|
+
const validationHelpers = collectValidateBody(flatProfile, tsIndex, errorLines, warningLines, w.nameFormatFunction);
|
|
2397
2523
|
const helperImports = collectHelperImports(isResourceBase, factoryInfo, sliceDefs, extensions, validationHelpers);
|
|
2398
2524
|
const typeImports = collectTypeImports(
|
|
2399
2525
|
w.opts.rootPackageName,
|
|
@@ -2500,7 +2626,8 @@ var AVAILABLE_STRING_FORMATS = {
|
|
|
2500
2626
|
var MAX_IMPORT_LINE_LENGTH = 100;
|
|
2501
2627
|
var GENERIC_FIELD_REWRITES = {
|
|
2502
2628
|
Coding: { code: "T" },
|
|
2503
|
-
CodeableConcept: { coding: "Coding[T]" }
|
|
2629
|
+
CodeableConcept: { coding: "Coding[T]" },
|
|
2630
|
+
Reference: { type: "T" }
|
|
2504
2631
|
};
|
|
2505
2632
|
var leafOf2 = (path) => path[path.length - 1] ?? "";
|
|
2506
2633
|
var collectResourceGenericTypeVars = (schema) => {
|
|
@@ -2897,6 +3024,11 @@ var Python = class extends Writer {
|
|
|
2897
3024
|
fieldType = `Literal[${s}]`;
|
|
2898
3025
|
}
|
|
2899
3026
|
}
|
|
3027
|
+
if (fieldType === "Reference" && "reference" in field && field.reference) {
|
|
3028
|
+
assert4(this.tsIndex !== void 0);
|
|
3029
|
+
const typeParam = pyReferenceTypeParam(field, this.tsIndex);
|
|
3030
|
+
if (typeParam) fieldType = `Reference[${typeParam}]`;
|
|
3031
|
+
}
|
|
2900
3032
|
if (field.array) {
|
|
2901
3033
|
fieldType = `PyList[${fieldType}]`;
|
|
2902
3034
|
}
|
|
@@ -3048,6 +3180,18 @@ var Python = class extends Writer {
|
|
|
3048
3180
|
}
|
|
3049
3181
|
};
|
|
3050
3182
|
|
|
3183
|
+
// src/typeschema/collision-order.ts
|
|
3184
|
+
var compareStrings = (left, right) => {
|
|
3185
|
+
if (left < right) return -1;
|
|
3186
|
+
if (left > right) return 1;
|
|
3187
|
+
return 0;
|
|
3188
|
+
};
|
|
3189
|
+
var compareCollisionSources = (left, right) => compareStrings(left.sourcePackage, right.sourcePackage) || compareStrings(left.sourceCanonical, right.sourceCanonical);
|
|
3190
|
+
var collisionSourcesKey = (sources) => JSON.stringify(
|
|
3191
|
+
[...sources].sort(compareCollisionSources).map(({ sourcePackage, sourceCanonical }) => [sourcePackage, sourceCanonical])
|
|
3192
|
+
);
|
|
3193
|
+
var compareCollisionVariants = (left, right) => right.sources.length - left.sources.length || compareStrings(collisionSourcesKey(left.sources), collisionSourcesKey(right.sources)) || compareStrings(left.schemaHash, right.schemaHash);
|
|
3194
|
+
|
|
3051
3195
|
// src/typeschema/skip-hack.ts
|
|
3052
3196
|
var codeableReferenceInR4 = "Use CodeableReference which is not provided by FHIR R4.";
|
|
3053
3197
|
var availabilityInR4 = "Use Availability which is not provided by FHIR R4.";
|
|
@@ -3360,9 +3504,9 @@ var assignRecommendedBaseNames = (profile) => {
|
|
|
3360
3504
|
key: `ext:${ext.url}:${ext.path}`,
|
|
3361
3505
|
candidates: ext.nameCandidates.candidates
|
|
3362
3506
|
}));
|
|
3363
|
-
const sliceEntries = Object.entries(profile.
|
|
3364
|
-
if (!
|
|
3365
|
-
return Object.entries(
|
|
3507
|
+
const sliceEntries = Object.entries(profile.slicing ?? {}).flatMap(([fieldName, fieldSlicing]) => {
|
|
3508
|
+
if (!fieldSlicing.slices) return [];
|
|
3509
|
+
return Object.entries(fieldSlicing.slices).map(([sliceName, slice]) => ({
|
|
3366
3510
|
key: `slice:${fieldName}:${sliceName}`,
|
|
3367
3511
|
candidates: slice.nameCandidates.candidates
|
|
3368
3512
|
}));
|
|
@@ -3376,9 +3520,9 @@ var assignRecommendedBaseNames = (profile) => {
|
|
|
3376
3520
|
const key = `ext:${ext.url}:${ext.path}`;
|
|
3377
3521
|
if (resolved[key]) ext.nameCandidates.recommended = resolved[key];
|
|
3378
3522
|
}
|
|
3379
|
-
for (const [fieldName,
|
|
3380
|
-
if (!
|
|
3381
|
-
for (const [sliceName, slice] of Object.entries(
|
|
3523
|
+
for (const [fieldName, fieldSlicing] of Object.entries(profile.slicing ?? {})) {
|
|
3524
|
+
if (!fieldSlicing.slices) continue;
|
|
3525
|
+
for (const [sliceName, slice] of Object.entries(fieldSlicing.slices)) {
|
|
3382
3526
|
const key = `slice:${fieldName}:${sliceName}`;
|
|
3383
3527
|
if (resolved[key]) slice.nameCandidates.recommended = resolved[key];
|
|
3384
3528
|
}
|
|
@@ -3585,8 +3729,8 @@ var registerFromManager = async (manager, { logger, focusedPackages }) => {
|
|
|
3585
3729
|
if (!sd.package_name) {
|
|
3586
3730
|
return {
|
|
3587
3731
|
...sd,
|
|
3588
|
-
package_name:
|
|
3589
|
-
package_version:
|
|
3732
|
+
package_name: r.pkg.name,
|
|
3733
|
+
package_version: r.pkg.version
|
|
3590
3734
|
};
|
|
3591
3735
|
}
|
|
3592
3736
|
return sd;
|
|
@@ -3715,6 +3859,7 @@ function collectNestedElements(fhirSchema, parentPath, elements) {
|
|
|
3715
3859
|
}
|
|
3716
3860
|
function transformNestedElements(register, fhirSchema, parentPath, elements, logger) {
|
|
3717
3861
|
const fields = {};
|
|
3862
|
+
const slicing = {};
|
|
3718
3863
|
const genealogy = register.resolveFsGenealogy(fhirSchema.package_meta, fhirSchema.url);
|
|
3719
3864
|
const elemGenealogy = resolveFsElementGenealogy(genealogy, parentPath);
|
|
3720
3865
|
const allKeys = /* @__PURE__ */ new Set();
|
|
@@ -3733,8 +3878,10 @@ function transformNestedElements(register, fhirSchema, parentPath, elements, log
|
|
|
3733
3878
|
} else {
|
|
3734
3879
|
fields[key] = mkField(register, fhirSchema, path, elemSnapshot, logger);
|
|
3735
3880
|
}
|
|
3881
|
+
const fieldSlicing = buildSlicing(key, elemSnapshot);
|
|
3882
|
+
if (fieldSlicing) slicing[key] = fieldSlicing;
|
|
3736
3883
|
}
|
|
3737
|
-
return fields;
|
|
3884
|
+
return { fields, slicing: Object.keys(slicing).length > 0 ? slicing : void 0 };
|
|
3738
3885
|
}
|
|
3739
3886
|
function mkNestedTypes(register, fhirSchema, logger) {
|
|
3740
3887
|
if (!fhirSchema.elements) return void 0;
|
|
@@ -3764,11 +3911,12 @@ function mkNestedTypes(register, fhirSchema, logger) {
|
|
|
3764
3911
|
name: baseName,
|
|
3765
3912
|
url: baseUrl
|
|
3766
3913
|
};
|
|
3767
|
-
const fields = transformNestedElements(register, fhirSchema, path, element.elements ?? {}, logger);
|
|
3914
|
+
const { fields, slicing } = transformNestedElements(register, fhirSchema, path, element.elements ?? {}, logger);
|
|
3768
3915
|
const nestedType = {
|
|
3769
3916
|
identifier,
|
|
3770
3917
|
base,
|
|
3771
|
-
fields
|
|
3918
|
+
fields,
|
|
3919
|
+
slicing
|
|
3772
3920
|
};
|
|
3773
3921
|
nestedTypes.push(nestedType);
|
|
3774
3922
|
}
|
|
@@ -3851,12 +3999,27 @@ function isExcluded(register, fhirSchema, path) {
|
|
|
3851
3999
|
}
|
|
3852
4000
|
var buildReferences = (register, fhirSchema, element) => {
|
|
3853
4001
|
if (!element.refers) return void 0;
|
|
3854
|
-
|
|
4002
|
+
const resource = [];
|
|
4003
|
+
const profiles = [];
|
|
4004
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4005
|
+
for (const ref of element.refers) {
|
|
3855
4006
|
const curl = register.ensureSpecializationCanonicalUrl(ref);
|
|
3856
4007
|
const fs6 = register.resolveFs(fhirSchema.package_meta, curl);
|
|
3857
4008
|
if (!fs6) throw new Error(`Failed to resolve fs for ${curl}`);
|
|
3858
|
-
|
|
3859
|
-
|
|
4009
|
+
const id = mkIdentifier(fs6);
|
|
4010
|
+
let resolved = id;
|
|
4011
|
+
if (isProfileIdentifier(id)) {
|
|
4012
|
+
profiles.push(id);
|
|
4013
|
+
const baseFs = register.resolveFsSpecializations(fs6.package_meta, fs6.url)[0];
|
|
4014
|
+
if (!baseFs) throw new Error(`Failed to resolve base specialization for ${curl}`);
|
|
4015
|
+
resolved = mkIdentifier(baseFs);
|
|
4016
|
+
}
|
|
4017
|
+
if (!seen.has(resolved.url)) {
|
|
4018
|
+
seen.add(resolved.url);
|
|
4019
|
+
resource.push(resolved);
|
|
4020
|
+
}
|
|
4021
|
+
}
|
|
4022
|
+
return { resource, profiles: profiles.length > 0 ? profiles : void 0 };
|
|
3860
4023
|
};
|
|
3861
4024
|
var extractSliceFieldNames = (schema) => {
|
|
3862
4025
|
const required = /* @__PURE__ */ new Set();
|
|
@@ -4082,7 +4245,6 @@ var mkField = (register, fhirSchema, path, element, logger, rawElement) => {
|
|
|
4082
4245
|
array: element.array || false,
|
|
4083
4246
|
min: element.min,
|
|
4084
4247
|
max: element.max,
|
|
4085
|
-
slicing: buildSlicing(path[path.length - 1] ?? "", element),
|
|
4086
4248
|
choices: element.choices,
|
|
4087
4249
|
choiceOf: element.choiceOf,
|
|
4088
4250
|
binding,
|
|
@@ -4097,8 +4259,7 @@ function mkNestedField(register, fhirSchema, path, element) {
|
|
|
4097
4259
|
type: nestedIdentifier,
|
|
4098
4260
|
array: element.array || false,
|
|
4099
4261
|
required: isRequired(register, fhirSchema, path),
|
|
4100
|
-
excluded: isExcluded(register, fhirSchema, path)
|
|
4101
|
-
slicing: buildSlicing(path[path.length - 1] ?? "", element)
|
|
4262
|
+
excluded: isExcluded(register, fhirSchema, path)
|
|
4102
4263
|
};
|
|
4103
4264
|
}
|
|
4104
4265
|
|
|
@@ -4237,8 +4398,9 @@ var extractProfileExtensions = (register, fhirSchema, logger) => {
|
|
|
4237
4398
|
|
|
4238
4399
|
// src/typeschema/core/transformer.ts
|
|
4239
4400
|
function mkFields(register, fhirSchema, parentPath, elements, logger) {
|
|
4240
|
-
if (!elements) return
|
|
4401
|
+
if (!elements) return {};
|
|
4241
4402
|
const fields = {};
|
|
4403
|
+
const slicing = {};
|
|
4242
4404
|
for (const key of register.getAllElementKeys(elements)) {
|
|
4243
4405
|
const path = [...parentPath, key];
|
|
4244
4406
|
const elemSnapshot = register.resolveElementSnapshot(fhirSchema, path);
|
|
@@ -4255,8 +4417,10 @@ function mkFields(register, fhirSchema, parentPath, elements, logger) {
|
|
|
4255
4417
|
} else {
|
|
4256
4418
|
fields[key] = mkField(register, fhirSchema, path, elemSnapshot, logger, elements[key]);
|
|
4257
4419
|
}
|
|
4420
|
+
const fieldSlicing = buildSlicing(key, elemSnapshot);
|
|
4421
|
+
if (fieldSlicing) slicing[key] = fieldSlicing;
|
|
4258
4422
|
}
|
|
4259
|
-
return fields;
|
|
4423
|
+
return { fields, slicing: Object.keys(slicing).length > 0 ? slicing : void 0 };
|
|
4260
4424
|
}
|
|
4261
4425
|
function extractFieldDependencies(fields) {
|
|
4262
4426
|
const deps = [];
|
|
@@ -4317,7 +4481,7 @@ function transformFhirSchema(register, fhirSchema, logger) {
|
|
|
4317
4481
|
assert4(!isNestedIdentifier(baseId), `Unexpected nested base for ${fhirSchema.url}`);
|
|
4318
4482
|
base = baseId;
|
|
4319
4483
|
}
|
|
4320
|
-
const fields = mkFields(register, fhirSchema, [], fhirSchema.elements, logger);
|
|
4484
|
+
const { fields, slicing } = mkFields(register, fhirSchema, [], fhirSchema.elements, logger);
|
|
4321
4485
|
const nested = mkNestedTypes(register, fhirSchema, logger);
|
|
4322
4486
|
const bindingSchemas = collectBindingSchemas(register, fhirSchema, logger);
|
|
4323
4487
|
if (fhirSchema.derivation === "constraint") {
|
|
@@ -4330,6 +4494,7 @@ function transformFhirSchema(register, fhirSchema, logger) {
|
|
|
4330
4494
|
identifier: identifier2,
|
|
4331
4495
|
base,
|
|
4332
4496
|
fields,
|
|
4497
|
+
slicing,
|
|
4333
4498
|
nested,
|
|
4334
4499
|
description: fhirSchema.description,
|
|
4335
4500
|
dependencies: concatIdentifiers(rawDeps, extensionDeps),
|
|
@@ -4356,6 +4521,7 @@ function transformFhirSchema(register, fhirSchema, logger) {
|
|
|
4356
4521
|
identifier,
|
|
4357
4522
|
base,
|
|
4358
4523
|
fields,
|
|
4524
|
+
slicing,
|
|
4359
4525
|
nested,
|
|
4360
4526
|
description: fhirSchema.description,
|
|
4361
4527
|
dependencies: extractDependencies(identifier, base, fields, nested),
|
|
@@ -4377,7 +4543,11 @@ var deduplicateSchemas = (schemasWithSources, resolveCollisions, logger) => {
|
|
|
4377
4543
|
const schemas = [];
|
|
4378
4544
|
const collisions = {};
|
|
4379
4545
|
for (const versions of Object.values(groups)) {
|
|
4380
|
-
const sorted = Object.
|
|
4546
|
+
const sorted = Object.entries(versions).map(([schemaHash, version]) => ({
|
|
4547
|
+
...version,
|
|
4548
|
+
schemaHash,
|
|
4549
|
+
sources: [...version.sources].sort(compareCollisionSources)
|
|
4550
|
+
})).sort(compareCollisionVariants);
|
|
4381
4551
|
const best = sorted[0];
|
|
4382
4552
|
if (!best) continue;
|
|
4383
4553
|
if (sorted.length > 1) {
|
|
@@ -4602,6 +4772,10 @@ var treeShakeTypeSchema = (schema, rule, _logger) => {
|
|
|
4602
4772
|
if (isProfileTypeSchema(schema) && rule.ignoreExtensions) {
|
|
4603
4773
|
mutableIgnoreExtensions(schema, rule.ignoreExtensions);
|
|
4604
4774
|
}
|
|
4775
|
+
if (schema.slicing) {
|
|
4776
|
+
const kept = Object.fromEntries(Object.entries(schema.slicing).filter(([name]) => schema.fields?.[name]));
|
|
4777
|
+
schema.slicing = Object.keys(kept).length > 0 ? kept : void 0;
|
|
4778
|
+
}
|
|
4605
4779
|
if (schema.nested) {
|
|
4606
4780
|
const usedTypes = /* @__PURE__ */ new Set();
|
|
4607
4781
|
const collectUsedNestedTypes = (s) => {
|
|
@@ -4630,16 +4804,36 @@ var treeShakeTypeSchema = (schema, rule, _logger) => {
|
|
|
4630
4804
|
}
|
|
4631
4805
|
return schema;
|
|
4632
4806
|
};
|
|
4633
|
-
var
|
|
4807
|
+
var collectReferenceTargets = (schema) => {
|
|
4808
|
+
if (!isSpecializationTypeSchema(schema) && !isProfileTypeSchema(schema)) return [];
|
|
4809
|
+
const fieldSets = [schema.fields, ...(schema.nested ?? []).map((n) => n.fields)];
|
|
4810
|
+
return fieldSets.flatMap(
|
|
4811
|
+
(fields) => Object.values(fields ?? {}).filter(isNotChoiceDeclarationField).flatMap((f) => [...f.reference?.resource ?? [], ...f.reference?.profiles ?? []]).filter((id) => !isNestedIdentifier(id))
|
|
4812
|
+
);
|
|
4813
|
+
};
|
|
4814
|
+
var treeShake = (tsIndex, treeShake2, defaults) => {
|
|
4634
4815
|
const focusedSchemas = [];
|
|
4816
|
+
const followedSchemas = [];
|
|
4635
4817
|
for (const [pkgId, requires] of Object.entries(treeShake2)) {
|
|
4636
4818
|
for (const [url, rule] of Object.entries(requires)) {
|
|
4637
4819
|
const schema = tsIndex.resolveByUrl(pkgId, url);
|
|
4638
4820
|
if (!schema || isNestedTypeSchema(schema)) throw new Error(`Schema not found for ${pkgId} ${url}`);
|
|
4639
4821
|
const shaked2 = treeShakeTypeSchema(schema, rule);
|
|
4640
4822
|
focusedSchemas.push(shaked2);
|
|
4823
|
+
if (rule.followReferences ?? defaults?.followReferences) {
|
|
4824
|
+
for (const refId of collectReferenceTargets(shaked2)) {
|
|
4825
|
+
const refSchema = tsIndex.resolve(refId);
|
|
4826
|
+
if (!refSchema)
|
|
4827
|
+
throw new Error(`Reference target ${JSON.stringify(refId)} not found for ${pkgId} ${url}`);
|
|
4828
|
+
followedSchemas.push(refSchema);
|
|
4829
|
+
}
|
|
4830
|
+
}
|
|
4641
4831
|
}
|
|
4642
4832
|
}
|
|
4833
|
+
const rootIds = new Set(focusedSchemas.map((s) => JSON.stringify(s.identifier)));
|
|
4834
|
+
for (const schema of followedSchemas) {
|
|
4835
|
+
if (!rootIds.has(JSON.stringify(schema.identifier))) focusedSchemas.push(schema);
|
|
4836
|
+
}
|
|
4643
4837
|
const collectDeps = (schemas, acc) => {
|
|
4644
4838
|
if (schemas.length === 0) return Object.values(acc);
|
|
4645
4839
|
for (const schema of schemas) {
|
|
@@ -4678,7 +4872,8 @@ var normalizeFileName = (str) => {
|
|
|
4678
4872
|
};
|
|
4679
4873
|
var typeSchemaToJson = (ts, pretty) => {
|
|
4680
4874
|
const pkgPath = normalizeFileName(ts.identifier.package);
|
|
4681
|
-
const
|
|
4875
|
+
const suffix = isSnapshotProfileTypeSchema(ts) ? ".snapshot" : "";
|
|
4876
|
+
const name = normalizeFileName(`${ts.identifier.name}(${extractNameFromCanonical(ts.identifier.url)})`) + suffix;
|
|
4682
4877
|
const baseName = Path5.join(pkgPath, name);
|
|
4683
4878
|
return {
|
|
4684
4879
|
filename: baseName,
|
|
@@ -4712,17 +4907,19 @@ var IntrospectionWriter = class extends FileSystemWriter {
|
|
|
4712
4907
|
this.logger()?.info(`IntrospectionWriter: Type tree written to ${this.opts.typeTree}`);
|
|
4713
4908
|
}
|
|
4714
4909
|
if (this.opts.typeSchemas) {
|
|
4715
|
-
|
|
4716
|
-
|
|
4910
|
+
const tsOpts = typeof this.opts.typeSchemas === "string" ? { target: this.opts.typeSchemas } : this.opts.typeSchemas;
|
|
4911
|
+
const schemas = tsOpts.profileSnapshots ? [...tsIndex.schemas, ...tsIndex.collectSnapshotProfiles()] : tsIndex.schemas;
|
|
4912
|
+
if (Path5.extname(tsOpts.target) === ".ndjson") {
|
|
4913
|
+
await this.writeNdjson(schemas, tsOpts.target, typeSchemaToJson);
|
|
4717
4914
|
} else {
|
|
4718
|
-
const items =
|
|
4915
|
+
const items = schemas.map((ts) => typeSchemaToJson(ts, true));
|
|
4719
4916
|
const seenFilenames = /* @__PURE__ */ new Set();
|
|
4720
4917
|
const dedupedItems = items.filter((item) => {
|
|
4721
4918
|
if (seenFilenames.has(item.filename)) return false;
|
|
4722
4919
|
seenFilenames.add(item.filename);
|
|
4723
4920
|
return true;
|
|
4724
4921
|
});
|
|
4725
|
-
this.cd(
|
|
4922
|
+
this.cd(tsOpts.target, () => {
|
|
4726
4923
|
for (const { filename, genContent } of dedupedItems) {
|
|
4727
4924
|
const fileName = `${filename}.json`;
|
|
4728
4925
|
this.cd(Path5.dirname(fileName), () => {
|
|
@@ -4753,15 +4950,15 @@ var IntrospectionWriter = class extends FileSystemWriter {
|
|
|
4753
4950
|
}
|
|
4754
4951
|
});
|
|
4755
4952
|
}
|
|
4756
|
-
this.logger()?.info(
|
|
4757
|
-
`IntrospectionWriter: ${tsIndex.schemas.length} TypeSchema written to ${this.opts.typeSchemas}`
|
|
4758
|
-
);
|
|
4953
|
+
this.logger()?.info(`IntrospectionWriter: ${schemas.length} TypeSchema written to ${tsOpts.target}`);
|
|
4759
4954
|
}
|
|
4955
|
+
const indexUrls = new Set(tsIndex.schemas.map((ts) => ts.identifier.url));
|
|
4760
4956
|
if (this.opts.fhirSchemas && tsIndex.register) {
|
|
4761
4957
|
const outputPath = this.opts.fhirSchemas;
|
|
4762
4958
|
const allFs = tsIndex.register.allFs();
|
|
4763
4959
|
const seenUrls = /* @__PURE__ */ new Set();
|
|
4764
4960
|
const fhirSchemas = allFs.filter((fs6) => {
|
|
4961
|
+
if (!indexUrls.has(fs6.url)) return false;
|
|
4765
4962
|
if (seenUrls.has(fs6.url)) return false;
|
|
4766
4963
|
seenUrls.add(fs6.url);
|
|
4767
4964
|
return true;
|
|
@@ -4781,6 +4978,7 @@ var IntrospectionWriter = class extends FileSystemWriter {
|
|
|
4781
4978
|
const allSd = tsIndex.register.allSd();
|
|
4782
4979
|
const seenUrls = /* @__PURE__ */ new Set();
|
|
4783
4980
|
const structureDefinitions = allSd.filter((sd) => {
|
|
4981
|
+
if (!indexUrls.has(sd.url)) return false;
|
|
4784
4982
|
if (seenUrls.has(sd.url)) return false;
|
|
4785
4983
|
seenUrls.add(sd.url);
|
|
4786
4984
|
return true;
|
|
@@ -4879,11 +5077,15 @@ var generatePackageSection = (lines, pkgName, treeShakePkg, promotedCanonicals)
|
|
|
4879
5077
|
var groupCollisionVersions = (entries, resolution) => {
|
|
4880
5078
|
const uniqueSchemas = /* @__PURE__ */ new Map();
|
|
4881
5079
|
for (const entry of entries) {
|
|
4882
|
-
const key =
|
|
5080
|
+
const key = hashSchema(entry.typeSchema);
|
|
4883
5081
|
if (!uniqueSchemas.has(key)) uniqueSchemas.set(key, []);
|
|
4884
5082
|
uniqueSchemas.get(key)?.push(entry);
|
|
4885
5083
|
}
|
|
4886
|
-
const sorted = [...uniqueSchemas.
|
|
5084
|
+
const sorted = [...uniqueSchemas.entries()].map(([schemaHash, group]) => ({
|
|
5085
|
+
entries: [...group].sort(compareCollisionSources),
|
|
5086
|
+
schemaHash,
|
|
5087
|
+
sources: group
|
|
5088
|
+
})).sort(compareCollisionVariants).map((group) => group.entries);
|
|
4887
5089
|
const markVersion = (group, i) => {
|
|
4888
5090
|
if (resolution)
|
|
4889
5091
|
return group.some(
|
|
@@ -5783,9 +5985,21 @@ var resolveFieldTsType = (schemaName, tsName, field, resolveRef, genericFieldMap
|
|
|
5783
5985
|
if (field.type.name === "CodeableConcept") return `CodeableConcept<${tsEnumType(field.enum)}>`;
|
|
5784
5986
|
return tsEnumType(field.enum);
|
|
5785
5987
|
}
|
|
5786
|
-
if (field.reference && field.reference.length > 0) {
|
|
5787
|
-
const
|
|
5788
|
-
|
|
5988
|
+
if (field.reference && field.reference.resource.length > 0) {
|
|
5989
|
+
const profilesByResource = {};
|
|
5990
|
+
if (resolveRef) {
|
|
5991
|
+
for (const profile of field.reference.profiles ?? []) {
|
|
5992
|
+
const base = resolveRef(profile).name;
|
|
5993
|
+
(profilesByResource[base] ??= []).push(profile.url);
|
|
5994
|
+
}
|
|
5995
|
+
}
|
|
5996
|
+
const references = field.reference.resource.map((original) => {
|
|
5997
|
+
const ref = resolveRef ? resolveRef(original) : original;
|
|
5998
|
+
if (isFamilyType?.(ref)) return `string /* ${ref.name} */`;
|
|
5999
|
+
const profiles = profilesByResource[ref.name];
|
|
6000
|
+
if (profiles) return `"${ref.name}" /* ${profiles.join(", ")} */`;
|
|
6001
|
+
return `"${ref.name}"`;
|
|
6002
|
+
}).join(" | ");
|
|
5789
6003
|
return `Reference<${references}>`;
|
|
5790
6004
|
}
|
|
5791
6005
|
if (isPrimitiveIdentifier(field.type)) return resolvePrimitiveType(field.type.name);
|
|
@@ -5834,9 +6048,10 @@ var valueFieldToTsType = (valueField) => {
|
|
|
5834
6048
|
};
|
|
5835
6049
|
var collectSubExtensionSlices = (extProfile) => {
|
|
5836
6050
|
const extensionField = extProfile.fields.extension;
|
|
5837
|
-
|
|
6051
|
+
const extensionSlicing = extProfile.slicing?.extension;
|
|
6052
|
+
if (!extensionField || isChoiceDeclarationField(extensionField) || !extensionSlicing?.slices) return [];
|
|
5838
6053
|
const result = [];
|
|
5839
|
-
for (const [sliceName, slice] of Object.entries(
|
|
6054
|
+
for (const [sliceName, slice] of Object.entries(extensionSlicing.slices)) {
|
|
5840
6055
|
const valueField = extractValueField(slice.elements);
|
|
5841
6056
|
if (!valueField) continue;
|
|
5842
6057
|
const tsType = valueFieldToTsType(valueField);
|
|
@@ -6174,10 +6389,11 @@ var extractResourceTypeFromMatch = (match) => {
|
|
|
6174
6389
|
};
|
|
6175
6390
|
var collectTypesFromSlices = (tsIndex, snapshot, addType) => {
|
|
6176
6391
|
const pkgName = snapshot.identifier.package;
|
|
6177
|
-
for (const
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6392
|
+
for (const [fieldName, fieldSlicing] of Object.entries(snapshot.slicing ?? {})) {
|
|
6393
|
+
const field = snapshot.fields[fieldName];
|
|
6394
|
+
if (!isNotChoiceDeclarationField(field) || !fieldSlicing.slices || !field.type) continue;
|
|
6395
|
+
const isTypeDisc = isTypeDiscriminated(fieldSlicing);
|
|
6396
|
+
for (const slice of Object.values(fieldSlicing.slices)) {
|
|
6181
6397
|
if (Object.keys(slice.match ?? {}).length > 0) {
|
|
6182
6398
|
addType(field.type);
|
|
6183
6399
|
const cc = slice.elements ? tsIndex.constrainedChoice(pkgName, field.type, slice.elements) : void 0;
|
|
@@ -6195,11 +6411,10 @@ var collectTypesFromSlices = (tsIndex, snapshot, addType) => {
|
|
|
6195
6411
|
}
|
|
6196
6412
|
}
|
|
6197
6413
|
};
|
|
6198
|
-
var collectRequiredSliceNames2 = (field) => {
|
|
6199
|
-
if (!field.array || !
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
const names = Object.entries(field.slicing.slices).filter(([_, s]) => {
|
|
6414
|
+
var collectRequiredSliceNames2 = (field, fieldSlicing) => {
|
|
6415
|
+
if (!field.array || !fieldSlicing?.slices) return void 0;
|
|
6416
|
+
if (isTypeDiscriminated(fieldSlicing)) return void 0;
|
|
6417
|
+
const names = Object.entries(fieldSlicing.slices).filter(([_, s]) => {
|
|
6203
6418
|
if (s.min === void 0 || s.min < 1 || !s.match || Object.keys(s.match).length === 0) return false;
|
|
6204
6419
|
const matchKeys = new Set(Object.keys(s.match));
|
|
6205
6420
|
const requiredBeyondMatch = (s.required ?? []).filter((name) => !matchKeys.has(name));
|
|
@@ -6207,13 +6422,14 @@ var collectRequiredSliceNames2 = (field) => {
|
|
|
6207
6422
|
}).map(([name]) => name);
|
|
6208
6423
|
return names.length > 0 ? names : void 0;
|
|
6209
6424
|
};
|
|
6210
|
-
var collectSliceDefs2 = (tsIndex, snapshot) => Object.entries(snapshot.
|
|
6211
|
-
|
|
6425
|
+
var collectSliceDefs2 = (tsIndex, snapshot) => Object.entries(snapshot.slicing ?? {}).flatMap(([fieldName, fieldSlicing]) => {
|
|
6426
|
+
const field = snapshot.fields[fieldName];
|
|
6427
|
+
if (!isNotChoiceDeclarationField(field) || !fieldSlicing.slices || !field.type) return [];
|
|
6212
6428
|
const baseType = tsTypeFromIdentifier(field.type);
|
|
6213
6429
|
const pkgName = snapshot.identifier.package;
|
|
6214
6430
|
const choiceBaseNames = collectChoiceBaseNames(tsIndex, field.type);
|
|
6215
|
-
const isTypeDisc =
|
|
6216
|
-
return Object.entries(
|
|
6431
|
+
const isTypeDisc = isTypeDiscriminated(fieldSlicing);
|
|
6432
|
+
return Object.entries(fieldSlicing.slices).filter(([_, slice]) => Object.keys(slice.match ?? {}).length > 0).map(([sliceName, slice]) => {
|
|
6217
6433
|
const matchFields = Object.keys(slice.match ?? {});
|
|
6218
6434
|
const required = (slice.required ?? []).filter(
|
|
6219
6435
|
(name) => !matchFields.includes(name) && !choiceBaseNames.has(name)
|
|
@@ -6387,7 +6603,7 @@ var generateSliceGetters2 = (w, sliceDefs, snapshot) => {
|
|
|
6387
6603
|
};
|
|
6388
6604
|
|
|
6389
6605
|
// src/api/writer-generator/typescript/profile-validation.ts
|
|
6390
|
-
var
|
|
6606
|
+
var collectRegularFieldValidation2 = (errors, warnings, name, field, resolveRef, canonicalUrlExpr, tsIndex, fieldSlicing) => {
|
|
6391
6607
|
if (field.excluded) {
|
|
6392
6608
|
errors.push(`...validateExcluded(res, profileName, ${JSON.stringify(name)})`);
|
|
6393
6609
|
return;
|
|
@@ -6403,12 +6619,12 @@ var collectRegularFieldValidation = (errors, warnings, name, field, resolveRef,
|
|
|
6403
6619
|
}
|
|
6404
6620
|
if (field.mustSupport && !field.required)
|
|
6405
6621
|
warnings.push(`...validateMustSupport(res, profileName, ${JSON.stringify(name)})`);
|
|
6406
|
-
if (field.reference && field.reference.length > 0)
|
|
6622
|
+
if (field.reference && field.reference.resource.length > 0)
|
|
6407
6623
|
errors.push(
|
|
6408
|
-
`...validateReference(res, profileName, ${JSON.stringify(name)}, ${JSON.stringify(field.reference.map((ref) => resolveRef(ref).name))})`
|
|
6624
|
+
`...validateReference(res, profileName, ${JSON.stringify(name)}, ${JSON.stringify(field.reference.resource.map((ref) => resolveRef(ref).name))})`
|
|
6409
6625
|
);
|
|
6410
|
-
if (
|
|
6411
|
-
for (const [sliceName, slice] of Object.entries(
|
|
6626
|
+
if (fieldSlicing?.slices) {
|
|
6627
|
+
for (const [sliceName, slice] of Object.entries(fieldSlicing.slices)) {
|
|
6412
6628
|
const match = slice.match ?? {};
|
|
6413
6629
|
if (Object.keys(match).length === 0) continue;
|
|
6414
6630
|
if (slice.min !== void 0 || slice.max !== void 0) {
|
|
@@ -6446,25 +6662,23 @@ var generateValidateMethod2 = (w, tsIndex, snapshot) => {
|
|
|
6446
6662
|
const errors = [];
|
|
6447
6663
|
const warnings = [];
|
|
6448
6664
|
for (const [name, field] of Object.entries(fields)) {
|
|
6449
|
-
if (isChoiceInstanceField(field))
|
|
6450
|
-
const decl = fields[field.choiceOf];
|
|
6451
|
-
if (decl && isChoiceDeclarationField(decl) && decl.prohibited?.includes(name))
|
|
6452
|
-
errors.push(`...validateExcluded(res, profileName, ${JSON.stringify(name)})`);
|
|
6453
|
-
continue;
|
|
6454
|
-
}
|
|
6665
|
+
if (isChoiceInstanceField(field)) continue;
|
|
6455
6666
|
if (isChoiceDeclarationField(field)) {
|
|
6456
6667
|
if (field.required)
|
|
6457
6668
|
errors.push(`...validateChoiceRequired(res, profileName, ${JSON.stringify(field.choices)})`);
|
|
6669
|
+
if (field.prohibited?.length)
|
|
6670
|
+
errors.push(`...validateChoiceProhibited(res, profileName, ${JSON.stringify(field.prohibited)})`);
|
|
6458
6671
|
continue;
|
|
6459
6672
|
}
|
|
6460
|
-
|
|
6673
|
+
collectRegularFieldValidation2(
|
|
6461
6674
|
errors,
|
|
6462
6675
|
warnings,
|
|
6463
6676
|
name,
|
|
6464
6677
|
field,
|
|
6465
6678
|
tsIndex.findLastSpecializationByIdentifier,
|
|
6466
6679
|
canonicalUrlExpr,
|
|
6467
|
-
tsIndex
|
|
6680
|
+
tsIndex,
|
|
6681
|
+
snapshot.slicing?.[name]
|
|
6468
6682
|
);
|
|
6469
6683
|
}
|
|
6470
6684
|
for (const inheritedName of snapshot.inheritedRequiredFields ?? []) {
|
|
@@ -6558,7 +6772,7 @@ var collectProfileFactoryInfo2 = (tsIndex, snapshot) => {
|
|
|
6558
6772
|
continue;
|
|
6559
6773
|
}
|
|
6560
6774
|
if (isNotChoiceDeclarationField(field)) {
|
|
6561
|
-
const sliceNames = collectRequiredSliceNames2(field);
|
|
6775
|
+
const sliceNames = collectRequiredSliceNames2(field, snapshot.slicing?.[name]);
|
|
6562
6776
|
if (sliceNames) {
|
|
6563
6777
|
if (field.type) {
|
|
6564
6778
|
const tsType = fieldTsType(field, resolveRef, isFamilyType);
|
|
@@ -6658,6 +6872,7 @@ var generateProfileHelpersImport = (w, tsIndex, snapshot, sliceDefs, factoryInfo
|
|
|
6658
6872
|
"validateEnum",
|
|
6659
6873
|
"validateReference",
|
|
6660
6874
|
"validateChoiceRequired",
|
|
6875
|
+
"validateChoiceProhibited",
|
|
6661
6876
|
"validateMustSupport"
|
|
6662
6877
|
);
|
|
6663
6878
|
if (imports.length > 0) {
|
|
@@ -7680,6 +7895,10 @@ var APIBuilder = class {
|
|
|
7680
7895
|
assert4(this.options.typeSchema.treeShake === void 0, "treeShake option is already set");
|
|
7681
7896
|
this.options.typeSchema.treeShake = cfg.treeShake;
|
|
7682
7897
|
}
|
|
7898
|
+
if (cfg.treeShakeDefaults) {
|
|
7899
|
+
assert4(this.options.typeSchema.treeShakeDefaults === void 0, "treeShakeDefaults option is already set");
|
|
7900
|
+
this.options.typeSchema.treeShakeDefaults = cfg.treeShakeDefaults;
|
|
7901
|
+
}
|
|
7683
7902
|
if (cfg.promoteLogical) {
|
|
7684
7903
|
assert4(this.options.typeSchema.promoteLogical === void 0, "promoteLogical option is already set");
|
|
7685
7904
|
this.options.typeSchema.promoteLogical = cfg.promoteLogical;
|
|
@@ -7754,7 +7973,12 @@ var APIBuilder = class {
|
|
|
7754
7973
|
};
|
|
7755
7974
|
const tsIndexOpts = { register, irReport, logger: tsLogger };
|
|
7756
7975
|
let tsIndex = mkTypeSchemaIndex(typeSchemas, tsIndexOpts);
|
|
7757
|
-
if (this.options.typeSchema?.treeShake)
|
|
7976
|
+
if (this.options.typeSchema?.treeShake)
|
|
7977
|
+
tsIndex = treeShake(
|
|
7978
|
+
tsIndex,
|
|
7979
|
+
this.options.typeSchema.treeShake,
|
|
7980
|
+
this.options.typeSchema.treeShakeDefaults
|
|
7981
|
+
);
|
|
7758
7982
|
if (this.options.typeSchema?.promoteLogical)
|
|
7759
7983
|
tsIndex = promoteLogical(tsIndex, this.options.typeSchema.promoteLogical);
|
|
7760
7984
|
tsLogger.printTagSummary();
|