@atomic-ehr/codegen 0.0.1-canary.20250821160126.c552195 → 0.0.1-canary.20250822150706.c3b8669

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 (122) hide show
  1. package/dist/api/builder.d.ts +3 -3
  2. package/dist/api/builder.d.ts.map +1 -1
  3. package/dist/api/builder.js +374 -0
  4. package/dist/api/generators/base/BaseGenerator.d.ts +4 -4
  5. package/dist/api/generators/base/BaseGenerator.d.ts.map +1 -1
  6. package/dist/api/generators/base/BaseGenerator.js +572 -0
  7. package/dist/api/generators/base/FileManager.d.ts +2 -2
  8. package/dist/api/generators/base/FileManager.d.ts.map +1 -1
  9. package/dist/api/generators/base/FileManager.js +204 -0
  10. package/dist/api/generators/base/PythonTypeMapper.d.ts +2 -2
  11. package/dist/api/generators/base/PythonTypeMapper.d.ts.map +1 -1
  12. package/dist/api/generators/base/PythonTypeMapper.js +71 -0
  13. package/dist/api/generators/base/TemplateEngine.d.ts +1 -1
  14. package/dist/api/generators/base/TemplateEngine.d.ts.map +1 -1
  15. package/dist/api/generators/base/TemplateEngine.js +133 -0
  16. package/dist/api/generators/base/TypeMapper.js +153 -0
  17. package/dist/api/generators/base/TypeScriptTypeMapper.d.ts +1 -1
  18. package/dist/api/generators/base/TypeScriptTypeMapper.d.ts.map +1 -1
  19. package/dist/api/generators/base/TypeScriptTypeMapper.js +232 -0
  20. package/dist/api/generators/base/builders/DirectoryBuilder.d.ts +4 -4
  21. package/dist/api/generators/base/builders/DirectoryBuilder.d.ts.map +1 -1
  22. package/dist/api/generators/base/builders/DirectoryBuilder.js +215 -0
  23. package/dist/api/generators/base/builders/FileBuilder.d.ts +2 -2
  24. package/dist/api/generators/base/builders/FileBuilder.d.ts.map +1 -1
  25. package/dist/api/generators/base/builders/FileBuilder.js +408 -0
  26. package/dist/api/generators/base/builders/IndexBuilder.d.ts +2 -2
  27. package/dist/api/generators/base/builders/IndexBuilder.d.ts.map +1 -1
  28. package/dist/api/generators/base/builders/IndexBuilder.js +290 -0
  29. package/dist/api/generators/base/enhanced-errors.d.ts +2 -2
  30. package/dist/api/generators/base/enhanced-errors.d.ts.map +1 -1
  31. package/dist/api/generators/base/enhanced-errors.js +259 -0
  32. package/dist/api/generators/base/error-handler.d.ts +1 -1
  33. package/dist/api/generators/base/error-handler.d.ts.map +1 -1
  34. package/dist/api/generators/base/error-handler.js +243 -0
  35. package/dist/api/generators/base/errors.d.ts +2 -2
  36. package/dist/api/generators/base/errors.d.ts.map +1 -1
  37. package/dist/api/generators/base/errors.js +694 -0
  38. package/dist/api/generators/base/index.d.ts +22 -22
  39. package/dist/api/generators/base/index.d.ts.map +1 -1
  40. package/dist/api/generators/base/index.js +161 -0
  41. package/dist/api/generators/base/types.d.ts +2 -2
  42. package/dist/api/generators/base/types.d.ts.map +1 -1
  43. package/dist/api/generators/base/types.js +12 -0
  44. package/dist/api/generators/rest-client.d.ts +2 -2
  45. package/dist/api/generators/rest-client.d.ts.map +1 -1
  46. package/dist/api/generators/rest-client.js +847 -0
  47. package/dist/api/generators/search-parameter-enhancer.d.ts +1 -1
  48. package/dist/api/generators/search-parameter-enhancer.d.ts.map +1 -1
  49. package/dist/api/generators/search-parameter-enhancer.js +801 -0
  50. package/dist/api/generators/types.js +4 -0
  51. package/dist/api/generators/typescript.d.ts +3 -3
  52. package/dist/api/generators/typescript.d.ts.map +1 -1
  53. package/dist/api/generators/typescript.js +537 -0
  54. package/dist/api/generators/validation-generator.js +632 -0
  55. package/dist/api/index.d.ts +10 -10
  56. package/dist/api/index.d.ts.map +1 -1
  57. package/dist/api/index.js +51 -0
  58. package/dist/cli/commands/generate/typescript.d.ts +1 -1
  59. package/dist/cli/commands/generate/typescript.d.ts.map +1 -1
  60. package/dist/cli/commands/generate/typescript.js +52 -0
  61. package/dist/cli/commands/generate.d.ts +5 -12
  62. package/dist/cli/commands/generate.d.ts.map +1 -1
  63. package/dist/cli/commands/generate.js +158 -0
  64. package/dist/cli/commands/index.d.ts +2 -1
  65. package/dist/cli/commands/index.d.ts.map +1 -1
  66. package/dist/cli/commands/index.js +100 -0
  67. package/dist/cli/commands/typeschema/generate.js +130 -0
  68. package/dist/cli/commands/typeschema.js +48 -0
  69. package/dist/cli/index.js +12 -8664
  70. package/dist/cli/utils/log.d.ts +2 -2
  71. package/dist/cli/utils/log.d.ts.map +1 -1
  72. package/dist/cli/utils/log.js +23 -0
  73. package/dist/cli/utils/prompts.js +224 -0
  74. package/dist/cli/utils/spinner.js +270 -0
  75. package/dist/config.d.ts +22 -2
  76. package/dist/config.d.ts.map +1 -1
  77. package/dist/config.js +703 -0
  78. package/dist/index.d.ts +2 -2
  79. package/dist/index.d.ts.map +1 -1
  80. package/dist/index.js +84 -38
  81. package/dist/logger.js +290 -0
  82. package/dist/typeschema/cache.d.ts +2 -2
  83. package/dist/typeschema/cache.d.ts.map +1 -1
  84. package/dist/typeschema/cache.js +285 -0
  85. package/dist/typeschema/core/binding.d.ts +1 -1
  86. package/dist/typeschema/core/binding.d.ts.map +1 -1
  87. package/dist/typeschema/core/binding.js +187 -0
  88. package/dist/typeschema/core/field-builder.d.ts +1 -1
  89. package/dist/typeschema/core/field-builder.d.ts.map +1 -1
  90. package/dist/typeschema/core/field-builder.js +259 -0
  91. package/dist/typeschema/core/identifier.js +117 -0
  92. package/dist/typeschema/core/nested-types.d.ts +1 -1
  93. package/dist/typeschema/core/nested-types.d.ts.map +1 -1
  94. package/dist/typeschema/core/nested-types.js +111 -0
  95. package/dist/typeschema/core/transformer.d.ts +2 -2
  96. package/dist/typeschema/core/transformer.d.ts.map +1 -1
  97. package/dist/typeschema/core/transformer.js +345 -0
  98. package/dist/typeschema/generator.d.ts +3 -3
  99. package/dist/typeschema/generator.d.ts.map +1 -1
  100. package/dist/typeschema/generator.js +352 -0
  101. package/dist/typeschema/index.d.ts +14 -14
  102. package/dist/typeschema/index.d.ts.map +1 -1
  103. package/dist/typeschema/index.js +92 -0
  104. package/dist/typeschema/parser.d.ts +2 -2
  105. package/dist/typeschema/parser.d.ts.map +1 -1
  106. package/dist/typeschema/parser.js +310 -0
  107. package/dist/typeschema/profile/processor.d.ts +1 -1
  108. package/dist/typeschema/profile/processor.d.ts.map +1 -1
  109. package/dist/typeschema/profile/processor.js +268 -0
  110. package/dist/typeschema/schema.js +456 -0
  111. package/dist/typeschema/type-schema.types.js +39 -0
  112. package/dist/typeschema/types.js +4 -0
  113. package/dist/typeschema/utils.d.ts +1 -1
  114. package/dist/typeschema/utils.d.ts.map +1 -1
  115. package/dist/typeschema/utils.js +13 -0
  116. package/dist/typeschema/value-set/processor.d.ts +1 -1
  117. package/dist/typeschema/value-set/processor.d.ts.map +1 -1
  118. package/dist/typeschema/value-set/processor.js +168 -0
  119. package/dist/utils/codegen-logger.js +204 -0
  120. package/dist/utils.js +42 -0
  121. package/package.json +15 -4
  122. package/dist/index-e7pfye24.js +0 -8532
