Security News
Opengrep Emerges as Open Source Alternative Amid Semgrep Licensing Controversy
Opengrep forks Semgrep to preserve open source SAST in response to controversial licensing changes.
Node.js implementation of IHE MHD, providing a RESTful API to access health documents from mobile devices.
MHD is an IHE profile for Mobile access to Health Documents. The implementation follows trial implementation rev1.1 and provides a MHD Document Responder actor using an XDS Document Consumer as a proxy to XDS registry/repository.
This is a partial implementation:
npm install mhd
npm test mhd
var mhd = require('mhd');
var http = require("http");
Implement an adapter for your document repository. The following implementation returns static data:
var repositoryAdapter = {
patientIdPattern: '^[0-9]{9}[\^]{3}[&]2.16.840.1.113883.2.1.3.9.1.0.0&ISO$',
getDocumentDossier: function(entryUuid, patientId, format, callback) {
var dossier = {
documentEntry:{
patientID:patientId,
classCode:{
code:'34133 -9',
codingScheme:'2.16.840.1.113883.6.1',
codeName:'Summary of Episode Note'},
confidentialityCode:{
code:'N',
codingScheme:'2.16.840.1.113883.5.25',
codeName:'Normal sensitivity'},
formatCode:{
code:'urn:ihe:lab:xd-lab:2008',
codingScheme:'1.3.6.1.4.1.19376.1.2.3',
codeName:'XD-Lab'},
typeCode:{
code:'',
codingScheme:'',
codeName:''},
Author:{
todo:'need to expand this!!!'},
practiceSettingCodes:{
code:'394802001',
codingScheme:'2.16.840.1.113883.6.96',
codeName:'General Medicine'},
Title:'document title',
creationTime:'20061224',
hash:'e543712c0e10501972de13a5bfcbe826c49feb75',
Size:'350',
languageCode:'en-us',
serviceStartTime:'200612230800',
serviceStopTime:'200612230900',
sourcePatientId:'4567856789^^^&3.4.5&ISO',
mimeType:'text/xml',
uniqueId:'1.2009.0827.08.33.5074',
entryUUID:entryUuid}};
callback(null, JSON.stringify(dossier));
},
findDocumentDossiers: function(query, format, callback) {
var timestamp = new Date().toString();
var response = {
updated:timestamp,
self:'http://127.0.0.1:1337/...',
entries:[
{
id:'urn:uuid:50a0807a-10a0-7c10-6296-71ed0c235b31',
self:'http://127.0.0.1:1337/net.ihe/DocumentDossier/urn:uuid:50a0807a-10a0-7c10-6296-71ed0c235b31/?PatientID=' + query.PatientID,
related:'http://127.0.0.1:1337/net.ihe/Document/urn:uuid:50a0807a-10a0-7c10-6296-71ed0c235b31/?PatientID=' + query.PatientID,
updated:timestamp}
]};
callback(null, JSON.stringify(response));
},
getDocument: function(entryUuid, patientId, format, callback){
var tmp = [];
tmp.push("<?xml version='1.0' encoding='UTF-8'?>");
tmp.push("<ClinicalDocument xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns='urn:hl7-org:v3'>");
tmp.push("<typeId extension='POCD_HD000040' root='2.16.840.1.113883.1.3'/>");
tmp.push("<templateId root='2.16.840.1.113883.2.1.3.9.10.0.0'/>");
tmp.push("<id extension='742318311954' root='2.16.840.1.113883.2.1.3.9'/>");
tmp.push("<code code='57027-5' codeSystem='2.16.840.1.113883.6.1' codeSystemName='LOINC' displayName='Measure Observations'/>");
tmp.push("<title>Measure Observations</title>");
tmp.push("<effectiveTime value='20080506143021+0100'/>");
tmp.push("<confidentialityCode code='N' codeSystem='2.16.840.1.113883.5.25' codeSystemName='HL7' displayName='Normal'/>");
tmp.push("<languageCode code='en-UK'/>");
tmp.push("<recordTarget>");
tmp.push("<patientRole>");
tmp.push("<id extension='223568611' root='2.16.840.1.113883.2.1.3.9.1.0.0'/>");
tmp.push("<addr><streetName>60 Hounslow Rd</streetName><city>SMYTHE'S GREEN</city><postalCode>CO5 1VO</postalCode></addr>");
tmp.push("<patient>");
tmp.push("<name><family>OWEN</family><given>OLIVER</given></name>");
tmp.push("<administrativeGenderCode code='M' codeSystem='2.16.840.1.113883.5.1'/>");
tmp.push("<birthTime value='19331210'/>");
tmp.push("</patient>");
tmp.push("</patientRole>");
tmp.push("</recordTarget>");
tmp.push("<author>");
tmp.push("<time value='20080506143021+0100'/>");
tmp.push("<assignedAuthor>");
tmp.push("<id extension='593978059683' root='2.16.840.1.113883.2.1.3.9.1.0.0'/>");
tmp.push("<assignedPerson>");
tmp.push("<name><family>HOOK</family><given>JAMES</given></name>");
tmp.push("</assignedPerson>");
tmp.push("<representedOrganization>");
tmp.push("<id root='2.16.840.1.113883.2.1.3.9.19.5'/>");
tmp.push("<name>Good Health Clinic</name>");
tmp.push("</representedOrganization>");
tmp.push("</assignedAuthor>");
tmp.push("</author>");
tmp.push("<custodian>");
tmp.push("<assignedCustodian>");
tmp.push("<representedCustodianOrganization>");
tmp.push("<id root='2.16.840.1.113883.2.1.3.9.1.1.1.2.0'/>");
tmp.push("<name>Sintero XDS</name>");
tmp.push("</representedCustodianOrganization>");
tmp.push("</assignedCustodian>");
tmp.push("</custodian>");
tmp.push("<documentationOf>");
tmp.push("<serviceEvent classCode='MPROT'>");
tmp.push("<effectiveTime>");
tmp.push("<low value='20080506141821'/>");
tmp.push("<high value='20080506144221+0100'/>");
tmp.push("</effectiveTime>");
tmp.push("</serviceEvent>");
tmp.push("</documentationOf>");
tmp.push("<component>");
tmp.push("<structuredBody>");
tmp.push("<component>");
tmp.push("<section>");
tmp.push("<templateId root='2.16.840.1.113883.2.1.3.9.10.1.1'/>");
tmp.push("<code code='2276-4' codeSystem='2.16.840.1.113883.6.1' codeSystemName='LOINC' displayName='Ferritin'/>");
tmp.push("<text>06-May-2008 13:30:21 GMT+01:00 Ferritin: 622.0 ug/L</text>");
tmp.push("<entry>");
tmp.push("<observation classCode='OBS' moodCode='EVN'>");
tmp.push("<code code='2276-4' codeSystem='2.16.840.1.113883.6.1' codeSystemName='LOINC' displayName='Ferritin'/>");
tmp.push("<effectiveTime value='20080506141821'/>");
tmp.push("<value xsi:type='PQ' unit='ug/L' value='622.0'/>");
tmp.push("</observation>");
tmp.push("</entry>");
tmp.push("</section>");
tmp.push("</component>");
tmp.push("</structuredBody>");
tmp.push("</component>");
tmp.push("</ClinicalDocument>");
var data = tmp.join("");
var document = {
headers:{
"content-type":"text/xml",
"content-transfer-encoding":"binary",
"content-id":"<1.urn:uuid:BA2B74DD7D946FD24E1359170843006@apache.org>"
},
data:data
}
callback(null, document);
}
}
Create the service config:
var config = {
repositoryAdapter: repositoryAdapter,
middleware: {
logger: mhd.logger('./logs/'),
authentication: mhd.basicAuth(function(user, pass, callback){
if (user == 'Aladdin' && pass == 'letmein'){
callback(null, user);
}
else {
callback(null, false);
}
})
}
}
var app = mhd.app(config);
Register the callback with mhd. As mhd.app is an express.app it can be started as usual:
function start(){
console.log('Starting service');
var svc = http.createServer(app);
svc.listen(1337);
console.log('Service listening on http://127.0.0.1:1337');
}
start();
The server can then be used to search for and retrieve documents. For example, to findDocuments:
to getDocumentDossier:
to getDocument:
Development supported by Black Pear Software Ltd
Work funded in part by NHS Information Sharing Challenge Fund
FAQs
IHE MHD profile service facade for node.js
The npm package mhd receives a total of 7 weekly downloads. As such, mhd popularity was classified as not popular.
We found that mhd demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Opengrep forks Semgrep to preserve open source SAST in response to controversial licensing changes.
Security News
Critics call the Node.js EOL CVE a misuse of the system, sparking debate over CVE standards and the growing noise in vulnerability databases.
Security News
cURL and Go security teams are publicly rejecting CVSS as flawed for assessing vulnerabilities and are calling for more accurate, context-aware approaches.