npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

openmrs-sdk

v1.0.0

Published

Lightweight, zero-dependency JavaScript/TypeScript client for the OpenMRS REST and FHIR R4 APIs. Works in Node.js, Deno, Bun, and modern browsers.

Readme

openmrs-sdk

npm version npm downloads bundle size zero dependencies TypeScript License: MIT

Lightweight, zero-dependency JavaScript/TypeScript client for the OpenMRS REST and FHIR R4 APIs.

Works in Node.js 18+, Deno, Bun, and modern browsers - anywhere fetch is available.

Why openmrs-sdk?

The OpenMRS ecosystem has many frontend-specific packages (@openmrs/esm-*), but no standalone SDK for backend or server-side use. If you're building a Node.js integration, a CLI tool, a data pipeline, or any server-side application that talks to OpenMRS, you've been writing raw fetch calls with Basic Auth headers every time.

openmrs-sdk fills that gap:

Zero dependencies: just your runtime's built-in fetch Dual API support: both REST and FHIR R4 from one client Full TypeScript types: every response is fully typed Tiny footprint: under 20KB minified + gzipped Human-readable errors: "Authentication failed" not "401"

Installation

npm install openmrs-sdk
yarn add openmrs-sdk
pnpm add openmrs-sdk

Quick Start

import { OpenMRS } from 'openmrs-sdk';

const client = new OpenMRS({
  baseUrl: 'https://demo.openmrs.org/openmrs',
  username: 'admin',
  password: 'Admin123',
});

// Validate connection
const isConnected = await client.validate();
console.log('Connected:', isConnected);

// Search patients
const results = await client.patient.search({ q: 'John' });
console.log('Found:', results.results.length, 'patients');

// Get a specific patient
const patient = await client.patient.get('patient-uuid-here');
console.log('Patient:', patient.display);

REST API

The REST API provides full access to OpenMRS resources with CRUD operations.

Patient

// Search by name or identifier
const results = await client.patient.search({ q: 'John Doe' });

// Get by UUID
const patient = await client.patient.get('abc-123-def-456');

// Create
const newPatient = await client.patient.create({
  person: {
    names: [{ givenName: 'Jane', familyName: 'Doe' }],
    gender: 'F',
    birthdate: '1990-01-15',
  },
  identifiers: [
    {
      identifier: 'MRN-001',
      identifierType: 'identifier-type-uuid',
      location: 'location-uuid',
    },
  ],
});

// Update
await client.patient.update('abc-123', { person: { gender: 'M' } });

// Delete (void)
await client.patient.delete('abc-123', 'Duplicate record');

Encounter

// Get all encounters for a patient
const encounters = await client.encounter.getByPatient('patient-uuid');

// Get specific encounter
const encounter = await client.encounter.get('encounter-uuid');

// Create encounter
const newEncounter = await client.encounter.create({
  patient: 'patient-uuid',
  encounterType: 'encounter-type-uuid',
  encounterDatetime: '2026-01-15T10:30:00.000+0000',
  obs: [
    {
      concept: 'concept-uuid',
      value: 120,
    },
  ],
});

Observation

// Get all observations for a patient
const obs = await client.obs.getByPatient('patient-uuid');

// Get specific observation
const observation = await client.obs.get('obs-uuid');

// Create observation
await client.obs.create({
  person: 'patient-uuid',
  concept: 'concept-uuid',
  obsDatetime: '2026-01-15T10:30:00.000+0000',
  value: 37.5,
});

Visit

// Get all visits for a patient
const visits = await client.visit.getByPatient('patient-uuid');

// Get specific visit
const visit = await client.visit.get('visit-uuid');

// Create visit
const newVisit = await client.visit.create({
  patient: 'patient-uuid',
  visitType: 'visit-type-uuid',
  startDatetime: '2026-01-15T08:00:00.000+0000',
});

// End a visit
await client.visit.update('visit-uuid', {
  stopDatetime: '2026-01-15T17:00:00.000+0000',
});

Person

// Get person details
const person = await client.person.get('person-uuid');

// Search
const people = await client.person.search({ q: 'Jane' });

// Update demographics
await client.person.update('person-uuid', { gender: 'F' });

Location

// List all locations
const locations = await client.location.list();

// Search
const results = await client.location.search({ q: 'Clinic' });

// Get specific location
const location = await client.location.get('location-uuid');

Session

// Get current session info
const session = await client.session.get();
console.log('User:', session.user?.username);
console.log('Locale:', session.locale);

// Validate credentials
const valid = await client.session.validate();

FHIR R4 API

The FHIR API provides standardized access to clinical data following the HL7 FHIR R4 specification.

FHIR Patient

// Get by ID
const patient = await client.fhir.patient.get('patient-uuid');
console.log(
  'Name:',
  patient.name?.[0]?.given?.join(' '),
  patient.name?.[0]?.family,
);

// Search
const bundle = await client.fhir.patient.search({ name: 'John' });

// List (returns unwrapped array)
const patients = await client.fhir.patient.list({ _count: 20 });

FHIR Observation

// Get all observations for a patient
const observations = await client.fhir.observation.list({
  patient: 'patient-uuid',
  _count: 100,
});

// Search with specific code
const vitals = await client.fhir.observation.search({
  patient: 'patient-uuid',
  code: '5085AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
});

FHIR Condition

