Service
and Card
classes. We'll use these to create our decision support service and to describe our responses to inbound requests. We also import an helper class, NoDecisionResponse
, used to reply with a standard "no comment" response. We're also importing HookRequest
and Hooks
- which are TypeScript declarations. Lastly, we import our helper method for the GoodRx API./cds-services
. We define an options object that we will use in the construction of Service
. Importantly, we declare that the Service
expects to respond to the order-select
hook request.async
function called handler
:draftOrders
key will exist on request.context
and that it will be shaped like a FHIR Bundle (we're using the @types/fhir
to annotate that here).order-select
hook requires that a Bundle of FHIR Resources be provided at draftOrders
, but those resources could be NutritionOrder
, ServiceRequest
, or VisionPrescription
in addition to the one we care about: MedicationRequest
. We filter the draftOrders
for MedicationRequest
resources.MedicationRequest
was found, we throw a NoDecisionResponse
because we can only provide decision support when one is present. This thrown error is handled by Sero automatically, sending back response the CDS Hooks specification expects:MedicationRequest
, so let's use the text associated with the request (i.e. the "name" of the drug) to make a price comparison request to the GoodRx Compare Price API (here we have abstracted the API requirements into a small utility library). The utility uses async/await
but we can also make use of Promise
:MedicationRequest
. We create an return a Card
containing a summary of the low/high price, the brand name, generic names, the cheapest pharmacy, and an associated coupon.Service
:Service
we defined in this example.Dockerfile
to build and run the project in isolation. Note that in order to actually successfully make requests to the Good RX Compare Price API you must set two environment variables GOOD_RX_API_KEY
and GOOD_RX_SECRET_KEY
which only GoodRx can issue.