babelfhir-ts 1.0.32 → 1.0.34
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/README.md +30 -11
- package/out/generator/cacheConfig.js +181 -0
- package/out/generator/classGenerator.js +1061 -19
- package/out/generator/clientGenerator.js +705 -0
- package/out/generator/fetchUtils.js +146 -0
- package/out/generator/fhirDataTypes.json +858 -0
- package/out/generator/fhirR4Rules.js +9 -6
- package/out/generator/importManager.js +36 -13
- package/out/generator/index.js +696 -65
- package/out/generator/interfaceGenerator.js +214 -74
- package/out/generator/packageManager.js +92 -13
- package/out/generator/packageParser.js +90 -39
- package/out/generator/postProcessExtensions.js +50 -23
- package/out/generator/randomSupportGenerator.js +624 -53
- package/out/generator/sdParser.js +392 -97
- package/out/generator/utils.js +97 -6
- package/out/generator/validatorGenerator.js +187 -68
- package/out/generator/vsParser.js +6 -4
- package/out/logger.js +237 -31
- package/out/main.js +154 -74
- package/package.json +9 -17
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="./
|
|
2
|
+
<img src="./logo_transparent.png" alt="BabelFHIR-TS Logo" width="200"/>
|
|
3
3
|
</div>
|
|
4
4
|
|
|
5
5
|
# BabelFHIR-TS
|
|
@@ -22,6 +22,22 @@
|
|
|
22
22
|
- **Fast and lightweight**—minimal runtime deps; only `fhirpath` is required for validators
|
|
23
23
|
- **Install any FHIR profile as a node module**—use `babelfhir-ts install` to add Implementation Guides directly to your project
|
|
24
24
|
|
|
25
|
+
<!-- PARITY-BADGES:START - Do not remove or modify this section -->
|
|
26
|
+
## Pipeline Parity Results
|
|
27
|
+
|
|
28
|
+
BabelFHIR-TS validators achieve **100% parity** with the Firely .NET SDK validator across major Implementation Guides:
|
|
29
|
+
|
|
30
|
+

|
|
31
|
+

|
|
32
|
+

|
|
33
|
+

|
|
34
|
+

