|
| 1 | +# CQL Test Server |
| 2 | + |
| 3 | +A barebones implementation of the FHIR [$cql](https://build.fhir.org/ig/HL7/cql-ig/en/OperationDefinition-cql-cql.html) operation that evaluates CQL expressions using the CQL execution engine and uses the [CQL FHIR Type Mapping](https://build.fhir.org/ig/HL7/cql-ig/en/conformance.html#fhir-type-mapping) to return results as a FHIR `Parameters` resource. This server is intended to be used as a target for the [cql-tests-runner](https://github.com/cqframework/cql-tests-runner) and is tuned specifically for that use case. |
| 4 | + |
| 5 | +## Endpoint |
| 6 | + |
| 7 | +- POST `/fhir/$cql` |
| 8 | + - Example request: |
| 9 | + ```json |
| 10 | + { |
| 11 | + "resourceType": "Parameters", |
| 12 | + "parameter": [{ "name": "expression", "valueString": "1 + 2" }] |
| 13 | + } |
| 14 | + ``` |
| 15 | + - Example response: |
| 16 | + ```json |
| 17 | + { |
| 18 | + "resourceType": "Parameters", |
| 19 | + "parameter": [{ |
| 20 | + "extension": [{ |
| 21 | + "url": "http://hl7.org/fhir/StructureDefinition/cqf-cqlType", |
| 22 | + "valueString": "System.Integer" |
| 23 | + }], |
| 24 | + "name": "return", |
| 25 | + "valueInteger": 3 |
| 26 | + }] |
| 27 | + } |
| 28 | + ``` |
| 29 | + - Errors: |
| 30 | + - HTTP 400 if the `expression` parameter is missing or empty |
| 31 | + - HTTP 500 if there is an unexpected / unrecoverable server-side error |
| 32 | + |
| 33 | +## Prerequisites |
| 34 | + |
| 35 | +This project uses Node.js. It has been tested using Node 24 but should work with any recent LTS version. |
| 36 | + |
| 37 | +## Developing Scripts |
| 38 | + |
| 39 | +The `package.json` file defines scripts to support development of the test-server source code. These include: |
| 40 | + |
| 41 | +- `npm run lint`: run eslint against the test-server source code |
| 42 | +- `npm run lint:fix`: fix eslint errors (as possible) |
| 43 | +- `npm run prettier`: run prettier against the test-server source code |
| 44 | +- `npm run prettier:fix`: fix prettier violations (as possible) |
| 45 | +- `npm test`: run the unit tests |
| 46 | + |
| 47 | +Scripts for building and running the server are documented below. |
| 48 | + |
| 49 | +## Start The Server |
| 50 | + |
| 51 | +From this directory: |
| 52 | + |
| 53 | +### Install dependencies: |
| 54 | + |
| 55 | +```sh |
| 56 | +npm install |
| 57 | +``` |
| 58 | + |
| 59 | +### Development mode: |
| 60 | + |
| 61 | +```sh |
| 62 | +npm run dev |
| 63 | +``` |
| 64 | + |
| 65 | +The development mode builds the `cql-execution` source (to ensure it uses the latest changes) before running the server. It watches for changes to the `test-server` source and hot-reloads as necessary. By default, it uses the javascript CQL-to-ELM translator and listens on `http://localhost:8000`. |
| 66 | + |
| 67 | +_NOTE: The watch mode will NOT detect or hot-reload changes in the `cql-execution` source. You must stop and restart the `test-server` to pick up changes in the `cql-execution` source._ |
| 68 | + |
| 69 | +# Production mode: |
| 70 | + |
| 71 | +```sh |
| 72 | +npm run build |
| 73 | +npm start |
| 74 | +``` |
| 75 | + |
| 76 | +The production mode builds the `cql-execution` source and `test-server` source then runs the server _without_ watching for changes. By default, it uses the javascript CQL-to-ELM translator and listens on `http://localhost:8000`. |
| 77 | + |
| 78 | +### Configuration |
| 79 | + |
| 80 | +- `PORT` (optional): Port to bind. Defaults to `8000`. |
| 81 | +- `USE_TRANSLATION_SERVICE` (optional, default: `false`): If `true`, the server will use a local [CQL Translation Service](https://github.com/cqframework/cql-translation-service) for CQL-to-ELM. In this case, the CQL Translation service must be running and available at `http://localhost:8080`. If `false`, the server will use the javascript CQL-to-ELM module to compile CQL. |
| 82 | + |
| 83 | +You can export these variables before running the server or place them in a `.env` file: |
| 84 | + |
| 85 | +```ini |
| 86 | +PORT=8000 |
| 87 | +USE_TRANSLATION_SERVICE=false |
| 88 | +``` |
| 89 | + |
| 90 | +## Quick Test With curl |
| 91 | + |
| 92 | +```sh |
| 93 | +curl -X POST http://localhost:8000/fhir/\$cql \ |
| 94 | + -H "Content-Type: application/fhir+json" \ |
| 95 | + -d '{ |
| 96 | + "resourceType": "Parameters", |
| 97 | + "parameter": [ |
| 98 | + { "name": "expression", "valueString": "1 + 2" } |
| 99 | + ] |
| 100 | + }' |
| 101 | +``` |
| 102 | + |
| 103 | +## Use With cql-tests-runner |
| 104 | + |
| 105 | +This server is designed to be a `$cql` target for the [cql-tests-runner](https://github.com/cqframework/cql-tests-runner). To execute the test-runner against this server: |
| 106 | + |
| 107 | +1. Download or clone the `cql-tests-runner` repository. |
| 108 | + |
| 109 | +2. Start this test-server (see above), e.g. at `http://localhost:8000`. |
| 110 | + |
| 111 | +3. In cql-tests-runner folder, create or edit a [test runner configuration](https://github.com/cqframework/cql-tests-runner?tab=readme-ov-file#configuration-settings) that points to the test-server endpoint. If you are using port 8000, you may choose to use the existing [conf/cql-execution-local.json](https://github.com/cqframework/cql-tests-runner/blob/main/conf/cql-execution-local.json) file. |
| 112 | + |
| 113 | +4. Run the tests from the cql-tests-runner folder: |
| 114 | + |
| 115 | + ```sh |
| 116 | + npm install |
| 117 | + git submodule update --init --recursive |
| 118 | + npx tsx src/bin/cql-tests.ts run-tests conf/cql-execution-local.json ./results |
| 119 | + ``` |
| 120 | + |
| 121 | +The runner will POST each test expression to `http://localhost:8000/fhir/$cql` and expect FHIR `Parameters` responses per the mapping. The test-server logs each incoming expression, the raw result, and the result mapped to `FHIR Parameters`. When the run is done, you can find the results in the cql-tests-runner folder's `results` sub-folder. |
| 122 | + |
0 commit comments