From 473fe4b6a73b402d409fdce6b6d0ff7f83d8a32a Mon Sep 17 00:00:00 2001 From: sedinkinya Date: Mon, 21 Nov 2022 19:17:11 -0500 Subject: [PATCH 1/8] Add a types() function to the fhirpath.js API LF-2344 --- CHANGELOG.md | 10 +++++++++ README.md | 13 ++++++++++++ index.d.ts | 1 + package-lock.json | 4 ++-- package.json | 2 +- src/fhirpath.js | 45 ++++++++++++++++++++++++++--------------- src/types.js | 2 ++ test/api.test.js | 27 +++++++++++++++++++++++++ test/cases/fhir-r4.yaml | 3 --- 9 files changed, 85 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ec7784..e3b619b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,16 @@ This log documents significant changes for each release. This project follows [Semantic Versioning](http://semver.org/). +## [3.3.0] - 2022-11-21 +### Added +- An API method `types` which returns the type of each element in FHIRPath result + array which was obtained from evaluate() with option resolveInternalTypes=false. +### Fixed +- The hidden (non-enumerable) property `__path__` has been moved from the entire + array of result values to each element of the array. Because the result array + may contain items of different types. +- The type of "today()" was defined as "System.DateTime". + ## [3.2.0] - 2022-10-28 ### Added - Functions: toDate(), convertsToDate(). diff --git a/README.md b/README.md index d77d61c..ce4ee55 100644 --- a/README.md +++ b/README.md @@ -132,6 +132,19 @@ standard JavaScript types you can use the special function "resolveInternalTypes const res = fhirpath.resolveInternalTypes(value); ``` +Also, there is a special API function to get the type of each element in FHIRPath +result array which was obtained from evaluate() (unless you resolve the internal +types), this function will work on sub-items too and always returns an array of +strings. +In the next example, `res` will have a value like this: + ['FHIR.dateTime', 'FHIR.string', ...]. + +```js +const res = fhirpath.types( + fhirpath.evaluate(resource, expression, context, model, {resolveInternalTypes: false}) +); +``` + ## fhirpath CLI diff --git a/index.d.ts b/index.d.ts index df4036a..1917820 100644 --- a/index.d.ts +++ b/index.d.ts @@ -16,6 +16,7 @@ declare module "fhirpath" { } ): any[]; export function resolveInternalTypes(value: any): any; + export function types(value: any): string[]; } declare module "fhirpath/fhir-context/dstu2" { diff --git a/package-lock.json b/package-lock.json index 3de25d8..a7e9ace 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "fhirpath", - "version": "3.2.0", + "version": "3.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "fhirpath", - "version": "3.2.0", + "version": "3.3.0", "license": "MIT", "dependencies": { "@lhncbc/ucum-lhc": "^4.1.3", diff --git a/package.json b/package.json index 3f1a5fa..a2cf144 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fhirpath", - "version": "3.2.0", + "version": "3.3.0", "description": "A FHIRPath engine", "main": "src/fhirpath.js", "dependencies": { diff --git a/src/fhirpath.js b/src/fhirpath.js index f661be4..0db6aff 100644 --- a/src/fhirpath.js +++ b/src/fhirpath.js @@ -649,29 +649,23 @@ function applyParsedPath(resource, parsedPath, context, model, options) { // in the MemberInvocation method. if (context) { context = Object.keys(context).reduce((restoredContext, key) => { - const path = context[key]?.__path__; - if (path) { - if (Array.isArray(context[key])) { - restoredContext[key] = context[key].map(i => makeResNode(i, path)); - } else { - restoredContext[key] = makeResNode(context[key], path); - } + if (Array.isArray(context[key])) { + restoredContext[key] = context[key].map(i => (i?.__path__ ? makeResNode(i, i?.__path__) : i)); } else { - restoredContext[key] = context[key]; + restoredContext[key] = context[key]?.__path__ ? makeResNode(context[key], context[key]?.__path__) : context[key]; } return restoredContext; }, {}); } let ctx = {dataRoot, vars: Object.assign(vars, context), model}; let rtn = engine.doEval(ctx, dataRoot, parsedPath.children[0]); - let firstRtn = Array.isArray(rtn) ? rtn[0] : rtn; - // Path for the data extracted from the resource. - let path = firstRtn instanceof ResourceNode ? firstRtn.path : null; // Resolve any internal "ResourceNode" instances to plain objects and if // options.resolveInternalTypes is true, resolve any internal "FP_Type" // instances to strings. rtn = (function visit(n) { + // Path for the data extracted from the resource. + let path = n instanceof ResourceNode ? n.path : null; n = util.valData(n); if (Array.isArray(n)) { for (let i=0, len=n.length; i