npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fhir-toolkit/cql

v1.3.2

Published

Native Clinical Quality Language (CQL) engine for TypeScript

Readme

@fhir-toolkit/cql

A Clinical Quality Language (CQL) expression engine for Node.js and browsers. Evaluates CQL 1.5 expressions against FHIR R4/R4B/R5 resources.

Installation

pnpm add @fhir-toolkit/cql
# or
npm install @fhir-toolkit/cql

Basic evaluation

import { CqlEngine } from '@fhir-toolkit/cql'

const engine = new CqlEngine()

const result = await engine.evaluateExpression(
  `library Test version '1.0'
define "Result": 2 + 2`,
  'Result',
  null,
)
console.log(result?.toString()) // '4'

Evaluate all expressions in a library

const results = await engine.evaluateLibrary(
  `library Demo version '1.0'
define "A": 1 + 1
define "B": 'hello'`,
  null,
)
// { A: CqlInteger(2), B: CqlString('hello') }

InMemoryDataProvider

Load a FHIR Bundle as in-memory data:

import { CqlEngine, InMemoryDataProvider } from '@fhir-toolkit/cql'

const bundle = {
  resourceType: 'Bundle' as const,
  entry: [
    { resource: { resourceType: 'Patient', id: 'p1', gender: 'female' } },
    { resource: { resourceType: 'Observation', id: 'o1', status: 'final' } },
  ],
}

const engine = new CqlEngine({
  dataProvider: new InMemoryDataProvider(bundle),
})

const result = await engine.evaluateExpression(
  `library Demo version '1.0'
context Patient
define "Patients": [Patient]`,
  'Patients',
  null,
)

InMemoryTerminologyProvider

Supply value sets for membership checks:

import { CqlEngine, InMemoryTerminologyProvider } from '@fhir-toolkit/cql'

const engine = new CqlEngine({
  terminologyProvider: new InMemoryTerminologyProvider({
    valueSets: {
      'http://example.org/vs/diabetes': [
        { system: 'http://snomed.info/sct', code: '44054006', display: 'Diabetes mellitus' },
      ],
    },
    codeSystems: {
      'http://snomed.info/sct': [
        { system: 'http://snomed.info/sct', code: '44054006' },
      ],
    },
  }),
})

Multi-library support

Resolve included CQL libraries at runtime:

import { CqlEngine } from '@fhir-toolkit/cql'

const engine = new CqlEngine({
  libraryResolver: async (name, version) => {
    const response = await fetch(`/libraries/${name}-${version}.cql`)
    return response.text()
  },
})

// A library that includes another:
const result = await engine.evaluateExpression(
  `library Main version '1.0'
include Helpers version '1.0' called H
define "Value": H.SomeHelper()`,
  'Value',
  null,
)

Expression tracing

Receive a callback after each expression definition is evaluated:

engine.on('trace', (event) => {
  console.log(`${event.expression} = ${JSON.stringify(event.value)}`)
})

on() returns this so calls can be chained:

const engine = new CqlEngine()
  .on('trace', (e) => console.log(e.expression, e.value))

UCUM unit support

Plug in @fhir-toolkit/ucum for Quantity arithmetic:

import { CqlEngine } from '@fhir-toolkit/cql'
import { createUcumService } from '@fhir-toolkit/ucum'

const engine = new CqlEngine({
  ucumService: createUcumService(),
})

Compile to AST

compile() parses CQL source and returns a cached Library AST (ELM-compatible):

import { CqlEngine } from '@fhir-toolkit/cql'

const engine = new CqlEngine()
const lib = engine.compile(`library Test version '1.0'
define "X": 42`)

console.log(lib.name)    // 'Test'
console.log(lib.version) // '1.0'

ELM import/export

import { translateLibrary, importElmLibrary } from '@fhir-toolkit/cql'

// CQL source → ELM JSON
const elm = translateLibrary(`library Test version '1.0'
define "X": 1 + 1`)

// ELM JSON → Library AST
const lib = importElmLibrary(elm)

Error handling

import {
  CqlSyntaxError,
  CqlEvalError,
  CqlTimeoutError,
  CqlTooCostlyError,
} from '@fhir-toolkit/cql'

try {
  await engine.evaluateExpression(source, 'Result', null)
} catch (err) {
  if (err instanceof CqlSyntaxError) {
    // err.code === 'CQL-001'
    // err.line, err.column available
    console.error(`Syntax error at ${err.line}:${err.column}`)
  } else if (err instanceof CqlEvalError) {
    // err.code === 'CQL-101'
    // err.definition — name of the failing define
    console.error(`Eval error in '${err.definition}'`)
  } else if (err instanceof CqlTimeoutError) {
    // err.code === 'CQL-201'
    console.error(`Timed out after ${err.timeoutMs}ms`)
  } else if (err instanceof CqlTooCostlyError) {
    // err.code === 'CQL-202'
    console.error('CQL source exceeds maximum allowed length')
  }
}

Engine options

const engine = new CqlEngine({
  modelInfo: 'R4',            // 'R4' | 'R4B' | 'R5' (default: 'R4')
  timeout: 5_000,             // ms per evaluation (default: 30 000)
  maxExpressionLen: 50_000,   // max CQL source length (default: 102 400)
  maxDepth: 50,               // max recursion depth (default: 100)
  dataProvider: ...,
  terminologyProvider: ...,
  ucumService: ...,
  libraryResolver: ...,
})

Browser usage

Works in any modern browser with no special bundler configuration:

import { CqlEngine } from '@fhir-toolkit/cql'
const engine = new CqlEngine()

Migration from the Java CQL engine

| Java CQL engine | @fhir-toolkit/cql | |-------------------------------------------|----------------------------------------------------------| | CqlEngine.evaluate(library, context) | engine.evaluateLibrary(source, context) | | CqlEngine.evaluate(library, context, expressionNames) | engine.evaluateExpression(source, name, context) | | LibraryLoader interface | libraryResolver: (name, version) => Promise<string> | | DataProvider interface | DataProvider interface / InMemoryDataProvider | | TerminologyProvider interface | TerminologyProvider interface / InMemoryTerminologyProvider | | ELM JSON | translateLibrary(source) / importElmLibrary(elm) |

Key differences:

  • Evaluation is async (Promise-based) rather than synchronous.
  • Libraries are supplied as CQL source strings; the engine compiles and caches them internally.
  • Result values are typed (CqlInteger, CqlString, CqlQuantity, etc.) with a .toString() method.