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 CHANGED
@@ -1,5 +1,5 @@
1
1
  <div align="center">
2
- <img src="./logo.png" alt="BabelFHIR-TS Logo" width="200"/>
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
+ ![US Core 8.0.0](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/quotentiroler/e9bc625cfe88a0a67a73abc06660f40f/raw/badge-us-core.json)
31
+ ![ISiK Basis 4.0.3](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/quotentiroler/e9bc625cfe88a0a67a73abc06660f40f/raw/badge-isik-basis.json)
32
+ ![IPS 2.0.0](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/quotentiroler/e9bc625cfe88a0a67a73abc06660f40f/raw/badge-ips.json)
33
+ ![SMART 2.2.0](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/quotentiroler/e9bc625cfe88a0a67a73abc06660f40f/raw/badge-smart.json)
34
+ ![CH Core 5.0.0](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/quotentiroler/e9bc625cfe88a0a67a73abc06660f40f/raw/badge-ch-core.json)
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 | Purpose |
140
- | ------------------------------ | ---------------------------------------------------------------------------- |
141
- | `npm run generate` | Execute the CLI against the local `input/` folder and refresh `output/`. |
142
- | `npm run generate:check` | End-to-end check: generate, type-check, and lint the emitted output. |
143
- | `npm test` | Type-check and run all Vitest suites (coverage enabled). |
144
- | `npm test validatorParity` | Run validator parity tests against Firely .NET SDK validator. |
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) or [Firely .NET SDK](https://fire.ly/products/firely-net-sdk/).
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
- - **`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) or [Firely .NET SDK](https://fire.ly/products/firely-net-sdk/) as the source of truth.
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
+ }