diff --git a/healthcare/fhir/README.md b/healthcare/fhir/README.md index 8b282a84d8..880ce093b3 100644 --- a/healthcare/fhir/README.md +++ b/healthcare/fhir/README.md @@ -37,6 +37,8 @@ Run the following command to install the library dependencies for Node.js: ## FHIR resources Commands: + createFhirResource.js Creates a FHIR resource. + deleteFhirResource.js Deletes a FHIR resource. deleteFhirResourcePurge.js Deletes all historical versions of a FHIR resource. @@ -57,14 +59,11 @@ Run the following command to install the library dependencies for Node.js: updateFhirResource.js Updates the entire contents of a resource. + patchFhirResource.js Updates part of a resource. + + executeFhirBundle.js Executes all the requests in the given Bundle. + - Commands: - fhir_resources.js createResource Creates a new resource in a FHIR store. - - fhir_resources.js patchResource Patches an existing resource in a FHIR store. - - fhir_resources.js executeBundle Executes all the requests in the given Bundle. - Options: --version Show version number [boolean] diff --git a/healthcare/fhir/createFhirResource.js b/healthcare/fhir/createFhirResource.js new file mode 100644 index 0000000000..55896bd201 --- /dev/null +++ b/healthcare/fhir/createFhirResource.js @@ -0,0 +1,66 @@ +/** + * Copyright 2020, Google, LLC + * Licensed under the Apache License, Version 2.0 (the `License`); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an `AS IS` BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +function main( + projectId = process.env.GCLOUD_PROJECT, + cloudRegion = 'us-central1', + datasetId, + fhirStoreId, + resourceType, +) { + // [START healthcare_create_fhir_resource] + const {google} = require('googleapis'); + const healthcare = google.healthcare('v1'); + + async function createFhirResource() { + const auth = await google.auth.getClient({ + scopes: ['https://www.googleapis.com/auth/cloud-platform'], + }); + + // Replace the following body with the data for the resource you want to + // create. + const body = { + "name": [{"use": "official", "family": "Smith", "given": ["Darcy"]}], + "gender": "female", + "birthDate": "1970-01-01", + "resourceType": "Patient", + }; + + google.options({auth, headers: {'Content-Type': 'application/fhir+json'}}); + + // TODO(developer): uncomment these lines before running the sample + // const cloudRegion = 'us-central1'; + // const projectId = 'adjective-noun-123'; + // const datasetId = 'my-dataset'; + // const fhirStoreId = 'my-fhir-store'; + // const resourceType = 'Patient'; + const parent = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/fhirStores/${fhirStoreId}`; + + const request = {parent, type: resourceType, requestBody: body}; + const resource = await healthcare.projects.locations.datasets.fhirStores.fhir.create( + request + ); + console.log(`Created FHIR resource with ID ${resource.data.id}`); + console.log(resource.data); + } + + createFhirResource(); + // [END healthcare_create_fhir_resource] +} + +// node createFhirResource.js +main(...process.argv.slice(2)); diff --git a/healthcare/fhir/deleteFhirResource.js b/healthcare/fhir/deleteFhirResource.js index 3c41c8cc7f..c2fab19a57 100644 --- a/healthcare/fhir/deleteFhirResource.js +++ b/healthcare/fhir/deleteFhirResource.js @@ -51,7 +51,7 @@ const main = ( await healthcare.projects.locations.datasets.fhirStores.fhir.delete( request ); - console.log(`Deleted FHIR resource ${resourceType}`); + console.log(`Deleted FHIR resource`); }; deleteFhirResource(); diff --git a/healthcare/fhir/deleteFhirResourcePurge.js b/healthcare/fhir/deleteFhirResourcePurge.js index 5d58c632e3..fb1cdf0ba3 100644 --- a/healthcare/fhir/deleteFhirResourcePurge.js +++ b/healthcare/fhir/deleteFhirResourcePurge.js @@ -47,7 +47,7 @@ const main = ( await healthcare.projects.locations.datasets.fhirStores.fhir.ResourcePurge( request ); - console.log(`Deleted all historical versions of ${resourceType} resource`); + console.log(`Deleted all historical versions of resource`); }; deleteFhirResourcePurge(); diff --git a/healthcare/fhir/executeFhirBundle.js b/healthcare/fhir/executeFhirBundle.js new file mode 100644 index 0000000000..cfad9d3a26 --- /dev/null +++ b/healthcare/fhir/executeFhirBundle.js @@ -0,0 +1,60 @@ +/** + * Copyright 2020, Google, LLC + * Licensed under the Apache License, Version 2.0 (the `License`); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an `AS IS` BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +function main( + projectId = process.env.GCLOUD_PROJECT, + cloudRegion = 'us-central1', + datasetId, + fhirStoreId, + bundleFile +) { + // [START healthcare_fhir_execute_bundle] + const {google} = require('googleapis'); + const healthcare = google.healthcare('v1'); + const fs = require('fs'); + + async function executeFhirBundle() { + const auth = await google.auth.getClient({ + scopes: ['https://www.googleapis.com/auth/cloud-platform'], + }); + + google.options({auth, headers: {'Content-Type': 'application/fhir+json'}}); + + // TODO(developer): uncomment these lines before running the sample + // const cloudRegion = 'us-central1'; + // const projectId = 'adjective-noun-123'; + // const datasetId = 'my-dataset'; + // const fhirStoreId = 'my-fhir-store'; + // const bundleFile = 'bundle.json'; + const parent = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/fhirStores/${fhirStoreId}`; + + const bundle = JSON.parse(fs.readFileSync(bundleFile)); + + const request = {parent, requestBody: bundle}; + const resource = await healthcare.projects.locations.datasets.fhirStores.fhir.executeBundle( + request + ); + console.log(`FHIR bundle executed`); + console.log(resource.data); + } + + executeFhirBundle(); + // [END healthcare_fhir_execute_bundle] +} + +// node executeFhirBundle.js +main(...process.argv.slice(2)); diff --git a/healthcare/fhir/fhir_resources.js b/healthcare/fhir/fhir_resources.js deleted file mode 100644 index 8d809e0768..0000000000 --- a/healthcare/fhir/fhir_resources.js +++ /dev/null @@ -1,256 +0,0 @@ -// Copyright 2018 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -const {GoogleToken} = require('gtoken'); -const request = require('request-promise'); - -const BASE_URL = 'https://healthcare.googleapis.com/v1'; - -// [START healthcare_get_token] -const getToken = (serviceAccountJson, cb) => { - const gtoken = new GoogleToken({ - keyFile: `${serviceAccountJson}`, - scope: ['https://www.googleapis.com/auth/cloud-platform'], // or space-delimited string of scopes - }); - - gtoken.getToken((err, token) => { - if (err) { - console.log('ERROR: ', err); - return; - } - cb(token); - }); -}; -// [END healthcare_get_token] - -// [START healthcare_create_resource] -const createResource = async ( - token, - projectId, - cloudRegion, - datasetId, - fhirStoreId, - resourceType -) => { - // Token retrieved in callback - // getToken(serviceAccountJson, function(cb) {...}); - // const cloudRegion = 'us-central1'; - // const projectId = 'adjective-noun-123'; - // const datasetId = 'my-dataset'; - // const fhirStoreId = 'my-fhir-store'; - // const resourceType = 'Patient'; - const parentName = `${BASE_URL}/projects/${projectId}/locations/${cloudRegion}`; - - const resourcePath = `${parentName}/datasets/${datasetId}/fhirStores/${fhirStoreId}/fhir/${resourceType}`; - - const postData = { - resourceType: resourceType, - }; - - const options = { - url: resourcePath, - headers: { - Authorization: `Bearer ${token}`, - 'Content-Type': 'application/fhir+json; charset=utf-8', - }, - body: postData, - json: true, - method: 'POST', - }; - - try { - const resource = await request(options); - console.log( - `Created FHIR resource ${resourceType} with ID ${resource.id}.` - ); - } catch (err) { - console.error(err); - } -}; -// [END healthcare_create_resource] - -// [START healthcare_patch_resource] -const patchResource = async ( - token, - projectId, - cloudRegion, - datasetId, - fhirStoreId, - resourceType, - resourceId -) => { - // Token retrieved in callback - // getToken(serviceAccountJson, function(cb) {...}); - // const cloudRegion = 'us-central1'; - // const projectId = 'adjective-noun-123'; - // const datasetId = 'my-dataset'; - // const fhirStoreId = 'my-fhir-store'; - // const resourceType = 'Patient'; - // const resourceId = 'd64a85ae-da1b-4a10-0eb8-cfaf55bdbe3f'; - const parentName = `${BASE_URL}/projects/${projectId}/locations/${cloudRegion}`; - - const resourcePath = `${parentName}/datasets/${datasetId}/fhirStores/${fhirStoreId}/fhir/${resourceType}/${resourceId}`; - - const patchOperations = [{op: 'replace', path: '/active', value: true}]; - - const options = { - url: resourcePath, - headers: { - Authorization: `Bearer ${token}`, - 'Content-Type': 'application/json-patch+json', - }, - body: patchOperations, - json: true, - method: 'PATCH', - }; - - try { - await request(options); - console.log(`Patched ${resourceType} resource`); - } catch (err) { - console.error(err); - } -}; -// [END healthcare_patch_resource] - -// [START healthcare_fhir_execute_bundle] -const executeBundle = async ( - token, - projectId, - cloudRegion, - datasetId, - fhirStoreId, - bundleFile -) => { - const fs = require('fs'); - // Token retrieved in callback - // getToken(serviceAccountJson, function(cb) {...}); - // const cloudRegion = 'us-central1'; - // const projectId = 'adjective-noun-123'; - // const datasetId = 'my-dataset'; - // const fhirStoreId = 'my-fhir-store'; - // const bundleFile = 'bundle.json'; - const parentName = `${BASE_URL}/projects/${projectId}/locations/${cloudRegion}`; - - const resourcesPath = `${parentName}/datasets/${datasetId}/fhirStores/${fhirStoreId}/fhir`; - - const bundle = fs.readFileSync(bundleFile); - - const options = { - url: resourcesPath, - headers: { - Authorization: `Bearer ${token}`, - 'Content-Type': 'application/fhir+json; charset=utf-8', - }, - body: bundle, - method: 'POST', - }; - - try { - const results = await request(options); - console.log('Executed Bundle\n'); - console.log(JSON.stringify(results, null, 2)); - } catch (err) { - console.error(err); - } -}; -// [END healthcare_fhir_execute_bundle] - -require(`yargs`) // eslint-disable-line - .demand(1) - .options({ - cloudRegion: { - alias: 'c', - default: 'us-central1', - requiresArg: true, - type: 'string', - }, - projectId: { - alias: 'p', - default: process.env.GCLOUD_PROJECT || process.env.GOOGLE_CLOUD_PROJECT, - description: - 'The Project ID to use. Defaults to the value of the GCLOUD_PROJECT or GOOGLE_CLOUD_PROJECT environment variables.', - requiresArg: true, - type: 'string', - }, - serviceAccount: { - alias: 's', - default: process.env.GOOGLE_APPLICATION_CREDENTIALS, - description: 'The path to your service credentials JSON.', - requiresArg: true, - type: 'string', - }, - }) - .command( - `createResource `, - `Creates a new resource in a FHIR store.`, - {}, - (opts) => { - const cb = (token) => { - createResource( - token, - opts.projectId, - opts.cloudRegion, - opts.datasetId, - opts.fhirStoreId, - opts.resourceType - ); - }; - getToken(opts.serviceAccount, cb); - } - ) - .command( - `patchResource `, - `Patches an existing resource in a FHIR store.`, - {}, - (opts) => { - const cb = (token) => { - patchResource( - token, - opts.projectId, - opts.cloudRegion, - opts.datasetId, - opts.fhirStoreId, - opts.resourceType, - opts.resourceId - ); - }; - getToken(opts.serviceAccount, cb); - } - ) - .command( - `executeBundle `, - `Executes all the requests in the given Bundle.`, - {}, - (opts) => { - const cb = (token) => { - executeBundle( - token, - opts.projectId, - opts.cloudRegion, - opts.datasetId, - opts.fhirStoreId, - opts.bundleFile - ); - }; - getToken(opts.serviceAccount, cb); - } - ) - .wrap(120) - .recommendCommands() - .epilogue( - `For more information, see https://cloud.google.com/healthcare/docs` - ) - .help() - .strict().argv; diff --git a/healthcare/fhir/patchFhirResource.js b/healthcare/fhir/patchFhirResource.js new file mode 100644 index 0000000000..992362bd23 --- /dev/null +++ b/healthcare/fhir/patchFhirResource.js @@ -0,0 +1,62 @@ +/** + * Copyright 2020, Google, LLC + * Licensed under the Apache License, Version 2.0 (the `License`); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an `AS IS` BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +function main( + projectId = process.env.GCLOUD_PROJECT, + cloudRegion = 'us-central1', + datasetId, + fhirStoreId, + resourceType, + resourceId +) { + // [START healthcare_patch_fhir_resource] + const {google} = require('googleapis'); + const healthcare = google.healthcare('v1'); + + async function patchFhirResource() { + const auth = await google.auth.getClient({ + scopes: ['https://www.googleapis.com/auth/cloud-platform'], + }); + // TODO(developer): replace patchOptions with your desired JSON patch body + const patchOptions = [{op: 'replace', path: '/active', value: false}]; + google.options({auth, headers: {'Content-Type': 'application/json-patch+json'}}); + + // TODO(developer): uncomment these lines before running the sample + // const cloudRegion = 'us-central1'; + // const projectId = 'adjective-noun-123'; + // const datasetId = 'my-dataset'; + // const fhirStoreId = 'my-fhir-store'; + // const resourceType = 'Patient'; + // const resourceId = '16e8a860-33b3-49be-9b03-de979feed14a'; + const name = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/fhirStores/${fhirStoreId}/fhir/${resourceType}/${resourceId}`; + const request = { + name, + requestBody: patchOptions + }; + + const resource = await healthcare.projects.locations.datasets.fhirStores.fhir.patch( + request, + ); + console.log(`Patched ${resourceType} resource`); + } + + patchFhirResource(); + // [END healthcare_patch_fhir_resource] +} + +// node patchFhirResource.js +main(...process.argv.slice(2)); diff --git a/healthcare/fhir/resources/bundle.json b/healthcare/fhir/resources/bundle.json index f1ecb029e6..ed60077310 100644 --- a/healthcare/fhir/resources/bundle.json +++ b/healthcare/fhir/resources/bundle.json @@ -1 +1,44 @@ -{ "resourceType": "Bundle", "type": "transaction", "entry": [ { "resource": { "resourceType": "Patient", "name": [ { "family": "Smith", "given": [ "Darcy" ] } ], "gender": "female", "address": [ { "line": [ "123 Main St." ], "city": "Anycity", "state": "CA", "postalCode": "12345" } ] }, "request": { "method": "POST" } } ] } +{ + "resourceType": "Bundle", + "id": "bundle-transaction", + "meta": { + "lastUpdated": "2018-03-11T11:22:16Z" + }, + "type": "transaction", + "entry": [ + { + "resource": { + "resourceType": "Patient", + "name": [ + { + "family": "Smith", + "given": [ + "Darcy" + ] + } + ], + "gender": "female", + "address": [ + { + "line": [ + "123 Main St." + ], + "city": "Anycity", + "state": "CA", + "postalCode": "12345" + } + ] + }, + "request": { + "method": "POST", + "url": "Patient" + } + }, + { + "request": { + "method": "DELETE", + "url": "Patient/1234567890" + } + } + ] +} diff --git a/healthcare/fhir/searchFhirResourcesGet.js b/healthcare/fhir/searchFhirResourcesGet.js index 4eeaebde37..a5cc77521e 100644 --- a/healthcare/fhir/searchFhirResourcesGet.js +++ b/healthcare/fhir/searchFhirResourcesGet.js @@ -38,6 +38,7 @@ const main = ( // const projectId = 'adjective-noun-123'; // const datasetId = 'my-dataset'; // const fhirStoreId = 'my-fhir-store'; + // const resourceType = 'Patient'; const parent = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/fhirStores/${fhirStoreId}/fhir`; const request = {parent, resourceType}; diff --git a/healthcare/fhir/system-test/fhir_resources.test.js b/healthcare/fhir/system-test/fhir_resources.test.js index 1eaff5eb3b..bfbcc8f765 100644 --- a/healthcare/fhir/system-test/fhir_resources.test.js +++ b/healthcare/fhir/system-test/fhir_resources.test.js @@ -64,11 +64,11 @@ it('should create a FHIR resource', () => { {cwd} ); const output = execSync( - `node fhir_resources.js createResource ${datasetId} ${fhirStoreId} ${resourceType}`, + `node createFhirResource ${projectId} ${cloudRegion} ${datasetId} ${fhirStoreId} ${resourceType}`, {cwd} ); const createdResource = new RegExp( - `Created FHIR resource ${resourceType} with ID (.*).` + `Created FHIR resource with ID (.*)` ); assert.strictEqual(createdResource.test(output), true); [, resourceId] = createdResource.exec(output); @@ -137,10 +137,13 @@ it('should update a FHIR resource', () => { it('should patch a FHIR resource', () => { const output = execSync( - `node fhir_resources.js patchResource ${datasetId} ${fhirStoreId} ${resourceType} ${resourceId}`, + `node patchFhirResource.js ${projectId} ${cloudRegion} ${datasetId} ${fhirStoreId} ${resourceType} ${resourceId}`, {cwd} ); - assert.strictEqual(output, `Patched ${resourceType} resource`); + assert.strictEqual( + new RegExp(`Patched ${resourceType} resource`).test(output), + true + ); }); it('should search for FHIR resources using GET', () => { @@ -162,18 +165,15 @@ it('should purge all historical versions of a FHIR resource', () => { `node deleteFhirResourcePurge.js ${projectId} ${cloudRegion} ${datasetId} ${fhirStoreId} ${resourceType} ${resourceId}`, {cwd} ); - assert.strictEqual( - output, - `Deleted all historical versions of ${resourceType} resource` - ); + assert.strictEqual(new RegExp('Deleted all historical versions of resource').test(output), true); }); it('should execute a Bundle', () => { const output = execSync( - `node fhir_resources.js executeBundle ${datasetId} ${fhirStoreId} ${bundleFile}`, + `node executeFhirBundle ${projectId} ${cloudRegion} ${datasetId} ${fhirStoreId} ${bundleFile}`, {cwd} ); - assert.strictEqual(new RegExp('Executed Bundle').test(output), true); + assert.strictEqual(new RegExp('FHIR bundle executed').test(output), true); }); it('should delete a FHIR resource', () => { @@ -181,7 +181,7 @@ it('should delete a FHIR resource', () => { `node deleteFhirResource.js ${projectId} ${cloudRegion} ${datasetId} ${fhirStoreId} ${resourceType} ${resourceId}`, {cwd} ); - assert.strictEqual(output, `Deleted FHIR resource ${resourceType}`); + assert.strictEqual(new RegExp('Deleted FHIR resource').test(output), true); // Clean up execSync( diff --git a/healthcare/fhir/updateFhirResource.js b/healthcare/fhir/updateFhirResource.js index 4df3ab66d5..437ea522e1 100644 --- a/healthcare/fhir/updateFhirResource.js +++ b/healthcare/fhir/updateFhirResource.js @@ -34,7 +34,6 @@ const main = ( }); google.options({ auth, - data: {resourceType: resourceType, id: resourceId, active: true}, headers: {'Content-Type': 'application/fhir+json'}, }); @@ -46,7 +45,8 @@ const main = ( // const resourceType = 'Patient'; // const resourceId = '16e8a860-33b3-49be-9b03-de979feed14a'; const name = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/fhirStores/${fhirStoreId}/fhir/${resourceType}/${resourceId}`; - const request = {name}; + const body = {resourceType: resourceType, id: resourceId, active: true}; + const request = {name, requestBody: body}; const resource = await healthcare.projects.locations.datasets.fhirStores.fhir.update( request