@@ -0,0 +1,310 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * TypeSchema Parser
4
+ *
5
+ * Parser for reading and manipulating TypeSchema documents from various formats.
6
+ * Supports both NDJSON and JSON formats with automatic format detection.
7
+ */
8
+ import { readFile } from "node:fs/promises";
9
+ /**
10
+ * TypeSchema Parser class
11
+ *
12
+ * Provides functionality to read, parse, and manipulate TypeSchema documents
13
+ * from files or strings in various formats.
14
+ */
15
+ export class TypeSchemaParser {
16
+ options;
17
+ constructor(options = {}) {
18
+ this.options = {
19
+ format: "auto",
20
+ validate: true,
21
+ strict: false,
22
+ ...options,
23
+ };
24
+ }
25
+ /**
26
+ * Parse TypeSchema from file
27
+ */
28
+ async parseFromFile(filePath) {
29
+ const content = await readFile(filePath, "utf-8");
30
+ const format = this.options.format === "auto"
31
+ ? this.detectFormat(content, filePath)
32
+ : this.options.format;
33
+ return this.parseFromString(content, format);
34
+ }
35
+ /**
36
+ * Parse TypeSchema from string content
37
+ */
38
+ async parseFromString(content, format) {
39
+ const actualFormat = format || this.detectFormat(content);
40
+ let schemas;
41
+ if (actualFormat === "ndjson") {
42
+ schemas = this.parseNDJSON(content);
43
+ }
44
+ else {
45
+ schemas = this.parseJSON(content);
46
+ }
47
+ if (this.options.validate) {
48
+ this.validateSchemas(schemas);
49
+ }
50
+ return schemas;
51
+ }
52
+ /**
53
+ * Parse multiple TypeSchema files
54
+ */
55
+ async parseFromFiles(filePaths) {
56
+ const allSchemas = [];
57
+ for (const filePath of filePaths) {
58
+ const schemas = await this.parseFromFile(filePath);
59
+ allSchemas.push(...schemas);
60
+ }
61
+ return allSchemas;
62
+ }
63
+ /**
64
+ * Parse a single TypeSchema object
65
+ */
66
+ parseSchema(schemaData) {
67
+ // Basic validation of required fields
68
+ if (!schemaData.identifier) {
69
+ throw new Error("TypeSchema must have an identifier");
70
+ }
71
+ if (!this.isValidIdentifier(schemaData.identifier)) {
72
+ throw new Error("TypeSchema identifier is invalid");
73
+ }
74
+ // Return the schema (assuming it's already in correct format)
75
+ // Additional validation would be performed by the validator
76
+ return schemaData;
77
+ }
78
+ /**
79
+ * Find schemas by identifier
80
+ */
81
+ findByIdentifier(schemas, identifier) {
82
+ return schemas.filter((schema) => this.matchesIdentifier(schema.identifier, identifier));
83
+ }
84
+ /**
85
+ * Find schema by URL
86
+ */
87
+ findByUrl(schemas, url) {
88
+ return schemas.find((schema) => schema.identifier.url === url);
89
+ }
90
+ /**
91
+ * Find schemas by kind
92
+ */
93
+ findByKind(schemas, kind) {
94
+ return schemas.filter((schema) => schema.identifier.kind === kind);
95
+ }
96
+ /**
97
+ * Find schemas by package
98
+ */
99
+ findByPackage(schemas, packageName) {
100
+ return schemas.filter((schema) => schema.identifier.package === packageName);
101
+ }
102
+ /**
103
+ * Get all dependencies from a schema
104
+ */
105
+ getDependencies(schema) {
106
+ const dependencies = [];
107
+ // Add base dependency
108
+ if ("base" in schema && schema.base) {
109
+ dependencies.push(schema.base);
110
+ }
111
+ // Add explicit dependencies
112
+ if ("dependencies" in schema && schema.dependencies) {
113
+ dependencies.push(...schema.dependencies);
114
+ }
115
+ // Add field type dependencies
116
+ if ("fields" in schema && schema.fields) {
117
+ for (const field of Object.values(schema.fields)) {
118
+ if ("type" in field && field.type) {
119
+ dependencies.push(field.type);
120
+ }
121
+ if ("binding" in field && field.binding) {
122
+ dependencies.push(field.binding);
123
+ }
124
+ if ("reference" in field && field.reference) {
125
+ dependencies.push(...field.reference);
126
+ }
127
+ }
128
+ }
129
+ // Add nested type dependencies
130
+ if ("nested" in schema && schema.nested) {
131
+ for (const nested of schema.nested) {
132
+ dependencies.push(nested.identifier);
133
+ dependencies.push(nested.base);
134
+ for (const field of Object.values(nested.fields)) {
135
+ if ("type" in field && field.type) {
136
+ dependencies.push(field.type);
137
+ }
138
+ if ("binding" in field && field.binding) {
139
+ dependencies.push(field.binding);
140
+ }
141
+ if ("reference" in field && field.reference) {
142
+ dependencies.push(...field.reference);
143
+ }
144
+ }
145
+ }
146
+ }
147
+ // Add binding dependencies
148
+ if ("valueset" in schema) {
149
+ const bindingSchema = schema;
150
+ dependencies.push(bindingSchema.valueset);
151
+ if (bindingSchema.type) {
152
+ dependencies.push(bindingSchema.type);
153
+ }
154
+ }
155
+ // Remove duplicates
156
+ return this.deduplicateDependencies(dependencies);
157
+ }
158
+ /**
159
+ * Resolve schema dependencies
160
+ */
161
+ resolveDependencies(schemas, targetSchema) {
162
+ const dependencies = this.getDependencies(targetSchema);
163
+ const resolved = [];
164
+ for (const dep of dependencies) {
165
+ const depSchema = this.findByUrl(schemas, dep.url);
166
+ if (depSchema) {
167
+ resolved.push(depSchema);
168
+ }
169
+ }
170
+ return resolved;
171
+ }
172
+ /**
173
+ * Detect format from content or filename
174
+ */
175
+ detectFormat(content, filename) {
176
+ // Check file extension first
177
+ if (filename) {
178
+ if (filename.endsWith(".ndjson"))
179
+ return "ndjson";
180
+ if (filename.endsWith(".json"))
181
+ return "json";
182
+ }
183
+ // Check content format
184
+ const trimmed = content.trim();
185
+ // NDJSON typically has multiple lines with JSON objects
186
+ if (trimmed.includes("\n")) {
187
+ const lines = trimmed.split("\n").filter((line) => line.trim());
188
+ if (lines.length > 1) {
189
+ try {
190
+ if (lines[0]) {
191
+ JSON.parse(lines[0]);
192
+ }
193
+ return "ndjson";
194
+ }
195
+ catch {
196
+ // Fall through to JSON detection
197
+ }
198
+ }
199
+ }
200
+ // Default to JSON for single objects or arrays
201
+ return "json";
202
+ }
203
+ /**
204
+ * Parse NDJSON format
205
+ */
206
+ parseNDJSON(content) {
207
+ const schemas = [];
208
+ const lines = content.split("\n").filter((line) => line.trim());
209
+ for (const line of lines) {
210
+ try {
211
+ const parsed = JSON.parse(line);
212
+ schemas.push(this.parseSchema(parsed));
213
+ }
214
+ catch (error) {
215
+ if (this.options.strict) {
216
+ throw new Error(`Failed to parse NDJSON line: ${error}`);
217
+ }
218
+ // Skip invalid lines in non-strict mode
219
+ }
220
+ }
221
+ return schemas;
222
+ }
223
+ /**
224
+ * Parse JSON format
225
+ */
226
+ parseJSON(content) {
227
+ try {
228
+ const parsed = JSON.parse(content);
229
+ if (Array.isArray(parsed)) {
230
+ return parsed.map((item) => this.parseSchema(item));
231
+ }
232
+ else {
233
+ return [this.parseSchema(parsed)];
234
+ }
235
+ }
236
+ catch (error) {
237
+ throw new Error(`Failed to parse JSON: ${error}`);
238
+ }
239
+ }
240
+ /**
241
+ * Validate schemas
242
+ */
243
+ validateSchemas(schemas) {
244
+ for (const schema of schemas) {
245
+ if (!schema.identifier) {
246
+ throw new Error("Schema missing identifier");
247
+ }
248
+ if (!this.isValidIdentifier(schema.identifier)) {
249
+ throw new Error(`Invalid identifier in schema: ${JSON.stringify(schema.identifier)}`);
250
+ }
251
+ }
252
+ }
253
+ /**
254
+ * Validate identifier structure
255
+ */
256
+ isValidIdentifier(identifier) {
257
+ return (typeof identifier === "object" &&
258
+ identifier !== null &&
259
+ typeof identifier.kind === "string" &&
260
+ typeof identifier.package === "string" &&
261
+ typeof identifier.version === "string" &&
262
+ typeof identifier.name === "string" &&
263
+ typeof identifier.url === "string");
264
+ }
265
+ /**
266
+ * Check if identifier matches criteria
267
+ */
268
+ matchesIdentifier(identifier, criteria) {
269
+ return ((!criteria.kind || identifier.kind === criteria.kind) &&
270
+ (!criteria.package || identifier.package === criteria.package) &&
271
+ (!criteria.version || identifier.version === criteria.version) &&
272
+ (!criteria.name || identifier.name === criteria.name) &&
273
+ (!criteria.url || identifier.url === criteria.url));
274
+ }
275
+ /**
276
+ * Remove duplicate dependencies
277
+ */
278
+ deduplicateDependencies(deps) {
279
+ const seen = new Set();
280
+ const unique = [];
281
+ for (const dep of deps) {
282
+ if (!seen.has(dep.url)) {
283
+ seen.add(dep.url);
284
+ unique.push(dep);
285
+ }
286
+ }
287
+ return unique.sort((a, b) => a.name.localeCompare(b.name));
288
+ }
289
+ }
290
+ /**
291
+ * Convenience function to parse TypeSchema from file
292
+ */
293
+ export async function parseTypeSchemaFromFile(filePath, options) {
294
+ const parser = new TypeSchemaParser(options);
295
+ return await parser.parseFromFile(filePath);
296
+ }
297
+ /**
298
+ * Convenience function to parse TypeSchema from string
299
+ */
300
+ export async function parseTypeSchemaFromString(content, format, options) {
301
+ const parser = new TypeSchemaParser(options);
302
+ return await parser.parseFromString(content, format);
303
+ }
304
+ /**
305
+ * Convenience function to parse TypeSchema from multiple files
306
+ */
307
+ export async function parseTypeSchemaFromFiles(filePaths, options) {
308
+ const parser = new TypeSchemaParser(options);
309
+ return await parser.parseFromFiles(filePaths);
310
+ }
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import type { CanonicalManager } from "@atomic-ehr/fhir-canonical-manager";
8
8
  import type { FHIRSchema } from "@atomic-ehr/fhirschema";
