TypeScript library for AM / RM / OPTs

@ian.mcnicoll motivated me to start working on a TypeScript generator.

Here are the TypeScript classes for RM 1.0.3 (rename the extension .md to .zip):

openehr_typescript_models_rm103.md (140.2 KB)

AM classes are also generated. I still need to port JSON serialization code (all generated) to TypeScript. This will add reading/writing JSON data instances and archetypes/templates.

Would something like this be useful for frontend implementation?

This is the first WIP version. I’ll update the attached file with new code.

Preview of the OperationalTemplate:

* Root object of an operational template. An operational template is derived from a TEMPLATE definition and the ARCHETYPEs and/or TEMPLATE_OVERLAYs mentioned by that template by a process of flattening, and potentially removal of unneeded languages and terminologies.
* An operational template is used for generating and validating RM-canonical instance data, and also as a source artefact for generating other downstream technical artefacts, including XML schemas, APIs and UI form definitions.
* isAbstract: false | isPrimitiveType: false | isOverride: false
export class OperationalTemplate extends AuthoredArchetype {
  * Compendium of flattened terminologies of archetypes externally referenced from this archetype, keyed by archetype identifier. This will almost always be present in a template.
  * BMM name: component_terminologies | BMM type: Hash<String,ARCHETYPE_TERMINOLOGY>
  * isMandatory: false | isComputed: false | isImRuntime: false | isImInfrastructure: false | existence: 0..1
  componentTerminologies?: Map<string, ArchetypeTerminology>;

  * Directory of term definitions as a two-level  table. The outer hash keys are term codes,  e.g. "at4", and the inner hash key are term  attribute names, e.g. "text", "description" etc.
  * BMM name: terminology_extracts | BMM type: Hash<String,ARCHETYPE_TERMINOLOGY>
  * isMandatory: false | isComputed: false | isImRuntime: false | isImInfrastructure: false | existence: 0..1
  terminologyExtracts?: Map<string, ArchetypeTerminology>;

  constructor(rmRelease: string, isGenerated: boolean, originalLanguage: TerminologyCode, archetypeId: ArchetypeHrid, isDifferential: boolean, terminology: ArchetypeTerminology, definition: CComplexObject) {
    super(rmRelease, isGenerated, originalLanguage, archetypeId, isDifferential, terminology, definition);

  equals(other: any): boolean {
    if (this === other) return true;
    if (!this || !other || (typeof this !== "object" && typeof other !== "object")) return this === other;
    let otherAsOperationalTemplate: OperationalTemplate = other as OperationalTemplate;
    return this.adlVersion === otherAsOperationalTemplate.adlVersion &&
      this.rmRelease === otherAsOperationalTemplate.rmRelease &&
      this.isGenerated === otherAsOperationalTemplate.isGenerated &&
      this.buildUid?.equals(otherAsOperationalTemplate.buildUid) &&

Interesting task :thinking:

What is the source (input) of your generating tool? Will the tool be opensourced/licensed?

What is your plan above with JSON? Should that be part of an API client library?

Source (input) are BMM files for AM and RM.

The next generator then takes OPTs to generate “domain model” classes as shown in this post.

Since the generated “domain model” classes extend the RM classes, they return their canonical JSON representation of e.g. COMPOSITION (example for the vital signs composition class used in the linked post above):

Notice the list of other classes on the left of the screenshot. There are 136 classes for this template. These are all generated from the OPT and extend RM classes:

Top level TEncounterVitalSignsComposition class converts the entire hierarchy to JSON. It also de-serializes JSON to TEncounterVitalSignsComposition.

With AM classes reading of JSON representation of archetypes/templates is possible.

The plan for the TypeScript version is to be used as a frontend client library. Either with UI components or headless. React and Vue components could be included and forms generated.

The same library also works on Node.js in case somebody would want to use it there.

The plan is to opensource at least some of the RM classes for free. The complete version could be available as “source available” license.

A SaaS option could be available for generating the code for OPTs.

I would like to open source the tool but it will probably be available as “source available” license since “open source != free” :blush:

1 Like

Sounds like a good plan, in general. Thanks for sharing.

Some thoughts:

  • BMM classes/files might not be complete comparing to UML we maintain. I’m also (passively) working on generating enriched BMM from UML. Those might be a better/safer fit for your project.
  • we learned over the last years that BMM or RM types are not always suitable for frontend app level consumptions; they are more suitable for backend platform services. Just as example, there are attributes that has be set by service on runtime, based on service processes, which from app perspective are readonly and mostly not transparent.
  • you should have some thoughts about what should be the repository to store this ref implementation and who /how should it be maintained in time (continuity plan)
1 Like

Thank you for the feedback Sebastian!

  • I’ve learned that about BMMs soon after I started to work on openEHR. Luckily Thomas and Pieter were helpful to update them so that they are in sync with UML now – at least I haven’t encountered any problems. Of course BMM could be extended to specify even more information about the model.
  • I had to accept early that openEHR has focused mostly on the backend as you mentioned. This leaves openEHR users locked-in to whoever develops their frontend apps – they can change their CDR vendor but changing app vendor(s) would be too expensive in most cases.
  • The best approach would be to publish all generated code (and tools) under the openEHR.org. This way it is independent of me. I do have BuildEHR.org as a plan B.