Skip to content

Commit

Permalink
Merge pull request #8 from cqframework/support-versions
Browse files Browse the repository at this point in the history
Improve Support for ValueSet Versions
  • Loading branch information
cmoesel authored Jun 5, 2020
2 parents 5c4ac52 + c1b5d4d commit 8f71e15
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 87 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,24 @@ valueset "Diabetes": 'https://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113883.3.
// or valueset "Diabetes": '2.16.840.1.113883.3.464.1003.103.12.1001'
```

As of 1.1.1, this library supports Value Set versions, so the following is also supported:

```
valueset "Diabetes": 'https://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113883.3.464.1003.103.12.1001' version '20190315'
// or valueset "Diabetes": 'urn:oid:2.16.840.1.113883.3.464.1003.103.12.1001' version '20190315'
// or valueset "Diabetes": '2.16.840.1.113883.3.464.1003.103.12.1001' version '20190315'
```

When using the canonical URL as a Value Set identifier, it is also possible to embed the version directly in the URL, using a vertical bar (`|`) to separate the identifier and version:

```
valueset "Diabetes": 'https://cts.nlm.nih.gov/fhir/ValueSet/2.16.840.1.113883.3.464.1003.103.12.1001|20190315'
```

The embedded version, however, is only supported for the canonical URL form of value sets. It is not supported for URN or OID identifiers.

## Credentials Required

This library requires that the credentials of a valid UMLS account be provided to it. If you do not have an UMLS
account, you can request one here: https://uts.nlm.nih.gov/license.html

Expand Down
46 changes: 23 additions & 23 deletions lib/download-vsac.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,31 @@ const extractOidAndVersion = require('./extractOidAndVersion');
const debug = require('debug')('vsac'); // To turn on DEBUG: $ export DEBUG=vsac

function downloadFromVSAC(username, password, input, output, vsDB={}, caching=true) {
var vsJSON = {};
if (typeof(input) === 'string') {
path.resolve(input);
vsJSON = require(input);
} else {
var keys = Object.keys(input);
keys.forEach(function(val) {
const [oid] = extractOidAndVersion(input[val].id);
if (!(oid in vsDB)) {
vsJSON[input[val].name] = oid;
}
});
}
if (Object.keys(vsJSON).length > 0) {
const oidsAndVersions = [];
Object.keys(input).forEach((key) => {
let [id, version] = [input[key].id, input[key].version];
const [oid, embeddedVersion] = extractOidAndVersion(id);
if (version == null && embeddedVersion != null) {
version = embeddedVersion;
}
if (vsDB[oid] == null || vsDB[oid][version] == null) {
oidsAndVersions.push({ oid, version });
}
});
if (oidsAndVersions.length) {
output = path.resolve(output);
const oids = Object.keys(vsJSON).map(k => vsJSON[k]);
if (caching && !fs.existsSync(output)){
mkdirp.sync(output);
}
return getTicketGrantingTicket(username, password)
.then((ticketGrantingTicket) => {
const promises = oids.map(oid => {
const promises = oidsAndVersions.map(({ oid, version }) => {
// Catch errors and convert to resolutions returning an error. This ensures Promise.all waits for all promises.
// See: http://stackoverflow.com/questions/31424561/wait-until-all-es6-promises-complete-even-rejected-promises
return downloadValueSet(ticketGrantingTicket, oid, output, vsDB, caching)
return downloadValueSet(ticketGrantingTicket, oid, version, output, vsDB, caching)
.catch((err) => {
debug(`Error downloading valueset ${oid}`, err);
return new Error(`Error downloading valueset: ${oid}`);
debug(`Error downloading valueset ${oid}${version || ''}`, err);
return new Error(`Error downloading valueset: ${oid}${version || ''}`);
});
});
return Promise.all(promises);
Expand Down Expand Up @@ -68,10 +65,10 @@ function getTicketGrantingTicket(username, password) {
return rpn(options);
}

function downloadValueSet(ticketGrantingTicket, oid, output, vsDB={}, caching=true) {
function downloadValueSet(ticketGrantingTicket, oid, version, output, vsDB={}, caching=true) {
return getServiceTicket(ticketGrantingTicket)
.then((serviceTicket) => {
return getValueSet(serviceTicket, oid);
return getValueSet(serviceTicket, oid, version);
})
.then((data) => {
parseVSACXML(data, vsDB);
Expand All @@ -89,12 +86,15 @@ function getServiceTicket(ticketGrantingTicket) {
return rpn(options);
}

function getValueSet(serviceTicket, oid) {
debug('Getting ValueSet:', oid);
function getValueSet(serviceTicket, oid, version) {
debug(`Getting ValueSet: ${oid}${version || ''}`);
const options = {
url: 'https://vsac.nlm.nih.gov/vsac/svs/RetrieveValueSet',
qs: { id: oid, ticket: serviceTicket }
};
if (version != null) {
options.qs.version = version;
}
return rpn(options);
}

Expand Down
7 changes: 4 additions & 3 deletions lib/extractOidAndVersion.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/**
* Extracts just the oid from a urn, url, or oid. If it is not a valid urn or VSAC URL,
* it is assumed to be an oid and returned as-is.
* Extracts the oid and version from a url, urn, or oid. Only url supports an embedded version
* (separately by |); urn and oid will never return a version. If the input value is not a valid
* urn or VSAC URL, it is assumed to be an oid and returned as-is.
* @param {string} id - the urn, url, or oid
* @returns {string} the oid
* @returns {[string,string]} the oid and optional version as a pair
*/
function extractOidAndVersion(id) {
if (id == null) return [];
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cql-exec-vsac",
"version": "1.1.0",
"version": "1.1.1",
"license": "Apache-2.0",
"repository": {
"type": "git",
Expand Down
Loading

0 comments on commit 8f71e15

Please sign in to comment.