@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.
- package/dist/api/builder.d.ts +3 -3
- package/dist/api/builder.d.ts.map +1 -1
- package/dist/api/builder.js +374 -0
- package/dist/api/generators/base/BaseGenerator.d.ts +4 -4
- package/dist/api/generators/base/BaseGenerator.d.ts.map +1 -1
- package/dist/api/generators/base/BaseGenerator.js +572 -0
- package/dist/api/generators/base/FileManager.d.ts +2 -2
- package/dist/api/generators/base/FileManager.d.ts.map +1 -1
- package/dist/api/generators/base/FileManager.js +204 -0
- package/dist/api/generators/base/PythonTypeMapper.d.ts +2 -2
- package/dist/api/generators/base/PythonTypeMapper.d.ts.map +1 -1
- package/dist/api/generators/base/PythonTypeMapper.js +71 -0
- package/dist/api/generators/base/TemplateEngine.d.ts +1 -1
- package/dist/api/generators/base/TemplateEngine.d.ts.map +1 -1
- package/dist/api/generators/base/TemplateEngine.js +133 -0
- package/dist/api/generators/base/TypeMapper.js +153 -0
- package/dist/api/generators/base/TypeScriptTypeMapper.d.ts +1 -1
- package/dist/api/generators/base/TypeScriptTypeMapper.d.ts.map +1 -1
- package/dist/api/generators/base/TypeScriptTypeMapper.js +232 -0
- package/dist/api/generators/base/builders/DirectoryBuilder.d.ts +4 -4
- package/dist/api/generators/base/builders/DirectoryBuilder.d.ts.map +1 -1
- package/dist/api/generators/base/builders/DirectoryBuilder.js +215 -0
- package/dist/api/generators/base/builders/FileBuilder.d.ts +2 -2
- package/dist/api/generators/base/builders/FileBuilder.d.ts.map +1 -1
- package/dist/api/generators/base/builders/FileBuilder.js +408 -0
- package/dist/api/generators/base/builders/IndexBuilder.d.ts +2 -2
- package/dist/api/generators/base/builders/IndexBuilder.d.ts.map +1 -1
- package/dist/api/generators/base/builders/IndexBuilder.js +290 -0
- package/dist/api/generators/base/enhanced-errors.d.ts +2 -2
- package/dist/api/generators/base/enhanced-errors.d.ts.map +1 -1
- package/dist/api/generators/base/enhanced-errors.js +259 -0
- package/dist/api/generators/base/error-handler.d.ts +1 -1
- package/dist/api/generators/base/error-handler.d.ts.map +1 -1
- package/dist/api/generators/base/error-handler.js +243 -0
- package/dist/api/generators/base/errors.d.ts +2 -2
- package/dist/api/generators/base/errors.d.ts.map +1 -1
- package/dist/api/generators/base/errors.js +694 -0
- package/dist/api/generators/base/index.d.ts +22 -22
- package/dist/api/generators/base/index.d.ts.map +1 -1
- package/dist/api/generators/base/index.js +161 -0
- package/dist/api/generators/base/types.d.ts +2 -2
- package/dist/api/generators/base/types.d.ts.map +1 -1
- package/dist/api/generators/base/types.js +12 -0
- package/dist/api/generators/rest-client.d.ts +2 -2
- package/dist/api/generators/rest-client.d.ts.map +1 -1
- package/dist/api/generators/rest-client.js +847 -0
- package/dist/api/generators/search-parameter-enhancer.d.ts +1 -1
- package/dist/api/generators/search-parameter-enhancer.d.ts.map +1 -1
- package/dist/api/generators/search-parameter-enhancer.js +801 -0
- package/dist/api/generators/types.js +4 -0
- package/dist/api/generators/typescript.d.ts +3 -3
- package/dist/api/generators/typescript.d.ts.map +1 -1
- package/dist/api/generators/typescript.js +537 -0
- package/dist/api/generators/validation-generator.js +632 -0
- package/dist/api/index.d.ts +10 -10
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +51 -0
- package/dist/cli/commands/generate/typescript.d.ts +1 -1
- package/dist/cli/commands/generate/typescript.d.ts.map +1 -1
- package/dist/cli/commands/generate/typescript.js +52 -0
- package/dist/cli/commands/generate.d.ts +5 -12
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +158 -0
- package/dist/cli/commands/index.d.ts +2 -1
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +100 -0
- package/dist/cli/commands/typeschema/generate.js +130 -0
- package/dist/cli/commands/typeschema.js +48 -0
- package/dist/cli/index.js +12 -8664
- package/dist/cli/utils/log.d.ts +2 -2
- package/dist/cli/utils/log.d.ts.map +1 -1
- package/dist/cli/utils/log.js +23 -0
- package/dist/cli/utils/prompts.js +224 -0
- package/dist/cli/utils/spinner.js +270 -0
- package/dist/config.d.ts +22 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +703 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +84 -38
- package/dist/logger.js +290 -0
- package/dist/typeschema/cache.d.ts +2 -2
- package/dist/typeschema/cache.d.ts.map +1 -1
- package/dist/typeschema/cache.js +285 -0
- package/dist/typeschema/core/binding.d.ts +1 -1
- package/dist/typeschema/core/binding.d.ts.map +1 -1
- package/dist/typeschema/core/binding.js +187 -0
- package/dist/typeschema/core/field-builder.d.ts +1 -1
- package/dist/typeschema/core/field-builder.d.ts.map +1 -1
- package/dist/typeschema/core/field-builder.js +259 -0
- package/dist/typeschema/core/identifier.js +117 -0
- package/dist/typeschema/core/nested-types.d.ts +1 -1
- package/dist/typeschema/core/nested-types.d.ts.map +1 -1
- package/dist/typeschema/core/nested-types.js +111 -0
- package/dist/typeschema/core/transformer.d.ts +2 -2
- package/dist/typeschema/core/transformer.d.ts.map +1 -1
- package/dist/typeschema/core/transformer.js +345 -0
- package/dist/typeschema/generator.d.ts +3 -3
- package/dist/typeschema/generator.d.ts.map +1 -1
- package/dist/typeschema/generator.js +352 -0
- package/dist/typeschema/index.d.ts +14 -14
- package/dist/typeschema/index.d.ts.map +1 -1
- package/dist/typeschema/index.js +92 -0
- package/dist/typeschema/parser.d.ts +2 -2
- package/dist/typeschema/parser.d.ts.map +1 -1
- package/dist/typeschema/parser.js +310 -0
- package/dist/typeschema/profile/processor.d.ts +1 -1
- package/dist/typeschema/profile/processor.d.ts.map +1 -1
- package/dist/typeschema/profile/processor.js +268 -0
- package/dist/typeschema/schema.js +456 -0
- package/dist/typeschema/type-schema.types.js +39 -0
- package/dist/typeschema/types.js +4 -0
- package/dist/typeschema/utils.d.ts +1 -1
- package/dist/typeschema/utils.d.ts.map +1 -1
- package/dist/typeschema/utils.js +13 -0
- package/dist/typeschema/value-set/processor.d.ts +1 -1
- package/dist/typeschema/value-set/processor.d.ts.map +1 -1
- package/dist/typeschema/value-set/processor.js +168 -0
- package/dist/utils/codegen-logger.js +204 -0
- package/dist/utils.js +42 -0
- package/package.json +15 -4
- package/dist/index-e7pfye24.js +0 -8532
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeSchema Cache System
|
|
3
|
+
*
|
|
4
|
+
* Caching system for TypeSchema documents with both in-memory and persistent file-based storage.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
7
|
+
import { readdir, readFile, stat, unlink, writeFile } from "node:fs/promises";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
/**
|
|
10
|
+
* TypeSchema Cache with optional persistent storage
|
|
11
|
+
*/
|
|
12
|
+
export class TypeSchemaCache {
|
|
13
|
+
cache = new Map();
|
|
14
|
+
config;
|
|
15
|
+
cacheDir;
|
|
16
|
+
constructor(config) {
|
|
17
|
+
this.config = {
|
|
18
|
+
enablePersistence: true,
|
|
19
|
+
cacheDir: ".typeschema-cache",
|
|
20
|
+
maxAge: 24 * 60 * 60 * 1000, // 24 hours
|
|
21
|
+
validateCached: true,
|
|
22
|
+
...config,
|
|
23
|
+
};
|
|
24
|
+
if (this.config.enablePersistence && this.config.cacheDir) {
|
|
25
|
+
this.cacheDir = this.config.cacheDir;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Store a schema in the cache
|
|
30
|
+
*/
|
|
31
|
+
async set(schema) {
|
|
32
|
+
const key = this.generateKey(schema.identifier);
|
|
33
|
+
this.cache.set(key, schema);
|
|
34
|
+
// Persist to disk if enabled
|
|
35
|
+
if (this.config.enablePersistence && this.cacheDir) {
|
|
36
|
+
await this.persistSchema(schema);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Retrieve a schema by identifier
|
|
41
|
+
*/
|
|
42
|
+
get(identifier) {
|
|
43
|
+
const key = this.generateKey(identifier);
|
|
44
|
+
return this.cache.get(key) || null;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Retrieve a schema by URL
|
|
48
|
+
*/
|
|
49
|
+
getByUrl(url) {
|
|
50
|
+
for (const schema of this.cache.values()) {
|
|
51
|
+
if (schema.identifier.url === url) {
|
|
52
|
+
return schema;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Check if a schema exists in cache
|
|
59
|
+
*/
|
|
60
|
+
has(identifier) {
|
|
61
|
+
const key = this.generateKey(identifier);
|
|
62
|
+
return this.cache.has(key);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Check if a schema exists by URL
|
|
66
|
+
*/
|
|
67
|
+
hasByUrl(url) {
|
|
68
|
+
for (const schema of this.cache.values()) {
|
|
69
|
+
if (schema.identifier.url === url) {
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Delete a schema from cache
|
|
77
|
+
*/
|
|
78
|
+
delete(identifier) {
|
|
79
|
+
const key = this.generateKey(identifier);
|
|
80
|
+
return this.cache.delete(key);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Delete a schema by URL
|
|
84
|
+
*/
|
|
85
|
+
deleteByUrl(url) {
|
|
86
|
+
for (const [key, schema] of this.cache.entries()) {
|
|
87
|
+
if (schema.identifier.url === url) {
|
|
88
|
+
return this.cache.delete(key);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get schemas by package
|
|
95
|
+
*/
|
|
96
|
+
getByPackage(packageName) {
|
|
97
|
+
const results = [];
|
|
98
|
+
for (const schema of this.cache.values()) {
|
|
99
|
+
if (schema.identifier.package === packageName) {
|
|
100
|
+
results.push(schema);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return results;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get schemas by kind
|
|
107
|
+
*/
|
|
108
|
+
getByKind(kind) {
|
|
109
|
+
const results = [];
|
|
110
|
+
for (const schema of this.cache.values()) {
|
|
111
|
+
if (schema.identifier.kind === kind) {
|
|
112
|
+
results.push(schema);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return results;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Store multiple schemas
|
|
119
|
+
*/
|
|
120
|
+
setMany(schemas) {
|
|
121
|
+
for (const schema of schemas) {
|
|
122
|
+
this.set(schema);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Clear all cached schemas
|
|
127
|
+
*/
|
|
128
|
+
clear() {
|
|
129
|
+
this.cache.clear();
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Generate cache key for identifier
|
|
133
|
+
*/
|
|
134
|
+
generateKey(identifier) {
|
|
135
|
+
return `${identifier.package}:${identifier.version}:${identifier.kind}:${identifier.name}`;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Initialize cache directory if persistence is enabled
|
|
139
|
+
*/
|
|
140
|
+
async initialize() {
|
|
141
|
+
if (this.config.enablePersistence && this.cacheDir) {
|
|
142
|
+
// Ensure cache directory exists
|
|
143
|
+
if (!existsSync(this.cacheDir)) {
|
|
144
|
+
mkdirSync(this.cacheDir, { recursive: true });
|
|
145
|
+
}
|
|
146
|
+
// Load all cached schemas from disk
|
|
147
|
+
await this.loadFromDisk();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Load all cached schemas from disk
|
|
152
|
+
*/
|
|
153
|
+
async loadFromDisk() {
|
|
154
|
+
if (!this.cacheDir || !existsSync(this.cacheDir)) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
try {
|
|
158
|
+
const files = await readdir(this.cacheDir);
|
|
159
|
+
const schemaFiles = files.filter((f) => f.endsWith(".typeschema.json"));
|
|
160
|
+
for (const file of schemaFiles) {
|
|
161
|
+
const filePath = join(this.cacheDir, file);
|
|
162
|
+
const stats = await stat(filePath);
|
|
163
|
+
// Check if cache is expired
|
|
164
|
+
if (this.config.maxAge) {
|
|
165
|
+
const age = Date.now() - stats.mtimeMs;
|
|
166
|
+
if (age > this.config.maxAge) {
|
|
167
|
+
// Remove expired cache file
|
|
168
|
+
await unlink(filePath);
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
const content = await readFile(filePath, "utf-8");
|
|
174
|
+
const metadata = JSON.parse(content);
|
|
175
|
+
// Validate cached schema if configured
|
|
176
|
+
if (this.config.validateCached) {
|
|
177
|
+
// Basic validation - check required fields
|
|
178
|
+
if (!metadata.schema?.identifier) {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Add to in-memory cache
|
|
183
|
+
const key = this.generateKey(metadata.schema.identifier);
|
|
184
|
+
this.cache.set(key, metadata.schema);
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
console.warn(`Failed to load cached schema from ${file}:`, error);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
console.warn("Failed to load cached schemas from disk:", error);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Persist a schema to disk
|
|
197
|
+
*/
|
|
198
|
+
async persistSchema(schema) {
|
|
199
|
+
if (!this.cacheDir) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
// Ensure cache directory exists
|
|
203
|
+
if (!existsSync(this.cacheDir)) {
|
|
204
|
+
mkdirSync(this.cacheDir, { recursive: true });
|
|
205
|
+
}
|
|
206
|
+
const metadata = {
|
|
207
|
+
schema,
|
|
208
|
+
timestamp: Date.now(),
|
|
209
|
+
version: schema.identifier.version,
|
|
210
|
+
};
|
|
211
|
+
// Generate filename from identifier
|
|
212
|
+
const fileName = `${schema.identifier.package}-${schema.identifier.version}-${schema.identifier.kind}-${schema.identifier.name}.typeschema.json`.replace(/[^a-zA-Z0-9.-]/g, "_");
|
|
213
|
+
const filePath = join(this.cacheDir, fileName);
|
|
214
|
+
try {
|
|
215
|
+
await writeFile(filePath, JSON.stringify(metadata, null, 2), "utf-8");
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
console.warn(`Failed to persist schema to ${filePath}:`, error);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Clear cache directory
|
|
223
|
+
*/
|
|
224
|
+
async clearDisk() {
|
|
225
|
+
if (!this.cacheDir || !existsSync(this.cacheDir)) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
try {
|
|
229
|
+
const files = await readdir(this.cacheDir);
|
|
230
|
+
const schemaFiles = files.filter((f) => f.endsWith(".typeschema.json"));
|
|
231
|
+
for (const file of schemaFiles) {
|
|
232
|
+
await unlink(join(this.cacheDir, file));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
console.warn("Failed to clear cache directory:", error);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
// Global cache instance
|
|
241
|
+
let globalCache = null;
|
|
242
|
+
/**
|
|
243
|
+
* Get the global cache instance
|
|
244
|
+
*/
|
|
245
|
+
export function getGlobalCache(config) {
|
|
246
|
+
if (!globalCache) {
|
|
247
|
+
globalCache = new TypeSchemaCache(config);
|
|
248
|
+
}
|
|
249
|
+
return globalCache;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Initialize global cache with configuration
|
|
253
|
+
*/
|
|
254
|
+
export async function initializeGlobalCache(config) {
|
|
255
|
+
globalCache = new TypeSchemaCache(config);
|
|
256
|
+
await globalCache.initialize();
|
|
257
|
+
return globalCache;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Clear the global cache
|
|
261
|
+
*/
|
|
262
|
+
export function clearGlobalCache() {
|
|
263
|
+
if (globalCache) {
|
|
264
|
+
globalCache.clear();
|
|
265
|
+
}
|
|
266
|
+
globalCache = null;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Cache a schema using global cache
|
|
270
|
+
*/
|
|
271
|
+
export function cacheSchema(schema) {
|
|
272
|
+
getGlobalCache().set(schema);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Get cached schema using global cache
|
|
276
|
+
*/
|
|
277
|
+
export function getCachedSchema(identifier) {
|
|
278
|
+
return getGlobalCache().get(identifier);
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Check if schema is cached using global cache
|
|
282
|
+
*/
|
|
283
|
+
export function isCached(identifier) {
|
|
284
|
+
return getGlobalCache().has(identifier);
|
|
285
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
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 { PackageInfo, TypeSchemaForBinding } from "../types";
|
|
8
|
+
import type { PackageInfo, TypeSchemaForBinding } from "../types.js";
|
|
9
9
|
/**
|
|
10
10
|
* Extract concepts from a ValueSet
|
|
11
11
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../../../src/typeschema/core/binding.ts"],"names":[],"mappings":"AACA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC5E,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"binding.d.ts","sourceRoot":"","sources":["../../../src/typeschema/core/binding.ts"],"names":[],"mappings":"AACA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC5E,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAQrE;;GAEG;AACH,wBAAsB,uBAAuB,CAC5C,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GAC1C,OAAO,CACT,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,SAAS,CACrE,CA8DA;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC9B,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GAC1C,OAAO,CAAC,MAAM,EAAE,GAAG,SAAS,CAAC,CA4C/B;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAC1C,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,EAC5C,WAAW,CAAC,EAAE,WAAW,GACvB,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,CA8C3C;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAC1C,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,EAC5C,WAAW,CAAC,EAAE,WAAW,GACvB,OAAO,CAAC,oBAAoB,EAAE,CAAC,CA0DjC"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Binding and Enum Handling
|
|
4
|
+
*
|
|
5
|
+
* Functions for processing value set bindings and generating enums
|
|
6
|
+
*/
|
|
7
|
+
import { buildFieldType } from "./field-builder.js";
|
|
8
|
+
import { buildBindingIdentifier, buildValueSetIdentifier, dropVersionFromUrl, } from "./identifier.js";
|
|
9
|
+
/**
|
|
10
|
+
* Extract concepts from a ValueSet
|
|
11
|
+
*/
|
|
12
|
+
export async function extractValueSetConcepts(valueSetUrl, manager) {
|
|
13
|
+
try {
|
|
14
|
+
const cleanUrl = dropVersionFromUrl(valueSetUrl) || valueSetUrl;
|
|
15
|
+
const valueSet = await manager.resolve(cleanUrl);
|
|
16
|
+
if (!valueSet)
|
|
17
|
+
return undefined;
|
|
18
|
+
// If expansion is available, use it
|
|
19
|
+
if (valueSet.expansion?.contains) {
|
|
20
|
+
return valueSet.expansion.contains.map((concept) => ({
|
|
21
|
+
system: concept.system,
|
|
22
|
+
code: concept.code,
|
|
23
|
+
display: concept.display,
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
// Otherwise try to extract from compose
|
|
27
|
+
const concepts = [];
|
|
28
|
+
if (valueSet.compose?.include) {
|
|
29
|
+
for (const include of valueSet.compose.include) {
|
|
30
|
+
if (include.concept) {
|
|
31
|
+
// Direct concept list
|
|
32
|
+
for (const concept of include.concept) {
|
|
33
|
+
concepts.push({
|
|
34
|
+
system: include.system,
|
|
35
|
+
code: concept.code,
|
|
36
|
+
display: concept.display,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else if (include.system && !include.filter) {
|
|
41
|
+
// Include all from CodeSystem
|
|
42
|
+
try {
|
|
43
|
+
const codeSystem = await manager.resolve(include.system);
|
|
44
|
+
if (codeSystem?.concept) {
|
|
45
|
+
const extractConcepts = (conceptList, system) => {
|
|
46
|
+
for (const concept of conceptList) {
|
|
47
|
+
concepts.push({
|
|
48
|
+
system,
|
|
49
|
+
code: concept.code,
|
|
50
|
+
display: concept.display,
|
|
51
|
+
});
|
|
52
|
+
// Handle nested concepts
|
|
53
|
+
if (concept.concept) {
|
|
54
|
+
extractConcepts(concept.concept, system);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
extractConcepts(codeSystem.concept, include.system);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
// Ignore if we can't resolve the CodeSystem
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return concepts.length > 0 ? concepts : undefined;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Build enum values from binding if applicable
|
|
75
|
+
*/
|
|
76
|
+
export async function buildEnum(element, manager) {
|
|
77
|
+
if (!element.binding)
|
|
78
|
+
return undefined;
|
|
79
|
+
const { strength, valueSet } = element.binding;
|
|
80
|
+
if (!valueSet)
|
|
81
|
+
return undefined;
|
|
82
|
+
// Enhanced support for more binding strengths and types
|
|
83
|
+
// Generate enum for:
|
|
84
|
+
// 1. Required bindings (always)
|
|
85
|
+
// 2. Extensible bindings on code types (for better type safety)
|
|
86
|
+
// 3. Preferred bindings on code types (for common usage patterns)
|
|
87
|
+
const shouldGenerateEnum = strength === "required" ||
|
|
88
|
+
(strength === "extensible" && element.type === "code") ||
|
|
89
|
+
(strength === "preferred" && element.type === "code");
|
|
90
|
+
if (!shouldGenerateEnum) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
// Check if manager is available and functional
|
|
94
|
+
if (!manager.resolve) {
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
const concepts = await extractValueSetConcepts(valueSet, manager);
|
|
99
|
+
if (!concepts || concepts.length === 0)
|
|
100
|
+
return undefined;
|
|
101
|
+
// Extract just the codes and filter out any empty/invalid ones
|
|
102
|
+
const codes = concepts
|
|
103
|
+
.map((c) => c.code)
|
|
104
|
+
.filter((code) => code && typeof code === "string" && code.trim().length > 0);
|
|
105
|
+
// Only return if we have valid codes and not too many (avoid huge enums)
|
|
106
|
+
return codes.length > 0 && codes.length <= 50 ? codes : undefined;
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
// Log the error for debugging but don't fail the generation
|
|
110
|
+
console.debug(`Failed to extract enum values for ${valueSet}: ${error}`);
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Generate a binding TypeSchema
|
|
116
|
+
*/
|
|
117
|
+
export async function generateBindingSchema(fhirSchema, path, element, manager, packageInfo) {
|
|
118
|
+
if (!element.binding?.valueSet)
|
|
119
|
+
return undefined;
|
|
120
|
+
const identifier = buildBindingIdentifier(fhirSchema, path, element.binding.bindingName, packageInfo);
|
|
121
|
+
const fieldType = buildFieldType(fhirSchema, path, element, manager, packageInfo);
|
|
122
|
+
const valueSetIdentifier = buildValueSetIdentifier(element.binding.valueSet, undefined, packageInfo);
|
|
123
|
+
const binding = {
|
|
124
|
+
identifier,
|
|
125
|
+
type: fieldType,
|
|
126
|
+
valueset: valueSetIdentifier,
|
|
127
|
+
strength: element.binding.strength,
|
|
128
|
+
dependencies: [],
|
|
129
|
+
};
|
|
130
|
+
// Add dependencies in specific order: type first, then value set
|
|
131
|
+
if (fieldType) {
|
|
132
|
+
binding.dependencies.push(fieldType);
|
|
133
|
+
}
|
|
134
|
+
binding.dependencies.push(valueSetIdentifier);
|
|
135
|
+
// Add enum if applicable
|
|
136
|
+
const enumValues = await buildEnum(element, manager);
|
|
137
|
+
if (enumValues) {
|
|
138
|
+
binding.enum = enumValues;
|
|
139
|
+
}
|
|
140
|
+
// Don't sort dependencies - keep them in the order: type, then value set
|
|
141
|
+
return binding;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Collect all binding schemas from a FHIRSchema
|
|
145
|
+
*/
|
|
146
|
+
export async function collectBindingSchemas(fhirSchema, manager, packageInfo) {
|
|
147
|
+
const bindings = [];
|
|
148
|
+
const processedPaths = new Set();
|
|
149
|
+
// Recursive function to process elements
|
|
150
|
+
async function processElement(elements, parentPath) {
|
|
151
|
+
for (const [key, element] of Object.entries(elements)) {
|
|
152
|
+
const path = [...parentPath, key];
|
|
153
|
+
const pathKey = path.join(".");
|
|
154
|
+
// Skip if already processed
|
|
155
|
+
if (processedPaths.has(pathKey))
|
|
156
|
+
continue;
|
|
157
|
+
processedPaths.add(pathKey);
|
|
158
|
+
// Generate binding if present
|
|
159
|
+
if (element.binding) {
|
|
160
|
+
const binding = await generateBindingSchema(fhirSchema, path, element, manager, packageInfo);
|
|
161
|
+
if (binding) {
|
|
162
|
+
bindings.push(binding);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Process nested elements
|
|
166
|
+
if (element.elements) {
|
|
167
|
+
await processElement(element.elements, path);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Start processing from root elements
|
|
172
|
+
if (fhirSchema.elements) {
|
|
173
|
+
await processElement(fhirSchema.elements, []);
|
|
174
|
+
}
|
|
175
|
+
// Sort bindings by identifier name for consistent output
|
|
176
|
+
bindings.sort((a, b) => a.identifier.name.localeCompare(b.identifier.name));
|
|
177
|
+
// Remove duplicates (same identifier URL)
|
|
178
|
+
const uniqueBindings = [];
|
|
179
|
+
const seenUrls = new Set();
|
|
180
|
+
for (const binding of bindings) {
|
|
181
|
+
if (!seenUrls.has(binding.identifier.url)) {
|
|
182
|
+
seenUrls.add(binding.identifier.url);
|
|
183
|
+
uniqueBindings.push(binding);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return uniqueBindings;
|
|
187
|
+
}
|
|
@@ -5,7 +5,7 @@
|
|
|
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 { PackageInfo, TypeSchemaField, TypeSchemaIdentifier } from "../types";
|
|
8
|
+
import type { PackageInfo, TypeSchemaField, TypeSchemaIdentifier } from "../types.js";
|
|
9
9
|
/**
|
|
10
10
|
* Get the full element hierarchy for a given path
|
|
11
11
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-builder.d.ts","sourceRoot":"","sources":["../../../src/typeschema/core/field-builder.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC5E,OAAO,KAAK,EACX,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,MAAM,
|
|
1
|
+
{"version":3,"file":"field-builder.d.ts","sourceRoot":"","sources":["../../../src/typeschema/core/field-builder.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC5E,OAAO,KAAK,EACX,WAAW,EACX,eAAe,EACf,oBAAoB,EACpB,MAAM,aAAa,CAAC;AAQrB;;GAEG;AACH,wBAAgB,mBAAmB,CAClC,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,EAAE,EACd,QAAQ,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GAC3C,iBAAiB,EAAE,CAkBrB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACpC,SAAS,EAAE,iBAAiB,EAAE,GAC5B,iBAAiB,CAoDnB;AAED;;GAEG;AACH,wBAAgB,UAAU,CACzB,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,EAAE,EACd,QAAQ,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GAC3C,OAAO,CA4BT;AAED;;GAEG;AACH,wBAAgB,UAAU,CACzB,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,EAAE,EACd,QAAQ,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GAC3C,OAAO,CA4BT;AAED;;GAEG;AACH,wBAAsB,eAAe,CACpC,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,EAC5C,WAAW,CAAC,EAAE,WAAW,GACvB,OAAO,CAAC,oBAAoB,EAAE,GAAG,SAAS,CAAC,CAmB7C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC7B,UAAU,EAAE,UAAU,EACtB,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,EAC7C,WAAW,CAAC,EAAE,WAAW,GACvB,oBAAoB,GAAG,SAAS,CAqClC;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC/B,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,EAC5C,WAAW,CAAC,EAAE,WAAW,GACvB,OAAO,CAAC,eAAe,CAAC,CAiD1B;AAoBD;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAMnE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC/B,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,EAC5C,WAAW,CAAC,EAAE,WAAW,GACvB,eAAe,CAOjB"}
|