Skip to content

Create "DataModelProvider" concept in support of Instance expression - #401

Open
dehall wants to merge 2 commits into
masterfrom
instance_datamodelproviders
Open

dehall wants to merge 2 commits into
masterfrom
instance_datamodelproviders

Conversation

@dehall

@dehall dehall commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Addresses #391

Currently, objects created with the instance syntax / Instance ELM expression are constructed as Tuples/plain JS objects, and only a few specific classes are then mapped to the real data model equivalent class. This caused issues with instances of objects outside of the system data model, where the Is expression was throwing an error. (For the system data model, the Is expression was permissive and always returned true, so a much simpler alternate fix would be to just use that same permissive check for any type, not just the system data model. But that would produce false positives)
A decent solution would be to tag the constructed JS objects with an _is function that allows typechecking. The problem with that is, in the Instance expression there's no way to know what the full hierarchy of the requested type is, it needs some way of calling out to the library that defines the relevant data model.

This PR introduces the concept of a DataModelProvider, which is an interface that defines a single function createInstance(type: string, obj: any). obj is the plain JS object with mapped fields, which previously would have been the direct return value of the Instance expression. The intent of this is for libraries that implement a data model, eg cql-exec-fhir, they can define a DataModelProvider that knows how to turn an arbitrary JS object into a real instance of the relevant class, and so then there's really no difference between a constructed instance and a value pulled from a DataSource.
DataModelProviders are registered on an Executor and/or a Context, with the idea that we can support multiple data models if needed.
System types are handled with a new SystemDataModelProvider that demonstrates the concept. Previously only a few types were handled, so I added support for the remaining classes in the ELM system data model.

Importantly, it is not mandatory for libraries to implement a DataModelProvider immediately. If the Instance expression gets a type that no registered DataModelProvider knows how to handle, the resulting object stays as a plain JS object, same as today, but it's still tagged with an _is function that knows the specific type it is. That said, cqframework/cql-exec-fhir#50 will implement the DataModelProvider for FHIR.

Pull requests into cql-execution require the following.
Submitter and reviewer should ✔ when done.
For items that are not-applicable, mark "N/A" and ✔.

Submitter:

  • This pull request describes why these changes were made
  • Code diff has been done and been reviewed (it does not contain: additional white space, not applicable code changes, debug statements, etc.)
  • Tests are included and test edge cases
  • Tests have been run locally and pass
  • Code coverage has not gone down and all code touched or added is covered.
  • Code passes lint and prettier (hint: use npm run check to run tests, lint, and prettier)
  • All dependent libraries are appropriately updated or have a corresponding PR related to this change
    Reviewer:

Name:

  • Code is maintainable and reusable, reuses existing code and infrastructure where appropriate, and accomplishes the task’s purpose
  • The tests appropriately test the new code, including edge cases
  • You have tried to break the code

@codecov-commenter

codecov-commenter commented Nov 2, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.93548% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.32%. Comparing base (e87e3fa) to head (ec4037d).

Files with missing lines Patch % Lines
src/runtime/executor.ts 70.00% 3 Missing ⚠️
src/runtime/context.ts 96.55% 1 Missing ⚠️
src/runtime/systemDataModelProvider.ts 92.85% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #401      +/-   ##
==========================================
+ Coverage   89.21%   89.32%   +0.10%     
==========================================
  Files          60       61       +1     
  Lines        5081     5123      +42     
  Branches     1451     1453       +2     
==========================================
+ Hits         4533     4576      +43     
+ Misses        317      315       -2     
- Partials      231      232       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dehall
dehall force-pushed the instance_datamodelproviders branch from 57a113e to ec4037d Compare November 3, 2026 17:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants