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

@fhirfly-io/shl

v0.6.0

Published

Official FHIRfly SDK for SMART Health Links - IPS bundle creation and SHL sharing

Readme

@fhirfly-io/shl

SMART Health Links SDK for Node.js — build IPS FHIR Bundles from clinical codes, encrypt, and share via SHL/QR code.

License: MIT

What It Does

Takes raw clinical data (NDC codes, ICD-10 codes, RxNorm, LOINC, CVX) and produces a shareable SMART Health Link:

Raw codes + patient info → Enriched FHIR Bundle → Encrypted SHL → QR code

PHI never leaves your server. Only terminology codes are sent to FHIRfly for enrichment — no BAA required.

Prerequisites

  • Node.js 18 or later
  • FHIRfly API key — optional, for code enrichment (display names, SNOMED mappings). Get a free key. Without it, use manual code/system/display input or bySNOMED/fromResource (no API call needed).

Installation

npm install @fhirfly-io/shl

For FHIRfly API enrichment (optional — adds display names and SNOMED cross-mappings):

npm install @fhirfly-io/shl @fhirfly-io/terminology

Quick Start

Without FHIRfly API (no key needed)

import { IPS, SHL } from "@fhirfly-io/shl";

const bundle = new IPS.Bundle({
  name: "Maria Garcia",
  birthDate: "1985-03-15",
  gender: "female",
});

// Manual coding — no API dependency
bundle.addMedication({ code: "376988009", system: "http://snomed.info/sct", display: "Levothyroxine" });
bundle.addCondition({ code: "44054006", system: "http://snomed.info/sct", display: "Type 2 diabetes" });
bundle.addAllergy({ bySNOMED: "387207008" });

const fhirBundle = await bundle.build();

const storage = new SHL.LocalStorage({ directory: "./shl-data", baseUrl: "http://localhost:3456/shl" });
const result = await SHL.create({ bundle: fhirBundle, storage, passcode: "1234" });

console.log(result.url);    // shlink:/eyJ...
console.log(result.qrCode); // data:image/png;base64,...

With FHIRfly API (enriched)

import { IPS, SHL } from "@fhirfly-io/shl";
import Fhirfly from "@fhirfly-io/terminology";

const client = new Fhirfly({ apiKey: process.env.FHIRFLY_API_KEY });

const bundle = new IPS.Bundle({
  name: "Maria Garcia",
  birthDate: "1985-03-15",
  gender: "female",
});

// Code-based input — FHIRfly enriches with display names, SNOMED mappings, etc.
bundle.addMedication({ byNDC: "00071015523", fhirfly: client.ndc });
bundle.addCondition({ byICD10: "E11.9", fhirfly: client.icd10 });
bundle.addAllergy({ bySNOMED: "387207008" });
bundle.addImmunization({ byCVX: "208", fhirfly: client.cvx });
bundle.addResult({ byLOINC: "2339-0", fhirfly: client.loinc, value: 95, unit: "mg/dL" });
bundle.addDocument({ content: pdfBuffer, contentType: "application/pdf", title: "Visit Summary" });

const fhirBundle = await bundle.build();

// FhirflyStorage — zero infrastructure, included free in all plans
const storage = new SHL.FhirflyStorage({ apiKey: process.env.FHIRFLY_API_KEY });

const result = await SHL.create({
  bundle: fhirBundle,
  storage,
  passcode: "1234",
  label: "Maria's Health Summary",
  expiresAt: "travel", // 90 days — or use "point-of-care" (15min), "appointment" (24h), "permanent"
});

console.log(result.url);      // shlink:/eyJ1cmwiOiJodHRwczovL...
console.log(result.qrCode);   // data:image/png;base64,...
console.log(result.passcode); // "1234"

Expiration Presets

Instead of calculating Date objects, use named presets:

await SHL.create({ bundle, storage, expiresAt: "point-of-care" }); // 15 minutes
await SHL.create({ bundle, storage, expiresAt: "appointment" });    // 24 hours
await SHL.create({ bundle, storage, expiresAt: "travel" });         // 90 days
await SHL.create({ bundle, storage, expiresAt: "permanent" });      // no expiration
await SHL.create({ bundle, storage, expiresAt: new Date(...) });    // raw Date still works

