diff --git a/CHANGELOG.md b/CHANGELOG.md index ae0bb16..11e6d5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,20 +3,36 @@ This log documents significant changes for each release. This project follows [Semantic Versioning](http://semver.org/). -## [3.14.1] - 2024-05-21 +## [3.14.1] - 2024-07-02 ### Fixed - impossibility to use attribute name that starts with a capital letter. -## [3.14.0] - 2024-05-09 +## [3.14.0] - 2024-07-02 ### Added - supplementary function `weight()` with alternative name `ordinal()`. -## [3.13.1] - 2024-04-24 +## [3.13.4] - 2024-06-13 +### Fixed +- a bug that could cause the context input parameter containing environment + variables to change. + +## [3.13.3] - 2024-05-24 +### Changed +- Added separate TypeScript type definition files for the main file and each + supported model. + +## [3.13.2] - 2024-05-15 ### Fixed - an issue with evaluating an expression for a resource passed through an environment variable. - an issue with "statusShift" during performance tests. +## [3.13.1] - 2024-04-25 +### Fixed +- Added flag 'u' for regular expressions in the specification's `matches` and + `replaceMatches` functions to support the use of unicode character class + escapes. + ## [3.13.0] - 2024-04-10 ### Added - Function `defineVariable(name: String [, expr: expression])`. diff --git a/demo/package-lock.json b/demo/package-lock.json index 3074d8e..ffcc12b 100644 --- a/demo/package-lock.json +++ b/demo/package-lock.json @@ -811,12 +811,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -1838,9 +1838,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -5462,9 +5462,9 @@ } }, "node_modules/webpack-plugin-serve/node_modules/ws": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "dev": true, "engines": { "node": ">=8.3.0" @@ -5737,9 +5737,9 @@ "dev": true }, "node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, "engines": { "node": ">=10.0.0" @@ -6468,12 +6468,12 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "browserslist": { @@ -7256,9 +7256,9 @@ } }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "requires": { "to-regex-range": "^5.0.1" @@ -9972,9 +9972,9 @@ } }, "ws": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "dev": true, "requires": {} } @@ -10162,9 +10162,9 @@ "dev": true }, "ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, "requires": {} }, diff --git a/fhir-context/dstu2/index.d.ts b/fhir-context/dstu2/index.d.ts new file mode 100644 index 0000000..32448c5 --- /dev/null +++ b/fhir-context/dstu2/index.d.ts @@ -0,0 +1,8 @@ +import { Model } from "../../src/fhirpath"; + +export const { + choiceTypePaths, + pathsDefinedElsewhere, + type2Parent, + path2Type +}: Model; diff --git a/fhir-context/r4/index.d.ts b/fhir-context/r4/index.d.ts new file mode 100644 index 0000000..32448c5 --- /dev/null +++ b/fhir-context/r4/index.d.ts @@ -0,0 +1,8 @@ +import { Model } from "../../src/fhirpath"; + +export const { + choiceTypePaths, + pathsDefinedElsewhere, + type2Parent, + path2Type +}: Model; diff --git a/fhir-context/r5/index.d.ts b/fhir-context/r5/index.d.ts new file mode 100644 index 0000000..32448c5 --- /dev/null +++ b/fhir-context/r5/index.d.ts @@ -0,0 +1,8 @@ +import { Model } from "../../src/fhirpath"; + +export const { + choiceTypePaths, + pathsDefinedElsewhere, + type2Parent, + path2Type +}: Model; diff --git a/fhir-context/stu3/index.d.ts b/fhir-context/stu3/index.d.ts new file mode 100644 index 0000000..32448c5 --- /dev/null +++ b/fhir-context/stu3/index.d.ts @@ -0,0 +1,8 @@ +import { Model } from "../../src/fhirpath"; + +export const { + choiceTypePaths, + pathsDefinedElsewhere, + type2Parent, + path2Type +}: Model; diff --git a/index.d.ts b/index.d.ts deleted file mode 100644 index 80d5390..0000000 --- a/index.d.ts +++ /dev/null @@ -1,97 +0,0 @@ -declare module "fhirpath" { - export function compile( - path: string | Path, - model?: Model, - options?: { - resolveInternalTypes?: boolean - traceFn?: (value: any, label: string) => void, - userInvocationTable?: UserInvocationTable - } - ): Compile; - export function evaluate( - fhirData: any, - path: string | Path, - context?: Context, - model?: Model, - options?: { - resolveInternalTypes?: boolean, - traceFn?: (value: any, label: string) => void, - userInvocationTable?: UserInvocationTable - } - ): any[]; - export function resolveInternalTypes(value: any): any; - export function types(value: any): string[]; - export function parse(expression: string): any; - export const version :string; -} - -declare module "fhirpath/fhir-context/dstu2" { - export const { - choiceTypePaths, - pathsDefinedElsewhere, - type2Parent, - path2Type - }: Model; -} - -declare module "fhirpath/fhir-context/r5" { - export const { - choiceTypePaths, - pathsDefinedElsewhere, - type2Parent, - path2Type - }: Model; -} - -declare module "fhirpath/fhir-context/r4" { - export const { - choiceTypePaths, - pathsDefinedElsewhere, - type2Parent, - path2Type - }: Model; -} - -declare module "fhirpath/fhir-context/stu3" { - export const { - choiceTypePaths, - pathsDefinedElsewhere, - type2Parent, - path2Type - }: Model; -} - -interface Path { - base: string; - expression: string; -} - -interface Model { - choiceTypePaths: { - [path: string]: string[]; - }; - pathsDefinedElsewhere: { - [path: string]: string; - }; - type2Parent: { - [path: string]: string; - }; - path2Type: { - [path: string]: string; - }; -} - -type Compile = (resource: any, context?: Context) => any[]; - -type Context = void | Record; - -type UserInvocationTable = { - [name: string]: { - fn: Function, - arity: { - [numberOfParams: number]: Array<'Expr' | 'AnyAtRoot' | 'Identifier' | 'TypeSpecifier' | 'Any' | 'Integer' | 'Boolean' | 'Number' | 'String'> - }, - nullable?: boolean, - internalStructures?: boolean - } -}; diff --git a/package-lock.json b/package-lock.json index b4e31ea..ffd3cbb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4400,12 +4400,12 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -6638,9 +6638,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -10085,27 +10085,6 @@ "node": ">= 6" } }, - "node_modules/jsdom/node_modules/ws": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -12998,27 +12977,6 @@ "node": ">=8" } }, - "node_modules/webpack-bundle-analyzer/node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/webpack-cli": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.1.tgz", @@ -13409,6 +13367,27 @@ "typedarray-to-buffer": "^3.1.5" } }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", @@ -16989,12 +16968,12 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "browser-process-hrtime": { @@ -18657,9 +18636,9 @@ } }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "requires": { "to-regex-range": "^5.0.1" @@ -21220,13 +21199,6 @@ "agent-base": "6", "debug": "4" } - }, - "ws": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", - "dev": true, - "requires": {} } } }, @@ -23490,13 +23462,6 @@ "requires": { "has-flag": "^4.0.0" } - }, - "ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "dev": true, - "requires": {} } } }, @@ -23749,6 +23714,13 @@ "typedarray-to-buffer": "^3.1.5" } }, + "ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, + "requires": {} + }, "xml-name-validator": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", diff --git a/package.json b/package.json index 3ee13e8..ec10f4d 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "3.14.1", "description": "A FHIRPath engine", "main": "src/fhirpath.js", + "types": "src/fhirpath.d.ts", "dependencies": { "@lhncbc/ucum-lhc": "^5.0.0", "antlr4": "~4.9.3", diff --git a/src/fhirpath.d.ts b/src/fhirpath.d.ts new file mode 100644 index 0000000..b24dbdc --- /dev/null +++ b/src/fhirpath.d.ts @@ -0,0 +1,64 @@ +export function compile( + path: string | Path, + model?: Model, + options?: { + resolveInternalTypes?: boolean + traceFn?: (value: any, label: string) => void, + userInvocationTable?: UserInvocationTable + } +): Compile; + +export function evaluate( + fhirData: any, + path: string | Path, + context?: Context, + model?: Model, + options?: { + resolveInternalTypes?: boolean, + traceFn?: (value: any, label: string) => void + userInvocationTable?: UserInvocationTable + } +): any[]; + +export function resolveInternalTypes(value: any): any; + +export function types(value: any): string[]; + +export function parse(expression: string): any; + +export const version :string; + +interface Path { + base: string; + expression: string; +} + +interface Model { + choiceTypePaths: { + [path: string]: string[]; + }; + pathsDefinedElsewhere: { + [path: string]: string; + }; + type2Parent: { + [path: string]: string; + }; + path2Type: { + [path: string]: string; + }; +} + +type Compile = (resource: any, context?: Context) => any[]; + +type Context = void | Record; + +type UserInvocationTable = { + [name: string]: { + fn: Function, + arity: { + [numberOfParams: number]: Array<'Expr' | 'AnyAtRoot' | 'Identifier' | 'TypeSpecifier' | 'Any' | 'Integer' | 'Boolean' | 'Number' | 'String'> + }, + nullable?: boolean, + internalStructures?: boolean + } +}; diff --git a/src/fhirpath.js b/src/fhirpath.js index 24bdc80..7fa3991 100644 --- a/src/fhirpath.js +++ b/src/fhirpath.js @@ -282,14 +282,16 @@ engine.ExternalConstantTerm = function(ctx, parentData, node) { ctx.processedVars[varName] = value; delete ctx.vars[varName]; } else if (varName in ctx.processedVars) { + // "processedVars" are variables with ready-to-use values that have already + // been converted to ResourceNodes if necessary. value = ctx.processedVars[varName]; + } else if (ctx.definedVars && varName in ctx.definedVars) { + // "definedVars" are variables defined with the "defineVariable" function. + value = ctx.definedVars[varName]; } else { - if (ctx.definedVars && varName in ctx.definedVars) - value = ctx.definedVars[varName]; - else - throw new Error( - "Attempting to access an undefined environment variable: " + varName - ); + throw new Error( + "Attempting to access an undefined environment variable: " + varName + ); } // For convenience, we all variable values to be passed in without their array // wrapper. However, when evaluating, we need to put the array back in. diff --git a/src/strings.js b/src/strings.js index 24ab343..5232ec0 100644 --- a/src/strings.js +++ b/src/strings.js @@ -162,7 +162,7 @@ if (dotAllIsSupported) { if (util.isEmpty(regex) || util.isEmpty(str)) { return []; } - const reg = new RegExp(regex, 's'); + const reg = new RegExp(regex, 'su'); return reg.test(str); }; } else { @@ -171,7 +171,7 @@ if (dotAllIsSupported) { if (util.isEmpty(regex) || util.isEmpty(str)) { return []; } - const reg = new RegExp(rewritePatternForDotAll(regex)); + const reg = new RegExp(rewritePatternForDotAll(regex), 'u'); return reg.test(str); }; } @@ -190,7 +190,7 @@ engine.replaceMatches = function (coll, regex, repl) { if (util.isEmpty(regex) || util.isEmpty(repl) || util.isEmpty(str)) { return []; } - const reg = new RegExp(regex, 'g'); + const reg = new RegExp(regex, 'gu'); return str.replace(reg, repl); }; diff --git a/test/api.test.js b/test/api.test.js index 46f9eef..60de04c 100644 --- a/test/api.test.js +++ b/test/api.test.js @@ -260,5 +260,16 @@ describe('evaluate type() on a FHIRPath evaluation result', () => { 'Quantity', 'Quantity', 'Quantity', 'Quantity', 'Date' ]); }); + + it('should not change the context input parameter containing environment variables', () => { + const originalVars = {a: 'abc'}; + const vars = _.cloneDeep(originalVars); + expect(fhirpath.evaluate( + {}, + '%a = \'abc\'', + vars + )).toStrictEqual([true]); + expect(originalVars).toStrictEqual(vars); + }) }); diff --git a/test/cases/5.6_string_manipulation.yaml b/test/cases/5.6_string_manipulation.yaml index 74936df..2533de9 100644 --- a/test/cases/5.6_string_manipulation.yaml +++ b/test/cases/5.6_string_manipulation.yaml @@ -258,6 +258,10 @@ tests: expression: Patient.name.given[0].matches('.*') result: [] + - desc: '** matches with unicode character class escapes' + expression: "'Taupō'.matches('^\\\\p{Lu}\\\\p{Ll}*$')" + result: [true] + - desc: '5.6.10. replaceMatches(regex : string, substitution: string) : string' # If the input collection contains a single item of type string, the function will match the input using the regular expression in regex and replace each match with the substitution string. The substitution may refer to identified match groups in the regular expression. # This example of replaceMatches() will convert a string with a date formatted as MM/dd/yy to dd-MM-yy: @@ -299,6 +303,10 @@ tests: expression: Patient.name.given[0].replaceMatches('(.*)', '$1') result: [] + - desc: '** replaceMatches with a unicode character class escape' + expression: "'Taupō'.replaceMatches('(\\\\p{Lu})', 'city: $1')" + result: ['city: Taupō'] + - desc: '5.6.11. length() : integer' # If the input collection contains a single item of type string, the function will return the length of the string. If the input collection is empty ({ }), the result is empty. - desc: '** length'