openmrs.js (JavaScript API Wrapper)

As some of you may know, I’m planning to start work on openmrs.js, a JavaScript library that will be an interface to the OpenMRS API. This library is necessary to avoid the problem we are now seeing, where app developers are duplicating work by rebuilding functionality such as login, patient search, etc. Have a look at what DHIS2 has to get an idea of what I’m thinking.

In fact, I’ve already hacked in the right direction by bringing our Swagger specification almost up to spec. The implementation strategy is still totally up for debate, and I plan to talk about this on the Design Forum next week.

Initial Goals

  1. Non-opinionated: Allow developers to use their current or future favourite JavaScript framework
  2. Front- & Backend: The library should work with your Express app and your React app
  3. Useful: Developers should be able to get up and running really quickly, which means common tasks such as login should be implemented.

Current Implementation Strategy

  • Write a wrapper around swagger-js and implement common tasks

The benefit of this is that JavaScript is automatically generated accoring to what REST resources are available. Loaded a new module into OpenMRS? It’s automagically available to you in JavaScript!

  • Use ES6/ES2015, Webpack & Babel

It’s 2016.

Tricky Problems

Form entry is going to be difficult to solve. I know @jdick and his team has put a lot of thought into this, so I hope to be able to reuse that work in our library.

The Problem of Angular

OpenMRS has adopted Angular for writing frontend apps, and this can’t be ignored. Tools such as swagger-js-codegen are able to generate Angular code, but I will have to investigate more thoroughly.

Please join the Design Forum next week and/or leave your thoughts/fears/insults here.


:pushpin: The swagger-codegen tool can be used to generate API clients in many different languages from a valid Swagger specification.

Unicorn Approved

11 Likes

For the form entry thing, maybe it’s worthwhile to take a look at https://www.typeform.com/

It’s hard to tell exactly how typeform works, but I imagine form-entry-as-a-service would not work in offline settings. The tricky problem I was referring to is discussed here. Basically, how do we decide on a schema for communicating form metadata from the server to the client (and form data back)? Then, how can we keep the current mechanism of implementers being able to easily create new forms as they have been able to do up to now.

In my opinion, form presentation should be up to the app developer, although we could provide html fragments and styles for the RefApp as discussed here.

1 Like

You’re right, it looks like a service (like Google docs) with the designer and rendering engines propietary. I wonder if there is such a thing in the open source world.

I think serializing a form schema as JSON will suffice here

AMPATH (@jdick et al) have built their angular-formentry tool around angular-formly. The JSON focuses on the field types, sequence, grouping, validation, etc. that are not UI-specific. It also allows for field type-specific settings (e.g., for a date field, date-specific settings might include “allowFuture”:“false”).

My bias would be not to try to solve the details of form schemas right now (we can tackle that separately). To start, providing easy access to forms and their resources should suffice. Form tools (like AMPATH’s angular form-entry) can store their tool-specific schema as a form resource.

1 Like

It’ll definitely be JSON, it’s just a question of what the appropriate schema should be (and what will produce/consume this in the backend). Or did you mean OpenMRS form schema as currently exists in the form, form_field, etc tables? There are a number of limitations with the latter idea that @jdick and team have solved.

Yeah, that was my thinking too. Let me whip up something to start and we can take it from there.

This is a fantastic idea and we hope to provide as much support as possible to the approach @pascal is taking. As an fyi, we’re in the process of building an angular service to store and retrieve form resource data. I realize this is in opposition to a vanilla js approach but should provide as least some insight into how we are thinking about this.

1 Like

I wouldn’t say it’s in opposition, it’s just framework-specific. I’ll definitely take a look at try to reuse as much as possible and make it available to people wanting to use other frameworks.

I’d personally like to rid you people of your Angular habit :stuck_out_tongue:

1 Like

@pascal for the use of Concepts OWA we’ve created https://github.com/rkorytkowski/openmrs-owa-conceptdictionary/blob/master/app/js/openmrs.js which allows us to easily work with openmrs rest resources. You could see how it is used here https://github.com/rkorytkowski/openmrs-owa-conceptdictionary/blob/master/app/js/classAdd.controller.js#L2525 It is simple enough for us and we can CRUD on virtually any resource. I’m currently working on adding support for paging of results and it will be complete.

That said I haven’t seen any js API auto-generated from swagger and I’m interested how it would improve the experience.

We would be happy to contribute the openmrsRest service to common openmrs.js.

3 Likes

Is it possible to define JS objects for all the domain model ? Using just associative maps and converting to JSON seems a bit fragile. In this particular case, concept class attributes are defined in the controller and are not reusable.

Okay thanks @raff, I hadn’t seen that. Let me get an initial version of auto-generated code ready and then we can compare the approaches.

1 Like

One of our priorities (IMO more important than json forms) should be to provide a way to translate OWA pages based on the locale selected in OpenMRS together with Transifex support.

3 Likes

Thanks @raff, good point. I’ll create a ticket for tracking this work.

I’m curious about how to approach this. I know how to solve it in Angular, and other frameworks have similar mechanisms.

But if we want a static framework-independent solution to this, we need something like a preprocessor that is run on html files as we serve them up. (Note that we would not actually want to use the current cookie locale resolver in that case, since it would make the static resources uncacheable.) This, however, is totally antithetical to how OWAs are supposed to work.

I was thinking about this in the context of how letting a distro or sysadmin configure some global CSS to be applied to every page (even OWA ones) in this comment (my code snippet was eaten my markdown, so I just fixed that now):

At this point I think the right approach is to just promote best-practice usage of a particular AngularJS approach (by default I’d choose the one Bahmni chose) + the same for other frameworks. (Including for my global CSS example, where that CSS can be loaded dynamically via JS.) But I’m curious whether anyone else thinks that macro preprocessing of the HTML files we serve is even worth considering.

1 Like

I agree with this. Also, l10n is done in the presentation layer, so should be done in an idiomatic way for whatever presentation tool is being used. That said, I think it would be good to take a look at some frameworks (Angular, React, etc) and try to provide whatever services might be useful.

https://issues.openmrs.org/browse/OMRSJS-6

1 Like

We’ve moved our angular approach to OpenMRS resources to a separate repo. This should make it easier for others to use if interested.

2 Likes

I’ve put together an initial proof of concept here: https://github.com/psbrandt/openmrs.js. This version currently does nothing besides wrap the Swagger object, but you’re all welcome to take a first look.

1 Like

So one nitpick – Shouldn’t lib/ be ignored, and be created during the build process? If you want – Travis can generate development and/or nightly builds – if that’s your end goal…just a suggestion.

My reasoning is that it is a build artifact and shouldn’t be cluttering the VCS history. It’s why we don’t track bower_components and node_modules.

1 Like