lantanagroup / fhir.js Goto Github PK
View Code? Open in Web Editor NEWNode.JS library for serializing/deserializing FHIR resources between JS/JSON and XML using various node.js XML libraries
License: Apache License 2.0
Node.JS library for serializing/deserializing FHIR resources between JS/JSON and XML using various node.js XML libraries
License: Apache License 2.0
The JSON validator incorrectly allows quotes around boolean and numeric values.
For example if you had a Patient resource with a property of ("active":"true")
The Validator accepts the above json, however to be valid json, the "true" should be unquoted ("active" : true)
The same happens for numbers ("multipleBirthInteger" : "2") will pass validation, but to be json conformant, it should be ("multipleBirthInteger" : 2)
Hi,
I am using the validator to create a bunch of unit tests for conformance with the UK Core IG. I am trying the custom loading for the StructureDefinitions, CodeSystems and ValueSets of the FHIR R4 plus the corresponding resources of the UK Core IG.
Despite of having loaded all the resources, I am still getting warnings when validating the resource. I decided to custom load the FHIR R4 resources instead of using the pre-loaded data of the ParseConformance
constructor in case there was an issue with the default data. I made sure the ValueSets are loaded before the StructureDefinitions as well, but I am still getting:
{
location: 'Patient.contact[0].relationship[0]',
resourceId: 'UKCore-Patient-RichardSmith-Example',
severity: 'warning',
message: 'Code "Personal" (https://fhir.hl7.org.uk/CodeSystem/UKCore-AdditionalPersonRelationshipRole) not found in value set'
},
{
location: 'Patient.communication[0].language',
resourceId: 'UKCore-Patient-RichardSmith-Example',
severity: 'warning',
message: 'Code "en" (https://fhir.hl7.org.uk/CodeSystem/UKCore-HumanLanguage) not found in value set'
}
I wonder if this is related to the UK Core StructureDefinitions, as they don't contain a snapshot
field. I am trying to create it using the fhir.generateSnapshot()
function on the bundle. However, when doing this, I get the following error: Cannot find base definition "http://hl7.org/fhir/StructureDefinition/Extension" in bundle or core FHIR specification.
Could you please help me identifying why I am still getting the warnings on the validation of the resource? This is code I came up with:
// Generate bundles
const fhirValueSetBundle = SnapshotGenerator.createBundle.apply(this, fhirValueSets);
const fhirStructureDefinitionBundle = SnapshotGenerator.createBundle.apply(
this,
fhirStructureDefinitions,
);
const ukCoreValueSetBundle = SnapshotGenerator.createBundle.apply(this, ukCoreValueSets);
const ukCoreStructureDefinitionBundle = SnapshotGenerator.createBundle.apply(
this,
ukCoreStructureDefinitions,
);
// Parse all bundles into the conformance checker
const parser = new ParseConformance(false, Versions.R4);
parser.parseBundle(fhirValueSetBundle);
parser.parseBundle(ukCoreValueSetBundle);
parser.parseBundle(fhirStructureDefinitionBundle);
parser.parseBundle(ukCoreStructureDefinitionBundle);
const fhir = new Fhir(parser);
// fhir.generateSnapshot(ukCoreStructureDefinitionBundle);
const results = fhir.validate(ukCorePatientExample);
console.log(results);
expect(results.valid).toBe(true);
PS: Additionally, I believe there is an issue with the package exports, as I had to manually expose the SnapShotGenerator in the index.js
file.
Many thanks.
Hi,
I'm trying to implement FHIR DSTU2. I'd like to ask you guys why DSTU2 is not supported? Why is the main reason or difference for that?
I ask you that questions because it is possible to download the "FHIR Definitions" of the version 3 and work with this version, so why is not possible to do the same with version2?
The example shows:
// Create a parser and parse it using the parser
var parser = new ParseConformance(false, FhirVersions.STU3); // don't load pre-parsed data
parser.parseBundle(newValueSets);
parser.parseBundle(newTypes);
parser.parseResources(newResources);
however "parser.parseResources()" does not exist as a function.
I believe it should be instead:
// Create a parser and parse it using the parser
var parser = new ParseConformance(false, FhirVersions.STU3); // don't load pre-parsed data
parser.parseBundle(newValueSets);
parser.parseBundle(newTypes);
parser.parseBundle(newResources);
The FHIR documentation highlights
Note that though a profile can constrain an element from x..* to x..1, this doesn't make any difference to the representation in the JSON format - the element will still be represented in an array. As an example, take Patient.name which has a cardinality of 0..*. In an unprofiled Patient, ... (https://www.hl7.org/fhir/profiling.html#cardinality)
However in the code it seems to me that the validation of multiple (Array/Object) is based on the cardinality of the profile.
Shouldn't the definition of multiple (Array/Object) be based on ElementDefinition.base.max instead of ElementDefinition.max?And that there is a permitted quantity inside the list?
profile:
{
"resourceType" : "StructureDefinition",
"id" : "patient",
...
{
"id" : "Patient.name",
"path" : "Patient.name",
...
"min" : 1,
"max" : "1",
"base" : {
"path" : "Patient.name",
"min" : 0,
"max" : "*"
},
...
You should consider it correct:
{
"resourceType" : "Patient",
...
"name" : [{
"text" : "Peter James"
}]
...
}
Hi,
The valueset http://hl7.org/fhir/ValueSet/name-use has the 'maiden" value as a sub-definition of the value "old". Maiden is Lvl 1 while old is Lvl 0.
{ "code": "old", "display": "Old", "definition": "This name is no longer in use (or was never correct, but retained for records)", "concept": [ { "code": "maiden", "display": "Name changed for Marriage", "definition": "..." } ]
validator.js however doesn't seem to check for this value.
The following bit of FHIR doesn't validate.
"name": [ { "use": "official", "text": "Walters, Wilma W", "family": [ "Walters" ], "given": [ "Wilma", "W" ], "period": { "start": "2014-08-04T22:20:44.000Z" } }, { "use": "maiden", "text": "Fredricks,", "family": [ "Fredricks" ], "period": { "start": "2018-12-20T19:49:51.000Z" } } ]
It returns
"'[{"location":"Patient.name[1].use","resourceId":"2648007","severity":"error","message":"Code \"maiden\" not found in value set"}]',"
A quick fix for the validator is to change valueset.json to have maiden on the same level as old, but that might break when we update to updates of the valueset.
Thank you!
Sometimes I'm getting an exception when passing in invalid payload:
error: TypeError: Cannot read property 'split' of undefined
at Validator.validateNext (/var/task/node_modules/fhir/validator.js:285:54)
at Validator.validateProperties (/var/task/node_modules/fhir/validator.js:355:26)
at Validator.validateNext (/var/task/node_modules/fhir/validator.js:268:36)
at Validator.validateProperties (/var/task/node_modules/fhir/validator.js:347:34)
at Validator.validateNext (/var/task/node_modules/fhir/validator.js:251:40)
at Validator.validateProperties (/var/task/node_modules/fhir/validator.js:355:26)
at Validator.validateNext (/var/task/node_modules/fhir/validator.js:303:18)
at Validator.validateProperties (/var/task/node_modules/fhir/validator.js:347:34)
at Validator.validate (/var/task/node_modules/fhir/validator.js:48:18)
at Fhir.validate (/var/task/node_modules/fhir/fhir.js:42:26)
Is there a specific condition that causes this?
I'm using version 4.9.0
I've been working with the Davinci Data Exchange for Quality Measure (DEQM) profile. As part of the profile there are a few resources where the base profile is being extended. This is done for a few different reasons: adding relevant extensions, requiring things that are optional in the base FHIR spec, etc.
Ideally, what I'd like to be able to do is use the base FHIR profile and "overlay" the changes for the DEQM spec. I tried the following code:
import { Fhir, Versions } from 'fhir/fhir'
import { ParseConformance } from 'fhir/parseConformance'
import * as fs from 'fs'
import * as deqmPractionerExample from '/mnt/c/Users/Matt/Downloads/package/example/Organization-organization01.json'
let deqmOrg = JSON.parse(fs.readFileSync('./deqm/StructureDefinition-organization-deqm.json').toString())
deqmParser.parseStructureDefinition(deqmOrg)
let fhirValid = new Fhir(deqmParser)
let resp = fhirValid.validate(deqmPractionerExample)
This the StructureDefinition from the DEQM spec that I'm using in the above example.
StructureDefinition-organization-deqm.txt
When doing this I get the following error:
/mnt/c/Users/Matt/projects/deqm-test/node_modules/fhir/parseConformance.js:350
parentBackboneElement._properties.push(newProperty);
^
TypeError: Cannot read property 'push' of undefined
at ParseConformance.populateBackboneElement (/mnt/c/Users/Matt/projects/deqm-test/node_modules/fhir/parseConformance.js:350:55)
at ParseConformance.parseStructureDefinition (/mnt/c/Users/Matt/projects/deqm-test/node_modules/fhir/parseConformance.js:152:30)
at Object.<anonymous> (/mnt/c/Users/Matt/projects/deqm-test/deqm.js:34:12)
at Module._compile (internal/modules/cjs/loader.js:1138:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
at Module.load (internal/modules/cjs/loader.js:986:32)
at Function.Module._load (internal/modules/cjs/loader.js:879:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47
After looking through the parser, I traced it back to this specific block in populateBackboneElement
(around line 349 in parseConformance.js).
else if (backboneElement.type.length == 1) {
const newProperty = {
_name: backboneElementId.substring(backboneElementId.lastIndexOf('.') + 1),
_type: backboneElement.type[0].code,
_multiple: backboneElement.max !== '1',
_required: backboneElement.min === 1,
_properties: []
};
parentBackboneElement._properties.push(newProperty);
this.populateValueSet(backboneElement, newProperty);
if (backboneElement.type[0].code === 'BackboneElement' || backboneElement.type[0].code == 'Element') {
this.populateBackboneElement(resourceType, profile.snapshot.element[y].id, profile);
}
}
It looks like the parentBackboneElement._properties.push(newProperty);
is throwing the error because previously if the element is defined without a _properties
it's an undefined object and, therefore, cannot push to it. Since I'm trying to in effect "modify" the resource after it's already been created, I believe this is where the error is coming from.
There's three possible fixes that I'm thinking of for this.
if (parentBackboneElement._properties === undefined || parentBackboneElement._properties === null) {
parentBackboneElement._properties = [];
}
For 2 and 3, I'm happy to submit a PR. I wanted to open an issue and discuss first to make sure I wasn't missing anything and this made sense for the library.
Here is a patch that was needed to allow STU3 profiles to work. It seems targetProfiles can be a string and not just an array of strings
--- a/node_modules/fhir/validator.js
+++ b/node_modules/fhir/validator.js
@@ -272,19 +272,19 @@ class Validator {
const nextValidationResponse = nextValidationInstance.response;
this.response.valid = !this.response.valid ? this.response.valid : nextValidationResponse.valid;
this.response.messages = this.response.messages.concat(nextValidationResponse.messages);
- const targetProfiles = (property._targetProfiles || [])
+ const targetProfiles = (property._targetProfiles ? (Array.isArray(property._targetProfiles) ? property._targetProfiles : [property._targetProfiles]) : [])
.filter(p => !!p && p.indexOf('/') >= 0)
.map((p) => {
- const split = p.split('/');
- return split[split.length - 1];
- });
- if (property._type === 'Reference' && targetProfiles.length != 0 && targetProfiles.indexOf('Resource') < 0) {
- const targetProfiles = (property._targetProfiles || [])
- .filter(p => !!p && p.indexOf('/') >= 0)
- .map((p) => {
const split = p.split('/');
return split[split.length - 1];
});
+ if (property._type === 'Reference' && targetProfiles.length != 0 && targetProfiles.indexOf('Resource') < 0) {
+ const targetProfiles = (property._targetProfiles ? (Array.isArray(property._targetProfiles) ? property._targetProfiles : [property._targetProfiles]) : [])
+ .filter(p => !!p && p.indexOf('/') >= 0)
+ .map((p) => {
+ const split = p.split('/');
+ return split[split.length - 1];
+ });
const referenceSplit = obj.reference ?
obj.reference.split('|')[0].split('/') :
[];
fhir/parseConformance.js:167
const anySliceRequired = structureDefinition.snapshot.element
.filter((e) => e.id.includes(elementId) && e.min >= 1)
.length > 0;
This code can find other attributes outside the correct context.
Example.:
Observation.value[x]
Observation.otherScope.value[x]
Moreover, and it seeks to validate a cardinality not included in the standard.
Removing this validation should resolve.
elementId = elementId.substring(0, elementId.length - 3);
// const anySliceRequired = structureDefinition.snapshot.element
// .filter((e) => e.id.includes(elementId) && e.min >= 1)
// .length > 0;
for (let y in element.type) {
let choiceType = element.type[y].code;
choiceType = choiceType.substring(0, 1).toUpperCase() + choiceType.substring(1);
const choiceElementId = elementId + choiceType;
const newProperty = {
_name: choiceElementId,
_choice: elementId,
_type: element.type[y].code,
_multiple: element.max !== '1',
_required: element.min === 1 //|| anySliceRequired
};
this.populateValueSet(element, newProperty);
parsedStructureDefinition._properties.push(newProperty);
}
Hey @seanmcilvenna, in order to publish my FHIR GraphQL utility library, it would be great if you could publish the latest changes to NPM.
Kind regards,
Lukas
Is there a way to convert a fhir xml file to json? On your example it always starts from a json object.
We have a fhir xml file that needs to be converted to a json.
See conversation from #27
Need to fill out details of enhancement.
With FHIR R4 (4.0.0) having been released at the end of 2018, is there a roadmap for getting FHIR.js updated to support it out of the box? With R4/4.0.0 providing the first normative content within the standard, it's a much more compelling target for supporting it in new applications.
Thanks!
The mocha test is not executing all tests.
In package.json there is a script: "test": "./node_modules/.bin/mocha test/.js" which is not working.
If this script is changed to the following "test": "./node_modules/.bin/mocha test/" then the mocha tests are executed for me.
Hope this helps!
FHIR allows for adding custom resources and define bindings to etc snomed ct. Do you plan on add this future or do you want help with that?
It would be good to add support for these at some point.
i.e.
<birthDate id="314159" value="1970-03-30" >
<extension url="http://example.org/fhir/StructureDefinition/text">
<valueString value="Easter 1970"/>
</extension>
</birthDate>
"birthDate": "1970-03-30",
"_birthDate": {
"id": "314159",
"extension" : [ {
"url": "http://example.org/fhir/StructureDefinition/text",
"valueString": "Easter 1970"
}]
}
(https://www.hl7.org/fhir/json.html#primitive)
Thanks
Hi guys, in your README.md file you mention Support for multiple FHIR versions (>= STU3)
as a Key Feature, but later in the "FHIR Version" block you mention If your implementation needs to support a specific FHIR version (as long as it is 3.6.0 or newer)
.
Taking into account that STU3 sequence ends with 3.0.1 as per the official documentation. Could you please confirm if STU3 is actually supported?
Thank you in advance
E.g, in the example Patient.json on the FHIR website:
...
"birthDate": "1974-12-25",
"_birthDate": {
"id": "314159",
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/patient-birthTime",
"valueDateTime": "1974-12-25T14:35:45-05:00"
}
]
}
...
Because brithDate is a primitive, in order to add "id" and/or "extension", you must use the _birthDate property. FHIR.js currently sees this as unexpected but should treat it as an object of type "Element"
I followed the link in Documentation section to here: http://lantanagroup.github.io/FHIR.js/. However, it seems that all links to the modules are broken (404 page like http://lantanagroup.github.io/FHIR.js/modules/_converttojs_.html)
Is there a limitation on this library? It cannot parse an xml file with ClinicalDocument.
Sample xml file
When trying to convert a Bundle with QuestionnaireResponse object inside of it, the conversion is not properly made, besides the fact that the validate method is saying that the XML file is valid. The problem happens when QuestionnaireResponse/item has an array of items inside it (which is described in FHIR API). The inner items are converted to empty arrays.
I am attaching both files (the original xml and the parsed json).
Thanks.
Good work on #22 but I think this has broken the xmlToJson code - the _ properties are all empty object now.
PR coming shortly to address this.
location: "Questionnaire.item[0].type" message: "Code \"choice\" not found in value set"
{
"identifier": [
{
"system": "http://us.truenth.org/questionnaire",
"use": "usual",
"value": "epic26"
}
],
"item": [
{
"linkId": "epic26.1",
"option": [
{
"valueCoding": {
"code": "epic26.1.1",
"display": "More than once a day"
}
},
{
"valueCoding": {
"code": "epic26.1.2",
"display": "About once a day"
}
},
{
"valueCoding": {
"code": "epic26.1.3",
"display": "More than once a week"
}
},
{
"valueCoding": {
"code": "epic26.1.4",
"display": "About once a week"
}
},
{
"valueCoding": {
"code": "epic26.1.5",
"display": "Rarely or never"
}
}
],
"text": "Over the past 4 weeks, how often have you leaked urine?",
"type": "choice"
},
{
"linkId": "epic26.2",
"option": [
{
"valueCoding": {
"code": "epic26.2.1",
"display": "No urinary control whatsoever"
}
},
{
"valueCoding": {
"code": "epic26.2.2",
"display": "Frequent dribbling"
}
},
{
"valueCoding": {
"code": "epic26.2.3",
"display": "Occasional dribbling"
}
},
{
"valueCoding": {
"code": "epic26.2.4",
"display": "Total control"
}
}
],
"text": "Which of the following best describes your urinary control during the last 4 weeks?",
"type": "choice"
},
{
"linkId": "epic26.3",
"option": [
{
"valueCoding": {
"code": "epic26.3.1",
"display": "None"
}
},
{
"valueCoding": {
"code": "epic26.3.2",
"display": "1 pad per day"
}
},
{
"valueCoding": {
"code": "epic26.3.3",
"display": "2 pads per day"
}
},
{
"valueCoding": {
"code": "epic26.3.4",
"display": "3 or more pads per day"
}
}
],
"text": "How many pads or adult diapers per day did you usually use to control leakage during the last 4 weeks?",
"type": "choice"
},
{
"linkId": "epic26.4",
"option": [
{
"valueCoding": {
"code": "epic26.4.1",
"display": "No problem"
}
},
{
"valueCoding": {
"code": "epic26.4.2",
"display": "Very small problem"
}
},
{
"valueCoding": {
"code": "epic26.4.3",
"display": "Small Problem"
}
},
{
"valueCoding": {
"code": "epic26.4.4",
"display": "Moderate Problem"
}
},
{
"valueCoding": {
"code": "epic26.4.5",
"display": "Big Problem"
}
}
],
"text": "Dripping or leaking urine",
"type": "choice"
}
],
"resourceType": "Questionnaire",
"status": "draft"
}
Cloned the current master branch and found the following npm audit
results:
`
.../FHIR.js$ npm audit
=== npm audit security report ===
// Run npm install --save-dev [email protected] to resolve 3 vulnerabilities
SEMVER WARNING: Recommended action is a potentially breaking change
│ Low │ Prototype Pollution
│ Package │ lodash
│ Dependency of │ webpack [dev]
│ Path │ webpack > async > lodash
│ More info │ https://nodesecurity.io/advisories/577
│ Low │ Prototype Pollution
│ Package │ lodash
│ Dependency of │ webpack [dev]
│ Path │ webpack > watchpack > async > lodash
│ More info │ https://nodesecurity.io/advisories/577
│ Low │ Cryptographically Weak PRNG
│ Package │ randomatic
│ Dependency of │ webpack [dev]
│ Path │ webpack > watchpack > chokidar > anymatch > micromatch >
│ │ braces > expand-range > fill-range > randomatic
│ More info │ https://nodesecurity.io/advisories/157
// Run npm update lodash --depth 4 to resolve 1 vulnerability
│ Low │ Prototype Pollution
│ Package │ lodash
│ Dependency of │ typedoc [dev]
│ Path │ typedoc > handlebars > async > lodash
│ More info │ https://nodesecurity.io/advisories/577
found 4 low severity vulnerabilities in 1119 scanned packages
run npm audit fix
to fix 1 of them.
3 vulnerabilities require semver-major dependency updates.
`
Hi,
Trying to parse the Epic sandbox conformance statement from XML to JSON using fhir.xmlToObj
, and it's returning a Cannot read property '_properties' of undefined
error.
I've used this library elsewhere to parse Epic sandbox responses, but I'm not sure I've used it to parse a conformance statement. Of course, it may simply be the difference between DST2 and v4.
-aw
Code that's generating the error:
import Fhir from 'fhir';
foo(){
HTTP.get('https://open-ic.epic.com/Argonaut/api/FHIR/Argonaut/metadata', function(error, result){
if(error){
console.log('error', error)
}
if(result){
console.log(result.content);
var parsed = Promise.await(fhir.xmlToObj(result.content));
self.setState({
metadata: EJSON.stringify(parsed, {indent: 2})
})
}
})
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.