@atomic-ehr/codegen 0.0.1-canary.20251006070905.fb6ed98 → 0.0.1-canary.20251006094042.7f0be72

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.
Files changed (90) hide show
  1. package/dist/cli/index.js +45 -124
  2. package/dist/index.d.ts +2130 -62
  3. package/dist/index.js +5865 -84
  4. package/dist/index.js.map +1 -0
  5. package/package.json +3 -7
  6. package/dist/api/builder.d.ts +0 -154
  7. package/dist/api/builder.js +0 -341
  8. package/dist/api/generators/base/BaseGenerator.d.ts +0 -186
  9. package/dist/api/generators/base/BaseGenerator.js +0 -565
  10. package/dist/api/generators/base/FileManager.d.ts +0 -88
  11. package/dist/api/generators/base/FileManager.js +0 -202
  12. package/dist/api/generators/base/PythonTypeMapper.d.ts +0 -16
  13. package/dist/api/generators/base/PythonTypeMapper.js +0 -71
  14. package/dist/api/generators/base/TemplateEngine.d.ts +0 -126
  15. package/dist/api/generators/base/TemplateEngine.js +0 -133
  16. package/dist/api/generators/base/TypeMapper.d.ts +0 -129
  17. package/dist/api/generators/base/TypeMapper.js +0 -153
  18. package/dist/api/generators/base/TypeScriptTypeMapper.d.ts +0 -51
  19. package/dist/api/generators/base/TypeScriptTypeMapper.js +0 -232
  20. package/dist/api/generators/base/builders/DirectoryBuilder.d.ts +0 -99
  21. package/dist/api/generators/base/builders/DirectoryBuilder.js +0 -215
  22. package/dist/api/generators/base/builders/FileBuilder.d.ts +0 -160
  23. package/dist/api/generators/base/builders/FileBuilder.js +0 -406
  24. package/dist/api/generators/base/builders/IndexBuilder.d.ts +0 -126
  25. package/dist/api/generators/base/builders/IndexBuilder.js +0 -290
  26. package/dist/api/generators/base/enhanced-errors.d.ts +0 -84
  27. package/dist/api/generators/base/enhanced-errors.js +0 -259
  28. package/dist/api/generators/base/error-handler.d.ts +0 -89
  29. package/dist/api/generators/base/error-handler.js +0 -243
  30. package/dist/api/generators/base/errors.d.ts +0 -251
  31. package/dist/api/generators/base/errors.js +0 -692
  32. package/dist/api/generators/base/index.d.ts +0 -99
  33. package/dist/api/generators/base/index.js +0 -160
  34. package/dist/api/generators/base/types.d.ts +0 -433
  35. package/dist/api/generators/base/types.js +0 -12
  36. package/dist/api/generators/types.d.ts +0 -53
  37. package/dist/api/generators/types.js +0 -4
  38. package/dist/api/generators/typescript.d.ts +0 -190
  39. package/dist/api/generators/typescript.js +0 -819
  40. package/dist/api/index.d.ts +0 -51
  41. package/dist/api/index.js +0 -50
  42. package/dist/cli/commands/generate/typescript.d.ts +0 -10
  43. package/dist/cli/commands/generate/typescript.js +0 -52
  44. package/dist/cli/commands/generate.d.ts +0 -15
  45. package/dist/cli/commands/generate.js +0 -159
  46. package/dist/cli/commands/index.d.ts +0 -29
  47. package/dist/cli/commands/index.js +0 -100
  48. package/dist/cli/commands/typeschema/generate.d.ts +0 -19
  49. package/dist/cli/commands/typeschema/generate.js +0 -124
  50. package/dist/cli/commands/typeschema.d.ts +0 -10
  51. package/dist/cli/commands/typeschema.js +0 -47
  52. package/dist/cli/index.d.ts +0 -9
  53. package/dist/cli/utils/log.d.ts +0 -10
  54. package/dist/cli/utils/log.js +0 -23
  55. package/dist/cli/utils/prompts.d.ts +0 -56
  56. package/dist/cli/utils/prompts.js +0 -202
  57. package/dist/cli/utils/spinner.d.ts +0 -110
  58. package/dist/cli/utils/spinner.js +0 -266
  59. package/dist/config.d.ts +0 -217
  60. package/dist/config.js +0 -591
  61. package/dist/logger.d.ts +0 -157
  62. package/dist/logger.js +0 -281
  63. package/dist/typeschema/cache.d.ts +0 -80
  64. package/dist/typeschema/cache.js +0 -239
  65. package/dist/typeschema/core/binding.d.ts +0 -11
  66. package/dist/typeschema/core/binding.js +0 -143
  67. package/dist/typeschema/core/field-builder.d.ts +0 -12
  68. package/dist/typeschema/core/field-builder.js +0 -123
  69. package/dist/typeschema/core/identifier.d.ts +0 -13
  70. package/dist/typeschema/core/identifier.js +0 -94
  71. package/dist/typeschema/core/nested-types.d.ts +0 -9
  72. package/dist/typeschema/core/nested-types.js +0 -94
  73. package/dist/typeschema/core/transformer.d.ts +0 -11
  74. package/dist/typeschema/core/transformer.js +0 -235
  75. package/dist/typeschema/generator.d.ts +0 -43
  76. package/dist/typeschema/generator.js +0 -264
  77. package/dist/typeschema/index.d.ts +0 -15
  78. package/dist/typeschema/index.js +0 -15
  79. package/dist/typeschema/parser.d.ts +0 -79
  80. package/dist/typeschema/parser.js +0 -274
  81. package/dist/typeschema/profile/processor.d.ts +0 -14
  82. package/dist/typeschema/profile/processor.js +0 -262
  83. package/dist/typeschema/register.d.ts +0 -21
  84. package/dist/typeschema/register.js +0 -117
  85. package/dist/typeschema/types.d.ts +0 -240
  86. package/dist/typeschema/types.js +0 -19
  87. package/dist/utils/codegen-logger.d.ts +0 -102
  88. package/dist/utils/codegen-logger.js +0 -196
  89. package/dist/utils.d.ts +0 -22
  90. package/dist/utils.js +0 -42
