@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
|
@@ -231,16 +231,12 @@ export async function withSpinner(promise, options) {
|
|
|
231
231
|
}).start();
|
|
232
232
|
try {
|
|
233
233
|
const result = await promise;
|
|
234
|
-
const successMessage = typeof options.success === "function"
|
|
235
|
-
? options.success(result)
|
|
236
|
-
: options.success || options.start;
|
|
234
|
+
const successMessage = typeof options.success === "function" ? options.success(result) : options.success || options.start;
|
|
237
235
|
spinner.succeed(successMessage);
|
|
238
236
|
return result;
|
|
239
237
|
}
|
|
240
238
|
catch (error) {
|
|
241
|
-
const failMessage = typeof options.fail === "function"
|
|
242
|
-
? options.fail(error)
|
|
243
|
-
: options.fail || `Failed: ${options.start}`;
|
|
239
|
+
const failMessage = typeof options.fail === "function" ? options.fail(error) : options.fail || `Failed: ${options.start}`;
|
|
244
240
|
spinner.fail(failMessage);
|
|
245
241
|
throw error;
|
|
246
242
|
}
|
package/dist/config.js
CHANGED
|
@@ -393,11 +393,7 @@ export class ConfigValidator {
|
|
|
393
393
|
});
|
|
394
394
|
}
|
|
395
395
|
// Validate boolean fields
|
|
396
|
-
const booleanFields = [
|
|
397
|
-
"includeConstraints",
|
|
398
|
-
"includeDocumentation",
|
|
399
|
-
"strictMode",
|
|
400
|
-
];
|
|
396
|
+
const booleanFields = ["includeConstraints", "includeDocumentation", "strictMode"];
|
|
401
397
|
for (const field of booleanFields) {
|
|
402
398
|
if (cfg[field] !== undefined && typeof cfg[field] !== "boolean") {
|
|
403
399
|
errors.push({
|
|
@@ -421,12 +417,7 @@ export class ConfigValidator {
|
|
|
421
417
|
}
|
|
422
418
|
const cfg = config;
|
|
423
419
|
// Validate boolean fields
|
|
424
|
-
const booleanFields = [
|
|
425
|
-
"enablePersistence",
|
|
426
|
-
"validateCached",
|
|
427
|
-
"forceRegenerate",
|
|
428
|
-
"shareCache",
|
|
429
|
-
];
|
|
420
|
+
const booleanFields = ["enablePersistence", "validateCached", "forceRegenerate", "shareCache"];
|
|
430
421
|
for (const field of booleanFields) {
|
|
431
422
|
if (cfg[field] !== undefined && typeof cfg[field] !== "boolean") {
|
|
432
423
|
errors.push({
|
|
@@ -469,8 +460,7 @@ export class ConfigValidator {
|
|
|
469
460
|
else {
|
|
470
461
|
const profiles = cfg.profiles;
|
|
471
462
|
// Validate autoDetect
|
|
472
|
-
if (profiles.autoDetect !== undefined &&
|
|
473
|
-
typeof profiles.autoDetect !== "boolean") {
|
|
463
|
+
if (profiles.autoDetect !== undefined && typeof profiles.autoDetect !== "boolean") {
|
|
474
464
|
errors.push({
|
|
475
465
|
path: "typeSchema.profiles.autoDetect",
|
|
476
466
|
message: "autoDetect must be a boolean",
|
|
@@ -517,9 +507,7 @@ export class ConfigLoader {
|
|
|
517
507
|
}
|
|
518
508
|
const validation = this.validator.validate(config);
|
|
519
509
|
if (!validation.valid) {
|
|
520
|
-
const errorMessages = validation.errors
|
|
521
|
-
.map((e) => `${e.path}: ${e.message}`)
|
|
522
|
-
.join("\n");
|
|
510
|
+
const errorMessages = validation.errors.map((e) => `${e.path}: ${e.message}`).join("\n");
|
|
523
511
|
throw new Error(`Configuration validation failed:\n${errorMessages}`);
|
|
524
512
|
}
|
|
525
513
|
// Merge with defaults
|
package/dist/logger.js
CHANGED
|
@@ -23,9 +23,7 @@ export class ConsoleOutput {
|
|
|
23
23
|
this.useStderr = useStderr;
|
|
24
24
|
}
|
|
25
25
|
write(entry, formatted) {
|
|
26
|
-
const output = this.useStderr || entry.level >= LogLevel.WARN
|
|
27
|
-
? console.error
|
|
28
|
-
: console.log;
|
|
26
|
+
const output = this.useStderr || entry.level >= LogLevel.WARN ? console.error : console.log;
|
|
29
27
|
output(formatted);
|
|
30
28
|
}
|
|
31
29
|
}
|
|
@@ -229,9 +227,7 @@ export class Logger {
|
|
|
229
227
|
child(component, context) {
|
|
230
228
|
const childLogger = new Logger({
|
|
231
229
|
...this.config,
|
|
232
|
-
component: this.config.component
|
|
233
|
-
? `${this.config.component}.${component}`
|
|
234
|
-
: component,
|
|
230
|
+
component: this.config.component ? `${this.config.component}.${component}` : component,
|
|
235
231
|
});
|
|
236
232
|
// If context is provided, wrap all logging methods to include it
|
|
237
233
|
if (context) {
|
|
@@ -268,14 +264,9 @@ export function createLoggerFromConfig(config) {
|
|
|
268
264
|
: config?.verbose
|
|
269
265
|
? LogLevel.INFO
|
|
270
266
|
: config?.logLevel
|
|
271
|
-
? (LogLevel[config.logLevel.toUpperCase()] ??
|
|
272
|
-
LogLevel.INFO)
|
|
267
|
+
? (LogLevel[config.logLevel.toUpperCase()] ?? LogLevel.INFO)
|
|
273
268
|
: LogLevel.INFO;
|
|
274
|
-
const format = config?.logFormat === "json"
|
|
275
|
-
? "json"
|
|
276
|
-
: config?.logFormat === "compact"
|
|
277
|
-
? "compact"
|
|
278
|
-
: "pretty";
|
|
269
|
+
const format = config?.logFormat === "json" ? "json" : config?.logFormat === "compact" ? "compact" : "pretty";
|
|
279
270
|
const outputs = [new ConsoleOutput()];
|
|
280
271
|
if (config?.logFile) {
|
|
281
272
|
outputs.push(new FileOutput(config.logFile));
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Caching system for TypeSchema documents with both in-memory and persistent file-based storage.
|
|
5
5
|
*/
|
|
6
6
|
import type { TypeSchemaConfig } from "@root/config";
|
|
7
|
-
import type {
|
|
7
|
+
import type { Identifier, TypeSchema } from "@typeschema/types";
|
|
8
8
|
/**
|
|
9
9
|
* TypeSchema Cache with optional persistent storage
|
|
10
10
|
*/
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* Functions for processing value set bindings and generating enums
|
|
5
5
|
*/
|
|
6
6
|
import type { CanonicalManager } from "@atomic-ehr/fhir-canonical-manager";
|
|
7
|
-
import type {
|
|
8
|
-
import type {
|
|
7
|
+
import type { FHIRSchemaElement } from "@atomic-ehr/fhirschema";
|
|
8
|
+
import type { PackageMeta, RichFHIRSchema, TypeSchemaForBinding } from "../types";
|
|
9
9
|
/**
|
|
10
10
|
* Extract concepts from a ValueSet
|
|
11
11
|
*/
|
|
@@ -18,11 +18,8 @@ export declare function extractValueSetConcepts(valueSetUrl: string, manager: Re
|
|
|
18
18
|
* Build enum values from binding if applicable
|
|
19
19
|
*/
|
|
20
20
|
export declare function buildEnum(element: FHIRSchemaElement, manager: ReturnType<typeof CanonicalManager>): Promise<string[] | undefined>;
|
|
21
|
-
|
|
22
|
-
* Generate a binding TypeSchema
|
|
23
|
-
*/
|
|
24
|
-
export declare function generateBindingSchema(fhirSchema: FHIRSchema, path: string[], element: FHIRSchemaElement, manager: ReturnType<typeof CanonicalManager>, packageInfo?: PackageInfo): Promise<TypeSchemaForBinding | undefined>;
|
|
21
|
+
export declare function generateBindingSchema(fhirSchema: RichFHIRSchema, path: string[], element: FHIRSchemaElement, manager: ReturnType<typeof CanonicalManager>, packageInfo?: PackageMeta): Promise<TypeSchemaForBinding | undefined>;
|
|
25
22
|
/**
|
|
26
23
|
* Collect all binding schemas from a FHIRSchema
|
|
27
24
|
*/
|
|
28
|
-
export declare function collectBindingSchemas(fhirSchema:
|
|
25
|
+
export declare function collectBindingSchemas(fhirSchema: RichFHIRSchema, manager: ReturnType<typeof CanonicalManager>): Promise<TypeSchemaForBinding[]>;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
/**
|
|
3
2
|
* Binding and Enum Handling
|
|
4
3
|
*
|
|
5
4
|
* Functions for processing value set bindings and generating enums
|
|
6
5
|
*/
|
|
7
6
|
import { buildFieldType } from "./field-builder";
|
|
8
|
-
import {
|
|
7
|
+
import { dropVersionFromUrl, mkBindingIdentifier, mkValueSetIdentifier } from "./identifier";
|
|
9
8
|
/**
|
|
10
9
|
* Extract concepts from a ValueSet
|
|
11
10
|
*/
|
|
@@ -86,10 +85,8 @@ export async function buildEnum(element, manager) {
|
|
|
86
85
|
// 3. Preferred bindings on code types (for common usage patterns)
|
|
87
86
|
// 4. Extensible bindings on Coding types (broader coverage)
|
|
88
87
|
const shouldGenerateEnum = strength === "required" ||
|
|
89
|
-
(strength === "extensible" &&
|
|
90
|
-
|
|
91
|
-
(strength === "preferred" &&
|
|
92
|
-
(element.type === "code" || element.type === "Coding"));
|
|
88
|
+
(strength === "extensible" && (element.type === "code" || element.type === "Coding")) ||
|
|
89
|
+
(strength === "preferred" && (element.type === "code" || element.type === "Coding"));
|
|
93
90
|
if (!shouldGenerateEnum) {
|
|
94
91
|
return undefined;
|
|
95
92
|
}
|
|
@@ -115,39 +112,32 @@ export async function buildEnum(element, manager) {
|
|
|
115
112
|
return undefined;
|
|
116
113
|
}
|
|
117
114
|
}
|
|
118
|
-
/**
|
|
119
|
-
* Generate a binding TypeSchema
|
|
120
|
-
*/
|
|
121
115
|
export async function generateBindingSchema(fhirSchema, path, element, manager, packageInfo) {
|
|
122
116
|
if (!element.binding?.valueSet)
|
|
123
117
|
return undefined;
|
|
124
|
-
const identifier =
|
|
118
|
+
const identifier = mkBindingIdentifier(fhirSchema, path, element.binding.bindingName, packageInfo);
|
|
125
119
|
const fieldType = buildFieldType(fhirSchema, path, element, manager, packageInfo);
|
|
126
|
-
const valueSetIdentifier =
|
|
127
|
-
const
|
|
120
|
+
const valueSetIdentifier = mkValueSetIdentifier(element.binding.valueSet, undefined, packageInfo);
|
|
121
|
+
const dependencies = [];
|
|
122
|
+
if (fieldType) {
|
|
123
|
+
dependencies.push(fieldType);
|
|
124
|
+
}
|
|
125
|
+
dependencies.push(valueSetIdentifier);
|
|
126
|
+
const enumValues = await buildEnum(element, manager);
|
|
127
|
+
return {
|
|
128
128
|
identifier,
|
|
129
129
|
type: fieldType,
|
|
130
130
|
valueset: valueSetIdentifier,
|
|
131
131
|
strength: element.binding.strength,
|
|
132
|
-
|
|
132
|
+
enum: enumValues,
|
|
133
|
+
dependencies,
|
|
133
134
|
};
|
|
134
|
-
// Add dependencies in specific order: type first, then value set
|
|
135
|
-
if (fieldType) {
|
|
136
|
-
binding.dependencies.push(fieldType);
|
|
137
|
-
}
|
|
138
|
-
binding.dependencies.push(valueSetIdentifier);
|
|
139
|
-
// Add enum if applicable
|
|
140
|
-
const enumValues = await buildEnum(element, manager);
|
|
141
|
-
if (enumValues) {
|
|
142
|
-
binding.enum = enumValues;
|
|
143
|
-
}
|
|
144
|
-
// Don't sort dependencies - keep them in the order: type, then value set
|
|
145
|
-
return binding;
|
|
146
135
|
}
|
|
147
136
|
/**
|
|
148
137
|
* Collect all binding schemas from a FHIRSchema
|
|
149
138
|
*/
|
|
150
|
-
export async function collectBindingSchemas(fhirSchema, manager
|
|
139
|
+
export async function collectBindingSchemas(fhirSchema, manager) {
|
|
140
|
+
const packageInfo = fhirSchema.package_meta;
|
|
151
141
|
const bindings = [];
|
|
152
142
|
const processedPaths = new Set();
|
|
153
143
|
// Recursive function to process elements
|
|
@@ -166,19 +156,15 @@ export async function collectBindingSchemas(fhirSchema, manager, packageInfo) {
|
|
|
166
156
|
bindings.push(binding);
|
|
167
157
|
}
|
|
168
158
|
}
|
|
169
|
-
// Process nested elements
|
|
170
159
|
if (element.elements) {
|
|
171
160
|
await processElement(element.elements, path);
|
|
172
161
|
}
|
|
173
162
|
}
|
|
174
163
|
}
|
|
175
|
-
// Start processing from root elements
|
|
176
164
|
if (fhirSchema.elements) {
|
|
177
165
|
await processElement(fhirSchema.elements, []);
|
|
178
166
|
}
|
|
179
|
-
// Sort bindings by identifier name for consistent output
|
|
180
167
|
bindings.sort((a, b) => a.identifier.name.localeCompare(b.identifier.name));
|
|
181
|
-
// Remove duplicates (same identifier URL)
|
|
182
168
|
const uniqueBindings = [];
|
|
183
169
|
const seenUrls = new Set();
|
|
184
170
|
for (const binding of bindings) {
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { CanonicalManager } from "@atomic-ehr/fhir-canonical-manager";
|
|
7
7
|
import type { FHIRSchema, FHIRSchemaElement } from "@atomic-ehr/fhirschema";
|
|
8
|
-
import type {
|
|
8
|
+
import type { Register } from "@root/typeschema/register";
|
|
9
|
+
import type { Identifier, PackageMeta, RichFHIRSchema, TypeSchemaField } from "../types";
|
|
9
10
|
/**
|
|
10
11
|
* Get the full element hierarchy for a given path
|
|
11
12
|
*/
|
|
@@ -22,23 +23,14 @@ export declare function isRequired(fhirSchema: FHIRSchema, path: string[], _mana
|
|
|
22
23
|
* Check if a field is excluded
|
|
23
24
|
*/
|
|
24
25
|
export declare function isExcluded(fhirSchema: FHIRSchema, path: string[], _manager: ReturnType<typeof CanonicalManager>): boolean;
|
|
25
|
-
|
|
26
|
-
* Build reference array from element refers
|
|
27
|
-
*/
|
|
28
|
-
export declare function buildReferences(element: FHIRSchemaElement, manager: ReturnType<typeof CanonicalManager>, packageInfo?: PackageInfo): Promise<Identifier[] | undefined>;
|
|
26
|
+
export declare const buildReferences: (element: FHIRSchemaElement, register: Register, _packageInfo?: PackageMeta) => Identifier[] | undefined;
|
|
29
27
|
/**
|
|
30
28
|
* Build field type identifier
|
|
31
29
|
*/
|
|
32
|
-
export declare function buildFieldType(fhirSchema:
|
|
33
|
-
|
|
34
|
-
* Build a TypeSchema field from a FHIRSchema element
|
|
35
|
-
*/
|
|
36
|
-
export declare function buildField(fhirSchema: FHIRSchema, path: string[], element: FHIRSchemaElement, manager: ReturnType<typeof CanonicalManager>, packageInfo?: PackageInfo): Promise<TypeSchemaField>;
|
|
30
|
+
export declare function buildFieldType(fhirSchema: RichFHIRSchema, _path: string[], element: FHIRSchemaElement, _manager: ReturnType<typeof CanonicalManager>, packageInfo?: PackageMeta): Identifier | undefined;
|
|
31
|
+
export declare const buildField: (fhirSchema: RichFHIRSchema, path: string[], element: FHIRSchemaElement, register: Register, packageInfo?: PackageMeta) => TypeSchemaField;
|
|
37
32
|
/**
|
|
38
33
|
* Check if an element represents a nested type (BackboneElement)
|
|
39
34
|
*/
|
|
40
35
|
export declare function isNestedElement(element: FHIRSchemaElement): boolean;
|
|
41
|
-
|
|
42
|
-
* Build a field reference to a nested type
|
|
43
|
-
*/
|
|
44
|
-
export declare function buildNestedField(fhirSchema: FHIRSchema, path: string[], element: FHIRSchemaElement, manager: ReturnType<typeof CanonicalManager>, packageInfo?: PackageInfo): TypeSchemaField;
|
|
36
|
+
export declare function mkNestedField(fhirSchema: RichFHIRSchema, path: string[], element: FHIRSchemaElement, manager: ReturnType<typeof CanonicalManager>, _packageInfo?: PackageMeta): TypeSchemaField;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Field Building Utilities
|
|
3
|
+
*
|
|
4
|
+
* Functions for transforming FHIRSchema elements into TypeSchema fields
|
|
5
|
+
*/
|
|
2
6
|
import { buildEnum } from "./binding";
|
|
3
|
-
import {
|
|
7
|
+
import { mkBindingIdentifier, mkIdentifier, mkNestedIdentifier } from "./identifier";
|
|
4
8
|
/**
|
|
5
9
|
* Get the full element hierarchy for a given path
|
|
6
10
|
*/
|
|
@@ -60,8 +64,7 @@ export function mergeElementHierarchy(hierarchy) {
|
|
|
60
64
|
// Override with specific properties from the first element
|
|
61
65
|
for (const prop of ["choices", "binding", "refers", "elementReference"]) {
|
|
62
66
|
// @ts-ignore
|
|
63
|
-
if (hierarchy[0] &&
|
|
64
|
-
hierarchy[0][prop] !== undefined) {
|
|
67
|
+
if (hierarchy[0] && hierarchy[0][prop] !== undefined) {
|
|
65
68
|
// @ts-ignore
|
|
66
69
|
snapshot[prop] = hierarchy[0][prop];
|
|
67
70
|
}
|
|
@@ -88,9 +91,7 @@ export function isRequired(fhirSchema, path, _manager) {
|
|
|
88
91
|
return true;
|
|
89
92
|
}
|
|
90
93
|
// Also check at root level
|
|
91
|
-
if (parentPath.length === 0 &&
|
|
92
|
-
fieldName &&
|
|
93
|
-
fhirSchema.required?.includes(fieldName)) {
|
|
94
|
+
if (parentPath.length === 0 && fieldName && fhirSchema.required?.includes(fieldName)) {
|
|
94
95
|
return true;
|
|
95
96
|
}
|
|
96
97
|
return false;
|
|
@@ -115,32 +116,20 @@ export function isExcluded(fhirSchema, path, _manager) {
|
|
|
115
116
|
return true;
|
|
116
117
|
}
|
|
117
118
|
// Also check at root level
|
|
118
|
-
if (parentPath.length === 0 &&
|
|
119
|
-
fieldName &&
|
|
120
|
-
fhirSchema.excluded?.includes(fieldName)) {
|
|
119
|
+
if (parentPath.length === 0 && fieldName && fhirSchema.excluded?.includes(fieldName)) {
|
|
121
120
|
return true;
|
|
122
121
|
}
|
|
123
122
|
return false;
|
|
124
123
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
*/
|
|
128
|
-
export async function buildReferences(element, manager, packageInfo) {
|
|
129
|
-
if (!element.refers || element.refers.length === 0) {
|
|
124
|
+
export const buildReferences = (element, register, _packageInfo) => {
|
|
125
|
+
if (!element.refers)
|
|
130
126
|
return undefined;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
references.push(buildSchemaIdentifier(resource));
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
catch { }
|
|
141
|
-
}
|
|
142
|
-
return references;
|
|
143
|
-
}
|
|
127
|
+
return element.refers.map((ref) => {
|
|
128
|
+
const curl = register.ensureCanonicalUrl(ref);
|
|
129
|
+
const fs = register.resolveFS(curl);
|
|
130
|
+
return mkIdentifier(fs);
|
|
131
|
+
});
|
|
132
|
+
};
|
|
144
133
|
/**
|
|
145
134
|
* Build field type identifier
|
|
146
135
|
*/
|
|
@@ -153,7 +142,7 @@ export function buildFieldType(fhirSchema, _path, element, _manager, packageInfo
|
|
|
153
142
|
.filter((p) => p !== "elements"); // Remove 'elements' which is just a container
|
|
154
143
|
// Only return nested identifier if we have a non-empty path
|
|
155
144
|
if (refPath.length > 0) {
|
|
156
|
-
return
|
|
145
|
+
return mkNestedIdentifier(fhirSchema, refPath);
|
|
157
146
|
}
|
|
158
147
|
}
|
|
159
148
|
// Handle normal type
|
|
@@ -162,15 +151,11 @@ export function buildFieldType(fhirSchema, _path, element, _manager, packageInfo
|
|
|
162
151
|
? element.type
|
|
163
152
|
: `http://hl7.org/fhir/StructureDefinition/${element.type}`;
|
|
164
153
|
// Always create a type identifier, even if we can't resolve
|
|
165
|
-
const kind = element.type.match(/^[a-z]/)
|
|
166
|
-
? "primitive-type"
|
|
167
|
-
: "complex-type";
|
|
154
|
+
const kind = element.type.match(/^[a-z]/) ? "primitive-type" : "complex-type";
|
|
168
155
|
const isStandardFhir = typeUrl.startsWith("http://hl7.org/fhir/");
|
|
169
156
|
return {
|
|
170
157
|
kind: kind,
|
|
171
|
-
package: isStandardFhir
|
|
172
|
-
? "hl7.fhir.r4.core"
|
|
173
|
-
: packageInfo?.name || "undefined",
|
|
158
|
+
package: isStandardFhir ? "hl7.fhir.r4.core" : packageInfo?.name || "undefined",
|
|
174
159
|
version: isStandardFhir ? "4.0.1" : packageInfo?.version || "undefined",
|
|
175
160
|
name: element.type,
|
|
176
161
|
url: typeUrl,
|
|
@@ -178,55 +163,29 @@ export function buildFieldType(fhirSchema, _path, element, _manager, packageInfo
|
|
|
178
163
|
}
|
|
179
164
|
return undefined;
|
|
180
165
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
export async function buildField(fhirSchema, path, element, manager, packageInfo) {
|
|
185
|
-
const field = {
|
|
186
|
-
array: element.array || false,
|
|
187
|
-
required: isRequired(fhirSchema, path, manager),
|
|
188
|
-
excluded: isExcluded(fhirSchema, path, manager),
|
|
189
|
-
};
|
|
190
|
-
// Add type if present
|
|
191
|
-
const type = buildFieldType(fhirSchema, path, element, manager, packageInfo);
|
|
192
|
-
if (type) {
|
|
193
|
-
field.type = type;
|
|
194
|
-
}
|
|
195
|
-
// Add cardinality
|
|
196
|
-
if (element.min !== undefined)
|
|
197
|
-
field.min = element.min;
|
|
198
|
-
if (element.max !== undefined)
|
|
199
|
-
field.max = element.max;
|
|
200
|
-
// Add choices
|
|
201
|
-
// @ts-ignore
|
|
202
|
-
if (element.choices)
|
|
203
|
-
field.choices = element.choices;
|
|
204
|
-
// @ts-ignore
|
|
205
|
-
if (element.choiceOf)
|
|
206
|
-
field.choiceOf = element.choiceOf;
|
|
207
|
-
// Add binding if present
|
|
166
|
+
export const buildField = (fhirSchema, path, element, register, packageInfo) => {
|
|
167
|
+
let binding;
|
|
168
|
+
let _enumValues;
|
|
208
169
|
if (element.binding) {
|
|
209
|
-
|
|
210
|
-
// Add enum for required bindings on code types
|
|
170
|
+
binding = mkBindingIdentifier(fhirSchema, path, element.binding.bindingName, packageInfo);
|
|
211
171
|
if (element.binding.strength === "required" && element.type === "code") {
|
|
212
|
-
|
|
213
|
-
if (enumValues && enumValues.length > 0) {
|
|
214
|
-
field.enum = enumValues;
|
|
215
|
-
}
|
|
172
|
+
_enumValues = buildEnum(element, register);
|
|
216
173
|
}
|
|
217
174
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
175
|
+
return {
|
|
176
|
+
type: buildFieldType(fhirSchema, path, element, register, packageInfo),
|
|
177
|
+
required: isRequired(fhirSchema, path, register),
|
|
178
|
+
excluded: isExcluded(fhirSchema, path, register),
|
|
179
|
+
reference: buildReferences(element, register, packageInfo),
|
|
180
|
+
array: element.array || false,
|
|
181
|
+
min: element.min,
|
|
182
|
+
max: element.max,
|
|
183
|
+
choices: element.choices,
|
|
184
|
+
choiceOf: element.choiceOf,
|
|
185
|
+
binding: binding,
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
function _removeEmptyValues(obj) {
|
|
230
189
|
const result = {};
|
|
231
190
|
for (const [key, value] of Object.entries(obj)) {
|
|
232
191
|
if (value !== undefined && value !== null) {
|
|
@@ -242,16 +201,11 @@ function removeEmptyValues(obj) {
|
|
|
242
201
|
* Check if an element represents a nested type (BackboneElement)
|
|
243
202
|
*/
|
|
244
203
|
export function isNestedElement(element) {
|
|
245
|
-
return (element.type === "BackboneElement" ||
|
|
246
|
-
(element.elements && Object.keys(element.elements).length > 0) ||
|
|
247
|
-
false);
|
|
204
|
+
return (element.type === "BackboneElement" || (element.elements && Object.keys(element.elements).length > 0) || false);
|
|
248
205
|
}
|
|
249
|
-
|
|
250
|
-
* Build a field reference to a nested type
|
|
251
|
-
*/
|
|
252
|
-
export function buildNestedField(fhirSchema, path, element, manager, packageInfo) {
|
|
206
|
+
export function mkNestedField(fhirSchema, path, element, manager, _packageInfo) {
|
|
253
207
|
return {
|
|
254
|
-
type:
|
|
208
|
+
type: mkNestedIdentifier(fhirSchema, path),
|
|
255
209
|
array: element.array || false,
|
|
256
210
|
required: isRequired(fhirSchema, path, manager),
|
|
257
211
|
excluded: isExcluded(fhirSchema, path, manager),
|
|
@@ -4,12 +4,9 @@
|
|
|
4
4
|
* Functions for creating TypeSchema identifiers from FHIRSchema entities
|
|
5
5
|
*/
|
|
6
6
|
import type { FHIRSchema } from "@atomic-ehr/fhirschema";
|
|
7
|
-
import type {
|
|
7
|
+
import type { BindingIdentifier, Identifier, NestedIdentifier, PackageMeta, RichFHIRSchema, TypeSchemaForValueSet } from "../types";
|
|
8
8
|
export declare function dropVersionFromUrl(url: string | undefined): string | undefined;
|
|
9
|
-
export declare function
|
|
10
|
-
export declare function
|
|
11
|
-
export declare function
|
|
12
|
-
|
|
13
|
-
* Build binding identifier for an element with value set binding
|
|
14
|
-
*/
|
|
15
|
-
export declare function buildBindingIdentifier(fhirSchema: FHIRSchema, path: string[], bindingName?: string, packageInfo?: PackageInfo): Identifier;
|
|
9
|
+
export declare function mkIdentifier(fhirSchema: RichFHIRSchema): Identifier;
|
|
10
|
+
export declare function mkNestedIdentifier(fhirSchema: RichFHIRSchema, path: string[]): NestedIdentifier;
|
|
11
|
+
export declare function mkValueSetIdentifier(valueSetUrl: string, valueSet: any, packageInfo?: PackageMeta): TypeSchemaForValueSet["identifier"];
|
|
12
|
+
export declare function mkBindingIdentifier(fhirSchema: FHIRSchema, path: string[], bindingName?: string, packageInfo?: PackageMeta): BindingIdentifier;
|
|
@@ -19,7 +19,7 @@ function determineKind(fhirSchema) {
|
|
|
19
19
|
return "resource";
|
|
20
20
|
return "resource";
|
|
21
21
|
}
|
|
22
|
-
export function
|
|
22
|
+
export function mkIdentifier(fhirSchema) {
|
|
23
23
|
return {
|
|
24
24
|
kind: determineKind(fhirSchema),
|
|
25
25
|
package: fhirSchema.package_meta.name,
|
|
@@ -28,17 +28,17 @@ export function buildSchemaIdentifier(fhirSchema) {
|
|
|
28
28
|
url: fhirSchema.url,
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
|
-
export function
|
|
31
|
+
export function mkNestedIdentifier(fhirSchema, path) {
|
|
32
32
|
const nestedName = path.join(".");
|
|
33
33
|
return {
|
|
34
34
|
kind: "nested",
|
|
35
|
-
package:
|
|
36
|
-
version:
|
|
35
|
+
package: fhirSchema.package_meta.name,
|
|
36
|
+
version: fhirSchema.package_meta.version,
|
|
37
37
|
name: nestedName,
|
|
38
38
|
url: `${fhirSchema.url}#${nestedName}`,
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
|
-
export function
|
|
41
|
+
export function mkValueSetIdentifier(valueSetUrl, valueSet, packageInfo) {
|
|
42
42
|
const cleanUrl = dropVersionFromUrl(valueSetUrl) || valueSetUrl;
|
|
43
43
|
// Generate a meaningful name from the URL instead of using potentially hash-like IDs
|
|
44
44
|
let name = "unknown";
|
|
@@ -54,9 +54,7 @@ export function buildValueSetIdentifier(valueSetUrl, valueSet, packageInfo) {
|
|
|
54
54
|
}
|
|
55
55
|
// Only fall back to valueSet.id if we couldn't extract a meaningful name from URL
|
|
56
56
|
// and the ID doesn't look like a hash (no long alphanumeric strings)
|
|
57
|
-
if (name === "unknown" &&
|
|
58
|
-
valueSet?.id &&
|
|
59
|
-
!/^[a-zA-Z0-9_-]{20,}$/.test(valueSet.id)) {
|
|
57
|
+
if (name === "unknown" && valueSet?.id && !/^[a-zA-Z0-9_-]{20,}$/.test(valueSet.id)) {
|
|
60
58
|
name = valueSet.id;
|
|
61
59
|
}
|
|
62
60
|
return {
|
|
@@ -67,10 +65,7 @@ export function buildValueSetIdentifier(valueSetUrl, valueSet, packageInfo) {
|
|
|
67
65
|
url: cleanUrl,
|
|
68
66
|
};
|
|
69
67
|
}
|
|
70
|
-
|
|
71
|
-
* Build binding identifier for an element with value set binding
|
|
72
|
-
*/
|
|
73
|
-
export function buildBindingIdentifier(fhirSchema, path, bindingName, packageInfo) {
|
|
68
|
+
export function mkBindingIdentifier(fhirSchema, path, bindingName, packageInfo) {
|
|
74
69
|
const pathStr = path.join(".");
|
|
75
70
|
const name = bindingName || `${fhirSchema.name}.${pathStr}_binding`;
|
|
76
71
|
return {
|
|
@@ -78,8 +73,6 @@ export function buildBindingIdentifier(fhirSchema, path, bindingName, packageInf
|
|
|
78
73
|
package: packageInfo?.name || fhirSchema.package_meta.name || "undefined",
|
|
79
74
|
version: packageInfo?.version || fhirSchema.package_meta.version || "undefined",
|
|
80
75
|
name,
|
|
81
|
-
url: bindingName
|
|
82
|
-
? `urn:fhir:binding:${name}`
|
|
83
|
-
: `${fhirSchema.url}#${pathStr}_binding`,
|
|
76
|
+
url: bindingName ? `urn:fhir:binding:${name}` : `${fhirSchema.url}#${pathStr}_binding`,
|
|
84
77
|
};
|
|
85
78
|
}
|
|
@@ -3,21 +3,18 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Functions for extracting and transforming nested types from FHIRSchema
|
|
5
5
|
*/
|
|
6
|
-
import type { CanonicalManager } from "@atomic-ehr/fhir-canonical-manager";
|
|
7
6
|
import type { FHIRSchema, FHIRSchemaElement } from "@atomic-ehr/fhirschema";
|
|
8
|
-
import type {
|
|
7
|
+
import type { Register } from "@root/typeschema/register";
|
|
8
|
+
import type { Identifier, PackageMeta, RichFHIRSchema, TypeSchemaField, TypeSchemaNestedType } from "../types";
|
|
9
9
|
/**
|
|
10
10
|
* Collect all nested elements from a FHIRSchema
|
|
11
11
|
*/
|
|
12
12
|
export declare function collectNestedElements(fhirSchema: FHIRSchema, parentPath: string[], elements: Record<string, FHIRSchemaElement>): Array<[string[], FHIRSchemaElement]>;
|
|
13
|
-
|
|
14
|
-
* Transform elements into fields for a nested type
|
|
15
|
-
*/
|
|
16
|
-
export declare function transformNestedElements(fhirSchema: FHIRSchema, parentPath: string[], elements: Record<string, FHIRSchemaElement>, manager: ReturnType<typeof CanonicalManager>, packageInfo?: PackageInfo): Promise<Record<string, TypeSchemaField>>;
|
|
13
|
+
export declare function transformNestedElements(fhirSchema: RichFHIRSchema, parentPath: string[], elements: Record<string, FHIRSchemaElement>, register: Register, packageInfo?: PackageMeta): Promise<Record<string, TypeSchemaField>>;
|
|
17
14
|
/**
|
|
18
15
|
* Build TypeSchema for all nested types in a FHIRSchema
|
|
19
16
|
*/
|
|
20
|
-
export declare function buildNestedTypes(fhirSchema:
|
|
17
|
+
export declare function buildNestedTypes(fhirSchema: RichFHIRSchema, register: Register, packageInfo?: PackageMeta): Promise<any[] | undefined>;
|
|
21
18
|
/**
|
|
22
19
|
* Extract dependencies from nested types
|
|
23
20
|
*/
|