FHIR R4 to R6 migration pipeline runner with automated profile comparison and rule-based analysis
npm install @gefyra/diffyr6-cliAn automated toolkit for comparing FHIR profiles across different versions, analyzing structural differences, and generating comprehensive impact reports with rule-based evaluation.
- π¦ Automated Package Download - Downloads FHIR packages from the official registry
- π FSH Generation - Converts FHIR resources to FSH using GoFSH
- β¬οΈ Profile Upgrade Pipeline - Automatically upgrades profiles between FHIR versions using SUSHI
- π Profile Comparison - Compares profile versions using the HL7 FHIR Validator
- π Rule-Based Difference Analysis - Applies customizable rules to classify and score structural changes
- π― Impact Scoring - Calculates complexity scores based on breaking changes and migration risks
- π¨ Removed Resource Detection - Identifies profiles based on resource types removed in newer FHIR versions
- π Markdown Reports - Generates detailed comparison reports with timestamps and findings categorization
``bash`
npm install @gefyra/diffyr6-cli
`bash`
git clone https://github.com/Gefyra/DiffyR6-Cli.git
cd DiffyR6-Cli
npm install
npm link
- Node.js 18.0.0 or higher
- npm for package management
- Java (for HL7 FHIR Validator)
- tar available on PATH (for extracting FHIR packages)
`bash`
npm install gofsh fsh-sushi
`bash`
fhir-r6-migrate --init
This creates a migration-config.json file with default settings.
`json`
{
"configVersion": "1.0.0",
"packageId": "de.basisprofil.r4",
"packageVersion": "1.5.0",
"enableGoFSH": true,
"resourcesDir": "Resources",
"resourcesR6Dir": "ResourcesR6",
"compareDir": "compare",
"outputDir": "output",
"rulesConfigPath": null,
"validatorJarPath": null,
"workdir": null,
"compareMode": "incremental",
"exportZip": true
}
`bash`
fhir-r6-migrate
Or with a custom config:
`bash`
fhir-r6-migrate --config my-config.json
`bashRun with default config
fhir-r6-migrate
$3
`javascript
import { runMigration } from '@gefyra/fhir-r6-migration-runner';
import { loadConfig } from '@gefyra/fhir-r6-migration-runner/config';// Load config from file
const config = await loadConfig('./migration-config.json');
// Or create config programmatically
const config = {
configVersion: '1.0.0',
packageId: 'de.basisprofil.r4',
packageVersion: '1.5.0',
enableGoFSH: true,
resourcesDir: 'Resources',
resourcesR6Dir: 'ResourcesR6',
compareDir: 'compare',
outputDir: 'output',
compareMode: 'incremental',
};
// Run migration
const result = await runMigration(config);
console.log('Migration complete!');
console.log('Report:', result.report);
console.log('Score:', result.score);
console.log('Findings:', result.findingsCount);
`Configuration Reference
$3
| Field | Type | Description |
|-------|------|-------------|
|
configVersion | string | Config schema version (must be "1.0.0") |
| packageId | string | FHIR package ID (required if enableGoFSH is true) |
| resourcesDir | string | Directory for baseline/source version resources |
| resourcesR6Dir | string | Directory for target/comparison version resources |
| compareDir | string | Directory for comparison HTML files |
| outputDir | string | Directory for generated reports |$3
| Field | Type | Default | Description |
|-------|------|---------|-------------|
|
packageVersion | string | "current" | FHIR package version |
| enableGoFSH | boolean | true | Enable GoFSH package download & FSH generation |
| rulesConfigPath | string | null | Path to custom rules config (uses default if null) |
| validatorJarPath | string | null | Path to validator_cli.jar (auto-downloads latest from GitHub if null) |
| workdir | string | null | Working directory (uses current dir if null) |
| compareMode | string | "incremental" | Comparison mode: "incremental" or "full" |
| exportZip | boolean | true | Create a ZIP export containing compare HTML, markdown report, and run config |Auto-download feature: When
validatorJarPath is null, the HL7 FHIR Validator will be automatically downloaded from a stable GitHub release to . This download only happens once - subsequent runs will reuse the existing JAR file.Pipeline Steps
The comparison pipeline consists of 4 steps:
$3
Downloads the specified FHIR package and converts it to FSH using GoFSH for the baseline version.
Skipped if:
resourcesDir/sushi-config.yaml already exists$3
Runs SUSHI to upgrade profiles to the target FHIR version, applying automatic fixes for common issues.
Skipped if:
resourcesR6Dir/sushi-config.yaml already exists$3
Uses the HL7 FHIR Validator to compare baseline and target profile versions, generating HTML comparison files showing structural differences.
Incremental mode: Only compares profiles with missing HTML files
Full mode: Compares all profiles, overwriting existing files
$3
Applies rules to the comparison HTML files and generates a markdown report with:
- Removed resource detection (profiles based on deprecated resource types)
- Detailed findings grouped by profile and category
- Impact score based on breaking changes
- Timestamped filename (e.g.,
comparison-report-20260123-143052.md)Compare Modes
$3
`json
{
"compareMode": "incremental"
}
`- Only compares profiles that don't have existing HTML files
- Faster for incremental updates
- Preserves existing comparisons
$3
`json
{
"compareMode": "full"
}
`- Compares all profiles, overwriting existing files
- Useful for clean rebuilds
- Ensures all comparisons are up-to-date
Custom Rules
The package includes a default set of rules for common migration issues. You can customize or extend these rules:
$3
`json
{
"rulesConfigPath": "./my-rules.json"
}
`$3
`json
{
"title": "Custom Analysis Rules",
"tables": [
{
"sectionHeading": "Structure",
"rules": [
{
"name": "Element removed in target version",
"description": "An element from the baseline version no longer exists in the target",
"rank": 50,
"value": 2,
"conditions": [
{
"column": "Comments",
"operator": "equals",
"value": "Removed this element"
}
],
"template": "The element {{Name}} exists in baseline but was removed in target."
}
]
}
]
}
`$3
- name: Rule category name (groups findings in the report)
- description: Detailed explanation of the difference
- rank: Sorting order in the report (lower = higher priority)
- value: Score contribution (higher = more significant change)
- conditions: Array of conditions that must ALL match
- template: Output text with variable substitution (
{{variableName}})$3
-
equals: Exact match (case-insensitive by default)
- contains: Substring match (case-insensitive by default)
- !equals / notequals: Not equal$3
- Column aliases (e.g.,
{{Name}}, {{Comments}})
- Index-based columns (e.g., {{col1}}, {{col2}})
- Context variables: {{file}}, {{section}}, {{profile}}Impact Score
The impact score is calculated by summing the
value field from all rule matches across all differences found.Interpretation:
- 0-50: Low impact - minor differences, straightforward adaptation
- 51-150: Medium impact - moderate structural changes requiring attention
- 151+: High impact - significant breaking changes and redesign needed
Output
$3
`markdown
FHIR Profile Comparison Report
Generated: 2026-01-23T14:30:52.000Z
Total Findings: 42
Impact Score: 135
Resources Removed: 0
---
β οΈ Resources Removed in Target Version
β
No profiles found that are based on resource types removed in target version.
Your baseline profiles do not use any deprecated resource types.
---
PatientProfile
Score: 25 | Findings: 8
$3
An element from baseline version no longer exists in target...
- Element identifier exists in baseline but removed in target. (Score: 15)
- Element photo exists in baseline but removed in target. (Score: 15)
$3
The cardinality of an element has changed...
- For element name, the cardinality changed: cardinalities differ (0.. vs 1..) (Score: 5)
---
Final Impact Score: 135
Lower scores indicate fewer structural changes.
`Configuration Versioning
The package uses semantic versioning for configuration schemas.
Current version:
1.0.0$3
- Major version must match exactly
- Minor/patch versions are backwards compatible
If you receive a config version error:
1. Update the package:
npm update @gefyra/fhir-r6-migration-runner
2. Or update your config's configVersion fieldTroubleshooting
$3
Add
"configVersion": "1.0.0" to your config file.$3
Update the package or adjust your config to match the expected major version.
$3
Ensure
gofsh is installed:
`bash
npm install gofsh
`Or specify a custom path in your environment:
`bash
export GOFSH_BIN=/path/to/gofsh
`$3
Download manually and specify the path:
`json
{
"validatorJarPath": "/path/to/validator_cli.jar"
}
`Development
$3
`
DiffyR6-Cli/
βββ src/
β βββ index.js # Main pipeline logic
β βββ cli.js # CLI entry point
β βββ config.js # Configuration loading & validation
β βββ rules-engine.js # Rule evaluation engine
β βββ generate-fsh.js # GoFSH package download & FSH generation
β βββ upgrade-sushi.js # SUSHI profile upgrade with auto-fixes
β βββ compare-profiles.js # HL7 Validator profile comparison
β βββ utils/
β βββ fs.js # Filesystem utilities
β βββ process.js # Process spawning utilities
β βββ sushi-log.js # SUSHI log parsing
β βββ html.js # HTML parsing utilities
β βββ validator.js # Validator JAR auto-download
β βββ removed-resources.js # Removed resource detection
βββ config/
β βββ default-rules.json # Default analysis rules
β βββ resources-r4-not-in-r6.json # List of removed resource types
βββ package.json
βββ README.md
`$3
`bash
npm run build
`$3
`bash
npm test
``Note: Tests are not yet implemented
Contributions are welcome! Please open an issue or pull request on GitHub.
MIT
Jonas SchΓΆn (Gefyra GmbH)
- Email: js@gefyra.de
- GitHub: @Gefyra
- GitHub Repository
- npm Package
- FHIR R6 Specification
- GoFSH
- SUSHI