@photonhealth/client
v2.0.0-rc.1
Published
Photon's prescribing API for JavaScript: patients, prescriptions and orders as live objects with the workflow rules inside. Framework-agnostic, zero runtime dependencies.
Keywords
Readme
@photonhealth/client
Photon's prescribing API for JavaScript: photon() gives you patients, prescriptions and orders as live
objects. Their state stays current, you can subscribe to them, and their methods await the web calls. The
workflow rules live inside them. Framework-agnostic, with zero runtime dependencies: it runs in the browser, Node
and Deno.
React cards built on it: @photonhealth/react.
Install
Release candidates are published under the rc tag:
npm install @photonhealth/client@rcQuick start
import { photon } from "@photonhealth/client";
const ph = photon({ environment: "neutron", auth: { clientId } }); // or { getToken }: your own sign-in
const { patient } = await ph.patient.sync({
demographic: { name: { first: "Paige", last: "Turner" }, dateOfBirth: "1990-01-01", sex: "FEMALE" },
});
patient.subscribe(() => render(patient.state)); // UIs; a backend just awaits
const { prescription: rx } = await ph.prescription.sync({ patient: { id: patient.id }, treatment: { id: "med_10" } });
await rx.update({ instructions: "1 tab PO daily", dispense: { quantity: 30, daysSupply: 30 } });
await rx.sign(); // the prescriber's approval of exactly what they saw
const { order } = await ph.order.sync({ patient: { id: patient.id }, prescriptions: { add: [{ id: rx.id }] } });
await order.submit(); // the patient chooses a pharmacyThe instance and auth
photon({ environment, auth, organization?, appUrl? }) returns an instance. Every URL is inferred from
environment: neutron (sandbox) or photon (production). auth is one of:
{ clientId }: the client signs the prescriber in, in the browser (Auth0 authorization code with PKCE).ph.sessionis a live object withstatus,user,start(),signIn()andsignOut(). The access token stays in memory;localStoragekeeps the refresh token so a reload signs back in. A script on your page can read that refresh token, so treat XSS on the page as a token leak. Auth0's refresh token rotation is the guard.{ getToken: () => Promise<string> }: you sign the prescriber in yourself. The client calls it before each request.ph.sessionisnull.
An instance built on a person's token is for that person. On a server, make one per request, never at module level.
ph.ping() checks the token without touching a record.
Get, sync, update
ph.patient, ph.prescription and ph.order each have the same three calls:
| Call | Means |
| ------------------- | -------------------------------------------------------------------------------------------- |
| get(id) | Read the record. Changes nothing. Returns the live object, or null when there's no record. |
| sync(input) | Send what's known, with or without an id: the server finds, matches, creates or updates. |
| update(id, input) | Change that one record: only the fields given change. |
sync and update return { <object>, candidates, changes }:
- the live object, with the record the server settled on, or still without one (
id: null). candidates: the records it might be, when the server isn't certain. The client never picks one for you: pick withpatient.pick(id),prescription.continueDraft(id)ororder.pick(id).changes: what was written, what wasn't and why, and any choices offered.
Live objects
Patient, Prescription and Order each have id, state (the record), status (idle / loading / saving /
error), changes, subscribe(listener), sync(input), update(input) and reload(), plus their workflow
methods (rx.sign(), order.submit(), …). An instance holds one object per record: the same patient opened twice,
or through an order, is the same object.
Errors
Anything the server answers about the data is a result, not an exception. Only failures that different data can't
fix throw a PhotonError, with kind: network (retryable), unauthorized, upstream (retryable says),
invalid (a request shape the server rejected) or refused (an object's rule said no).
Testing
@photonhealth/client/testing is for your own tests: photonOver(scriptedClient(...)) is an instance over a
scripted network client, with fixtures (patient, rx, order, …) to script it with. It may change before 2.0.0.
License
ISC
