This repo contains source code for FHIR IG to zen-lang converter which uses zen.fhir namespace to describe FHIR data structure in zen FHIR format.
FHIR IG can be converted to zen-lang using the cli tool published on release.
Release workflow is also set up to convert various IGs to zen-lang.
- About
- Zen FHIR format
- Use zen FHIR schemas to describe FHIR constraints and extensions
- Convert FHIR IG to zen-lang
Zen FHIR format is FHIR json format for storage. Resources structure has 3 types of isomorphic transformations applied:
- References
- First-Class Extensions
- Polymorphics (choice of types)
In FHIR, references are represented as URI string. In most cases, systems are interested in discrete parts of references like resource id and type. For performance and accuracy reasons zen FHIR format suggests to store reference parts in separate fields. In FHIR there are three types of references - absolute, relative and local. By Zen FHIR format they're stored in different attributes.
-
Relative (interpreted as a reference to a resource on the same server; triggers referential consistency check):
reference is parsed into a pair of
{id,resourceType}
attributes# FHIR subject: reference: "Patient/pt-1" # Zen FHIR subject: resourceType: "Patient" id: "pt-1"
-
Absolute (interpreted as a reference to an external resource; no ref validation)
reference is parsed into the uri attribute
# FHIR subject: reference: "http://external/fhir/Patient/pt-1" # zen FHIR subject: uri: "http://external/fhir/Patient/pt-1"
-
Local (interpreted as a local ref to contained resources)
reference is parsed into a localRef attribute
# FHIR subject: reference: "#pt" # zen FHIR subject: localRef: "pt"
While FHIR uses two different ways to define core elements and extensions, zen FHIR format provides unified framework to describe both. Zen FHIR format offers user-defined elements or "first-class extensions". In zen FHIR format, you can define new attributes (elements) for existing (FHIR) resources. Let's illustrate this on complex attribute for Patient from US-Core FHIR Profile us-core-race
.
This is how a patient with race looks in FHIR format:
resourceType: Patient
id: sample-pt
extension:
- url: http://hl7.org/fhir/us/core/StructureDefinition/us-core-race
extension:
- url: text
valueString: Asian Indian
- url: ombCategory
valueCoding:
system: urn:oid:2.16.840.1.113883.6.238
code: 2028-9
display: Asian
- url: detailed
valueCoding:
system:
code: 2029-7
display: Asian Indian
If you describe the extension in zen-lang then resource can be transformed and validated in zen FHIR format:
resourceType: Patient
id: sample-pt
race:
text: Asian Indian
category:
- {system: 'urn:oid:2.16.840.1.113883.6.238', code: 2028-9, display: Asian}
detailed:
- {system: 'urn:oid:2.16.840.1.113883.6.238', code: 2029-7, display: Asian Indian}
In FHIR some elements can have multiple types. Such elements in FHIR spec postfixed with [x]
, like Observation.value[x]
, but in JSON such element is represented in a different way: Observation.valueString
. The simple logical check "why this is wrong" is "you could not have a collection of union elements in FHIR JSON". zen FHIR format fixes this by moving type as a key inside of a nested object - valueString:... => value: {string: ...}
#FHIR
resourceType: Observation
valueQuantity:
unit: ...
# zen FHIR
resourceType: Observation
value:
Quantity:
unit: ...
zen.fhir
extends zen/schema
to allow describing FHIR specific info such as bindings, references, extensions, etc. Documentation with examples is located here.
This repository contains FHIR package to zen-lang schemas converter.
On each release Github action publishes:
How to enable and use zen-lang packages is described in this guide
Download and execute a jar executable from the latest release like this:
java -jar [JAR_PATH] [COMMAND] [OPTIONS]
ig-to-zenpackage
Builds zen-packages from provided IGs
-i
, --input
S Node modules folder
-o
, --output
S Output directory
-m
, --output
S Sets main package, FTR/Validation index will be created only for specified package name
stndlp
Builds standalone zen project. Result is a zip archive.
-i
, --input
S Path to node-modules-folder (including node-modules)
-o
, --output
S Path to resulting zip archive
--omit-deps
Remove deps from resulting project
zenbnd
Builds zen project from provided IG. Result is a NPM package directory
-i
, --input
S Path to node-modules-folder (including node-modules)
-o
, --output
S Path to resulting directory
-v
, --version
S Resulting package version
-n
, --name
S Resulting package name (optional)
cmndj
Converts ConceptMap to .ndjson.gz bundle
-i
, --input
S Path to node-modules-folder (including node-modules)
-o
, --output
S Path to resulting zip archive
# Create and open directory
$ mkdir zen-profiling && cd zen-profiling && mkdir output
# Get tarball link
$ npm --registry https://packages.simplifier.net view hl7.fhir.us.davinci-pdex@latest
# Copy tarball link
# ...
# .tarball: https://packages.simplifier.net/hl7.fhir.us.davinci-pdex/2.0.0-ballot
# ...
# Download needed FHIR package
$ npm --registry https://packages.simplifier.net install https://packages.simplifier.net/hl7.fhir.us.davinci-pdex/2.0.0-ballot
+ [email protected]
added 1 package from 1 contributor
# Current directory structure:
├── node_modules
│ ├── hl7.fhir.r4.core
│ ├── hl7.fhir.us.core
│ ├── hl7.fhir.us.davinci-hrex
│ └── hl7.fhir.us.davinci-pdex
├── package-lock.json
└── package.json
# Convert downloaded FHIR packages to zen-lang
$ java -jar -Xmx8g ~/Downloads/zen-fhir.jar ig-to-zenpackage -i node_modules -o output -m hl7.fhir.us.davinci-pdex
:done
# Directory structure after convertion
output
├── ftr
│ └── hl7-fhir-us-davinci-pdex
├── index.nippy
├── zen-package.edn
└── zrc
├── hl7-fhir-us-davinci-pdex
└── hl7-fhir-us-davinci-pdex.edn