PSHD Compliance

For CMS-aligned patient-to-provider sharing at the point of care:

const fhirBundle = await bundle.build({ profile: "pshd" }); // strips meta.profile, uses collection bundle

const result = await SHL.create({
  bundle: fhirBundle,
  storage,
  compliance: "pshd",
  expiresAt: "point-of-care",
});

See the PSHD Guide for full details.

Storage Adapters

// FHIRfly hosted (zero infrastructure, recommended)
new SHL.FhirflyStorage({ apiKey: "..." });

// AWS S3
new SHL.S3Storage({ bucket: "my-bucket", region: "us-east-1", baseUrl: "https://shl.example.com" });

// Azure Blob Storage
new SHL.AzureStorage({ container: "shl-data", connectionString: "...", baseUrl: "https://shl.example.com" });

// Google Cloud Storage
new SHL.GCSStorage({ bucket: "my-bucket", baseUrl: "https://shl.example.com" });

// Local filesystem (development)
new SHL.LocalStorage({ directory: "./shl-data", baseUrl: "http://localhost:3456/shl" });

Input Formats

Each add* method supports multiple input formats:

// From codes (enriched via FHIRfly API)
bundle.addMedication({ byNDC: "00071015523", fhirfly: client.ndc });
bundle.addMedication({ byRxNorm: "161", fhirfly: client.rxnorm });
bundle.addCondition({ byICD10: "E11.9", fhirfly: client.icd10 });
bundle.addResult({ byLOINC: "2339-0", fhirfly: client.loinc, value: 95, unit: "mg/dL" });
bundle.addImmunization({ byCVX: "208", fhirfly: client.cvx });

// From SNOMED (no API call needed)
bundle.addMedication({ bySNOMED: "376988009" });
bundle.addAllergy({ bySNOMED: "387207008" });

// From existing FHIR R4 resources
bundle.addMedication({ fromResource: existingMedicationStatement });
bundle.addCondition({ fromResource: existingCondition });

// Manual coding (no API dependency)
bundle.addMedication({ code: "376988009", system: "http://snomed.info/sct", display: "Levothyroxine" });

CLI

npx @fhirfly-io/shl validate bundle.json   # Validate a FHIR Bundle
npx @fhirfly-io/shl create bundle.json     # Create an SHL from a bundle
npx @fhirfly-io/shl decode shlink:/eyJ...  # Decode an SHL URL
npx @fhirfly-io/shl serve                  # Start a local SHL server
npx @fhirfly-io/shl demo                   # Full round-trip demo

Server Middleware

Host your own SHL endpoints:

import express from "express";
import { expressMiddleware } from "@fhirfly-io/shl/express";
import { ServerLocalStorage } from "@fhirfly-io/shl/server";

const storage = new ServerLocalStorage({
  directory: "./shl-data",
  baseUrl: "http://localhost:3000/shl",
});

const app = express();
app.use("/shl", expressMiddleware({ storage }));
app.listen(3000);

Also available for Fastify (@fhirfly-io/shl/fastify) and Lambda (@fhirfly-io/shl/lambda).

Audit Logging

Use AuditableStorage to capture access events at the storage level — plug in any logging backend:

import { AuditableStorage, SHLServerStorage, AccessEvent } from "@fhirfly-io/shl/server";

class MyAuditStorage extends ServerLocalStorage implements AuditableStorage {
  async onAccess(shlId: string, event: AccessEvent): Promise<void> {
    await db.auditLog.insert({
      shlId,
      recipient: event.recipient,
      ip: event.ip,
      timestamp: event.timestamp,
    });
  }
}

app.use("/shl", expressMiddleware({ storage: new MyAuditStorage({ ... }) }));

The server handler detects AuditableStorage at runtime via isAuditableStorage() — existing storage implementations work unchanged.

Live Exercise

Run the comprehensive integration test against the live API to exercise every SDK path:

npx tsx examples/live-exercise/index.ts --api-key <your-key> --verbose

Covers bundle building, FhirflyStorage, LocalStorage + Express, SHL consumption, access control, and edge cases. See examples/live-exercise/README.md for details.

Related

License

MIT