Skip to content

Commit

Permalink
Merge pull request #312 from OpenFn/improve-fhir
Browse files Browse the repository at this point in the history
`fhir` improvements
  • Loading branch information
mtuchi authored Jul 28, 2023
2 parents 95da6f2 + 9e302a2 commit 04a9754
Show file tree
Hide file tree
Showing 10 changed files with 982 additions and 271 deletions.
5 changes: 5 additions & 0 deletions .changeset/sixty-rockets-buy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@openfn/language-fhir': minor
---

Migrate from axios to using `fetch` from `undici` and add uniti tests
75 changes: 72 additions & 3 deletions packages/fhir/ast.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
},
{
"title": "example",
"description": "create(\"/endpoint\", {\"foo\": \"bar\"})"
"description": "create(\"Bundle\", {...state.data: type: \"collection\"})"
},
{
"title": "function",
Expand Down Expand Up @@ -79,7 +79,7 @@
},
{
"title": "example",
"description": "createTransactionBundle( {\"entry\": [{...},, {...}]})"
"description": "createTransactionBundle({\n resourceType: \"Bundle\",\n type: \"transaction\",\n entry: [\n {\n fullUrl: \"https://hapi.fhir.org/baseR4/Patient/592442\",\n resource: {\n resourceType: \"Patient\",\n id: \"592442\",\n name: [{ given: \"Caleb\", family: \"Cushing\" }],\n },\n request: {\n method: \"POST\",\n url: \"Patient\",\n },\n },\n ],\n});"
},
{
"title": "function",
Expand Down Expand Up @@ -133,7 +133,13 @@
},
{
"title": "example",
"description": "get(\"/endpoint\", {\"foo\": \"bar\"})"
"description": "get(\"Claim\", { _include: \"Claim:patient\", _sort: \"-_lastUpdated\", _count: 200 })",
"caption": "Get Claim from FHIR with optional query"
},
{
"title": "example",
"description": "get('Patient');",
"caption": "Get Patient from FHIR"
},
{
"title": "function",
Expand Down Expand Up @@ -178,6 +184,69 @@
]
},
"valid": true
},
{
"name": "getClaim",
"params": [
"claimId",
"query",
"callback"
],
"docs": {
"description": "Get Claim in a FHIR system",
"tags": [
{
"title": "public",
"description": null,
"type": null
},
{
"title": "example",
"description": "getClaim({ _include: \"Claim:patient\", _sort: \"-_lastUpdated\", _count: 200 });"
},
{
"title": "function",
"description": null,
"name": null
},
{
"title": "param",
"description": "(optional) claim id",
"type": {
"type": "NameExpression",
"name": "string"
},
"name": "claimId"
},
{
"title": "param",
"description": "(optinal) query parameters",
"type": {
"type": "NameExpression",
"name": "object"
},
"name": "query"
},
{
"title": "param",
"description": "(Optional) callback function",
"type": {
"type": "NameExpression",
"name": "function"
},
"name": "callback"
},
{
"title": "returns",
"description": null,
"type": {
"type": "NameExpression",
"name": "Operation"
}
}
]
},
"valid": true
}
],
"exports": [],
Expand Down
11 changes: 5 additions & 6 deletions packages/fhir/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,16 @@
],
"dependencies": {
"@openfn/language-common": "workspace:^1.8.1",
"axios": "0.21.4"
"undici": "^5.22.1"
},
"devDependencies": {
"@openfn/buildtools": "workspace:^1.0.2",
"@openfn/simple-ast": "^0.4.1",
"assertion-error": "^1.1.0",
"chai": "^3.5.0",
"deep-eql": "^0.1.3",
"assertion-error": "2.0.0",
"chai": "^4.3.6",
"deep-eql": "4.1.1",
"esno": "^0.16.3",
"mocha": "^7.2.0",
"nock": "^12.0.3",
"mocha": "9.2.2",
"rimraf": "^3.0.2"
},
"repository": {
Expand Down
117 changes: 76 additions & 41 deletions packages/fhir/src/Adaptor.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
import {
execute as commonExecute,
expandReferences,
http,
} from '@openfn/language-common';
import { handleError, handleResponse } from './Utils';
import { execute as commonExecute } from '@openfn/language-common';
import { expandReferences } from '@openfn/language-common/util';

const { axios } = http;
export { axios };
import { handleResponse, request } from './Utils';

/**
* Execute a sequence of operations.
Expand Down Expand Up @@ -38,7 +33,7 @@ export function execute(...operations) {
* Creates a resource in a destination system using a POST request
* @public
* @example
* create("/endpoint", {"foo": "bar"})
* create("Bundle", {...state.data: type: "collection"})
* @function
* @param {string} path - Path to resource
* @param {object} params - data to create the new resource
Expand All @@ -47,50 +42,67 @@ export function execute(...operations) {
*/
export function create(path, params, callback) {
return state => {
const resolvedpath = expandReferences(path)(state);
const resolvedParams = expandReferences(params)(state);
const [resolvedpath, resolvedParams] = expandReferences(
state,
path,
params
);

const { baseUrl, apiPath } = state.configuration;

const url = `${baseUrl}/${apiPath}/${resolvedpath}`;

const config = {
url,
const options = {
headers: {
accept: 'application/fhir+json',
'Content-Type': 'application/fhir+json',
},
data: resolvedParams,
...resolvedParams,
};

return http
.post(config)(state)
.then(response => handleResponse(response, state, callback))
.catch(handleError);
return request(url, options, 'POST').then(response =>
handleResponse(response, state, callback)
);
};
}

/**
* Creates a transactionBundle for HAPI FHIR
* @public
* @example
* createTransactionBundle( {"entry": [{...},, {...}]})
* createTransactionBundle({
* resourceType: "Bundle",
* type: "transaction",
* entry: [
* {
* fullUrl: "https://hapi.fhir.org/baseR4/Patient/592442",
* resource: {
* resourceType: "Patient",
* id: "592442",
* name: [{ given: "Caleb", family: "Cushing" }],
* },
* request: {
* method: "POST",
* url: "Patient",
* },
* },
* ],
* });
* @function
* @param {object} params - data to create the new transaction
* @param {function} callback - (Optional) callback function
* @returns {Operation}
*/
export function createTransactionBundle(params, callback) {
return state => {
const resolvedParams = expandReferences(params)(state);
const [resolvedParams] = expandReferences(state, params);

const { baseUrl, apiPath, authType, token } = state.configuration;

const url = `${baseUrl}/${apiPath}`;
const auth = `${authType} ${token}`;

const config = {
url,
const options = {
body: {
resourceType: 'Bundle',
type: 'transaction',
Expand All @@ -99,45 +111,69 @@ export function createTransactionBundle(params, callback) {
auth,
};

return http
.post(config)(state)
.then(response => handleResponse(response, state, callback))
.catch(handleError);
return request(url, options, 'POST').then(response =>
handleResponse(response, state, callback)
);
};
}

/**
* Get a resource in a FHIR system
* @public
* @example
* get("/endpoint", {"foo": "bar"})
* @example <caption>Get Claim from FHIR with optional query</caption>
* get("Claim", { _include: "Claim:patient", _sort: "-_lastUpdated", _count: 200 })
* @example <caption>Get Patient from FHIR</caption>
* get('Patient');
* @function
* @param {string} path - Path to resource
* @param {object} query - data to get the new resource
* @param {function} callback - (Optional) callback function
* @returns {Operation}
*/
export function get(path, query, callback = false) {
export function get(path, query, callback = s => s) {
return state => {
const resolvedPath = expandReferences(path)(state);
const resolvedQuery = expandReferences(query)(state);
const [resolvedPath, resolvedQuery] = expandReferences(state, path, query);

const { baseUrl, apiPath } = state.configuration;
const url = `${baseUrl}/${apiPath}/${resolvedPath}`;

const config = {
url,
query: resolvedQuery,
};
return request(url, { ...resolvedQuery }).then(response =>
handleResponse(response, state, callback)
);
};
}

/**
* Get Claim in a FHIR system
* @public
* @example
* getClaim({ _include: "Claim:patient", _sort: "-_lastUpdated", _count: 200 });
* @function
* @param {string} claimId - (optional) claim id
* @param {object} query - (optinal) query parameters
* @param {function} callback - (Optional) callback function
* @returns {Operation}
*/
export function getClaim(claimId, query, callback = s => s) {
return state => {
const [resourcedclaimId, resolvedQuery] = expandReferences(
state,
claimId,
query
);

const { baseUrl, apiPath } = state.configuration;
const url = resourcedclaimId
? `${baseUrl}/${apiPath}/Claim/${resourcedclaimId}`
: `${baseUrl}/${apiPath}/Claim`;

return http
.get(config)(state)
.then(response => handleResponse(response, state, callback))
.catch(handleError);
return request(url, { ...resolvedQuery }).then(response =>
handleResponse(response, state, callback)
);
};
}
export { request } from './Utils';

// What functions do you want from the common adaptor?
export {
alterState,
dataPath,
Expand All @@ -147,7 +183,6 @@ export {
field,
fields,
fn,
http,
lastReferenceValue,
merge,
sourceValue,
Expand Down
Loading

0 comments on commit 04a9754

Please sign in to comment.