|
|
35
|
+
|
|
36
|
+
> **11 profiles excluded** due to [Firely SDK bugs](./docs/FIRELY-VALIDATOR-BUGS.md) — validated successfully with HL7 Java Validator.
|
|
37
|
+
|
|
38
|
+
📊 **[Full Report](https://gist.github.com/quotentiroler/e9bc625cfe88a0a67a73abc06660f40f)** · *Last updated: Dec 10, 2025*
|
|
39
|
+
<!-- PARITY-BADGES:END -->
|
|
40
|
+
|
|
25
41
|
## Installation
|
|
26
42
|
|
|
27
43
|
Install globally (recommended when using the CLI frequently):
|
|
@@ -125,6 +141,7 @@ babelfhir-ts [options] [<input> [output]]
|
|
|
125
141
|
| `--log <level>` | Control logging output:`none` (default), `console`, or `file`. |
|
|
126
142
|
| `--no-cache` | Remove the `.cache` directory once generation completes. |
|
|
127
143
|
| `--no-classes` | Skip emitting helper classes (interfaces & validators only). |
|
|
144
|
+
| `--cache-dir <path>` | Custom cache directory (default:`.cache`). Also configurable via `FHIR_CACHE_ROOT` env var. |
|
|
128
145
|
| `-h, --help` | Print usage help. |
|
|
129
146
|
| `-v, --version` | Print the BabelFHIR-TS version. |
|
|
130
147
|
|
|
@@ -136,12 +153,12 @@ babelfhir-ts [options] [<input> [output]]
|
|
|
136
153
|
|
|
137
154
|
## Scripts for contributors
|
|
138
155
|
|
|
139
|
-
| Script
|
|
140
|
-
|
|
|
141
|
-
| `npm run generate`
|
|
142
|
-
| `npm run generate:check`
|
|
143
|
-
| `npm test`
|
|
144
|
-
| `npm test
|
|
156
|
+
| Script | Purpose |
|
|
157
|
+
| --------------------------- | ---------------------------------------------------------------------------- |
|
|
158
|
+
| `npm run generate` | Execute the CLI against the local `input/` folder and refresh `output/`. |
|
|
159
|
+
| `npm run generate:check` | End-to-end check: generate, type-check, and lint the emitted output. |
|
|
160
|
+
| `npm test` | Type-check and run all Vitest suites (coverage enabled). |
|
|
161
|
+
| `npm test pipelineParity` | Run pipeline parity tests against Firely .NET SDK validator. |
|
|
145
162
|
|
|
146
163
|
## Caching notes
|
|
147
164
|
|
|
@@ -166,6 +183,7 @@ BabelFHIR-TS is a code generation tool that parses FHIR StructureDefinitions and
|
|
|
166
183
|
### Validation Scope
|
|
167
184
|
|
|
168
185
|
The generated `validate()` methods DO check:
|
|
186
|
+
|
|
169
187
|
- **FHIRPath constraints** from StructureDefinition invariants
|
|
170
188
|
- **Cardinality rules** (min/max occurrences)
|
|
171
189
|
- **Required fields** from profiles
|
|
@@ -174,12 +192,13 @@ The generated `validate()` methods DO check:
|
|
|
174
192
|
- **Data type correctness** (string, number, boolean, etc.)
|
|
175
193
|
|
|
176
194
|
The generated validators DO NOT check:
|
|
195
|
+
|
|
177
196
|
- **Terminology validation** (ValueSet expansion, code system membership) - requires terminology server
|
|
178
197
|
- **Reference resolution** (checking that referenced resources exist) - requires FHIR server
|
|
179
198
|
- **Complex discriminator types** (type, profile, exists, position) - only pattern/value discriminators supported
|
|
180
199
|
- **Cross-resource business rules** - application-specific logic
|
|
181
200
|
|
|
182
|
-
For comprehensive conformance testing, use the official [HL7 FHIR Validator](https://confluence.hl7.org/display/FHIR/Using+the+FHIR+Validator)
|
|
201
|
+
For comprehensive conformance testing, use the official [HL7 FHIR Validator](https://confluence.hl7.org/display/FHIR/Using+the+FHIR+Validator)!
|
|
183
202
|
|
|
184
203
|
### TypeScript Limitations
|
|
185
204
|
|
|
@@ -190,14 +209,14 @@ For comprehensive conformance testing, use the official [HL7 FHIR Validator](htt
|
|
|
190
209
|
### Generated Helper Methods
|
|
191
210
|
|
|
192
211
|
- **`random()` is not fully conformant**: The generated `.random()` methods create test data that satisfies TypeScript types and basic cardinality, but **do not guarantee** fully valid FHIR resources. Random data may violate:
|
|
212
|
+
|
|
193
213
|
- Complex FHIRPath invariants
|
|
194
214
|
- ValueSet bindings (codes are randomly chosen from required bindings but not guaranteed to be semantically correct)
|
|
195
215
|
- Profile-specific business rules
|
|
196
216
|
- Reference integrity constraints
|
|
197
|
-
|
|
198
|
-
Use `random()` for development, testing, and prototyping, but always validate production data on the FHIR server side.
|
|
199
217
|
|
|
200
|
-
|
|
218
|
+
Use `random()` for development, testing, and prototyping, but always validate production data on the FHIR server side.
|
|
219
|
+
- **`validate()` parity**: The generated validation methods execute FHIRPath expressions and check constraints from StructureDefinitions, but are **only guaranteed to match** the Firely .NET SDK validator for scenarios covered by our test suite (see GitHub actions). Edge cases, complex slicing patterns, or profiles not in our test pipeline may produce different results. For production conformance testing, use the official [HL7 FHIR Validator](https://confluence.hl7.org/display/FHIR/Using+the+FHIR+Validator) as the source of truth.
|
|
201
220
|
|
|
202
221
|
### FHIR Version Support
|
|
203
222
|
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized cache configuration for the FHIR TypeScript generator.
|
|
3
|
+
*
|
|
4
|
+
* This module provides a unified approach to cache management across the project.
|
|
5
|
+
*
|
|
6
|
+
* Cache Structure:
|
|
7
|
+
* Root cache directory: configurable via environment variable or defaults to .cache
|
|
8
|
+
* FHIR packages: cacheRoot/.fhir/packages/packageName@version/
|
|
9
|
+
* FHIR resources (StructureDefinitions): cacheRoot/fhir-resources/
|
|
10
|
+
* Temporary files: cacheRoot/tmp/
|
|
11
|
+
*
|
|
12
|
+
* Environment Variables:
|
|
13
|
+
* FHIR_CACHE_ROOT: Override the root cache directory (useful for CI)
|
|
14
|
+
* FHIR_CACHE_LOCAL: If set to "true", use package-local cache (in output directory)
|
|
15
|
+
*/
|
|
16
|
+
import * as path from 'path';
|
|
17
|
+
import * as fs from 'fs';
|
|
18
|
+
// Module-level state for cache configuration
|
|
19
|
+
let currentConfig = null;
|
|
20
|
+
/**
|
|
21
|
+
* Get the default cache root directory based on environment
|
|
22
|
+
*/
|
|
23
|
+
function getDefaultCacheRoot() {
|
|
24
|
+
// Check for explicit override
|
|
25
|
+
if (process.env.FHIR_CACHE_ROOT) {
|
|
26
|
+
return process.env.FHIR_CACHE_ROOT;
|
|
27
|
+
}
|
|
28
|
+
// Default to .cache in current working directory
|
|
29
|
+
return path.join(process.cwd(), '.cache');
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get the cache mode based on environment
|
|
33
|
+
*/
|
|
34
|
+
function getDefaultCacheMode() {
|
|
35
|
+
if (process.env.FHIR_CACHE_LOCAL === 'true') {
|
|
36
|
+
return 'local';
|
|
37
|
+
}
|
|
38
|
+
return 'global';
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Initialize or get the current cache configuration
|
|
42
|
+
*/
|
|
43
|
+
export function getCacheConfig() {
|
|
44
|
+
if (!currentConfig) {
|
|
45
|
+
currentConfig = {
|
|
46
|
+
rootDir: getDefaultCacheRoot(),
|
|
47
|
+
mode: getDefaultCacheMode(),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return currentConfig;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Override the cache configuration (useful for testing or CLI options)
|
|
54
|
+
*/
|
|
55
|
+
export function setCacheConfig(config) {
|
|
56
|
+
const current = getCacheConfig();
|
|
57
|
+
currentConfig = {
|
|
58
|
+
...current,
|
|
59
|
+
...config,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Reset cache configuration to defaults (useful for testing)
|
|
64
|
+
*/
|
|
65
|
+
export function resetCacheConfig() {
|
|
66
|
+
currentConfig = null;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get the FHIR packages cache directory
|
|
70
|
+
* This is where downloaded FHIR packages (tgz files) are stored
|
|
71
|
+
*/
|
|
72
|
+
export function getFhirPackagesCacheDir() {
|
|
73
|
+
const config = getCacheConfig();
|
|
74
|
+
return path.join(config.rootDir, '.fhir', 'packages');
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get the FHIR resources cache directory
|
|
78
|
+
* This is where fetched StructureDefinitions are cached
|
|
79
|
+
*/
|
|
80
|
+
export function getFhirResourcesCacheDir() {
|
|
81
|
+
const config = getCacheConfig();
|
|
82
|
+
return path.join(config.rootDir, 'fhir-resources');
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get the temporary files directory
|
|
86
|
+
*/
|
|
87
|
+
export function getTempCacheDir() {
|
|
88
|
+
const config = getCacheConfig();
|
|
89
|
+
return path.join(config.rootDir, 'tmp');
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get the path for a specific FHIR package
|
|
93
|
+
* @param packageName The package name (e.g., "hl7.fhir.us.core")
|
|
94
|
+
* @param version The package version (e.g., "8.0.0")
|
|
95
|
+
*/
|
|
96
|
+
export function getPackageCachePath(packageName, version) {
|
|
97
|
+
const packagesDir = getFhirPackagesCacheDir();
|
|
98
|
+
return path.join(packagesDir, `${packageName}@${version}`);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get the path for a package tgz file
|
|
102
|
+
* @param packageName The package name
|
|
103
|
+
* @param version The package version
|
|
104
|
+
*/
|
|
105
|
+
export function getPackageTgzPath(packageName, version) {
|
|
106
|
+
const packagesDir = getFhirPackagesCacheDir();
|
|
107
|
+
return path.join(packagesDir, `${packageName}-${version}.tgz`);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Get the path for a cached FHIR resource (StructureDefinition)
|
|
111
|
+
* @param url The canonical URL of the resource
|
|
112
|
+
*/
|
|
113
|
+
export function getResourceCachePath(url) {
|
|
114
|
+
const resourcesDir = getFhirResourcesCacheDir();
|
|
115
|
+
// Convert URL to safe filename
|
|
116
|
+
const filename = url.replace(/[^a-zA-Z0-9]/g, '_') + '.json';
|
|
117
|
+
return path.join(resourcesDir, filename);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Ensure a cache directory exists
|
|
121
|
+
*/
|
|
122
|
+
export function ensureCacheDir(dir) {
|
|
123
|
+
if (!fs.existsSync(dir)) {
|
|
124
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Ensure all cache directories exist
|
|
129
|
+
*/
|
|
130
|
+
export function ensureAllCacheDirs() {
|
|
131
|
+
ensureCacheDir(getFhirPackagesCacheDir());
|
|
132
|
+
ensureCacheDir(getFhirResourcesCacheDir());
|
|
133
|
+
ensureCacheDir(getTempCacheDir());
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Clear a specific cache directory
|
|
137
|
+
*/
|
|
138
|
+
export function clearCacheDir(dir) {
|
|
139
|
+
if (fs.existsSync(dir)) {
|
|
140
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Clear all caches
|
|
145
|
+
*/
|
|
146
|
+
export function clearAllCaches() {
|
|
147
|
+
const config = getCacheConfig();
|
|
148
|
+
if (fs.existsSync(config.rootDir)) {
|
|
149
|
+
fs.rmSync(config.rootDir, { recursive: true, force: true });
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Get cache statistics for debugging
|
|
154
|
+
*/
|
|
155
|
+
export function getCacheStats() {
|
|
156
|
+
const config = getCacheConfig();
|
|
157
|
+
const packagesDir = getFhirPackagesCacheDir();
|
|
158
|
+
const resourcesDir = getFhirResourcesCacheDir();
|
|
159
|
+
let packageCount = 0;
|
|
160
|
+
let resourceCount = 0;
|
|
161
|
+
try {
|
|
162
|
+
if (fs.existsSync(packagesDir)) {
|
|
163
|
+
packageCount = fs.readdirSync(packagesDir).filter(f => fs.statSync(path.join(packagesDir, f)).isDirectory()).length;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch { /* ignore */ }
|
|
167
|
+
try {
|
|
168
|
+
if (fs.existsSync(resourcesDir)) {
|
|
169
|
+
resourceCount = fs.readdirSync(resourcesDir).filter(f => f.endsWith('.json')).length;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
catch { /* ignore */ }
|
|
173
|
+
return {
|
|
174
|
+
rootDir: config.rootDir,
|
|
175
|
+
mode: config.mode,
|
|
176
|
+
packagesDir,
|
|
177
|
+
resourcesDir,
|
|
178
|
+
packageCount,
|
|
179
|
+
resourceCount,
|
|
180
|
+
};
|
|
181
|
+
}
|