@atomic-ehr/codegen 0.0.1-canary.20251008162621.549c5d8 → 0.0.1-canary.20251009074815.3e20aa6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +21 -21
- package/dist/index.d.ts +3 -0
- package/dist/index.js +217 -190
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -433,6 +433,7 @@ interface Config {
|
|
|
433
433
|
overwrite?: boolean;
|
|
434
434
|
validate?: boolean;
|
|
435
435
|
cache?: boolean;
|
|
436
|
+
cleanOutput?: boolean;
|
|
436
437
|
typescript?: TypeScriptGeneratorConfig;
|
|
437
438
|
typeSchema?: TypeSchemaConfig;
|
|
438
439
|
packages?: string[];
|
|
@@ -752,6 +753,7 @@ interface APIBuilderOptions {
|
|
|
752
753
|
verbose?: boolean;
|
|
753
754
|
overwrite?: boolean;
|
|
754
755
|
cache?: boolean;
|
|
756
|
+
cleanOutput?: boolean;
|
|
755
757
|
typeSchemaConfig?: TypeSchemaConfig;
|
|
756
758
|
logger?: CodegenLogger;
|
|
757
759
|
manager?: ReturnType<typeof CanonicalManager> | null;
|
|
@@ -823,6 +825,7 @@ declare class APIBuilder {
|
|
|
823
825
|
outputTo(directory: string): APIBuilder;
|
|
824
826
|
verbose(enabled?: boolean): APIBuilder;
|
|
825
827
|
throwException(enabled?: boolean): APIBuilder;
|
|
828
|
+
cleanOutput(enabled?: boolean): APIBuilder;
|
|
826
829
|
generate(): Promise<GenerationResult>;
|
|
827
830
|
/**
|
|
828
831
|
* Generate and return the results without writing to files
|
package/dist/index.js
CHANGED
|
@@ -1421,6 +1421,15 @@ var isFhirSchemaBased = (schema) => {
|
|
|
1421
1421
|
var isSpecializationTypeSchema = (schema) => {
|
|
1422
1422
|
return schema?.identifier.kind === "resource" || schema?.identifier.kind === "complex-type" || schema?.identifier.kind === "logical";
|
|
1423
1423
|
};
|
|
1424
|
+
var isComplexTypeTypeSchema = (schema) => {
|
|
1425
|
+
return schema?.identifier.kind === "complex-type";
|
|
1426
|
+
};
|
|
1427
|
+
var isResourceTypeSchema = (schema) => {
|
|
1428
|
+
return schema?.identifier.kind === "resource";
|
|
1429
|
+
};
|
|
1430
|
+
var isLogicalTypeSchema = (schema) => {
|
|
1431
|
+
return schema?.identifier.kind === "logical";
|
|
1432
|
+
};
|
|
1424
1433
|
var isProfileTypeSchema = (schema) => {
|
|
1425
1434
|
return schema?.identifier.kind === "profile";
|
|
1426
1435
|
};
|
|
@@ -1487,29 +1496,29 @@ var registerFromManager = async (manager, logger) => {
|
|
|
1487
1496
|
);
|
|
1488
1497
|
}
|
|
1489
1498
|
const complexTypes = {};
|
|
1490
|
-
for (const
|
|
1491
|
-
if (
|
|
1492
|
-
complexTypes[
|
|
1499
|
+
for (const fs3 of Object.values(fsIndex)) {
|
|
1500
|
+
if (fs3.kind === "complex-type") {
|
|
1501
|
+
complexTypes[fs3.url] = fs3;
|
|
1493
1502
|
}
|
|
1494
1503
|
}
|
|
1495
1504
|
const resolveFsGenealogy = (canonicalUrl) => {
|
|
1496
|
-
let
|
|
1497
|
-
if (
|
|
1498
|
-
const genealogy = [
|
|
1499
|
-
while (
|
|
1500
|
-
|
|
1501
|
-
genealogy.push(
|
|
1502
|
-
if (
|
|
1505
|
+
let fs3 = fsIndex[canonicalUrl];
|
|
1506
|
+
if (fs3 === void 0) throw new Error(`Failed to resolve FHIR Schema genealogy for '${canonicalUrl}'`);
|
|
1507
|
+
const genealogy = [fs3];
|
|
1508
|
+
while (fs3?.base) {
|
|
1509
|
+
fs3 = fsIndex[fs3.base] || fsIndex[nameToCanonical[fs3.base]];
|
|
1510
|
+
genealogy.push(fs3);
|
|
1511
|
+
if (fs3 === void 0) throw new Error(`Failed to resolve FHIR Schema genealogy for '${canonicalUrl}'`);
|
|
1503
1512
|
}
|
|
1504
1513
|
return genealogy;
|
|
1505
1514
|
};
|
|
1506
1515
|
const resolveFsSpecializations = (canonicalUrl) => {
|
|
1507
|
-
return resolveFsGenealogy(canonicalUrl).filter((
|
|
1516
|
+
return resolveFsGenealogy(canonicalUrl).filter((fs3) => fs3.derivation === "specialization");
|
|
1508
1517
|
};
|
|
1509
1518
|
return {
|
|
1510
1519
|
...manager,
|
|
1511
|
-
appendFs(
|
|
1512
|
-
const rfs = enrichFHIRSchema(
|
|
1520
|
+
appendFs(fs3) {
|
|
1521
|
+
const rfs = enrichFHIRSchema(fs3);
|
|
1513
1522
|
fsIndex[rfs.url] = rfs;
|
|
1514
1523
|
nameToCanonical[rfs.name] = rfs.url;
|
|
1515
1524
|
},
|
|
@@ -1529,9 +1538,9 @@ var registerFromManager = async (manager, logger) => {
|
|
|
1529
1538
|
var resolveFsElementGenealogy = (genealogy, path) => {
|
|
1530
1539
|
const [top, ...rest] = path;
|
|
1531
1540
|
if (top === void 0) return [];
|
|
1532
|
-
return genealogy.map((
|
|
1533
|
-
if (!
|
|
1534
|
-
let elem =
|
|
1541
|
+
return genealogy.map((fs3) => {
|
|
1542
|
+
if (!fs3.elements) return void 0;
|
|
1543
|
+
let elem = fs3.elements?.[top];
|
|
1535
1544
|
for (const k of rest) {
|
|
1536
1545
|
elem = elem?.elements?.[k];
|
|
1537
1546
|
}
|
|
@@ -1613,7 +1622,7 @@ function mkNestedIdentifier(register, fhirSchema, path, logger) {
|
|
|
1613
1622
|
var nestedTypeOrigins = {};
|
|
1614
1623
|
if (fhirSchema.derivation === "constraint") {
|
|
1615
1624
|
const specializations = register.resolveFsSpecializations(fhirSchema.url);
|
|
1616
|
-
const nestedTypeGenealogy = specializations.map((
|
|
1625
|
+
const nestedTypeGenealogy = specializations.map((fs3) => mkNestedTypes(register, fs3, logger)).filter((e) => e !== void 0).flat();
|
|
1617
1626
|
for (const nt of nestedTypeGenealogy.reverse()) {
|
|
1618
1627
|
nestedTypeOrigins[nt.identifier.name] = nt.identifier.url;
|
|
1619
1628
|
}
|
|
@@ -1707,10 +1716,10 @@ function extractNestedDependencies(nestedTypes) {
|
|
|
1707
1716
|
function isRequired(register, fhirSchema, path) {
|
|
1708
1717
|
const fieldName = path[path.length - 1];
|
|
1709
1718
|
const parentPath = path.slice(0, -1);
|
|
1710
|
-
const requires = register.resolveFsGenealogy(fhirSchema.url).flatMap((
|
|
1711
|
-
if (parentPath.length === 0) return
|
|
1712
|
-
if (!
|
|
1713
|
-
let elem =
|
|
1719
|
+
const requires = register.resolveFsGenealogy(fhirSchema.url).flatMap((fs3) => {
|
|
1720
|
+
if (parentPath.length === 0) return fs3.required || [];
|
|
1721
|
+
if (!fs3.elements) return [];
|
|
1722
|
+
let elem = fs3;
|
|
1714
1723
|
for (const k of parentPath) {
|
|
1715
1724
|
elem = elem?.elements?.[k];
|
|
1716
1725
|
}
|
|
@@ -1722,10 +1731,10 @@ function isExcluded(register, fhirSchema, path) {
|
|
|
1722
1731
|
const fieldName = path[path.length - 1];
|
|
1723
1732
|
if (!fieldName) throw new Error(`Internal error: fieldName is missing for path ${path.join("/")}`);
|
|
1724
1733
|
const parentPath = path.slice(0, -1);
|
|
1725
|
-
const requires = register.resolveFsGenealogy(fhirSchema.url).flatMap((
|
|
1726
|
-
if (parentPath.length === 0) return
|
|
1727
|
-
if (!
|
|
1728
|
-
let elem =
|
|
1734
|
+
const requires = register.resolveFsGenealogy(fhirSchema.url).flatMap((fs3) => {
|
|
1735
|
+
if (parentPath.length === 0) return fs3.excluded || [];
|
|
1736
|
+
if (!fs3.elements) return [];
|
|
1737
|
+
let elem = fs3;
|
|
1729
1738
|
for (const k of parentPath) {
|
|
1730
1739
|
elem = elem?.elements?.[k];
|
|
1731
1740
|
}
|
|
@@ -1737,8 +1746,8 @@ var buildReferences = (element, register, _packageInfo) => {
|
|
|
1737
1746
|
if (!element.refers) return void 0;
|
|
1738
1747
|
return element.refers.map((ref) => {
|
|
1739
1748
|
const curl = register.ensureCanonicalUrl(ref);
|
|
1740
|
-
const
|
|
1741
|
-
return mkIdentifier(
|
|
1749
|
+
const fs3 = register.resolveFs(curl);
|
|
1750
|
+
return mkIdentifier(fs3);
|
|
1742
1751
|
});
|
|
1743
1752
|
};
|
|
1744
1753
|
function buildFieldType(register, fhirSchema, element, logger) {
|
|
@@ -2554,7 +2563,7 @@ var TypeSchemaGenerator = class {
|
|
|
2554
2563
|
};
|
|
2555
2564
|
const register = await this.registerFromPackageMetas([packageInfo]);
|
|
2556
2565
|
const valueSets = await this.generateValueSetSchemas(register.allVs(), logger);
|
|
2557
|
-
const fhirSchemas = (await Promise.all(register.allFs().map(async (
|
|
2566
|
+
const fhirSchemas = (await Promise.all(register.allFs().map(async (fs3) => await transformFhirSchema(register, fs3, logger)))).flat();
|
|
2558
2567
|
const allSchemas = [...fhirSchemas, ...valueSets];
|
|
2559
2568
|
if (this.cache) {
|
|
2560
2569
|
for (const schema of allSchemas) {
|
|
@@ -2934,6 +2943,143 @@ var generateTypeSchemas = async (register, logger) => {
|
|
|
2934
2943
|
return fhirSchemas;
|
|
2935
2944
|
};
|
|
2936
2945
|
|
|
2946
|
+
// src/typeschema/utils.ts
|
|
2947
|
+
var groupByPackages = (typeSchemas) => {
|
|
2948
|
+
const grouped = {};
|
|
2949
|
+
for (const ts of typeSchemas) {
|
|
2950
|
+
const packageName = ts.identifier.package;
|
|
2951
|
+
if (!grouped[packageName]) {
|
|
2952
|
+
grouped[packageName] = [];
|
|
2953
|
+
}
|
|
2954
|
+
grouped[packageName].push(ts);
|
|
2955
|
+
}
|
|
2956
|
+
for (const [_packageName, typeSchemas2] of Object.entries(grouped)) {
|
|
2957
|
+
typeSchemas2.sort((a, b) => a.identifier.name.localeCompare(b.identifier.name));
|
|
2958
|
+
}
|
|
2959
|
+
return grouped;
|
|
2960
|
+
};
|
|
2961
|
+
var resourceRelatives = (schemas) => {
|
|
2962
|
+
const regularSchemas = schemas.filter(isResourceTypeSchema);
|
|
2963
|
+
const directPairs = [];
|
|
2964
|
+
for (const schema of regularSchemas) {
|
|
2965
|
+
if (schema.base) {
|
|
2966
|
+
directPairs.push({ parent: schema.base, child: schema.identifier });
|
|
2967
|
+
}
|
|
2968
|
+
}
|
|
2969
|
+
const allPairs = [...directPairs];
|
|
2970
|
+
const findTransitiveRelatives = (parentRef) => {
|
|
2971
|
+
const directChildren = directPairs.filter((pair) => pair.parent.name === parentRef.name).map((pair) => pair.child);
|
|
2972
|
+
const transitiveChildren = [];
|
|
2973
|
+
for (const child of directChildren) {
|
|
2974
|
+
transitiveChildren.push(...findTransitiveRelatives(child));
|
|
2975
|
+
}
|
|
2976
|
+
return [...directChildren, ...transitiveChildren];
|
|
2977
|
+
};
|
|
2978
|
+
for (const pair of directPairs) {
|
|
2979
|
+
const transitiveChildren = findTransitiveRelatives(pair.child);
|
|
2980
|
+
for (const transitiveChild of transitiveChildren) {
|
|
2981
|
+
if (!directPairs.some((dp) => dp.parent.name === pair.parent.name && dp.child.name === transitiveChild.name)) {
|
|
2982
|
+
allPairs.push({ parent: pair.parent, child: transitiveChild });
|
|
2983
|
+
}
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
return allPairs;
|
|
2987
|
+
};
|
|
2988
|
+
var mkTypeSchemaIndex = (schemas) => {
|
|
2989
|
+
const index = {};
|
|
2990
|
+
const append = (schema) => {
|
|
2991
|
+
const url = schema.identifier.url;
|
|
2992
|
+
if (!index[url]) {
|
|
2993
|
+
index[url] = {};
|
|
2994
|
+
}
|
|
2995
|
+
index[url][schema.identifier.package] = schema;
|
|
2996
|
+
};
|
|
2997
|
+
for (const schema of schemas) {
|
|
2998
|
+
append(schema);
|
|
2999
|
+
}
|
|
3000
|
+
const relations = resourceRelatives(schemas);
|
|
3001
|
+
const resolve2 = (id) => index[id.url]?.[id.package];
|
|
3002
|
+
const resourceChildren = (id) => {
|
|
3003
|
+
return relations.filter((relative2) => relative2.parent.name === id.name).map((relative2) => relative2.child);
|
|
3004
|
+
};
|
|
3005
|
+
const hierarchy = (schema) => {
|
|
3006
|
+
const res = [];
|
|
3007
|
+
let cur = schema;
|
|
3008
|
+
while (cur) {
|
|
3009
|
+
res.push(cur);
|
|
3010
|
+
const base = cur.base;
|
|
3011
|
+
if (base === void 0) break;
|
|
3012
|
+
const resolved = resolve2(base);
|
|
3013
|
+
if (!resolved) {
|
|
3014
|
+
throw new Error(
|
|
3015
|
+
`Failed to resolve base type: ${res.map((e) => `${e.identifier.url} (${e.identifier.kind})`).join(", ")}`
|
|
3016
|
+
);
|
|
3017
|
+
}
|
|
3018
|
+
cur = resolved;
|
|
3019
|
+
}
|
|
3020
|
+
return res;
|
|
3021
|
+
};
|
|
3022
|
+
const findLastSpecialization = (id) => {
|
|
3023
|
+
const schema = resolve2(id);
|
|
3024
|
+
if (!schema) return id;
|
|
3025
|
+
const nonConstraintSchema = hierarchy(schema).find((s) => s.identifier.kind !== "profile");
|
|
3026
|
+
if (!nonConstraintSchema) {
|
|
3027
|
+
throw new Error(`No non-constraint schema found in hierarchy for ${id.name}`);
|
|
3028
|
+
}
|
|
3029
|
+
return nonConstraintSchema.identifier;
|
|
3030
|
+
};
|
|
3031
|
+
const flatProfile = (schema) => {
|
|
3032
|
+
const hierarchySchemas = hierarchy(schema);
|
|
3033
|
+
const constraintSchemas = hierarchySchemas.filter((s) => s.identifier.kind === "profile");
|
|
3034
|
+
const nonConstraintSchema = hierarchySchemas.find((s) => s.identifier.kind !== "profile");
|
|
3035
|
+
if (!nonConstraintSchema)
|
|
3036
|
+
throw new Error(`No non-constraint schema found in hierarchy for ${schema.identifier.name}`);
|
|
3037
|
+
const mergedFields = {};
|
|
3038
|
+
for (const anySchema of constraintSchemas.slice().reverse()) {
|
|
3039
|
+
const schema2 = anySchema;
|
|
3040
|
+
if (!schema2.fields) continue;
|
|
3041
|
+
for (const [fieldName, fieldConstraints] of Object.entries(schema2.fields)) {
|
|
3042
|
+
if (mergedFields[fieldName]) {
|
|
3043
|
+
mergedFields[fieldName] = { ...mergedFields[fieldName], ...fieldConstraints };
|
|
3044
|
+
} else {
|
|
3045
|
+
mergedFields[fieldName] = { ...fieldConstraints };
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
3048
|
+
}
|
|
3049
|
+
const deps = {};
|
|
3050
|
+
for (const e of constraintSchemas.flatMap((e2) => e2.dependencies ?? [])) {
|
|
3051
|
+
deps[e.url] = e;
|
|
3052
|
+
}
|
|
3053
|
+
const dependencies = Object.values(deps);
|
|
3054
|
+
return {
|
|
3055
|
+
...schema,
|
|
3056
|
+
base: nonConstraintSchema.identifier,
|
|
3057
|
+
fields: mergedFields,
|
|
3058
|
+
dependencies
|
|
3059
|
+
};
|
|
3060
|
+
};
|
|
3061
|
+
const isWithMetaField = (profile) => {
|
|
3062
|
+
return hierarchy(profile).filter(isSpecializationTypeSchema).some((schema) => {
|
|
3063
|
+
console.log(schema.fields?.meta);
|
|
3064
|
+
return schema.fields?.meta !== void 0;
|
|
3065
|
+
});
|
|
3066
|
+
};
|
|
3067
|
+
return {
|
|
3068
|
+
_schemaIndex: index,
|
|
3069
|
+
_relations: relations,
|
|
3070
|
+
collectComplexTypes: () => schemas.filter(isComplexTypeTypeSchema),
|
|
3071
|
+
collectResources: () => schemas.filter(isResourceTypeSchema),
|
|
3072
|
+
collectLogicalModels: () => schemas.filter(isLogicalTypeSchema),
|
|
3073
|
+
collectProfiles: () => schemas.filter(isProfileTypeSchema),
|
|
3074
|
+
resolve: resolve2,
|
|
3075
|
+
resourceChildren,
|
|
3076
|
+
hierarchy,
|
|
3077
|
+
findLastSpecialization,
|
|
3078
|
+
flatProfile,
|
|
3079
|
+
isWithMetaField
|
|
3080
|
+
};
|
|
3081
|
+
};
|
|
3082
|
+
|
|
2937
3083
|
// src/api/generators/base/error-handler.ts
|
|
2938
3084
|
init_errors();
|
|
2939
3085
|
var ErrorHandler = class {
|
|
@@ -5019,7 +5165,7 @@ var FileSystemWriter = class {
|
|
|
5019
5165
|
if (!this.currentFileDescriptor) throw new Error("No file opened");
|
|
5020
5166
|
fs.writeSync(this.currentFileDescriptor, str);
|
|
5021
5167
|
}
|
|
5022
|
-
generate(
|
|
5168
|
+
generate(_tsIndex) {
|
|
5023
5169
|
throw new Error("Not implemented");
|
|
5024
5170
|
}
|
|
5025
5171
|
writtenFiles() {
|
|
@@ -5101,142 +5247,6 @@ var Writer = class extends FileSystemWriter {
|
|
|
5101
5247
|
}
|
|
5102
5248
|
};
|
|
5103
5249
|
|
|
5104
|
-
// src/typeschema/utils.ts
|
|
5105
|
-
var groupByPackages = (typeSchemas) => {
|
|
5106
|
-
const grouped = {};
|
|
5107
|
-
for (const ts of typeSchemas) {
|
|
5108
|
-
const packageName = ts.identifier.package;
|
|
5109
|
-
if (!grouped[packageName]) {
|
|
5110
|
-
grouped[packageName] = [];
|
|
5111
|
-
}
|
|
5112
|
-
grouped[packageName].push(ts);
|
|
5113
|
-
}
|
|
5114
|
-
for (const [_packageName, typeSchemas2] of Object.entries(grouped)) {
|
|
5115
|
-
typeSchemas2.sort((a, b) => a.identifier.name.localeCompare(b.identifier.name));
|
|
5116
|
-
}
|
|
5117
|
-
return grouped;
|
|
5118
|
-
};
|
|
5119
|
-
var collectComplexTypes = (tss) => tss.filter((t) => t.identifier.kind === "complex-type");
|
|
5120
|
-
var collectResources = (tss) => tss.filter((t) => t.identifier.kind === "resource");
|
|
5121
|
-
var collectProfiles = (tss) => tss.filter(isProfileTypeSchema);
|
|
5122
|
-
var resourceRelatives = (schemas) => {
|
|
5123
|
-
const regularSchemas = collectResources(schemas);
|
|
5124
|
-
const directPairs = [];
|
|
5125
|
-
for (const schema of regularSchemas) {
|
|
5126
|
-
if (schema.base) {
|
|
5127
|
-
directPairs.push({ parent: schema.base, child: schema.identifier });
|
|
5128
|
-
}
|
|
5129
|
-
}
|
|
5130
|
-
const allPairs = [...directPairs];
|
|
5131
|
-
const findTransitiveRelatives = (parentRef) => {
|
|
5132
|
-
const directChildren = directPairs.filter((pair) => pair.parent.name === parentRef.name).map((pair) => pair.child);
|
|
5133
|
-
const transitiveChildren = [];
|
|
5134
|
-
for (const child of directChildren) {
|
|
5135
|
-
transitiveChildren.push(...findTransitiveRelatives(child));
|
|
5136
|
-
}
|
|
5137
|
-
return [...directChildren, ...transitiveChildren];
|
|
5138
|
-
};
|
|
5139
|
-
for (const pair of directPairs) {
|
|
5140
|
-
const transitiveChildren = findTransitiveRelatives(pair.child);
|
|
5141
|
-
for (const transitiveChild of transitiveChildren) {
|
|
5142
|
-
if (!directPairs.some((dp) => dp.parent.name === pair.parent.name && dp.child.name === transitiveChild.name)) {
|
|
5143
|
-
allPairs.push({ parent: pair.parent, child: transitiveChild });
|
|
5144
|
-
}
|
|
5145
|
-
}
|
|
5146
|
-
}
|
|
5147
|
-
return allPairs;
|
|
5148
|
-
};
|
|
5149
|
-
var mkTypeSchemaIndex = (schemas) => {
|
|
5150
|
-
const index = {};
|
|
5151
|
-
const append = (schema) => {
|
|
5152
|
-
const url = schema.identifier.url;
|
|
5153
|
-
if (!index[url]) {
|
|
5154
|
-
index[url] = {};
|
|
5155
|
-
}
|
|
5156
|
-
index[url][schema.identifier.package] = schema;
|
|
5157
|
-
};
|
|
5158
|
-
for (const schema of schemas) {
|
|
5159
|
-
append(schema);
|
|
5160
|
-
}
|
|
5161
|
-
const relations = resourceRelatives(schemas);
|
|
5162
|
-
const resolve2 = (id) => index[id.url]?.[id.package];
|
|
5163
|
-
const resourceChildren = (id) => {
|
|
5164
|
-
return relations.filter((relative2) => relative2.parent.name === id.name).map((relative2) => relative2.child);
|
|
5165
|
-
};
|
|
5166
|
-
const hierarchy = (schema) => {
|
|
5167
|
-
const res = [];
|
|
5168
|
-
let cur = schema;
|
|
5169
|
-
while (cur) {
|
|
5170
|
-
res.push(cur);
|
|
5171
|
-
const base = cur.base;
|
|
5172
|
-
if (base === void 0) break;
|
|
5173
|
-
const resolved = resolve2(base);
|
|
5174
|
-
if (!resolved) {
|
|
5175
|
-
throw new Error(
|
|
5176
|
-
`Failed to resolve base type: ${res.map((e) => `${e.identifier.url} (${e.identifier.kind})`).join(", ")}`
|
|
5177
|
-
);
|
|
5178
|
-
}
|
|
5179
|
-
cur = resolved;
|
|
5180
|
-
}
|
|
5181
|
-
return res;
|
|
5182
|
-
};
|
|
5183
|
-
const findLastSpecialization = (id) => {
|
|
5184
|
-
const schema = resolve2(id);
|
|
5185
|
-
if (!schema) return id;
|
|
5186
|
-
const nonConstraintSchema = hierarchy(schema).find((s) => s.identifier.kind !== "profile");
|
|
5187
|
-
if (!nonConstraintSchema) {
|
|
5188
|
-
throw new Error(`No non-constraint schema found in hierarchy for ${id.name}`);
|
|
5189
|
-
}
|
|
5190
|
-
return nonConstraintSchema.identifier;
|
|
5191
|
-
};
|
|
5192
|
-
const flatProfile = (schema) => {
|
|
5193
|
-
const hierarchySchemas = hierarchy(schema);
|
|
5194
|
-
const constraintSchemas = hierarchySchemas.filter((s) => s.identifier.kind === "profile");
|
|
5195
|
-
const nonConstraintSchema = hierarchySchemas.find((s) => s.identifier.kind !== "profile");
|
|
5196
|
-
if (!nonConstraintSchema)
|
|
5197
|
-
throw new Error(`No non-constraint schema found in hierarchy for ${schema.identifier.name}`);
|
|
5198
|
-
const mergedFields = {};
|
|
5199
|
-
for (const anySchema of constraintSchemas.slice().reverse()) {
|
|
5200
|
-
const schema2 = anySchema;
|
|
5201
|
-
if (!schema2.fields) continue;
|
|
5202
|
-
for (const [fieldName, fieldConstraints] of Object.entries(schema2.fields)) {
|
|
5203
|
-
if (mergedFields[fieldName]) {
|
|
5204
|
-
mergedFields[fieldName] = { ...mergedFields[fieldName], ...fieldConstraints };
|
|
5205
|
-
} else {
|
|
5206
|
-
mergedFields[fieldName] = { ...fieldConstraints };
|
|
5207
|
-
}
|
|
5208
|
-
}
|
|
5209
|
-
}
|
|
5210
|
-
const deps = {};
|
|
5211
|
-
for (const e of constraintSchemas.flatMap((e2) => e2.dependencies ?? [])) {
|
|
5212
|
-
deps[e.url] = e;
|
|
5213
|
-
}
|
|
5214
|
-
const dependencies = Object.values(deps);
|
|
5215
|
-
return {
|
|
5216
|
-
...schema,
|
|
5217
|
-
base: nonConstraintSchema.identifier,
|
|
5218
|
-
fields: mergedFields,
|
|
5219
|
-
dependencies
|
|
5220
|
-
};
|
|
5221
|
-
};
|
|
5222
|
-
const isWithMetaField = (profile) => {
|
|
5223
|
-
return hierarchy(profile).filter(isSpecializationTypeSchema).some((schema) => {
|
|
5224
|
-
console.log(schema.fields?.meta);
|
|
5225
|
-
return schema.fields?.meta !== void 0;
|
|
5226
|
-
});
|
|
5227
|
-
};
|
|
5228
|
-
return {
|
|
5229
|
-
schemaIndex: index,
|
|
5230
|
-
relations,
|
|
5231
|
-
resolve: resolve2,
|
|
5232
|
-
resourceChildren,
|
|
5233
|
-
hierarchy,
|
|
5234
|
-
findLastSpecialization,
|
|
5235
|
-
flatProfile,
|
|
5236
|
-
isWithMetaField
|
|
5237
|
-
};
|
|
5238
|
-
};
|
|
5239
|
-
|
|
5240
5250
|
// src/api/writer-generator/typescript.ts
|
|
5241
5251
|
var primitiveType2tsType = {
|
|
5242
5252
|
boolean: "boolean",
|
|
@@ -5302,7 +5312,6 @@ var normalizeTsName = (n) => {
|
|
|
5302
5312
|
return n.replace(/[- ]/g, "_");
|
|
5303
5313
|
};
|
|
5304
5314
|
var TypeScript = class extends Writer {
|
|
5305
|
-
tsIndex = mkTypeSchemaIndex([]);
|
|
5306
5315
|
tsImportType(tsPackageName, ...entities) {
|
|
5307
5316
|
this.lineSM(`import type { ${entities.join(", ")} } from "${tsPackageName}"`);
|
|
5308
5317
|
}
|
|
@@ -5368,7 +5377,7 @@ var TypeScript = class extends Writer {
|
|
|
5368
5377
|
this.lineSM(`_${tsFieldName(fieldName)}?: Element`);
|
|
5369
5378
|
}
|
|
5370
5379
|
}
|
|
5371
|
-
generateType(schema) {
|
|
5380
|
+
generateType(tsIndex, schema) {
|
|
5372
5381
|
var name;
|
|
5373
5382
|
if (schema.identifier.name === "Reference") {
|
|
5374
5383
|
name = "Reference<T extends string = string>";
|
|
@@ -5384,7 +5393,7 @@ var TypeScript = class extends Writer {
|
|
|
5384
5393
|
if (!schema.fields) return;
|
|
5385
5394
|
if (schema.identifier.kind === "resource") {
|
|
5386
5395
|
const possibleResourceTypes = [schema.identifier];
|
|
5387
|
-
possibleResourceTypes.push(...
|
|
5396
|
+
possibleResourceTypes.push(...tsIndex.resourceChildren(schema.identifier));
|
|
5388
5397
|
this.lineSM(`resourceType: ${possibleResourceTypes.map((e) => `"${e.name}"`).join(" | ")}`);
|
|
5389
5398
|
this.line();
|
|
5390
5399
|
}
|
|
@@ -5420,14 +5429,14 @@ var TypeScript = class extends Writer {
|
|
|
5420
5429
|
}
|
|
5421
5430
|
});
|
|
5422
5431
|
}
|
|
5423
|
-
generateNestedTypes(schema) {
|
|
5432
|
+
generateNestedTypes(tsIndex, schema) {
|
|
5424
5433
|
if (schema.nested) {
|
|
5425
5434
|
for (const subtype of schema.nested) {
|
|
5426
|
-
this.generateType(subtype);
|
|
5435
|
+
this.generateType(tsIndex, subtype);
|
|
5427
5436
|
}
|
|
5428
5437
|
}
|
|
5429
5438
|
}
|
|
5430
|
-
generateProfileType(schema) {
|
|
5439
|
+
generateProfileType(tsIndex, schema) {
|
|
5431
5440
|
const name = tsResourceName(schema.identifier);
|
|
5432
5441
|
this.debugComment("identifier", schema.identifier);
|
|
5433
5442
|
this.debugComment("base", schema.base);
|
|
@@ -5445,8 +5454,8 @@ var TypeScript = class extends Writer {
|
|
|
5445
5454
|
} else if (field.enum) {
|
|
5446
5455
|
tsType = field.enum.map((e) => `'${e}'`).join(" | ");
|
|
5447
5456
|
} else if (field.reference && field.reference.length > 0) {
|
|
5448
|
-
const specializationId =
|
|
5449
|
-
const specialization =
|
|
5457
|
+
const specializationId = tsIndex.findLastSpecialization(schema.identifier);
|
|
5458
|
+
const specialization = tsIndex.resolve(specializationId);
|
|
5450
5459
|
if (!isSpecializationTypeSchema(specialization))
|
|
5451
5460
|
throw new Error(`Invalid specialization for ${schema.identifier}`);
|
|
5452
5461
|
const sField = specialization.fields?.[fieldName];
|
|
@@ -5454,7 +5463,7 @@ var TypeScript = class extends Writer {
|
|
|
5454
5463
|
throw new Error(`Invalid field declaration for ${fieldName}`);
|
|
5455
5464
|
const sRefs = (sField.reference ?? []).map((e) => e.name);
|
|
5456
5465
|
const references = field.reference.map((ref) => {
|
|
5457
|
-
const resRef =
|
|
5466
|
+
const resRef = tsIndex.findLastSpecialization(ref);
|
|
5458
5467
|
if (resRef.name !== ref.name) {
|
|
5459
5468
|
return `"${resRef.name}" /*${ref.name}*/`;
|
|
5460
5469
|
}
|
|
@@ -5499,13 +5508,13 @@ var TypeScript = class extends Writer {
|
|
|
5499
5508
|
);
|
|
5500
5509
|
this.line();
|
|
5501
5510
|
}
|
|
5502
|
-
generateExtractProfile(flatProfile) {
|
|
5511
|
+
generateExtractProfile(tsIndex, flatProfile) {
|
|
5503
5512
|
const tsBaseResourceName = tsResourceName(flatProfile.base);
|
|
5504
5513
|
const tsProfileName = tsResourceName(flatProfile.identifier);
|
|
5505
5514
|
const profileFields = Object.entries(flatProfile.fields || {}).filter(([_fieldName, field]) => {
|
|
5506
5515
|
return isNotChoiceDeclarationField(field) && field.type !== void 0;
|
|
5507
5516
|
}).map(([fieldName]) => fieldName);
|
|
5508
|
-
const specialization =
|
|
5517
|
+
const specialization = tsIndex.resolve(tsIndex.findLastSpecialization(flatProfile.identifier));
|
|
5509
5518
|
if (!isSpecializationTypeSchema(specialization))
|
|
5510
5519
|
throw new Error(`Specialization not found for ${flatProfile.identifier.url}`);
|
|
5511
5520
|
const shouldCast = {};
|
|
@@ -5571,30 +5580,29 @@ var TypeScript = class extends Writer {
|
|
|
5571
5580
|
}
|
|
5572
5581
|
);
|
|
5573
5582
|
}
|
|
5574
|
-
generateResourceModule(schema) {
|
|
5583
|
+
generateResourceModule(tsIndex, schema) {
|
|
5575
5584
|
this.cat(`${tsModuleFileName(schema.identifier)}`, () => {
|
|
5576
5585
|
this.generateDisclaimer();
|
|
5577
5586
|
if (["complex-type", "resource", "logical"].includes(schema.identifier.kind)) {
|
|
5578
5587
|
this.generateDependenciesImports(schema);
|
|
5579
5588
|
this.generateComplexTypeReexports(schema);
|
|
5580
|
-
this.generateNestedTypes(schema);
|
|
5581
|
-
this.generateType(schema);
|
|
5589
|
+
this.generateNestedTypes(tsIndex, schema);
|
|
5590
|
+
this.generateType(tsIndex, schema);
|
|
5582
5591
|
} else if (isProfileTypeSchema(schema)) {
|
|
5583
|
-
const flatProfile =
|
|
5592
|
+
const flatProfile = tsIndex.flatProfile(schema);
|
|
5584
5593
|
this.generateDependenciesImports(flatProfile);
|
|
5585
|
-
this.generateProfileType(flatProfile);
|
|
5594
|
+
this.generateProfileType(tsIndex, flatProfile);
|
|
5586
5595
|
this.generateAttachProfile(flatProfile);
|
|
5587
|
-
this.generateExtractProfile(flatProfile);
|
|
5596
|
+
this.generateExtractProfile(tsIndex, flatProfile);
|
|
5588
5597
|
} else throw new Error(`Profile generation not implemented for kind: ${schema.identifier.kind}`);
|
|
5589
5598
|
});
|
|
5590
5599
|
}
|
|
5591
|
-
generate(
|
|
5592
|
-
this.tsIndex = mkTypeSchemaIndex(schemas);
|
|
5600
|
+
generate(tsIndex) {
|
|
5593
5601
|
const typesToGenerate = [
|
|
5594
|
-
...collectComplexTypes(
|
|
5595
|
-
...collectResources(
|
|
5596
|
-
// ...collectLogicalModels(
|
|
5597
|
-
...collectProfiles(
|
|
5602
|
+
...tsIndex.collectComplexTypes(),
|
|
5603
|
+
...tsIndex.collectResources(),
|
|
5604
|
+
// ...tsIndex.collectLogicalModels(),
|
|
5605
|
+
...tsIndex.collectProfiles().filter((p) => tsIndex.isWithMetaField(p))
|
|
5598
5606
|
];
|
|
5599
5607
|
const grouped = groupByPackages(typesToGenerate);
|
|
5600
5608
|
this.cd("/", () => {
|
|
@@ -5602,7 +5610,7 @@ var TypeScript = class extends Writer {
|
|
|
5602
5610
|
const tsPackageDir = tsFhirPackageDir(packageName);
|
|
5603
5611
|
this.cd(tsPackageDir, () => {
|
|
5604
5612
|
for (const schema of packageSchemas) {
|
|
5605
|
-
this.generateResourceModule(schema);
|
|
5613
|
+
this.generateResourceModule(tsIndex, schema);
|
|
5606
5614
|
}
|
|
5607
5615
|
this.generateFhirPackageIndexFile(packageSchemas);
|
|
5608
5616
|
});
|
|
@@ -5627,7 +5635,8 @@ var writerToGenerator = (writerGen) => {
|
|
|
5627
5635
|
};
|
|
5628
5636
|
return {
|
|
5629
5637
|
generate: async (schemas) => {
|
|
5630
|
-
|
|
5638
|
+
const tsIndex = mkTypeSchemaIndex(schemas);
|
|
5639
|
+
writerGen.generate(tsIndex);
|
|
5631
5640
|
return getGeneratedFiles();
|
|
5632
5641
|
},
|
|
5633
5642
|
setOutputDir: (outputDir) => writerGen.opts.outputDir = outputDir,
|
|
@@ -5651,6 +5660,7 @@ var APIBuilder = class {
|
|
|
5651
5660
|
verbose: options.verbose ?? false,
|
|
5652
5661
|
overwrite: options.overwrite ?? true,
|
|
5653
5662
|
cache: options.cache ?? true,
|
|
5663
|
+
cleanOutput: options.cleanOutput ?? true,
|
|
5654
5664
|
typeSchemaConfig: options.typeSchemaConfig,
|
|
5655
5665
|
manager: options.manager || null,
|
|
5656
5666
|
throwException: options.throwException || false
|
|
@@ -5752,6 +5762,10 @@ var APIBuilder = class {
|
|
|
5752
5762
|
this.options.throwException = enabled;
|
|
5753
5763
|
return this;
|
|
5754
5764
|
}
|
|
5765
|
+
cleanOutput(enabled = true) {
|
|
5766
|
+
this.options.cleanOutput = enabled;
|
|
5767
|
+
return this;
|
|
5768
|
+
}
|
|
5755
5769
|
async generate() {
|
|
5756
5770
|
const startTime = performance.now();
|
|
5757
5771
|
const result = {
|
|
@@ -5763,6 +5777,17 @@ var APIBuilder = class {
|
|
|
5763
5777
|
duration: 0
|
|
5764
5778
|
};
|
|
5765
5779
|
this.logger.debug(`Starting generation with ${this.generators.size} generators`);
|
|
5780
|
+
if (this.options.cleanOutput) {
|
|
5781
|
+
this.logger.info(`Cleaning output directory: ${this.options.outputDir}`);
|
|
5782
|
+
try {
|
|
5783
|
+
fs.rmSync(this.options.outputDir, { recursive: true, force: true });
|
|
5784
|
+
fs.mkdirSync(this.options.outputDir, { recursive: true });
|
|
5785
|
+
} catch (error) {
|
|
5786
|
+
this.logger.warn(
|
|
5787
|
+
`Error cleaning output directory: ${error instanceof Error ? error.message : String(error)}`
|
|
5788
|
+
);
|
|
5789
|
+
}
|
|
5790
|
+
}
|
|
5766
5791
|
try {
|
|
5767
5792
|
this.logger.info("Initialize Canonical Manager");
|
|
5768
5793
|
const manager = CanonicalManager({
|
|
@@ -5864,6 +5889,7 @@ function createAPIFromConfig(config) {
|
|
|
5864
5889
|
verbose: config.verbose,
|
|
5865
5890
|
overwrite: config.overwrite,
|
|
5866
5891
|
cache: config.cache,
|
|
5892
|
+
cleanOutput: config.cleanOutput,
|
|
5867
5893
|
typeSchemaConfig: config.typeSchema
|
|
5868
5894
|
});
|
|
5869
5895
|
if (config.packages && config.packages.length > 0) {
|
|
@@ -5897,6 +5923,7 @@ var DEFAULT_CONFIG = {
|
|
|
5897
5923
|
overwrite: true,
|
|
5898
5924
|
validate: true,
|
|
5899
5925
|
cache: true,
|
|
5926
|
+
cleanOutput: true,
|
|
5900
5927
|
typescript: {
|
|
5901
5928
|
moduleFormat: "esm",
|
|
5902
5929
|
generateIndex: true,
|