@@ -1,94 +0,0 @@
1
- /**
2
- * Nested Types (BackboneElement) Handling
3
- *
4
- * Functions for extracting and transforming nested types from FHIRSchema
5
- */
6
- import { isNestedElement, mkField, mkNestedField } from "./field-builder";
7
- import { mkNestedIdentifier } from "./identifier";
8
- function collectNestedElements(fhirSchema, parentPath, elements) {
9
- const nested = [];
10
- for (const [key, element] of Object.entries(elements)) {
11
- const path = [...parentPath, key];
12
- if (isNestedElement(element)) {
13
- nested.push([path, element]);
14
- }
15
- if (element.elements) {
16
- nested.push(...collectNestedElements(fhirSchema, path, element.elements));
17
- }
18
- }
19
- return nested;
20
- }
21
- async function transformNestedElements(fhirSchema, parentPath, elements, register, _packageInfo) {
22
- const fields = {};
23
- for (const [key, element] of Object.entries(elements)) {
24
- const path = [...parentPath, key];
25
- if (isNestedElement(element)) {
26
- fields[key] = mkNestedField(register, fhirSchema, path, element);
27
- }
28
- else {
29
- fields[key] = mkField(register, fhirSchema, path, element);
30
- }
31
- }
32
- return fields;
33
- }
34
- export async function mkNestedTypes(register, fhirSchema) {
35
- if (!fhirSchema.elements)
36
- return undefined;
37
- const nestedElements = collectNestedElements(fhirSchema, [], fhirSchema.elements);
38
- const actualNested = nestedElements.filter(([_, element]) => element.elements && Object.keys(element.elements).length > 0);
39
- const nestedTypes = [];
40
- for (const [path, element] of actualNested) {
41
- const identifier = mkNestedIdentifier(fhirSchema, path);
42
- // Base is usually BackboneElement - ensure all nested types have a base
43
- // biome-ignore lint/suspicious/noImplicitAnyLet: <explanation>
44
- let base;
45
- if (element.type === "BackboneElement" || !element.type) {
46
- // For BackboneElement or undefined type, always use BackboneElement as base
47
- base = {
48
- kind: "complex-type",
49
- package: fhirSchema.package_meta.name,
50
- version: fhirSchema.package_meta.version,
51
- name: "BackboneElement",
52
- url: "http://hl7.org/fhir/StructureDefinition/BackboneElement",
53
- };
54
- }
55
- else {
56
- // Use the specified type as base
57
- base = {
58
- kind: "complex-type",
59
- package: fhirSchema.package_meta.name,
60
- version: fhirSchema.package_meta.version,
61
- name: element.type,
62
- url: `http://hl7.org/fhir/StructureDefinition/${element.type}`,
63
- };
64
- }
65
- // Transform sub-elements into fields
66
- const fields = await transformNestedElements(fhirSchema, path, element.elements, register, fhirSchema.package_meta);
67
- const nestedType = {
68
- identifier,
69
- base,
70
- fields,
71
- };
72
- nestedTypes.push(nestedType);
73
- }
74
- // Sort by URL for consistent output
75
- nestedTypes.sort((a, b) => a.identifier.url.localeCompare(b.identifier.url));
76
- return nestedTypes.length === 0 ? undefined : nestedTypes;
77
- }
78
- export function extractNestedDependencies(nestedTypes) {
79
- const deps = [];
80
- for (const nested of nestedTypes) {
81
- if (nested.base) {
82
- deps.push(nested.base);
83
- }
84
- for (const field of Object.values(nested.fields || {})) {
85
- if ("type" in field && field.type) {
86
- deps.push(field.type);
87
- }
88
- if ("binding" in field && field.binding) {
89
- deps.push(field.binding);
90
- }
91
- }
92
- }
93
- return deps;
94
- }
@@ -1,11 +0,0 @@
1
- /**
2
- * Main FHIRSchema to TypeSchema Transformer
3
- *
4
- * Core transformation logic for converting FHIRSchema to TypeSchema format
5
- */
6
- import type { FHIRSchemaElement } from "@atomic-ehr/fhirschema";
7
- import { type Register } from "@typeschema/register";
8
- import type { Field, RichFHIRSchema, RichValueSet, TypeSchema, ValueSetTypeSchema } from "@typeschema/types";
9
- export declare function mkFields(register: Register, fhirSchema: RichFHIRSchema, parentPath: string[], elements: Record<string, FHIRSchemaElement> | undefined): Promise<Record<string, Field> | undefined>;
10
- export declare function transformValueSet(register: Register, valueSet: RichValueSet): Promise<ValueSetTypeSchema>;
11
- export declare function transformFHIRSchema(register: Register, fhirSchema: RichFHIRSchema): Promise<TypeSchema[]>;
@@ -1,235 +0,0 @@
1
- /**
2
- * Main FHIRSchema to TypeSchema Transformer
3
- *
4
- * Core transformation logic for converting FHIRSchema to TypeSchema format
5
- */
6
- import { fsElementSnapshot, resolveFsElementGenealogy } from "@typeschema/register";
7
- import { transformProfile } from "../profile/processor";
8
- import { collectBindingSchemas, extractValueSetConceptsByUrl } from "./binding";
9
- import { isNestedElement, mkField, mkNestedField } from "./field-builder";
10
- import { mkIdentifier, mkValueSetIdentifierByUrl } from "./identifier";
11
- import { extractNestedDependencies, mkNestedTypes } from "./nested-types";
12
- export async function mkFields(register, fhirSchema, parentPath, elements) {
13
- if (!elements)
14
- return undefined;
15
- const geneology = register.resolveFsGenealogy(fhirSchema.url);
16
- const elems = {};
17
- for (const [key, elem] of Object.entries(elements)) {
18
- const path = [...parentPath, key];
19
- const elemGeneology = resolveFsElementGenealogy(geneology, path);
20
- const elemSnapshot = fsElementSnapshot(elemGeneology);
21
- elems[key] = { elem, elemSnapshot, path };
22
- }
23
- for (const [_key, { elem, elemSnapshot, path }] of Object.entries(elems)) {
24
- for (const choiceKey of elem?.choices || []) {
25
- if (!elems[choiceKey]) {
26
- const path = [...parentPath, choiceKey];
27
- const elemGeneology = resolveFsElementGenealogy(geneology, path);
28
- const elemSnapshot = fsElementSnapshot(elemGeneology);
29
- elems[choiceKey] = { elem: undefined, elemSnapshot, path };
30
- }
31
- }
32
- }
33
- const fields = {};
34
- for (const [key, { elem, elemSnapshot, path }] of Object.entries(elems)) {
35
- if (isNestedElement(elemSnapshot)) {
36
- fields[key] = mkNestedField(register, fhirSchema, path, elemSnapshot);
37
- }
38
- else {
39
- fields[key] = mkField(register, fhirSchema, path, elemSnapshot);
40
- }
41
- }
42
- return fields;
43
- }
44
- function extractFieldDependencies(fields) {
45
- const deps = [];
46
- for (const field of Object.values(fields)) {
47
- if ("type" in field && field.type) {
48
- deps.push(field.type);
49
- }
50
- if ("binding" in field && field.binding) {
51
- deps.push(field.binding);
52
- }
53
- }
54
- return deps;
55
- }
56
- function deduplicateDependencies(deps) {
57
- const seen = new Set();
58
- const unique = [];
59
- for (const dep of deps) {
60
- const key = dep.url;
61
- if (!seen.has(key)) {
62
- seen.add(key);
63
- unique.push(dep);
64
- }
65
- }
66
- // Sort by name for consistent output (matching Clojure implementation)
67
- unique.sort((a, b) => a.name.localeCompare(b.name));
68
- return unique;
69
- }
70
- /**
71
- * Check if a FHIR schema represents an extension
72
- */
73
- function isExtensionSchema(fhirSchema, _identifier) {
74
- // Check if this is based on Extension
75
- if (fhirSchema.base === "Extension" || fhirSchema.base === "http://hl7.org/fhir/StructureDefinition/Extension") {
76
- return true;
77
- }
78
- // Check if the URL indicates this is an extension
79
- if (fhirSchema.url?.includes("/extension/") || fhirSchema.url?.includes("-extension")) {
80
- return true;
81
- }
82
- // Check if the name indicates this is an extension
83
- if (fhirSchema.name?.toLowerCase().includes("extension")) {
84
- return true;
85
- }
86
- // Check if the type is Extension
87
- if (fhirSchema.type === "Extension") {
88
- return true;
89
- }
90
- return false;
91
- }
92
- export async function transformValueSet(register, valueSet) {
93
- if (!valueSet.url)
94
- throw new Error("ValueSet URL is required");
95
- const identifier = mkValueSetIdentifierByUrl(register, valueSet.url);
96
- const concept = extractValueSetConceptsByUrl(register, valueSet.url);
97
- return {
98
- identifier: identifier,
99
- description: valueSet.description,
100
- concept: concept,
101
- compose: !concept ? valueSet.compose : undefined,
102
- };
103
- }
104
- /**
105
- * Transform an Extension FHIRSchema to TypeSchema with extension metadata
106
- */
107
- async function transformExtension(fhirSchema, register, _packageInfo) {
108
- try {
109
- const identifier = mkIdentifier(fhirSchema);
110
- // Build base identifier if present
111
- let base;
112
- if (fhirSchema.base && fhirSchema.base !== "Extension") {
113
- const baseUrl = fhirSchema.base.includes("/")
114
- ? fhirSchema.base
115
- : `http://hl7.org/fhir/StructureDefinition/${fhirSchema.base}`;
116
- const baseName = fhirSchema.base.split("/").pop() || fhirSchema.base;
117
- base = {
118
- kind: "complex-type",
119
- package: "hl7.fhir.r4.core",
120
- version: "4.0.1",
121
- name: baseName,
122
- url: baseUrl,
123
- };
124
- }
125
- else {
126
- // Default to Extension base
127
- base = {
128
- kind: "complex-type",
129
- package: "hl7.fhir.r4.core",
130
- version: "4.0.1",
131
- name: "Extension",
132
- url: "http://hl7.org/fhir/StructureDefinition/Extension",
133
- };
134
- }
135
- const extensionSchema = {
136
- identifier,
137
- base,
138
- description: fhirSchema.description,
139
- dependencies: [],
140
- metadata: {
141
- isExtension: true, // Mark as extension for file organization
142
- },
143
- };
144
- // Add base to dependencies
145
- if (base) {
146
- extensionSchema.dependencies.push(base);
147
- }
148
- // Transform elements into fields if present
149
- if (fhirSchema.elements) {
150
- const fields = await mkFields(register, fhirSchema, [], fhirSchema.elements);
151
- if (fields && Object.keys(fields).length > 0) {
152
- extensionSchema.fields = fields;
153
- extensionSchema.dependencies.push(...extractFieldDependencies(fields));
154
- }
155
- }
156
- // Build nested types
157
- const nestedTypes = await mkNestedTypes(register, fhirSchema);
158
- if (nestedTypes && nestedTypes.length > 0) {
159
- extensionSchema.nested = nestedTypes;
160
- extensionSchema.dependencies.push(...extractNestedDependencies(nestedTypes));
161
- }
162
- // Deduplicate and sort dependencies
163
- extensionSchema.dependencies = deduplicateDependencies(extensionSchema.dependencies);
164
- // Remove self-reference from dependencies
165
- extensionSchema.dependencies = extensionSchema.dependencies.filter((dep) => dep.url !== identifier.url);
166
- return extensionSchema;
167
- }
168
- catch (error) {
169
- console.warn(`Failed to transform extension ${fhirSchema.name}: ${error}`);
170
- return null;
171
- }
172
- }
173
- function extractDependencies(identifier, base, fields, nestedTypes) {
174
- const deps = [];
175
- if (base)
176
- deps.push(base);
177
- if (fields)
178
- deps.push(...extractFieldDependencies(fields));
179
- if (nestedTypes)
180
- deps.push(...extractNestedDependencies(nestedTypes));
181
- const uniqDeps = {};
182
- for (const dep of deps) {
183
- if (dep.url === identifier.url)
184
- continue;
185
- uniqDeps[dep.url] = dep;
186
- }
187
- const localNestedTypeUrls = new Set(nestedTypes?.map((nt) => nt.identifier.url));
188
- const result = Object.values(uniqDeps)
189
- .filter((e) => !(e.kind === "nested" && localNestedTypeUrls.has(e.url)))
190
- .sort((a, b) => a.url.localeCompare(b.url));
191
- return result.length > 0 ? result : undefined;
192
- }
193
- async function transformResource(register, fhirSchema) {
194
- const identifier = mkIdentifier(fhirSchema);
195
- let base;
196
- if (fhirSchema.base && fhirSchema.type !== "Element") {
197
- const baseFs = register.resolveFs(register.ensureCanonicalUrl(fhirSchema.base));
198
- if (!baseFs) {
199
- throw new Error(`Base resource not found '${fhirSchema.base}' for '${fhirSchema.url}'`);
200
- }
201
- base = mkIdentifier(baseFs);
202
- }
203
- const fields = await mkFields(register, fhirSchema, [], fhirSchema.elements);
204
- const nested = await mkNestedTypes(register, fhirSchema);
205
- const dependencies = extractDependencies(identifier, base, fields, nested);
206
- const typeSchema = {
207
- identifier,
208
- base,
209
- fields,
210
- nested,
211
- description: fhirSchema.description,
212
- dependencies,
213
- };
214
- const bindingSchemas = await collectBindingSchemas(register, fhirSchema);
215
- return [typeSchema, ...bindingSchemas];
216
- }
217
- export async function transformFHIRSchema(register, fhirSchema) {
218
- const results = [];
219
- const identifier = mkIdentifier(fhirSchema);
220
- if (identifier.kind === "profile") {
221
- const profileSchema = await transformProfile(register, fhirSchema);
222
- results.push(profileSchema);
223
- const bindingSchemas = await collectBindingSchemas(register, fhirSchema);
224
- results.push(...bindingSchemas);
225
- return results;
226
- }
227
- if (isExtensionSchema(fhirSchema, identifier)) {
228
- const extensionSchema = await transformExtension(fhirSchema, register, fhirSchema.package_meta);
229
- if (extensionSchema) {
230
- results.push(extensionSchema);
231
- }
232
- return results;
233
- }
234
- return await transformResource(register, fhirSchema);
235
- }
@@ -1,43 +0,0 @@
1
- /**
2
- * TypeSchema Generator
3
- *
4
- * Generates TypeSchema documents from FHIR packages using fhrischema.
5
- * Provides high-level API for converting FHIR Structure Definitions to TypeSchema format.
6
- */
7
- import type { FHIRSchema, StructureDefinition } from "@atomic-ehr/fhirschema";
8
- import type { TypeSchemaConfig } from "@root/config";
9
- import type { Register } from "@typeschema/register";
10
- import type { PackageMeta, TypeSchema, TypeschemaGeneratorOptions } from "./types";
11
- /**
12
- * TypeSchema Generator class
13
- *
14
- * Main class for generating TypeSchema documents from FHIR packages.
15
- * Leverages fhrischema for FHIR parsing and canonical manager for dependency resolution.
16
- */
17
- export declare class TypeSchemaGenerator {
18
- private manager;
19
- private options;
20
- private cacheConfig?;
21
- private cache?;
22
- private logger;
23
- constructor(options?: TypeschemaGeneratorOptions, cacheConfig?: TypeSchemaConfig);
24
- private initializeCache;
25
- registerFromPackageMetas(packageMetas: PackageMeta[]): Promise<Register>;
26
- generateFhirSchemas(structureDefinitions: StructureDefinition[]): FHIRSchema[];
27
- generateValueSetSchemas(valueSets: any[], _packageInfo: PackageMeta): Promise<TypeSchema[]>;
28
- generateFromPackage(packageName: string, packageVersion?: string): Promise<TypeSchema[]>;
29
- /**
30
- * Apply treeshaking to StructureDefinitions before FHIR schema transformation
31
- * This is more efficient and includes smart reference handling
32
- */
33
- private applyStructureDefinitionTreeshaking;
34
- /**
35
- * Extract dependencies from StructureDefinition with smart reference handling
36
- * Returns both real dependencies and reference targets separately
37
- */
38
- private extractStructureDefinitionDependenciesWithReferences;
39
- /**
40
- * Extract resource name from FHIR URL
41
- */
42
- private extractResourceNameFromUrl;
43
- }
@@ -1,264 +0,0 @@
1
- /**
2
- * TypeSchema Generator
3
- *
4
- * Generates TypeSchema documents from FHIR packages using fhrischema.
5
- * Provides high-level API for converting FHIR Structure Definitions to TypeSchema format.
6
- */
7
- import { CanonicalManager } from "@atomic-ehr/fhir-canonical-manager";
8
- import * as fhirschema from "@atomic-ehr/fhirschema";
9
- import { createLogger } from "@root/utils/codegen-logger";
10
- import { registerFromManager } from "@typeschema/register";
11
- import { TypeSchemaCache } from "./cache";
12
- import { transformFHIRSchema, transformValueSet } from "./core/transformer";
13
- /**
14
- * TypeSchema Generator class
15
- *
16
- * Main class for generating TypeSchema documents from FHIR packages.
17
- * Leverages fhrischema for FHIR parsing and canonical manager for dependency resolution.
18
- */
19
- export class TypeSchemaGenerator {
20
- manager;
21
- options;
22
- cacheConfig;
23
- cache;
24
- logger;
25
- constructor(options = {}, cacheConfig) {
26
- this.options = { verbose: false, ...options };
27
- this.manager = options.manager || CanonicalManager({ packages: [], workingDir: "tmp/fhir" });
28
- this.cacheConfig = cacheConfig;
29
- this.logger =
30
- options.logger ||
31
- createLogger({
32
- verbose: this.options.verbose,
33
- prefix: "TypeSchema",
34
- });
35
- }
36
- async initializeCache() {
37
- if (this.cacheConfig && !this.cache) {
38
- this.cache = new TypeSchemaCache(this.cacheConfig);
39
- await this.cache.initialize();
40
- }
41
- }
42
- async registerFromPackageMetas(packageMetas) {
43
- const packageNames = packageMetas.map((meta) => `${meta.name}${meta.version}`);
44
- this.logger.step(`Loading FHIR packages: ${packageNames.join(", ")}`);
45
- await this.manager.init();
46
- return registerFromManager(this.manager);
47
- }
48
- generateFhirSchemas(structureDefinitions) {
49
- this.logger.progress(`Converting ${structureDefinitions.length} StructureDefinitions to FHIRSchemas`);
50
- // TODO: do it on the TypeSchema?
51
- const filteredStructureDefinitions = this.applyStructureDefinitionTreeshaking(structureDefinitions);
52
- const fhirSchemas = [];
53
- let convertedCount = 0;
54
- let failedCount = 0;
55
- for (const sd of filteredStructureDefinitions) {
56
- try {
57
- const fhirSchema = fhirschema.translate(sd);
58
- fhirSchemas.push(fhirSchema);
59
- convertedCount++;
60
- this.logger.debug(`Converted StructureDefinition: ${sd.name || sd.id} (${sd.resourceType})`);
61
- }
62
- catch (error) {
63
- failedCount++;
64
- this.logger.warn(`Failed to convert StructureDefinition ${sd.name || sd.id}: ${error instanceof Error ? error.message : String(error)}`);
65
- }
66
- }
67
- this.logger.success(`FHIR Schema conversion completed: ${convertedCount}/${filteredStructureDefinitions.length} successful, ${failedCount} failed`);
68
- return fhirSchemas;
69
- }
70
- async generateValueSetSchemas(valueSets, _packageInfo) {
71
- if (valueSets.length > 0) {
72
- this.logger.debug(`${valueSets.length} ValueSets available for enum extraction`);
73
- }
74
- // Process ValueSets separately to add to TypeSchema output
75
- const valueSetSchemas = [];
76
- if (valueSets.length > 0) {
77
- this.logger.progress(`Converting ${valueSets.length} ValueSets to TypeSchema`);
78
- let valueSetConvertedCount = 0;
79
- let valueSetFailedCount = 0;
80
- for (const vs of valueSets) {
81
- try {
82
- const valueSetSchema = await transformValueSet(await registerFromManager(this.manager), vs);
83
- if (valueSetSchema) {
84
- valueSetSchemas.push(valueSetSchema);
85
- valueSetConvertedCount++;
86
- this.logger.debug(`Converted ValueSet: ${vs.name || vs.id}`);
87
- }
88
- }
89
- catch (error) {
90
- valueSetFailedCount++;
91
- this.logger.warn(`Failed to convert ValueSet ${vs.name || vs.id}: ${error instanceof Error ? error.message : String(error)}`);
92
- }
93
- }
94
- this.logger.success(`ValueSet conversion completed: ${valueSetConvertedCount}/${valueSets.length} successful, ${valueSetFailedCount} failed`);
95
- }
96
- return valueSetSchemas;
97
- }
98
- async generateFromPackage(packageName, packageVersion) {
99
- await this.initializeCache();
100
- if (this.cache && !(this.cacheConfig?.forceRegenerate ?? false)) {
101
- const cachedSchemas = this.cache.getByPackage(packageName);
102
- if (cachedSchemas.length > 0) {
103
- this.logger.info(`Using cached TypeSchemas for package: ${packageName} (${cachedSchemas.length} schemas)`);
104
- return cachedSchemas;
105
- }
106
- }
107
- const packageInfo = {
108
- name: packageName,
109
- version: packageVersion || "latest",
110
- };
111
- const register = await this.registerFromPackageMetas([packageInfo]);
112
- const allSchemas = [
113
- ...(await Promise.all(register.allFs().map(async (fs) => await transformFHIRSchema(register, fs)))).flat(),
114
- ...(await this.generateValueSetSchemas(register.allVs(), packageInfo)),
115
- ];
116
- if (this.cache) {
117
- for (const schema of allSchemas) {
118
- await this.cache.set(schema);
119
- }
120
- }
121
- return allSchemas;
122
- }
123
- // async generateResourceTypeSchemas(
124
- // fhirSchemas: RichFHIRSchema[],
125
- // ): Promise<TypeSchema[]> {
126
- // this.logger.info(
127
- // `Transforming ${fhirSchemas.length} FHIR schemas to Type Schema`,
128
- // );
129
- // const typeSchemas: TypeSchema[] = [];
130
- // for (const fhirSchema of fhirSchemas) {
131
- // typeSchemas.push(
132
- // ...(await transformFHIRSchema(this.manager, fhirSchema)),
133
- // );
134
- // }
135
- // return typeSchemas;
136
- // }
137
- /**
138
- * Apply treeshaking to StructureDefinitions before FHIR schema transformation
139
- * This is more efficient and includes smart reference handling
140
- */
141
- applyStructureDefinitionTreeshaking(structureDefinitions) {
142
- const treeshakeList = this.options.treeshake;
143
- if (!treeshakeList || treeshakeList.length === 0) {
144
- return structureDefinitions;
145
- }
146
- this.logger.info(`Applying treeshaking filter for ResourceTypes: ${treeshakeList.join(", ")}`);
147
- const allStructureDefinitions = new Map();
148
- const realDependencies = new Map();
149
- const referenceTargets = new Map();
150
- for (const sd of structureDefinitions) {
151
- const name = sd.name || sd.id;
152
- if (name) {
153
- allStructureDefinitions.set(name, sd);
154
- realDependencies.set(name, new Set());
155
- referenceTargets.set(name, new Set());
156
- }
157
- }
158
- for (const sd of structureDefinitions) {
159
- const name = sd.name || sd.id;
160
- if (!name)
161
- continue;
162
- const { realDeps, refTargets } = this.extractStructureDefinitionDependenciesWithReferences(sd);
163
- realDependencies.set(name, new Set(realDeps));
164
- referenceTargets.set(name, new Set(refTargets));
165
- }
166
- const structureDefinitionsToKeep = new Set();
167
- for (const resourceType of treeshakeList) {
168
- if (allStructureDefinitions.has(resourceType)) {
169
- structureDefinitionsToKeep.add(resourceType);
170
- }
171
- else {
172
- this.logger.warn(`ResourceType '${resourceType}' not found in structure definitions`);
173
- }
174
- }
175
- const addRealDependenciesRecursively = (name, visited = new Set()) => {
176
- if (visited.has(name) || !realDependencies.has(name)) {
177
- return;
178
- }
179
- visited.add(name);
180
- const deps = realDependencies.get(name) || new Set();
181
- for (const dep of Array.from(deps)) {
182
- if (allStructureDefinitions.has(dep)) {
183
- structureDefinitionsToKeep.add(dep);
184
- addRealDependenciesRecursively(dep, visited);
185
- }
186
- }
187
- };
188
- for (const resourceType of Array.from(structureDefinitionsToKeep)) {
189
- addRealDependenciesRecursively(resourceType);
190
- }
191
- const filteredStructureDefinitions = structureDefinitions.filter((sd) => {
192
- const name = sd.name || sd.id;
193
- return name && structureDefinitionsToKeep.has(name);
194
- });
195
- const excludedReferenceTargets = new Set();
196
- for (const sd of structureDefinitions) {
197
- const name = sd.name || sd.id;
198
- if (name && !structureDefinitionsToKeep.has(name)) {
199
- const isOnlyReferenceTarget = Array.from(referenceTargets.values()).some((targets) => targets.has(name));
200
- if (isOnlyReferenceTarget) {
201
- excludedReferenceTargets.add(name);
202
- }
203
- }
204
- }
205
- if (excludedReferenceTargets.size > 0) {
206
- this.logger.info(`Excluded reference-only targets: ${Array.from(excludedReferenceTargets).join(", ")}`);
207
- }
208
- this.logger.success(`Treeshaking completed: kept ${filteredStructureDefinitions.length}/${structureDefinitions.length} structure definitions`);
209
- return filteredStructureDefinitions;
210
- }
211
- /**
212
- * Extract dependencies from StructureDefinition with smart reference handling
213
- * Returns both real dependencies and reference targets separately
214
- */
215
- extractStructureDefinitionDependenciesWithReferences(sd) {
216
- const realDeps = new Set();
217
- const refTargets = new Set();
218
- if (sd.baseDefinition) {
219
- const baseName = this.extractResourceNameFromUrl(sd.baseDefinition);
220
- if (baseName) {
221
- realDeps.add(baseName);
222
- }
223
- }
224
- if (sd.snapshot?.element || sd.differential?.element) {
225
- const elements = sd.snapshot?.element || sd.differential?.element;
226
- for (const element of elements) {
227
- if (element.type) {
228
- for (const type of element.type) {
229
- if (type.code) {
230
- realDeps.add(type.code);
231
- if (type.code === "Reference" && type.targetProfile) {
232
- for (const targetProfile of type.targetProfile) {
233
- const targetName = this.extractResourceNameFromUrl(targetProfile);
234
- if (targetName) {
235
- refTargets.add(targetName);
236
- }
237
- }
238
- }
239
- }
240
- if (type.profile) {
241
- for (const profile of type.profile) {
242
- const profileName = this.extractResourceNameFromUrl(profile);
243
- if (profileName) {
244
- realDeps.add(profileName);
245
- }
246
- }
247
- }
248
- }
249
- }
250
- }
251
- }
252
- return {
253
- realDeps: Array.from(realDeps),
254
- refTargets: Array.from(refTargets),
255
- };
256
- }
257
- /**
258
- * Extract resource name from FHIR URL
259
- */
260
- extractResourceNameFromUrl(url) {
261
- const match = url.match(/\/([^/]+)$/);
262
- return match ? (match[1] ?? null) : null;
263
- }
264
- }
@@ -1,15 +0,0 @@
1
- /**
2
- * TypeSchema Core Module
3
- *
4
- * Main entry point for the TypeSchema library providing core functions
5
- * for FHIR-to-TypeSchema generation, parsing, and validation.
6
- *
7
- * This module focuses on:
8
- * - Converting FHIR to TypeSchema format
9
- * - Reading TypeSchema documents
10
- * - Validating TypeSchema documents
11
- */
12
- export { TypeSchemaCache } from "./cache";
13
- export { TypeSchemaGenerator } from "./generator";
14
- export { TypeSchemaParser } from "./parser";
15
- export type { Identifier, TypeSchema } from "./types";
@@ -1,15 +0,0 @@
1
- /**
2
- * TypeSchema Core Module
3
- *
4
- * Main entry point for the TypeSchema library providing core functions
5
- * for FHIR-to-TypeSchema generation, parsing, and validation.
6
- *
7
- * This module focuses on:
8
- * - Converting FHIR to TypeSchema format
9
- * - Reading TypeSchema documents
10
- * - Validating TypeSchema documents
11
- */
12
- // Re-export core dependencies
13
- export { TypeSchemaCache } from "./cache";
14
- export { TypeSchemaGenerator } from "./generator";
15
- export { TypeSchemaParser } from "./parser";