Skip to content

(feat) Expose dayjs library in expression evaluation context#687

Open
pirupius wants to merge 2 commits intomainfrom
feat/expose-dayjs-expression
Open

(feat) Expose dayjs library in expression evaluation context#687
pirupius wants to merge 2 commits intomainfrom
feat/expose-dayjs-expression

Conversation

@pirupius
Copy link
Member

@pirupius pirupius commented Feb 20, 2026

Requirements

  • This PR has a title that briefly describes the work done including the ticket number. If there is a ticket, make sure your PR title includes a conventional commit label. See existing PR titles for inspiration.
  • My work conforms to the OpenMRS 3.0 Styleguide and design documentation.
  • My work includes tests or is validated by existing tests.

Summary

Currently, users cannot use date manipulation functions directly in form expression calculations. This limits the ability to perform complex date-based calculations like computing age in days from a date of birth field.

Example usage

{
  "id": "ageInDays",
  "label": "Age in Days",
  "type": "obs",
  "questionOptions": {
    "rendering": "number",
    "concept": "age-in-days-concept"
    "calculate": {
      "calculateExpression": "dayjs().diff(dayjs(dateOfBirth), 'day')"
    }
  }
}

Screenshots

Screenshot 2026-02-21 at 12 21 30

Related Issue

Other

@github-actions
Copy link

github-actions bot commented Feb 20, 2026

Size Change: +8 B (+0.01%)

Total Size: 104 kB