9
- import type { PackageInfo, TypeSchemaForProfile } from "../types";
9
+ import type { PackageInfo, TypeSchemaForProfile } from "../types.js";
10
10
  /**
11
11
  * Transform a FHIR profile to TypeSchema format
12
12
  * Profiles are treated as specialized resources that extend base resources
@@ -1 +1 @@
1
- {"version":3,"file":"processor.d.ts","sourceRoot":"","sources":["../../../src/typeschema/profile/processor.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAIzD,OAAO,KAAK,EACX,WAAW,EAIX,oBAAoB,EAEpB,MAAM,UAAU,CAAC;AAElB;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,EAC5C,WAAW,CAAC,EAAE,WAAW,GACvB,OAAO,CAAC,oBAAoB,CAAC,CAwF/B"}
1
+ {"version":3,"file":"processor.d.ts","sourceRoot":"","sources":["../../../src/typeschema/profile/processor.ts"],"names":[],"mappings":"AACA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAIzD,OAAO,KAAK,EACX,WAAW,EAIX,oBAAoB,EAEpB,MAAM,aAAa,CAAC;AAErB;;;GAGG;AACH,wBAAsB,gBAAgB,CACrC,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,EAC5C,WAAW,CAAC,EAAE,WAAW,GACvB,OAAO,CAAC,oBAAoB,CAAC,CAwF/B"}
@@ -0,0 +1,268 @@
1
+ // @ts-nocheck
2
+ /**
3
+ * Profile Processor (DEPRECATED - Profiles not in core TypeSchema spec)
4
+ *
5
+ * Handles transformation of FHIR profiles to TypeSchema format
6
+ * This file is deprecated as profiles are not part of the core TypeSchema specification
7
+ */
8
+ import { buildSchemaIdentifier } from "../core/identifier.js";
9
+ import { transformElements } from "../core/transformer.js";
10
+ /**
11
+ * Transform a FHIR profile to TypeSchema format
12
+ * Profiles are treated as specialized resources that extend base resources
13
+ */
14
+ export async function transformProfile(fhirSchema, manager, packageInfo) {
15
+ // Build profile identifier
16
+ const identifier = buildSchemaIdentifier(fhirSchema, packageInfo);
17
+ // Ensure this is recognized as a profile
18
+ if (identifier.kind !== "profile") {
19
+ throw new Error(`Expected profile, got ${identifier.kind} for ${fhirSchema.name}`);
20
+ }
21
+ // Build base identifier - profiles always have a base
22
+ let base;
23
+ if (fhirSchema.base) {
24
+ const baseUrl = fhirSchema.base.includes("/")
25
+ ? fhirSchema.base
26
+ : `http://hl7.org/fhir/StructureDefinition/${fhirSchema.base}`;
27
+ const baseName = fhirSchema.base.split("/").pop() || fhirSchema.base;
28
+ // Determine base kind - could be another profile or a base resource
29
+ const baseKind = await determineBaseKind(baseUrl, manager);
30
+ // For standard FHIR types, use the standard package
31
+ const isStandardFhir = baseUrl.startsWith("http://hl7.org/fhir/");
32
+ base = {
33
+ kind: baseKind,
34
+ package: isStandardFhir
35
+ ? "hl7.fhir.r4.core"
36
+ : packageInfo?.name || fhirSchema.package_name || "undefined",
37
+ version: isStandardFhir
38
+ ? "4.0.1"
39
+ : packageInfo?.version || fhirSchema.package_version || "undefined",
40
+ name: baseName,
41
+ url: baseUrl,
42
+ };
43
+ }
44
+ // Initialize the profile schema
45
+ const profileSchema = {
46
+ identifier,
47
+ base: base,
48
+ dependencies: base ? [base] : [],
49
+ };
50
+ // Add description if present
51
+ if (fhirSchema.description) {
52
+ profileSchema.description = fhirSchema.description;
53
+ }
54
+ // Add profile-specific metadata
55
+ const metadata = extractProfileMetadata(fhirSchema, packageInfo);
56
+ if (Object.keys(metadata).length > 0) {
57
+ profileSchema.metadata = metadata;
58
+ }
59
+ // Process profile fields from differential elements
60
+ if (fhirSchema.elements) {
61
+ const fields = await transformElements(fhirSchema, [], fhirSchema.elements, manager, packageInfo);
62
+ if (Object.keys(fields).length > 0) {
63
+ profileSchema.fields = fields;
64
+ }
65
+ }
66
+ // Process profile constraints
67
+ const constraints = await processProfileConstraints(fhirSchema, manager);
68
+ if (Object.keys(constraints).length > 0) {
69
+ profileSchema.constraints = constraints;
70
+ }
71
+ // Process extensions
72
+ const extensions = await processProfileExtensions(fhirSchema, manager);
73
+ if (extensions.length > 0) {
74
+ profileSchema.extensions = extensions;
75
+ }
76
+ // Add validation rules
77
+ const validationRules = extractValidationRules(fhirSchema);
78
+ if (validationRules.length > 0) {
79
+ profileSchema.validation = validationRules;
80
+ }
81
+ return profileSchema;
82
+ }
83
+ /**
84
+ * Determine the kind of the base type for a profile
85
+ */
86
+ async function determineBaseKind(baseUrl, manager) {
87
+ try {
88
+ // Try to resolve the base schema
89
+ const baseSchema = await manager.resolve(baseUrl);
90
+ if (baseSchema) {
91
+ // If it's also a constraint, it's likely another profile
92
+ if (baseSchema.derivation === "constraint") {
93
+ return "profile";
94
+ }
95
+ // Otherwise, use the base schema's kind
96
+ if (baseSchema.kind === "resource")
97
+ return "resource";
98
+ if (baseSchema.kind === "complex-type")
99
+ return "complex-type";
100
+ }
101
+ }
102
+ catch (error) {
103
+ // If we can't resolve, make a reasonable guess
104
+ console.warn(`Could not resolve base schema ${baseUrl}:`, error);
105
+ }
106
+ // Check if the URL suggests it's a profile from any implementation guide
107
+ // Non-standard FHIR StructureDefinition URLs (not from base FHIR) are likely profiles
108
+ // Check if it's any other profile URL pattern
109
+ if (baseUrl.includes("StructureDefinition/") &&
110
+ !baseUrl.startsWith("http://hl7.org/fhir/StructureDefinition/")) {
111
+ // Non-standard FHIR StructureDefinition URLs are likely profiles
112
+ return "profile";
113
+ }
114
+ // Default to resource for profiles
115
+ return "resource";
116
+ }
117
+ /**
118
+ * Extract profile metadata from FHIR schema
119
+ */
120
+ function extractProfileMetadata(fhirSchema, packageInfo) {
121
+ const metadata = {};
122
+ // Add profile-specific metadata
123
+ // @ts-ignore
124
+ if (fhirSchema.publisher)
125
+ metadata.publisher = fhirSchema.publisher;
126
+ // @ts-ignore
127
+ if (fhirSchema.contact)
128
+ metadata.contact = fhirSchema.contact;
129
+ // @ts-ignore
130
+ if (fhirSchema.copyright)
131
+ metadata.copyright = fhirSchema.copyright;
132
+ // @ts-ignore
133
+ if (fhirSchema.purpose)
134
+ metadata.purpose = fhirSchema.purpose;
135
+ // @ts-ignore
136
+ if (fhirSchema.experimental !== undefined) {
137
+ // @ts-ignore
138
+ metadata.experimental = fhirSchema.experimental;
139
+ }
140
+ // @ts-ignore
141
+ if (fhirSchema.date)
142
+ metadata.date = fhirSchema.date;
143
+ // @ts-ignore
144
+ if (fhirSchema.jurisdiction)
145
+ metadata.jurisdiction = fhirSchema.jurisdiction;
146
+ // Add package-specific metadata from packageInfo or schema
147
+ // @ts-ignore
148
+ if (packageInfo?.name) {
149
+ metadata.package = packageInfo.name;
150
+ // @ts-ignore
151
+ }
152
+ else if (fhirSchema.package_name) {
153
+ // @ts-ignore
154
+ metadata.package = fhirSchema.package_name;
155
+ }
156
+ return metadata;
157
+ }
158
+ /**
159
+ * Process profile constraints from FHIR schema elements
160
+ */
161
+ async function processProfileConstraints(fhirSchema, _manager) {
162
+ const constraints = {};
163
+ if (!fhirSchema.elements)
164
+ return constraints;
165
+ // Process each element for constraints
166
+ for (const [path, element] of Object.entries(fhirSchema.elements)) {
167
+ const elementConstraints = {};
168
+ // Cardinality constraints
169
+ if (element.min !== undefined)
170
+ elementConstraints.min = element.min;
171
+ if (element.max !== undefined)
172
+ elementConstraints.max = String(element.max);
173
+ // Must Support elements
174
+ if (element.mustSupport)
175
+ elementConstraints.mustSupport = true;
176
+ // Fixed values
177
+ // @ts-ignore
178
+ if (element.fixedValue !== undefined)
179
+ // @ts-ignore
180
+ elementConstraints.fixedValue = element.fixedValue;
181
+ // @ts-ignore
182
+ if (element.patternValue !== undefined)
183
+ // @ts-ignore
184
+ elementConstraints.patternValue = element.patternValue;
185
+ // Value set bindings
186
+ if (element.binding) {
187
+ elementConstraints.binding = {
188
+ strength: element.binding.strength,
189
+ valueSet: element.binding.valueSet ?? "",
190
+ };
191
+ }
192
+ // Type constraints
193
+ if (element.type &&
194
+ Array.isArray(element.type) &&
195
+ element.type.length > 0) {
196
+ elementConstraints.types = element.type.map((t) => {
197
+ const typeConstraint = { code: t.code };
198
+ if (t.profile)
199
+ typeConstraint.profile = t.profile;
200
+ if (t.targetProfile)
201
+ typeConstraint.targetProfile = t.targetProfile;
202
+ return typeConstraint;
203
+ });
204
+ }
205
+ // Slicing information
206
+ if (element.slicing) {
207
+ elementConstraints.slicing = {
208
+ discriminator: element.slicing.discriminator ?? [],
209
+ rules: String(element.slicing),
210
+ ordered: element.slicing.ordered,
211
+ };
212
+ }
213
+ if (Object.keys(elementConstraints).length > 0) {
214
+ constraints[path] = elementConstraints;
215
+ }
216
+ }
217
+ return constraints;
218
+ }
219
+ /**
220
+ * Process profile extensions
221
+ */
222
+ async function processProfileExtensions(fhirSchema, _manager) {
223
+ const extensions = [];
224
+ if (!fhirSchema.elements)
225
+ return extensions;
226
+ // Look for extension elements
227
+ for (const [path, element] of Object.entries(fhirSchema.elements)) {
228
+ if (path.includes("extension") &&
229
+ element.type &&
230
+ Array.isArray(element.type)) {
231
+ for (const type of element.type) {
232
+ if (type.code === "Extension" && type.profile) {
233
+ extensions.push({
234
+ path,
235
+ profile: type.profile,
236
+ min: element.min,
237
+ max: String(element.max),
238
+ mustSupport: element.mustSupport,
239
+ });
240
+ }
241
+ }
242
+ }
243
+ }
244
+ return extensions;
245
+ }
246
+ /**
247
+ * Extract validation rules from profile
248
+ */
249
+ function extractValidationRules(fhirSchema) {
250
+ const rules = [];
251
+ if (!fhirSchema.elements)
252
+ return rules;
253
+ // Extract invariants and constraints
254
+ for (const [path, element] of Object.entries(fhirSchema.elements)) {
255
+ if (element.constraint && Array.isArray(element.constraint)) {
256
+ for (const constraint of element.constraint) {
257
+ rules.push({
258
+ path,
259
+ key: constraint.key,
260
+ severity: constraint.severity,
261
+ human: constraint.human,
262
+ expression: constraint.expression,
263
+ });
264
+ }
265
+ }
266
+ }
267
+ return rules;
268
+ }