Skip to content

feat(#11192): support extension libs in messages#11244

Draft
belwalshubham wants to merge 5 commits into
medic:masterfrom
belwalshubham:11192-extension-libs-messages
Draft

feat(#11192): support extension libs in messages#11244
belwalshubham wants to merge 5 commits into
medic:masterfrom
belwalshubham:11192-extension-libs-messages

Conversation

@belwalshubham

@belwalshubham belwalshubham commented Jul 12, 2026

Copy link
Copy Markdown

Summary

Adds project-defined extension-libs as synchronous Mustache section helpers for translations and outgoing messages.

This allows configurers to transform message values without adding a new built-in helper to CHT Core, for example:

{{#to_devanagari}}{{patient_id}}{{/to_devanagari}}

Closes #11192.

Architecture

flowchart LR
  Couch[("CouchDB<br/>extension-libs")]
  Loader["Extension-libs loader<br/>decode + atomic registry replacement"]

  Couch --> Loader

  Loader --> Webapp["Webapp cache"]
  Loader --> API["API config cache"]
  Loader --> Sentinel["Sentinel config cache"]
  Loader --> Admin["Admin preview load"]

  Webapp --> Translation["Webapp translations"]
  Webapp --> Report["Report detail messages"]
  API --> Export["Message export rendering"]
  Sentinel --> Transitions["Transitions and scheduled SMS"]
  Admin --> Preview["Message queue preview"]

  Translation --> MessageUtils["message-utils<br/>template(opts) / generate(opts)"]
  Report --> MessageUtils
  Export --> MessageUtils
  Transitions --> MessageUtils
  Preview --> MessageUtils

  MessageUtils --> Output["Consistent rendered message"]
Loading

Changes

  • Adds @medic/extension-libs for loading and decoding the extension-libs CouchDB document.
  • Refactors message-utils.generate and message-utils.template to accept an options object containing extensionLibs.
  • Keeps positional argument compatibility for downstream callers while migrating all CHT Core production call sites.
  • Exposes function exports as Mustache section helpers, using the attachment filename without the .js suffix.
  • Ensures built-in helpers take precedence over extension-lib name collisions.
  • Loads and refreshes extension-libs in API and Sentinel when the document changes.
  • Passes extension-libs through transitions, scheduled/due messages, API message exports, Webapp report details and validation messages, and Admin message queue previews.
  • Adds a Webapp translation parser that uses extension-lib helpers for Mustache sections while preserving the default parser for normal and compiled MessageFormat translations.
  • Treats a missing document as an empty registry, skips malformed attachments, and retains the previous valid registry after transient load failures.

Security

Extension-libs are trusted application configuration uploaded by authorized administrators. This change does not present extension-lib execution as sandboxed.

Verification

Manual end-to-end evidence

The following screenshot records the manually executed live CouchDB flow. It uses a real extension-libs document and attachments, the production @medic/extension-libs loader, and the production message-utils rendering path.

Manual end-to-end verification: real CouchDB extension-lib attachment loading, outgoing SMS transformation, document replacement, reload, and second transformation

Manual steps verified:

  1. Created an isolated cht_11192_e2e database on CouchDB 3.5.2.
  2. Uploaded to_devanagari.js as an attachment on the extension-libs document.
  3. Loaded the real attachment with the production extension-libs loader.
  4. Rendered an outgoing message through message-utils.generate and confirmed ID १२३४५.
  5. Replaced the document attachment with uppercase.js.
  6. Reloaded the extension-libs registry and confirmed the previous helper was atomically replaced.
  7. Rendered through message-utils.template and confirmed Hello ADA.
  8. Deleted the isolated test database after verification.

This screenshot is evidence of the loader/reload/rendering end-to-end path. The Admin, API, Sentinel, and Webapp integrations are additionally covered by their regression suites listed below.

  • npm run build-dev
  • npm run lint
  • COUCH_URL=http://medic:password@localhost:5984/medic npm run unit-api — 1,636 passing
  • npm run unit-admin — 435 passing
  • TZ=UTC COUCH_URL=http://medic:password@localhost:5984/medic npm run unit-sentinel — 231 passing
  • npm test --workspace=@medic/extension-libs — 6 passing, 100% coverage
  • npm test --workspace=@medic/message-utils — 112 passing, 100% statements/lines
  • Webapp Angular compilation and Karma suite command completed successfully.
  • Docker-backed API integration suite completed successfully.
  • Live CouchDB smoke test:
    • uploaded to_devanagari.js as an attachment;
    • loaded it through the production loader;
    • rendered ID १२३४५ through message-utils.generate;
    • replaced the document with uppercase.js;
    • reloaded it and rendered Hello ADA through message-utils.template;
    • deleted the isolated temporary database afterward.

Notes for reviewers

  • The shared loader centralizes identical attachment decoding and error behavior across browser and server runtimes.
  • Application services still own their loading/cache lifecycle and explicitly inject the current extension-lib snapshot into message-utils.
  • The options-object refactor follows the direction discussed in Support extension-libs in translations and outgoing messages #11192 and avoids adding another positional parameter to the existing APIs.

Comment thread shared-libs/extension-libs/src/index.js Fixed
@belwalshubham
belwalshubham force-pushed the 11192-extension-libs-messages branch from aeba59b to 54db099 Compare July 12, 2026 14:43
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.

Support extension-libs in translations and outgoing messages

2 participants