Demo | Custom resources using FHIR Schema
In this example, you can see the custom resources demonstration on the minimalistic JavaScript example project which implemented the typical flow for notifications: requesting a notification, locking it for sending, and then sending it (placeholder).
Scenarios:
- We create a notification resource for sending (status:
requested
). - A worker (one of many) gets a notification that should be sent.
- The worker locks the notification for itself and marks the notification as
in-progress
. - When the worker's job is done, the worker marks the notification as
completed
.
For that we define the following custom resources:
- TutorNotification: Represents notifications with details like type, status, template, sendAfter date, and subject.
- TutorNotificationTemplate: Represents templates used for notification messages.
- Search Parameters: Custom search parameters enable efficient querying of notifications based on criteria such as type and status.
- Learn how to use custom resources via FHIR Schema.
- How to use existing value set with additional constraints as element type.
- How to use FHIR Schema extension for additional properties.
- Understand how to implement lock behavior via FHIR condition update.
Table of Contents
- A running instance of Aidbox: Run Aidbox locally
- Basic authentication setup: Basic Auth
Before starting the example, you need to:
- Define custom resources
- Define search parameters
- Load initial data
You can do this manually or via a bootstrap inside the example.
To run the example, clone the repository and open the index.html
file in your browser or open: Aidbox Notify via Custom Resources.
In Aidbox REST Console:
POST /fhir/FHIRSchema
{
"id": "TutorNotificationTemplate",
"resourceType": "FHIRSchema",
"url": "http://example.com/aidbox-sms-tutor/TutorNotificationTemplate",
"type": "TutorNotificationTemplate",
"name": "TutorNotificationTemplate",
"base": "DomainResource",
"kind": "resource",
"derivation": "specialization",
"required": [
"template"
],
"elements": {
"template": {
"type": "string",
"scalar": true
}
}
}
POST /fhir/FHIRSchema
{
"id": "TutorNotification",
"resourceType": "FHIRSchema",
"url": "http://example.com/aidbox-sms-tutor/TutorNotification",
"type": "TutorNotification",
"name": "TutorNotification",
"base": "DomainResource",
"kind": "resource",
"ALLOW_FHIR_SCHEMA_FHIR_INCOMPATIBLE_EXTENSIONS": true,
"derivation": "specialization",
"required": [
"sendAfter",
"status",
"subject",
"template",
"type"
],
"elements": {
"type": {
"type": "string",
"scalar": true,
"binding": {
"valueSet": "http://hl7.org/fhir/ValueSet/contact-point-system",
"strength": "required"
}
},
"status": {
"type": "string",
"scalar": true,
"constraints": {
"cont-status": {
"human": "Status should be 'requested', 'in-progress' or 'completed'",
"severity": "error",
"expression": "%context='requested' or %context='in-progress' or %context='completed'"
}
},
"binding": {
"valueSet": "http://hl7.org/fhir/ValueSet/task-status",
"strength": "required"
}
},
"template": {
"type": "Reference",
"scalar": true,
"refers": [
"TutorNotificationTemplate"
]
},
"message": {
"type": "string",
"scalar": true
},
"sendAfter": {
"type": "dateTime",
"scalar": true
},
"subject": {
"type": "Reference",
"scalar": true,
"refers": [
"Patient"
]
},
"templateParameters": {
"scalar": true,
"additionalProperties": {
"type": "string"
}
}
}
}
In this FHIRShema:
- Here we use the standard task status value set (link) for
TutorNotification.status
, but it contains too many codes, so we restrict them via the element-specific constraint. - Also, we use additionalProperties FHIR Schema extensions which is FHIR incompatible but allows us to put all template parameters in TutorNotification resource.
For our example we need to perform the following request types:
GET /fhir/TutorNotification?type=sms
GET /fhir/TutorNotification?status=requested
GET /fhir/TutorNotification?after=gt2024-06-12T12:00:00Z
GET /fhir/TutorNotification?_include=TutorNotification:template:TutorNotificationTemplate
GET /fhir/TutorNotification?_include=TutorNotification:subject:Patient
- in the example, we use a combination of all of them.
For them we need to create the following search parameters:
POST /fhir/SearchParameter
{
"resourceType": "SearchParameter",
"id": "TutorNotification-type",
"url": "http://example.com/aidbox-sms-tutor/TutorNotification-type",
"version": "0.0.1",
"status": "draft",
"name": "type",
"code": "type",
"base": [
"TutorNotification"
],
"type": "token",
"description": "Search TutorNotification by type",
"expression": "TutorNotification.type"
}
POST /fhir/SearchParameter
{
"resourceType": "SearchParameter",
"id": "TutorNotification-status",
"url": "http://example.com/aidbox-sms-tutor/TutorNotification-status",
"version": "0.0.1",
"status": "draft",
"name": "status",
"code": "status",
"base": [
"TutorNotification"
],
"type": "token",
"description": "Search TutorNotification by status",
"expression": "TutorNotification.status"
}
POST /fhir/SearchParameter
{
"resourceType": "SearchParameter",
"id": "TutorNotification-after",
"url": "http://example.com/aidbox-sms-tutor/TutorNotification-after",
"version": "0.0.1",
"status": "draft",
"name": "after",
"code": "after",
"base": [
"TutorNotification"
],
"type": "date",
"description": "Search TutorNotification by sendAfter",
"expression": "TutorNotification.sendAfter"
}
POST /fhir/SearchParameter
{
"resourceType": "SearchParameter",
"id": "TutorNotification-subject",
"url": "http://example.com/aidbox-sms-tutor/TutorNotification-subject",
"version": "0.0.1",
"status": "draft",
"name": "subject",
"code": "subject",
"base": [
"TutorNotification"
],
"type": "reference",
"description": "Search TutorNotification by subject",
"expression": "TutorNotification.subject"
}
POST /fhir/SearchParameter
{
"resourceType": "SearchParameter",
"id": "TutorNotification-template",
"url": "http://example.com/aidbox-sms-tutor/TutorNotification-template",
"version": "0.0.1",
"status": "draft",
"name": "template",
"code": "template",
"base": [
"TutorNotification"
],
"type": "reference",
"description": "Search TutorNotification by template",
"expression": "TutorNotification.template"
}
POST /fhir/TutorNotificationTemplate
{
"id": "welcome",
"resourceType": "TutorNotificationTemplate",
"template": "Hello user name: {{patient.name.given}}\n"
}
POST /fhir/Patient
{
"id": "pt-1",
"name": [
{
"given": [
"James"
],
"family": "Morgan"
}
],
"resourceType": "Patient"
}
This section explains the technical details of the notification workflow, including how each step works and what is expected at each stage.
To run the example, clone the repository and open the index.html
file in your browser or open: Aidbox Notify via Custom Resources.
To request a notification, follow these steps:
- Click the "Request notification" button. This triggers the
requestNotification
function in theindex.js
file. - The
requestNotification
function constructs aTutorNotification
resource with the necessary details such as type, status, template reference, sendAfter date, and subject. - A POST request is made to the Aidbox server at the
/TutorNotification
endpoint with the generated notification data. - Upon a successful response, the notification ID is logged and displayed in the journal section.
To retrieve a notification for sending:
- Click the "Get notification" button. This triggers the
getNotification
function in theindex.js
file. - The
getNotification
function constructs a URL with the appropriate search parameters to filter notifications by type, status, and includes related resources. - A GET request is made to the Aidbox server at the
/TutorNotification
endpoint with the constructed URL. - The response is parsed, and the retrieved notification, patient, and template details are displayed in the notification section.
Locking a notification ensures that it is marked as in-progress and cannot be processed by another entity simultaneously. This is achieved through a conditional update:
- Click the "Lock notification" button. This triggers the
lockNotification
function in theindex.js
file. - The
lockNotification
function updates the status of the notification to "in-progress". - A PUT request is made to the Aidbox server at the
/TutorNotification/{id}
endpoint with the updated notification data. - The conditional update checks the
If-Match
header with the notification's version ID to ensure the update only occurs if the notification has not been modified since it was retrieved.
Sending a notification involves:
- Clicking the "Send notification" button, which triggers the
sendNotification
function in theindex.js
file. - The
sendNotification
function checks if a notification is in-progress before proceeding. - A message is generated using the template and patient details.
- The actual sending process should be implemented in the designated section of the
index.js
file. - The notification status is updated to "completed" and a PUT request is made to the Aidbox server to save the changes.
- The notification ID is logged, and the notification section is cleared.