// Get diagnoses for a patient
const conditions = await client.fhir.condition.list({
  patient: 'patient-uuid',
});

FHIR Encounter

const encounters = await client.fhir.encounter.list({
  patient: 'patient-uuid',
  _count: 50,
});

FHIR MedicationStatement

const medications = await client.fhir.medicationStatement.list({
  patient: 'patient-uuid',
});

FHIR DiagnosticReport

const reports = await client.fhir.diagnosticReport.list({
  patient: 'patient-uuid',
});

Configuration

const client = new OpenMRS({
  // Required
  baseUrl: 'https://demo.openmrs.org/openmrs',
  username: 'admin',
  password: 'Admin123',

  // Optional
  timeout: 30000, // Request timeout in ms (default: 30000)
});

| Option | Type | Required | Default | Description | | ---------- | -------- | -------- | ------- | ---------------------------------------------- | | baseUrl | string | Yes | - | OpenMRS instance URL (include /openmrs path) | | username | string | Yes | - | OpenMRS username | | password | string | Yes | - | OpenMRS password | | timeout | number | No | 30000 | Request timeout in milliseconds |

Error Handling

All errors throw OpenMRSError with clear, actionable messages:

import { OpenMRS, OpenMRSError } from 'openmrs-sdk';

try {
  const patient = await client.patient.get('nonexistent-uuid');
} catch (error) {
  if (error instanceof OpenMRSError) {
    console.log(error.message); // "Resource not found: check the ID or endpoint"
    console.log(error.status); // 404
    console.log(error.statusText); // "Not Found"
    console.log(error.body); // Raw response body
  }
}

| Status | Message | | ------ | -------------------------------------------------------------------- | | 401 | Authentication failed: check your username and password | | 403 | Access denied: your user does not have permission for this operation | | 404 | Resource not found: check the ID or endpoint | | 500 | OpenMRS server error: the server encountered an internal error | | 0 | Network error or request timeout |

Real-World Examples

Clinical Decision Support Pipeline

Pull patient data for AI-powered clinical insights:

const client = new OpenMRS({
  baseUrl: 'https://my-clinic.org/openmrs',
  username: 'integration-user',
  password: 'secure-password',
});

// Gather comprehensive patient data
const patient = await client.fhir.patient.get(patientId);
const observations = await client.fhir.observation.list({
  patient: patientId,
  _count: 200,
});
const conditions = await client.fhir.condition.list({ patient: patientId });
const medications = await client.fhir.medicationStatement.list({
  patient: patientId,
});

// Feed into your analysis pipeline
const clinicalSummary = {
  demographics: patient,
  labs: observations,
  diagnoses: conditions,
  treatments: medications,
};

OpenMRS → DHIS2 Reporting

Aggregate clinical data for national health reporting:

// Fetch encounters for a reporting period
const encounters = await client.encounter.getByPatient(patientId);

// Count encounters by type for aggregate reporting
const malariaCases = encounters.results.filter(
  (e) => e.encounterType.display === 'Malaria Consultation',
);

// Push count to DHIS2 via dhis2 API or n8n-nodes-dhis2
console.log(`Malaria cases this month: ${malariaCases.length}`);

Bulk Patient Search

// Paginate through all patients
let startIndex = 0;
const allPatients = [];

while (true) {
  const page = await client.patient.search({
    v: 'default',
    limit: 100,
    startIndex,
  });

  allPatients.push(...page.results);

  if (page.results.length < 100) break;
  startIndex += 100;
}

console.log(`Total patients: ${allPatients.length}`);

Express.js API Endpoint

import express from 'express';
import { OpenMRS } from 'openmrs-sdk';

const app = express();
const client = new OpenMRS({
  baseUrl: process.env.OPENMRS_URL!,
  username: process.env.OPENMRS_USER!,
  password: process.env.OPENMRS_PASS!,
});

app.get('/api/patients/:id', async (req, res) => {
  try {
    const patient = await client.patient.get(req.params.id);
    res.json(patient);
  } catch (error) {
    res.status(error.status || 500).json({ error: error.message });
  }
});

API Reference

REST Resources

| Resource | Methods | | ----------- | ------------------------------------------------------------- | | patient | get, search, create, update, delete | | encounter | get, search, getByPatient, create, update, delete | | obs | get, search, getByPatient, create, delete | | visit | get, search, getByPatient, create, update, delete | | person | get, search, update | | location | get, search, list | | session | get, validate |

FHIR R4 Resources

| Resource | Methods | | -------------------------- | ----------------------- | | fhir.patient | get, search, list | | fhir.encounter | get, search, list | | fhir.observation | get, search, list | | fhir.condition | get, search, list | | fhir.medicationStatement | get, search, list | | fhir.diagnosticReport | get, search, list |

search returns the raw FHIR Bundle. list returns an unwrapped array of resources.

Compatibility

  • Runtime: Node.js 18+, Deno, Bun, modern browsers
  • OpenMRS: 2.3+ with FHIR2 module (for FHIR endpoints)
  • Module: ESM and CommonJS (dual package)
  • TypeScript: Full type definitions included

Demo Server

You can test against the OpenMRS demo server:

Base URL:  https://demo.openmrs.org/openmrs
Username:  admin
Password:  Admin123

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Related Projects

License

MIT - Copyright (c) 2026 Monfort Brian N.

Support


Made with ❤️ for the global health community