ℹ️ View Unchanged
Filename Size Change
dist/adapters/control-adapter.js 187 B 0 B
dist/adapters/encounter-datetime-adapter.js 366 B 0 B
dist/adapters/encounter-diagnosis-adapter.js 952 B 0 B
dist/adapters/encounter-location-adapter.js 342 B 0 B
dist/adapters/encounter-provider-adapter.js 414 B 0 B
dist/adapters/encounter-role-adapter.js 459 B 0 B
dist/adapters/inline-date-adapter.js 726 B 0 B
dist/adapters/obs-adapter.js 2.82 kB 0 B
dist/adapters/obs-comment-adapter.js 664 B 0 B
dist/adapters/orders-adapter.js 853 B 0 B
dist/adapters/patient-identifier-adapter.js 498 B 0 B
dist/adapters/program-state-adapter.js 555 B 0 B
dist/api/index.js 1.75 kB 0 B
dist/components/error/error-modal.component.js 566 B 0 B
dist/components/extension/extension-parcel.component.js 471 B 0 B
dist/components/field-label/field-label.component.js 518 B 0 B
dist/components/group/obs-group.component.js 739 B 0 B
dist/components/inputs/content-switcher/content-switcher.component.js 992 B 0 B
dist/components/inputs/date/date.component.js 1.63 kB 0 B
dist/components/inputs/file/file-thumbnail.component.js 521 B 0 B
dist/components/inputs/file/file.component.js 1.21 kB 0 B
dist/components/inputs/fixed-value/fixed-value.component.js 341 B 0 B
dist/components/inputs/markdown/markdown-wrapper.component.js 240 B 0 B
dist/components/inputs/markdown/markdown.component.js 391 B 0 B
dist/components/inputs/multi-select/multi-select.component.js 1.66 kB 0 B
dist/components/inputs/number/number.component.js 1.06 kB 0 B
dist/components/inputs/radio/radio.component.js 1.07 kB 0 B
dist/components/inputs/select/dropdown.component.js 1.16 kB 0 B
dist/components/inputs/text-area/text-area.component.js 883 B 0 B
dist/components/inputs/text/text.component.js 919 B 0 B
dist/components/inputs/toggle/toggle.component.js 919 B 0 B
dist/components/inputs/ui-select-extended/ui-select-extended.component.js 2.28 kB 0 B
dist/components/inputs/unspecified/unspecified.component.js 881 B 0 B
dist/components/inputs/workspace-launcher/workspace-launcher.component.js 790 B 0 B
dist/components/label/label.component.js 286 B 0 B
dist/components/loaders/loader.component.js 275 B 0 B
dist/components/patient-banner/patient-banner.component.js 293 B 0 B
dist/components/previous-value-review/previous-value-review.component.js 496 B 0 B
dist/components/processor-factory/form-processor-factory.component.js 1.31 kB 0 B
dist/components/renderer/custom-hooks-renderer.component.js 232 B 0 B
dist/components/renderer/field/fieldLogic.js 1.93 kB 0 B
dist/components/renderer/field/fieldRenderUtils.js 263 B 0 B
dist/components/renderer/field/form-field-renderer.component.js 2.5 kB 0 B
dist/components/renderer/form/form-renderer.component.js 1.1 kB 0 B
dist/components/renderer/form/state.js 397 B 0 B
dist/components/renderer/page/page.renderer.component.js 1.03 kB 0 B
dist/components/renderer/section/section-renderer.component.js 411 B 0 B
dist/components/repeat/helpers.js 777 B 0 B
dist/components/repeat/repeat-controls.component.js 458 B 0 B
dist/components/repeat/repeat.component.js 1.89 kB 0 B
dist/components/sidebar/page-observer.js 534 B 0 B
dist/components/sidebar/sidebar.component.js 1.07 kB 0 B
dist/components/sidebar/useCurrentActivePage.js 1.53 kB 0 B
dist/components/sidebar/usePageObserver.js 416 B 0 B
dist/components/value/value.component.js 346 B 0 B
dist/components/value/view/field-value-view.component.js 391 B 0 B
dist/constants.js 527 B 0 B
dist/datasources/concept-data-source.js 620 B 0 B
dist/datasources/data-source.js 561 B 0 B
dist/datasources/encounter-role-datasource.js 306 B 0 B
dist/datasources/historical-data-source.js 265 B 0 B
dist/datasources/location-data-source.js 437 B 0 B
dist/datasources/provider-datasource.js 298 B 0 B
dist/datasources/select-concept-answers-datasource.js 404 B 0 B
dist/declarations.d.js 20 B 0 B
dist/external-function-context.js 116 B 0 B
dist/form-engine.component.js 1.98 kB 0 B
dist/globals.js 97 B 0 B
dist/hooks/useConcepts.js 506 B 0 B
dist/hooks/useDataSourceDependentValue.js 284 B 0 B
dist/hooks/useEncounter.js 485 B 0 B
dist/hooks/useEncounterRole.js 317 B 0 B
dist/hooks/useEvaluateFormFieldExpressions.js 1.16 kB 0 B
dist/hooks/useExternalFormAction.js 1.2 kB 0 B
dist/hooks/useFormCollapse.js 395 B 0 B
dist/hooks/useFormFields.js 642 B 0 B
dist/hooks/useFormFieldsMeta.js 528 B 0 B
dist/hooks/useFormFieldValidators.js 351 B 0 B
dist/hooks/useFormFieldValueAdapters.js 355 B 0 B
dist/hooks/useFormJson.js 2.54 kB 0 B
dist/hooks/useFormStateHelpers.js 593 B 0 B
dist/hooks/useFormWorkspaceSize.js 593 B 0 B
dist/hooks/useInitialValues.js 383 B 0 B
dist/hooks/usePatientData.js 487 B 0 B
dist/hooks/usePatientPrograms.js 526 B 0 B
dist/hooks/usePostSubmissionActions.js 344 B 0 B
dist/hooks/useProcessorDependencies.js 376 B 0 B
dist/index.js 213 B 0 B
dist/lifecycle.js 320 B 0 B
dist/post-submission-actions/mark-patient-deceased-action.js 794 B 0 B
dist/post-submission-actions/program-enrollment-action.js 1.39 kB 0 B
dist/processors/encounter/encounter-form-processor.js 3.41 kB 0 B
dist/processors/encounter/encounter-processor-helper.js 2.94 kB 0 B
dist/processors/form-processor.js 315 B 0 B
dist/provider/form-factory-helper.js 1.05 kB 0 B
dist/provider/form-factory-provider.js 1.52 kB 0 B
dist/provider/form-provider.js 276 B 0 B
dist/registry/inbuilt-components/control-templates.js 341 B 0 B
dist/registry/inbuilt-components/inbuiltControls.js 647 B 0 B
dist/registry/inbuilt-components/inbuiltDataSources.js 364 B 0 B
dist/registry/inbuilt-components/inbuiltFieldValueAdapters.js 421 B 0 B
dist/registry/inbuilt-components/InbuiltPostSubmissionActions.js 190 B 0 B
dist/registry/inbuilt-components/inbuiltTransformers.js 154 B 0 B
dist/registry/inbuilt-components/inbuiltValidators.js 275 B 0 B
dist/registry/inbuilt-components/template-component-map.js 219 B 0 B
dist/registry/registry.js 1.93 kB 0 B
dist/transformers/default-schema-transformer.js 2.32 kB 0 B
dist/types/domain.js 32 B 0 B
dist/types/index.js 60 B 0 B
dist/types/schema.js 32 B 0 B
dist/typings.d.js 32 B 0 B
dist/utils/boolean-utils.js 327 B 0 B
dist/utils/common-expression-helpers.js 6.16 kB +8 B (+0.13%)
dist/utils/common-utils.js 1.05 kB 0 B
dist/utils/error-utils.js 523 B 0 B
dist/utils/expression-runner.js 1.22 kB 0 B
dist/utils/form-helper.js 2.53 kB 0 B
dist/utils/form-page-utils.js 179 B 0 B
dist/utils/forms-loader.js 2.65 kB 0 B
dist/utils/post-submission-action-helper.js 792 B 0 B
dist/utils/zscore-service.js 596 B 0 B
dist/validators/conditional-answered-validator.js 322 B 0 B
dist/validators/date-validator.js 326 B 0 B
dist/validators/default-value-validator.js 492 B 0 B
dist/validators/form-validator.js 865 B 0 B
dist/validators/js-expression-validator.js 484 B 0 B
dist/validators/schema.js 568 B 0 B

compressed-size-action

@pirupius
Copy link
Member Author

pirupius commented Mar 3, 2026

@samuelmale @denniskigen do you have any concerns with this PR?

Comment on lines +388 to +390
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
const dateOfBirthString = thirtyDaysAgo.toISOString().split('T')[0];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, but this is actually kind of a better use of dayjs, because this splitting the ISO String is not stable and this test will break in my timezone.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That will also remove the testing ambiguity.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @ibacher for flagging this. I've edited it not to be dependent on the ISOString

@pirupius pirupius force-pushed the feat/expose-dayjs-expression branch from a9b03be to 42852d1 Compare March 3, 2026 16:30
@pirupius pirupius requested a review from ibacher March 3, 2026 20:21
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