@atomic-ehr/codegen 0.0.1-canary.20250929141928.699688c → 0.0.1-canary.20250930075344.1c0b689
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/api/builder.d.ts +2 -2
- package/dist/api/builder.js +1 -1
- package/dist/api/generators/base/BaseGenerator.js +5 -12
- package/dist/api/generators/base/FileManager.js +1 -3
- package/dist/api/generators/base/TemplateEngine.js +2 -2
- package/dist/api/generators/base/TypeScriptTypeMapper.js +1 -1
- package/dist/api/generators/base/builders/FileBuilder.js +6 -8
- package/dist/api/generators/base/errors.js +1 -3
- package/dist/api/generators/base/index.d.ts +1 -1
- package/dist/api/generators/base/index.js +1 -2
- package/dist/api/generators/base/types.d.ts +1 -1
- package/dist/api/generators/typescript.d.ts +1 -3
- package/dist/api/generators/typescript.js +13 -38
- package/dist/api/index.d.ts +1 -2
- package/dist/cli/commands/typeschema/generate.js +4 -10
- package/dist/cli/commands/typeschema.js +1 -2
- package/dist/cli/index.js +54 -54
- package/dist/cli/utils/spinner.js +2 -6
- package/dist/config.js +4 -16
- package/dist/logger.js +4 -13
- package/dist/typeschema/cache.d.ts +1 -1
- package/dist/typeschema/core/binding.d.ts +4 -7
- package/dist/typeschema/core/binding.js +16 -30
- package/dist/typeschema/core/field-builder.d.ts +6 -14
- package/dist/typeschema/core/field-builder.js +42 -88
- package/dist/typeschema/core/identifier.d.ts +5 -8
- package/dist/typeschema/core/identifier.js +8 -15
- package/dist/typeschema/core/nested-types.d.ts +4 -7
- package/dist/typeschema/core/nested-types.js +15 -14
- package/dist/typeschema/core/transformer.d.ts +6 -13
- package/dist/typeschema/core/transformer.js +74 -144
- package/dist/typeschema/generator.d.ts +5 -8
- package/dist/typeschema/generator.js +26 -24
- package/dist/typeschema/parser.d.ts +7 -8
- package/dist/typeschema/parser.js +67 -82
- package/dist/typeschema/profile/processor.d.ts +3 -2
- package/dist/typeschema/profile/processor.js +13 -23
- package/dist/typeschema/register.d.ts +16 -0
- package/dist/typeschema/register.js +65 -0
- package/dist/typeschema/types.d.ts +32 -21
- package/dist/typeschema/types.js +5 -5
- package/dist/typeschema/value-set/processor.d.ts +2 -2
- package/dist/typeschema/value-set/processor.js +3 -3
- package/dist/utils/codegen-logger.js +4 -12
- package/package.json +2 -2
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Nested Types (BackboneElement) Handling
|
|
3
|
+
*
|
|
4
|
+
* Functions for extracting and transforming nested types from FHIRSchema
|
|
5
|
+
*/
|
|
6
|
+
import { buildField, isNestedElement, mkNestedField } from "./field-builder";
|
|
7
|
+
import { mkNestedIdentifier } from "./identifier";
|
|
4
8
|
/**
|
|
5
9
|
* Collect all nested elements from a FHIRSchema
|
|
6
10
|
*/
|
|
@@ -19,20 +23,17 @@ export function collectNestedElements(fhirSchema, parentPath, elements) {
|
|
|
19
23
|
}
|
|
20
24
|
return nested;
|
|
21
25
|
}
|
|
22
|
-
|
|
23
|
-
* Transform elements into fields for a nested type
|
|
24
|
-
*/
|
|
25
|
-
export async function transformNestedElements(fhirSchema, parentPath, elements, manager, packageInfo) {
|
|
26
|
+
export async function transformNestedElements(fhirSchema, parentPath, elements, register, packageInfo) {
|
|
26
27
|
const fields = {};
|
|
27
28
|
for (const [key, element] of Object.entries(elements)) {
|
|
28
29
|
const path = [...parentPath, key];
|
|
29
30
|
if (isNestedElement(element)) {
|
|
30
31
|
// Reference to another nested type
|
|
31
|
-
fields[key] =
|
|
32
|
+
fields[key] = mkNestedField(fhirSchema, path, element, register, packageInfo);
|
|
32
33
|
}
|
|
33
34
|
else {
|
|
34
35
|
// Regular field
|
|
35
|
-
fields[key] = await buildField(fhirSchema, path, element,
|
|
36
|
+
fields[key] = await buildField(fhirSchema, path, element, register, packageInfo);
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
return fields;
|
|
@@ -40,15 +41,15 @@ export async function transformNestedElements(fhirSchema, parentPath, elements,
|
|
|
40
41
|
/**
|
|
41
42
|
* Build TypeSchema for all nested types in a FHIRSchema
|
|
42
43
|
*/
|
|
43
|
-
export async function buildNestedTypes(fhirSchema,
|
|
44
|
+
export async function buildNestedTypes(fhirSchema, register, packageInfo) {
|
|
44
45
|
if (!fhirSchema.elements)
|
|
45
|
-
return
|
|
46
|
+
return undefined;
|
|
46
47
|
const nestedTypes = [];
|
|
47
48
|
const nestedElements = collectNestedElements(fhirSchema, [], fhirSchema.elements);
|
|
48
49
|
// Filter to only include elements that have sub-elements (actual nested types)
|
|
49
50
|
const actualNested = nestedElements.filter(([_, element]) => element.elements && Object.keys(element.elements).length > 0);
|
|
50
51
|
for (const [path, element] of actualNested) {
|
|
51
|
-
const identifier =
|
|
52
|
+
const identifier = mkNestedIdentifier(fhirSchema, path);
|
|
52
53
|
// Base is usually BackboneElement - ensure all nested types have a base
|
|
53
54
|
// biome-ignore lint/suspicious/noImplicitAnyLet: <explanation>
|
|
54
55
|
let base;
|
|
@@ -73,7 +74,7 @@ export async function buildNestedTypes(fhirSchema, manager, packageInfo) {
|
|
|
73
74
|
};
|
|
74
75
|
}
|
|
75
76
|
// Transform sub-elements into fields
|
|
76
|
-
const fields = await transformNestedElements(fhirSchema, path, element.elements,
|
|
77
|
+
const fields = await transformNestedElements(fhirSchema, path, element.elements, register, packageInfo);
|
|
77
78
|
const nestedType = {
|
|
78
79
|
identifier,
|
|
79
80
|
base, // Always include base
|
|
@@ -98,7 +99,7 @@ export function extractNestedDependencies(nestedTypes) {
|
|
|
98
99
|
deps.push(nested.base);
|
|
99
100
|
}
|
|
100
101
|
// Add field type dependencies
|
|
101
|
-
for (const field of Object.values(nested.fields)) {
|
|
102
|
+
for (const field of Object.values(nested.fields || {})) {
|
|
102
103
|
if ("type" in field && field.type) {
|
|
103
104
|
deps.push(field.type);
|
|
104
105
|
}
|
|
@@ -3,16 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Core transformation logic for converting FHIRSchema to TypeSchema format
|
|
5
5
|
*/
|
|
6
|
-
import type {
|
|
7
|
-
import type {
|
|
8
|
-
import type { TypeSchema, TypeSchemaField
|
|
9
|
-
import type {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
*/
|
|
13
|
-
export declare function transformElements(fhirSchema: FHIRSchema, parentPath: string[], elements: Record<string, FHIRSchemaElement>, manager: ReturnType<typeof CanonicalManager>, packageInfo?: PackageInfo): Promise<Record<string, TypeSchemaField>>;
|
|
14
|
-
/**
|
|
15
|
-
* Transform a single FHIRSchema to TypeSchema(s) with enhanced categorization
|
|
16
|
-
* Returns the main schema plus any binding schemas
|
|
17
|
-
*/
|
|
18
|
-
export declare function transformFHIRSchema(manager: ReturnType<typeof CanonicalManager>, fhirSchema: RichFHIRSchema): Promise<TypeSchema[]>;
|
|
6
|
+
import type { FHIRSchemaElement } from "@atomic-ehr/fhirschema";
|
|
7
|
+
import type { Register } from "@typeschema/register";
|
|
8
|
+
import type { RichFHIRSchema, TypeSchema, TypeSchemaField } from "@typeschema/types";
|
|
9
|
+
import type { PackageMeta } from "../types";
|
|
10
|
+
export declare function transformElements(fhirSchema: RichFHIRSchema, parentPath: string[], elements: Record<string, FHIRSchemaElement> | undefined, register: Register, packageInfo?: PackageMeta): Promise<Record<string, TypeSchemaField> | undefined>;
|
|
11
|
+
export declare function transformFHIRSchema(register: Register, fhirSchema: RichFHIRSchema): Promise<TypeSchema[]>;
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Main FHIRSchema to TypeSchema Transformer
|
|
3
|
+
*
|
|
4
|
+
* Core transformation logic for converting FHIRSchema to TypeSchema format
|
|
5
|
+
*/
|
|
2
6
|
import { transformProfile } from "../profile/processor";
|
|
3
7
|
import { collectBindingSchemas } from "./binding";
|
|
4
|
-
import { buildField,
|
|
5
|
-
import {
|
|
8
|
+
import { buildField, getElementHierarchy, isNestedElement, mergeElementHierarchy, mkNestedField, } from "./field-builder";
|
|
9
|
+
import { mkIdentifier } from "./identifier";
|
|
6
10
|
import { buildNestedTypes, extractNestedDependencies } from "./nested-types";
|
|
7
|
-
|
|
8
|
-
* Transform elements into fields
|
|
9
|
-
*/
|
|
10
|
-
export async function transformElements(fhirSchema, parentPath, elements, manager, packageInfo) {
|
|
11
|
+
export async function transformElements(fhirSchema, parentPath, elements, register, packageInfo) {
|
|
11
12
|
const fields = {};
|
|
13
|
+
if (!elements)
|
|
14
|
+
return undefined;
|
|
12
15
|
for (const [key, element] of Object.entries(elements)) {
|
|
13
16
|
const path = [...parentPath, key];
|
|
14
17
|
// Get element snapshot from hierarchy
|
|
15
|
-
const hierarchy = getElementHierarchy(fhirSchema, path,
|
|
18
|
+
const hierarchy = getElementHierarchy(fhirSchema, path, register);
|
|
16
19
|
const snapshot = hierarchy.length > 0 ? mergeElementHierarchy(hierarchy) : element;
|
|
17
20
|
if (isNestedElement(snapshot)) {
|
|
18
21
|
// Reference to nested type
|
|
19
|
-
fields[key] =
|
|
22
|
+
fields[key] = mkNestedField(fhirSchema, path, snapshot, register, packageInfo);
|
|
20
23
|
}
|
|
21
24
|
else {
|
|
22
25
|
// Regular field
|
|
23
|
-
fields[key] = await buildField(fhirSchema, path, snapshot,
|
|
26
|
+
fields[key] = await buildField(fhirSchema, path, snapshot, register, packageInfo);
|
|
24
27
|
}
|
|
25
28
|
}
|
|
26
29
|
return fields;
|
|
27
30
|
}
|
|
28
|
-
/**
|
|
29
|
-
* Extract dependencies from fields
|
|
30
|
-
*/
|
|
31
31
|
function extractFieldDependencies(fields) {
|
|
32
32
|
const deps = [];
|
|
33
33
|
for (const field of Object.values(fields)) {
|
|
@@ -40,9 +40,6 @@ function extractFieldDependencies(fields) {
|
|
|
40
40
|
}
|
|
41
41
|
return deps;
|
|
42
42
|
}
|
|
43
|
-
/**
|
|
44
|
-
* Remove duplicate dependencies
|
|
45
|
-
*/
|
|
46
43
|
function deduplicateDependencies(deps) {
|
|
47
44
|
const seen = new Set();
|
|
48
45
|
const unique = [];
|
|
@@ -62,13 +59,11 @@ function deduplicateDependencies(deps) {
|
|
|
62
59
|
*/
|
|
63
60
|
function isExtensionSchema(fhirSchema, _identifier) {
|
|
64
61
|
// Check if this is based on Extension
|
|
65
|
-
if (fhirSchema.base === "Extension" ||
|
|
66
|
-
fhirSchema.base === "http://hl7.org/fhir/StructureDefinition/Extension") {
|
|
62
|
+
if (fhirSchema.base === "Extension" || fhirSchema.base === "http://hl7.org/fhir/StructureDefinition/Extension") {
|
|
67
63
|
return true;
|
|
68
64
|
}
|
|
69
65
|
// Check if the URL indicates this is an extension
|
|
70
|
-
if (fhirSchema.url?.includes("/extension/") ||
|
|
71
|
-
fhirSchema.url?.includes("-extension")) {
|
|
66
|
+
if (fhirSchema.url?.includes("/extension/") || fhirSchema.url?.includes("-extension")) {
|
|
72
67
|
return true;
|
|
73
68
|
}
|
|
74
69
|
// Check if the name indicates this is an extension
|
|
@@ -84,12 +79,12 @@ function isExtensionSchema(fhirSchema, _identifier) {
|
|
|
84
79
|
/**
|
|
85
80
|
* Transform a ValueSet FHIRSchema to TypeSchemaValueSet
|
|
86
81
|
*/
|
|
87
|
-
async function transformValueSet(fhirSchema,
|
|
82
|
+
async function transformValueSet(fhirSchema, _register, _packageInfo) {
|
|
88
83
|
try {
|
|
89
|
-
const identifier =
|
|
90
|
-
identifier.kind = "value-set";
|
|
84
|
+
const identifier = mkIdentifier(fhirSchema);
|
|
85
|
+
identifier.kind = "value-set";
|
|
91
86
|
const valueSetSchema = {
|
|
92
|
-
identifier,
|
|
87
|
+
identifier: identifier,
|
|
93
88
|
description: fhirSchema.description,
|
|
94
89
|
};
|
|
95
90
|
// If there are elements that represent concepts
|
|
@@ -121,9 +116,9 @@ async function transformValueSet(fhirSchema, _manager, packageInfo) {
|
|
|
121
116
|
/**
|
|
122
117
|
* Transform an Extension FHIRSchema to TypeSchema with extension metadata
|
|
123
118
|
*/
|
|
124
|
-
async function transformExtension(fhirSchema,
|
|
119
|
+
async function transformExtension(fhirSchema, register, packageInfo) {
|
|
125
120
|
try {
|
|
126
|
-
const identifier =
|
|
121
|
+
const identifier = mkIdentifier(fhirSchema);
|
|
127
122
|
// Build base identifier if present
|
|
128
123
|
let base;
|
|
129
124
|
if (fhirSchema.base && fhirSchema.base !== "Extension") {
|
|
@@ -164,15 +159,15 @@ async function transformExtension(fhirSchema, manager, packageInfo) {
|
|
|
164
159
|
}
|
|
165
160
|
// Transform elements into fields if present
|
|
166
161
|
if (fhirSchema.elements) {
|
|
167
|
-
const fields = await transformElements(fhirSchema, [], fhirSchema.elements,
|
|
168
|
-
if (Object.keys(fields).length > 0) {
|
|
162
|
+
const fields = await transformElements(fhirSchema, [], fhirSchema.elements, register, packageInfo);
|
|
163
|
+
if (fields && Object.keys(fields).length > 0) {
|
|
169
164
|
extensionSchema.fields = fields;
|
|
170
165
|
extensionSchema.dependencies.push(...extractFieldDependencies(fields));
|
|
171
166
|
}
|
|
172
167
|
}
|
|
173
168
|
// Build nested types
|
|
174
|
-
const nestedTypes = await buildNestedTypes(fhirSchema,
|
|
175
|
-
if (nestedTypes.length > 0) {
|
|
169
|
+
const nestedTypes = await buildNestedTypes(fhirSchema, register, packageInfo);
|
|
170
|
+
if (nestedTypes && nestedTypes.length > 0) {
|
|
176
171
|
extensionSchema.nested = nestedTypes;
|
|
177
172
|
extensionSchema.dependencies.push(...extractNestedDependencies(nestedTypes));
|
|
178
173
|
}
|
|
@@ -187,25 +182,63 @@ async function transformExtension(fhirSchema, manager, packageInfo) {
|
|
|
187
182
|
return null;
|
|
188
183
|
}
|
|
189
184
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
185
|
+
function extractDependencies(identifier, base, fields, nestedTypes) {
|
|
186
|
+
const deps = [];
|
|
187
|
+
if (base)
|
|
188
|
+
deps.push(base);
|
|
189
|
+
if (fields)
|
|
190
|
+
deps.push(...extractFieldDependencies(fields));
|
|
191
|
+
if (nestedTypes)
|
|
192
|
+
deps.push(...extractNestedDependencies(nestedTypes));
|
|
193
|
+
const uniqDeps = {};
|
|
194
|
+
for (const dep of deps) {
|
|
195
|
+
if (dep.url === identifier.url)
|
|
196
|
+
continue;
|
|
197
|
+
uniqDeps[dep.url] = dep;
|
|
198
|
+
}
|
|
199
|
+
const result = Object.values(uniqDeps).sort((a, b) => a.name.localeCompare(b.name));
|
|
200
|
+
return result.length > 0 ? result : undefined;
|
|
201
|
+
}
|
|
202
|
+
async function transformResource(register, fhirSchema) {
|
|
203
|
+
const identifier = mkIdentifier(fhirSchema);
|
|
204
|
+
let base;
|
|
205
|
+
if (fhirSchema.base && fhirSchema.type !== "Element") {
|
|
206
|
+
const curl = register.ensureCanonicalUrl(fhirSchema.base);
|
|
207
|
+
const baseFS = register.resolveFS(curl);
|
|
208
|
+
base = mkIdentifier(baseFS);
|
|
209
|
+
}
|
|
210
|
+
const fields = await transformElements(fhirSchema, [], fhirSchema.elements, register, fhirSchema.package_meta);
|
|
211
|
+
const nested = await buildNestedTypes(fhirSchema, register, fhirSchema.package_meta);
|
|
212
|
+
const dependencies = extractDependencies(identifier, base, fields, nested);
|
|
213
|
+
const results = [
|
|
214
|
+
{
|
|
215
|
+
identifier,
|
|
216
|
+
base,
|
|
217
|
+
fields,
|
|
218
|
+
nested,
|
|
219
|
+
description: fhirSchema.description,
|
|
220
|
+
dependencies,
|
|
221
|
+
},
|
|
222
|
+
];
|
|
223
|
+
const bindingSchemas = await collectBindingSchemas(fhirSchema, register);
|
|
224
|
+
results.push(...bindingSchemas);
|
|
225
|
+
return results;
|
|
226
|
+
}
|
|
227
|
+
export async function transformFHIRSchema(register, fhirSchema) {
|
|
195
228
|
const results = [];
|
|
196
|
-
const identifier =
|
|
229
|
+
const identifier = mkIdentifier(fhirSchema);
|
|
197
230
|
// Handle profiles with specialized processor
|
|
198
231
|
if (identifier.kind === "profile") {
|
|
199
|
-
const profileSchema = await transformProfile(fhirSchema,
|
|
232
|
+
const profileSchema = await transformProfile(fhirSchema, register);
|
|
200
233
|
results.push(profileSchema);
|
|
201
234
|
// Collect binding schemas for profiles too
|
|
202
|
-
const bindingSchemas = await collectBindingSchemas(fhirSchema,
|
|
235
|
+
const bindingSchemas = await collectBindingSchemas(fhirSchema, register);
|
|
203
236
|
results.push(...bindingSchemas);
|
|
204
237
|
return results;
|
|
205
238
|
}
|
|
206
239
|
// Handle value sets specially
|
|
207
240
|
if (identifier.kind === "value-set" || fhirSchema.kind === "value-set") {
|
|
208
|
-
const valueSetSchema = await transformValueSet(fhirSchema,
|
|
241
|
+
const valueSetSchema = await transformValueSet(fhirSchema, register, fhirSchema.package_meta);
|
|
209
242
|
if (valueSetSchema) {
|
|
210
243
|
results.push(valueSetSchema);
|
|
211
244
|
}
|
|
@@ -213,114 +246,11 @@ export async function transformFHIRSchema(manager, fhirSchema) {
|
|
|
213
246
|
}
|
|
214
247
|
// Handle extensions specially
|
|
215
248
|
if (isExtensionSchema(fhirSchema, identifier)) {
|
|
216
|
-
const extensionSchema = await transformExtension(fhirSchema,
|
|
249
|
+
const extensionSchema = await transformExtension(fhirSchema, register, fhirSchema.package_meta);
|
|
217
250
|
if (extensionSchema) {
|
|
218
251
|
results.push(extensionSchema);
|
|
219
252
|
}
|
|
220
253
|
return results;
|
|
221
254
|
}
|
|
222
|
-
|
|
223
|
-
let base;
|
|
224
|
-
if (fhirSchema.base && fhirSchema.type !== "Element") {
|
|
225
|
-
// Create base identifier directly
|
|
226
|
-
const baseUrl = fhirSchema.base.includes("/")
|
|
227
|
-
? fhirSchema.base
|
|
228
|
-
: `http://hl7.org/fhir/StructureDefinition/${fhirSchema.base}`;
|
|
229
|
-
const baseName = fhirSchema.base.split("/").pop() || fhirSchema.base;
|
|
230
|
-
// Check if this is a known complex type by looking at common FHIR complex types
|
|
231
|
-
const complexTypes = new Set([
|
|
232
|
-
"Element",
|
|
233
|
-
"BackboneElement",
|
|
234
|
-
"Quantity",
|
|
235
|
-
"Duration",
|
|
236
|
-
"Distance",
|
|
237
|
-
"Count",
|
|
238
|
-
"Age",
|
|
239
|
-
"Address",
|
|
240
|
-
"Annotation",
|
|
241
|
-
"Attachment",
|
|
242
|
-
"CodeableConcept",
|
|
243
|
-
"Coding",
|
|
244
|
-
"ContactPoint",
|
|
245
|
-
"HumanName",
|
|
246
|
-
"Identifier",
|
|
247
|
-
"Period",
|
|
248
|
-
"Range",
|
|
249
|
-
"Ratio",
|
|
250
|
-
"Reference",
|
|
251
|
-
"Timing",
|
|
252
|
-
"Money",
|
|
253
|
-
"SampledData",
|
|
254
|
-
"Signature",
|
|
255
|
-
"ContactDetail",
|
|
256
|
-
"Contributor",
|
|
257
|
-
"DataRequirement",
|
|
258
|
-
"Expression",
|
|
259
|
-
"ParameterDefinition",
|
|
260
|
-
"RelatedArtifact",
|
|
261
|
-
"TriggerDefinition",
|
|
262
|
-
"UsageContext",
|
|
263
|
-
"Dosage",
|
|
264
|
-
"Meta",
|
|
265
|
-
"Extension",
|
|
266
|
-
]);
|
|
267
|
-
const kind = complexTypes.has(baseName) ? "complex-type" : "resource";
|
|
268
|
-
// For standard FHIR types, use the standard package even if no package info
|
|
269
|
-
const isStandardFhir = baseUrl.startsWith("http://hl7.org/fhir/");
|
|
270
|
-
base = {
|
|
271
|
-
kind: kind,
|
|
272
|
-
package: isStandardFhir
|
|
273
|
-
? "hl7.fhir.r4.core"
|
|
274
|
-
: fhirSchema.package_meta.name || "undefined",
|
|
275
|
-
version: isStandardFhir
|
|
276
|
-
? "4.0.1"
|
|
277
|
-
: fhirSchema.package_meta.version || "undefined",
|
|
278
|
-
name: baseName,
|
|
279
|
-
url: baseUrl,
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
|
-
// Initialize the main schema
|
|
283
|
-
const mainSchema = {
|
|
284
|
-
identifier,
|
|
285
|
-
dependencies: [],
|
|
286
|
-
};
|
|
287
|
-
// Collect dependencies in the same order as Clojure implementation
|
|
288
|
-
const allDependencies = [];
|
|
289
|
-
// Add base if present (first in dependencies)
|
|
290
|
-
if (base) {
|
|
291
|
-
mainSchema.base = base;
|
|
292
|
-
allDependencies.push(base);
|
|
293
|
-
}
|
|
294
|
-
// Add description if present
|
|
295
|
-
if (fhirSchema.description) {
|
|
296
|
-
mainSchema.description = fhirSchema.description;
|
|
297
|
-
}
|
|
298
|
-
// Transform elements into fields (for non-primitive types)
|
|
299
|
-
if (fhirSchema.kind !== "primitive-type" && fhirSchema.elements) {
|
|
300
|
-
const fields = await transformElements(fhirSchema, [], fhirSchema.elements, manager, fhirSchema.package_meta);
|
|
301
|
-
if (Object.keys(fields).length > 0) {
|
|
302
|
-
mainSchema.fields = fields;
|
|
303
|
-
}
|
|
304
|
-
// Extract field dependencies (types and bindings)
|
|
305
|
-
allDependencies.push(...extractFieldDependencies(fields));
|
|
306
|
-
// Build nested types
|
|
307
|
-
const nestedTypes = await buildNestedTypes(fhirSchema, manager, fhirSchema.package_meta);
|
|
308
|
-
if (nestedTypes.length > 0) {
|
|
309
|
-
mainSchema.nested = nestedTypes;
|
|
310
|
-
// Add nested type dependencies
|
|
311
|
-
allDependencies.push(...extractNestedDependencies(nestedTypes));
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
// Set all dependencies at once
|
|
315
|
-
mainSchema.dependencies = allDependencies;
|
|
316
|
-
// Deduplicate and sort dependencies
|
|
317
|
-
mainSchema.dependencies = deduplicateDependencies(mainSchema.dependencies);
|
|
318
|
-
// Remove self-reference from dependencies
|
|
319
|
-
mainSchema.dependencies = mainSchema.dependencies.filter((dep) => dep.url !== identifier.url);
|
|
320
|
-
// Add main schema to results
|
|
321
|
-
results.push(mainSchema);
|
|
322
|
-
// Collect and add binding schemas
|
|
323
|
-
const bindingSchemas = await collectBindingSchemas(fhirSchema, manager, fhirSchema.package_meta);
|
|
324
|
-
results.push(...bindingSchemas);
|
|
325
|
-
return results;
|
|
255
|
+
return await transformResource(register, fhirSchema);
|
|
326
256
|
}
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
* Generates TypeSchema documents from FHIR packages using fhrischema.
|
|
5
5
|
* Provides high-level API for converting FHIR Structure Definitions to TypeSchema format.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import type { FHIRSchema, StructureDefinition } from "@atomic-ehr/fhirschema";
|
|
8
8
|
import type { TypeSchemaConfig } from "@root/config";
|
|
9
|
-
import type {
|
|
9
|
+
import type { Register } from "@typeschema/register";
|
|
10
|
+
import type { PackageMeta, TypeSchema, TypeschemaGeneratorOptions } from "./types";
|
|
10
11
|
/**
|
|
11
12
|
* TypeSchema Generator class
|
|
12
13
|
*
|
|
@@ -21,14 +22,10 @@ export declare class TypeSchemaGenerator {
|
|
|
21
22
|
private logger;
|
|
22
23
|
constructor(options?: TypeschemaGeneratorOptions, cacheConfig?: TypeSchemaConfig);
|
|
23
24
|
private initializeCache;
|
|
24
|
-
|
|
25
|
-
structureDefinitions: StructureDefinition[];
|
|
26
|
-
valueSets: any[];
|
|
27
|
-
}>;
|
|
25
|
+
registerFromPackageMetas(packageMetas: PackageMeta[]): Promise<Register>;
|
|
28
26
|
generateFhirSchemas(structureDefinitions: StructureDefinition[]): FHIRSchema[];
|
|
29
|
-
generateValueSetSchemas(valueSets: any[], packageInfo:
|
|
27
|
+
generateValueSetSchemas(valueSets: any[], packageInfo: PackageMeta): Promise<TypeSchema[]>;
|
|
30
28
|
generateFromPackage(packageName: string, packageVersion?: string): Promise<TypeSchema[]>;
|
|
31
|
-
generateResourceTypeSchemas(fhirSchemas: RichFHIRSchema[]): Promise<TypeSchema[]>;
|
|
32
29
|
/**
|
|
33
30
|
* Apply treeshaking to StructureDefinitions before FHIR schema transformation
|
|
34
31
|
* This is more efficient and includes smart reference handling
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
import { CanonicalManager } from "@atomic-ehr/fhir-canonical-manager";
|
|
8
8
|
import * as fhirschema from "@atomic-ehr/fhirschema";
|
|
9
9
|
import { createLogger } from "@root/utils/codegen-logger";
|
|
10
|
+
import { registerFromManager } from "@typeschema/register";
|
|
10
11
|
import { TypeSchemaCache } from "./cache";
|
|
11
12
|
import { transformFHIRSchema } from "./core/transformer";
|
|
12
|
-
import { enrichFHIRSchema } from "./types";
|
|
13
13
|
import { transformValueSet } from "./value-set/processor";
|
|
14
14
|
/**
|
|
15
15
|
* TypeSchema Generator class
|
|
@@ -25,8 +25,7 @@ export class TypeSchemaGenerator {
|
|
|
25
25
|
logger;
|
|
26
26
|
constructor(options = {}, cacheConfig) {
|
|
27
27
|
this.options = { verbose: false, ...options };
|
|
28
|
-
this.manager = options.manager ||
|
|
29
|
-
CanonicalManager({ packages: [], workingDir: "tmp/fhir" });
|
|
28
|
+
this.manager = options.manager || CanonicalManager({ packages: [], workingDir: "tmp/fhir" });
|
|
30
29
|
this.cacheConfig = cacheConfig;
|
|
31
30
|
this.logger =
|
|
32
31
|
options.logger ||
|
|
@@ -41,14 +40,11 @@ export class TypeSchemaGenerator {
|
|
|
41
40
|
await this.cache.initialize();
|
|
42
41
|
}
|
|
43
42
|
}
|
|
44
|
-
async
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const valueSets = allResources.filter((resource) => resource.resourceType === "ValueSet");
|
|
50
|
-
this.logger.info(`Found ${structureDefinitions.length} StructureDefinitions and ${valueSets.length} ValueSets in package`);
|
|
51
|
-
return { structureDefinitions, valueSets };
|
|
43
|
+
async registerFromPackageMetas(packageMetas) {
|
|
44
|
+
const packageNames = packageMetas.map((meta) => `${meta.name}${meta.version}`);
|
|
45
|
+
this.logger.step(`Loading FHIR packages: ${packageNames.join(", ")}`);
|
|
46
|
+
await this.manager.init();
|
|
47
|
+
return registerFromManager(this.manager);
|
|
52
48
|
}
|
|
53
49
|
generateFhirSchemas(structureDefinitions) {
|
|
54
50
|
this.logger.progress(`Converting ${structureDefinitions.length} StructureDefinitions to FHIRSchemas`);
|
|
@@ -113,11 +109,11 @@ export class TypeSchemaGenerator {
|
|
|
113
109
|
name: packageName,
|
|
114
110
|
version: packageVersion || "latest",
|
|
115
111
|
};
|
|
116
|
-
const
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
112
|
+
const register = await this.registerFromPackageMetas([packageInfo]);
|
|
113
|
+
const allSchemas = [
|
|
114
|
+
...(await Promise.all(register.allFS().map(async (fs) => await transformFHIRSchema(register, fs)))).flat(),
|
|
115
|
+
...(await this.generateValueSetSchemas(register.allVS(), packageInfo)),
|
|
116
|
+
];
|
|
121
117
|
if (this.cache) {
|
|
122
118
|
for (const schema of allSchemas) {
|
|
123
119
|
await this.cache.set(schema);
|
|
@@ -125,14 +121,20 @@ export class TypeSchemaGenerator {
|
|
|
125
121
|
}
|
|
126
122
|
return allSchemas;
|
|
127
123
|
}
|
|
128
|
-
async generateResourceTypeSchemas(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
124
|
+
// async generateResourceTypeSchemas(
|
|
125
|
+
// fhirSchemas: RichFHIRSchema[],
|
|
126
|
+
// ): Promise<TypeSchema[]> {
|
|
127
|
+
// this.logger.info(
|
|
128
|
+
// `Transforming ${fhirSchemas.length} FHIR schemas to Type Schema`,
|
|
129
|
+
// );
|
|
130
|
+
// const typeSchemas: TypeSchema[] = [];
|
|
131
|
+
// for (const fhirSchema of fhirSchemas) {
|
|
132
|
+
// typeSchemas.push(
|
|
133
|
+
// ...(await transformFHIRSchema(this.manager, fhirSchema)),
|
|
134
|
+
// );
|
|
135
|
+
// }
|
|
136
|
+
// return typeSchemas;
|
|
137
|
+
// }
|
|
136
138
|
/**
|
|
137
139
|
* Apply treeshaking to StructureDefinitions before FHIR schema transformation
|
|
138
140
|
* This is more efficient and includes smart reference handling
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* TypeSchema Parser
|
|
3
|
+
*
|
|
4
|
+
* Parser for reading and manipulating TypeSchema documents from various formats.
|
|
5
|
+
* Supports both NDJSON and JSON formats with automatic format detection.
|
|
6
|
+
*/
|
|
7
|
+
import type { Identifier, TypeSchema, TypeschemaParserOptions } from "@typeschema/types";
|
|
3
8
|
/**
|
|
4
9
|
* TypeSchema Parser class
|
|
5
10
|
*
|
|
@@ -44,11 +49,9 @@ export declare class TypeSchemaParser {
|
|
|
44
49
|
/**
|
|
45
50
|
* Get all dependencies from a schema
|
|
46
51
|
*/
|
|
47
|
-
getDependencies(schema: TypeSchema): Identifier[];
|
|
48
52
|
/**
|
|
49
53
|
* Resolve schema dependencies
|
|
50
54
|
*/
|
|
51
|
-
resolveDependencies(schemas: TypeSchema[], targetSchema: TypeSchema): TypeSchema[];
|
|
52
55
|
/**
|
|
53
56
|
* Detect format from content or filename
|
|
54
57
|
*/
|
|
@@ -73,10 +76,6 @@ export declare class TypeSchemaParser {
|
|
|
73
76
|
* Check if identifier matches criteria
|
|
74
77
|
*/
|
|
75
78
|
private matchesIdentifier;
|
|
76
|
-
/**
|
|
77
|
-
* Remove duplicate dependencies
|
|
78
|
-
*/
|
|
79
|
-
private deduplicateDependencies;
|
|
80
79
|
}
|
|
81
80
|
/**
|
|
82
81
|
* Convenience function to parse TypeSchema from file
|