diff --git a/healthcare/dicom/README.md b/healthcare/dicom/README.md
new file mode 100644
index 0000000000..cadd6f61eb
--- /dev/null
+++ b/healthcare/dicom/README.md
@@ -0,0 +1,68 @@
+
+
+# Cloud Healthcare API Node.js DICOM store and DICOMweb example
+
+This sample app demonstrates DICOM store management and the DICOMweb implementation for the Cloud Healthcare API.
+
+# Setup
+
+Run the following command to install the library dependencies for Node.js:
+
+ npm install
+
+# Running the samples
+
+## DICOM stores
+
+ dicom_stores.js
+
+ Commands:
+ dicom_stores.js createDicomStore Creates a new DICOM store within the parent dataset.
+ dicom_stores.js deleteDicomStore Deletes the DICOM store and removes all resources that
+ are contained within it.
+ dicom_stores.js getDicomStore Gets the specified DICOM store or returns NOT_FOUND if
+ it doesn't exist.
+ dicom_stores.js listDicomStores Lists the DICOM stores in the given dataset.
+ dicom_stores.js patchDicomStore Updates the DICOM store.
+
+ dicom_stores.js importDicomObject Imports data into the DICOM store by copying it from the
+ specified source.
+ dicom_stores.js exportDicomInstanceGcs Exports data to a Cloud Storage bucket by copying it
+ from the DICOM store.
+
+ Options:
+ --version Show version number [boolean]
+ --apiKey, -a The API key used for discovering the API.
+ [string]
+ --cloudRegion, -c [string] [default: "us-central1"]
+ --projectId, -p The Project ID to use. Defaults to the value of the GCLOUD_PROJECT or GOOGLE_CLOUD_PROJECT
+ environment variables. [string]
+ --serviceAccount, -s The path to your service credentials JSON.
+ [string]
+ --help Show help [boolean]
+
+
+## DICOMweb
+
+ dicomweb.js
+
+ Commands:
+ dicomweb.js dicomWebStoreInstance Handles the POST requests specified in the DICOMweb
+ standard.
+ dicomweb.js dicomWebSearchInstances Handles the GET requests specified in the DICOMweb
+ standard.
+ dicomweb.js dicomWebRetrieveStudy Handles the GET requests specified in the DICOMweb
+ standard.
+ dicomweb.js dicomWebDeleteStudy Handles DELETE requests.
+
+
+ Options:
+ --version Show version number [boolean]
+ --cloudRegion, -c [string] [default: "us-central1"]
+ --projectId, -p The Project ID to use. Defaults to the value of the GCLOUD_PROJECT or GOOGLE_CLOUD_PROJECT
+ environment variables. [string]
+ --serviceAccount, -s The path to your service credentials JSON.
+ [string]
+ --help Show help [boolean]
+
+For more information, see https://cloud.google.com/healthcare/docs
diff --git a/healthcare/dicom/dicom_stores.js b/healthcare/dicom/dicom_stores.js
new file mode 100644
index 0000000000..de6daba881
--- /dev/null
+++ b/healthcare/dicom/dicom_stores.js
@@ -0,0 +1,341 @@
+/**
+ * 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.
+ */
+
+'use strict';
+
+const {google} = require('googleapis');
+
+// [START healthcare_create_dicom_store]
+function createDicomStore (client, projectId, cloudRegion, datasetId, dicomStoreId) {
+ // Client retrieved in callback
+ // getClient(serviceAccountJson, function(cb) {...});
+ // const cloudRegion = 'us-central1';
+ // const projectId = 'adjective-noun-123';
+ // const datasetId = 'my-dataset';
+ // const dicomStoreId = 'my-dicom-store';
+ const parentName = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}`;
+
+ const request = {parent: parentName, dicomStoreId: dicomStoreId};
+
+ client.projects.locations.datasets.dicomStores.create(request)
+ .then(() => {
+ console.log(`Created DICOM store: ${dicomStoreId}`);
+ })
+ .catch(err => {
+ console.error(err);
+ });
+}
+// [END healthcare_create_dicom_store]
+
+// [START healthcare_delete_dicom_store]
+function deleteDicomStore (client, projectId, cloudRegion, datasetId, dicomStoreId) {
+ // Client retrieved in callback
+ // getClient(serviceAccountJson, function(cb) {...});
+ // const cloudRegion = 'us-central1';
+ // const projectId = 'adjective-noun-123';
+ // const datasetId = 'my-dataset';
+ // const dicomStoreId = 'my-dicom-store';
+ const dicomStoreName =
+ `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/dicomStores/${dicomStoreId}`;
+
+ const request = {name: dicomStoreName};
+
+ client.projects.locations.datasets.dicomStores.delete(request)
+ .then(() => {
+ console.log(`Deleted DICOM store: ${dicomStoreId}`);
+ })
+ .catch(err => {
+ console.error(err);
+ });
+}
+// [END healthcare_delete_dicom_store]
+
+// [START healthcare_get_dicom_store]
+function getDicomStore (client, projectId, cloudRegion, datasetId, dicomStoreId) {
+ // Client retrieved in callback
+ // getClient(serviceAccountJson, function(cb) {...});
+ // const cloudRegion = 'us-central1';
+ // const projectId = 'adjective-noun-123';
+ // const datasetId = 'my-dataset';
+ // const dicomStoreId = 'my-dicom-store';
+ const dicomStoreName =
+ `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/dicomStores/${dicomStoreId}`;
+
+ const request = {name: dicomStoreName};
+
+ client.projects.locations.datasets.dicomStores.get(request)
+ .then(results => {
+ console.log('Got DICOM store:\n', results['data']);
+ })
+ .catch(err => {
+ console.error(err);
+ });
+}
+// [END healthcare_get_dicom_store]
+
+// [START healthcare_list_dicom_stores]
+function listDicomStores (client, projectId, cloudRegion, datasetId) {
+ // Client retrieved in callback
+ // getClient(serviceAccountJson, function(cb) {...});
+ // const cloudRegion = 'us-central1';
+ // const projectId = 'adjective-noun-123';
+ // const datasetId = 'my-dataset';
+ const parentName = `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}`;
+
+ const request = {parent: parentName};
+
+ client.projects.locations.datasets.dicomStores.list(request)
+ .then(results => {
+ console.log('DICOM stores:\n', results['data']['dicomStores']);
+ })
+ .catch(err => {
+ console.error(err);
+ });
+}
+// [END healthcare_list_dicom_stores]
+
+// [START healthcare_patch_dicom_store]
+function patchDicomStore (client, projectId, cloudRegion, datasetId, dicomStoreId, pubsubTopic) {
+ // Client retrieved in callback
+ // getClient(serviceAccountJson, function(cb) {...});
+ // const cloudRegion = 'us-central1';
+ // const projectId = 'adjective-noun-123';
+ // const datasetId = 'my-dataset';
+ // const dicomStoreId = 'my-dicom-store';
+ // const pubsubTopic = 'my-topic'
+ const dicomStoreName =
+ `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/dicomStores/${dicomStoreId}`;
+
+ const request = {
+ name: dicomStoreName,
+ updateMask: 'notificationConfig',
+ resource: { 'notificationConfig': { pubsubTopic: `projects/${projectId}/locations/${cloudRegion}/topics/${pubsubTopic}` } }
+ };
+
+ client.projects.locations.datasets.dicomStores.patch(request)
+ .then(results => {
+ console.log(
+ 'Patched DICOM store with Cloud Pub/Sub topic', results['data']['notificationConfig']['pubsubTopic']);
+ })
+ .catch(err => {
+ console.error(err);
+ });
+}
+// [END healthcare_patch_dicom_store]
+
+// [START healthcare_import_dicom_object]
+function importDicomObject (client, projectId, cloudRegion, datasetId, dicomStoreId, contentUri) {
+ // Token retrieved in callback
+ // getToken(serviceAccountJson, function(cb) {...});
+ // const cloudRegion = 'us-central1';
+ // const projectId = 'adjective-noun-123';
+ // const datasetId = 'my-dataset';
+ // const dicomStoreId = 'my-dicom-store';
+ // const contentUri = 'my-bucket'
+ const dicomStoreName =
+ `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/dicomStores/${dicomStoreId}`;
+
+ const request = {
+ name: dicomStoreName,
+ resource: {
+ inputConfig: {
+ gcsSource: {
+ contentUri: `gs://${contentUri}`
+ }
+ }
+ }};
+
+ client.projects.locations.datasets.dicomStores.import(request)
+ .then(results => {
+ console.log(`Imported DICOM objects from bucket ${contentUri}`);
+ })
+ .catch(err => {
+ console.error(err);
+ });
+}
+// [END healthcare_import_dicom_object]
+
+// [START healthcare_export_dicom_instance_gcs]
+function exportDicomInstanceGcs (client, projectId, cloudRegion, datasetId, dicomStoreId, uriPrefix) {
+ // Token retrieved in callback
+ // getToken(serviceAccountJson, function(cb) {...});
+ // const cloudRegion = 'us-central1';
+ // const projectId = 'adjective-noun-123';
+ // const datasetId = 'my-dataset';
+ // const dicomStoreId = 'my-dicom-store';
+ // const uriPrefix = 'my-bucket'
+ const dicomStoreName =
+ `projects/${projectId}/locations/${cloudRegion}/datasets/${datasetId}/dicomStores/${dicomStoreId}`;
+
+ const request = {
+ name: dicomStoreName,
+ resource: {
+ outputConfig: {
+ gcsDestination: {
+ uriPrefix: `gs://${uriPrefix}`
+ }
+ }
+ }};
+
+ client.projects.locations.datasets.dicomStores.export(request)
+ .then(results => {
+ console.log(`Exported DICOM instances to bucket ${uriPrefix}`);
+ })
+ .catch(err => {
+ console.error(err);
+ });
+}
+// [END healthcare_export_dicom_instance_gcs]
+
+// Returns an authorized API client by discovering the Healthcare API with
+// the provided API key.
+// [START healthcare_get_client]
+function getClient (apiKey, serviceAccountJson, cb) {
+ const API_VERSION = 'v1alpha';
+ const DISCOVERY_API = 'https://healthcare.googleapis.com/$discovery/rest';
+
+ google.auth
+ .getClient({scopes: ['https://www.googleapis.com/auth/cloud-platform']})
+ .then(authClient => {
+ const discoveryUrl = `${DISCOVERY_API}?labels=CHC_ALPHA&version=${
+ API_VERSION}&key=${apiKey}`;
+
+ google.options({auth: authClient});
+
+ google.discoverAPI(discoveryUrl)
+ .then((client) => {
+ cb(client);
+ })
+ .catch((err) => {
+ console.error(err);
+ });
+ });
+}
+// [END healthcare_get_client]
+
+require(`yargs`) // eslint-disable-line
+ .demand(1)
+ .options({
+ apiKey: {
+ alias: 'a',
+ default: process.env.API_KEY,
+ description: 'The API key used for discovering the API.',
+ requiresArg: true,
+ type: 'string'
+ },
+ 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(
+ `createDicomStore `,
+ `Creates a new DICOM store within the parent dataset.`,
+ {},
+ (opts) => {
+ const cb = function (client) {
+ createDicomStore(client, opts.projectId, opts.cloudRegion, opts.datasetId, opts.dicomStoreId);
+ };
+ getClient(opts.apiKey, opts.serviceAccount, cb);
+ }
+ )
+ .command(
+ `deleteDicomStore `,
+ `Deletes the DICOM store and removes all resources that are contained within it.`,
+ {},
+ (opts) => {
+ const cb = function (client) {
+ deleteDicomStore(client, opts.projectId, opts.cloudRegion, opts.datasetId, opts.dicomStoreId);
+ };
+ getClient(opts.apiKey, opts.serviceAccount, cb);
+ }
+ )
+ .command(
+ `getDicomStore `,
+ `Gets the specified DICOM store or returns NOT_FOUND if it doesn't exist.`,
+ {},
+ (opts) => {
+ const cb = function (client) {
+ getDicomStore(client, opts.projectId, opts.cloudRegion, opts.datasetId, opts.dicomStoreId);
+ };
+ getClient(opts.apiKey, opts.serviceAccount, cb);
+ }
+ )
+ .command(
+ `listDicomStores `,
+ `Lists the DICOM stores in the given dataset.`,
+ {},
+ (opts) => {
+ const cb = function (client) {
+ listDicomStores(client, opts.projectId, opts.cloudRegion, opts.datasetId);
+ };
+ getClient(opts.apiKey, opts.serviceAccount, cb);
+ }
+ )
+ .command(
+ `patchDicomStore `,
+ `Updates the DICOM store.`,
+ {},
+ (opts) => {
+ const cb = function (client) {
+ patchDicomStore(client, opts.projectId, opts.cloudRegion, opts.datasetId, opts.dicomStoreId, opts.pubsubTopic);
+ };
+ getClient(opts.apiKey, opts.serviceAccount, cb);
+ }
+ )
+ .command(
+ `importDicomObject `,
+ `Imports data into the DICOM store by copying it from the specified source.`,
+ {},
+ (opts) => {
+ const cb = function (client) {
+ importDicomObject(client, opts.projectId, opts.cloudRegion, opts.datasetId, opts.dicomStoreId, opts.contentUri);
+ };
+ getClient(opts.apiKey, opts.serviceAccount, cb);
+ }
+ )
+ .command(
+ `exportDicomInstanceGcs `,
+ `Exports data to a Cloud Storage bucket by copying it from the DICOM store.`,
+ {},
+ (opts) => {
+ const cb = function (client) {
+ exportDicomInstanceGcs(client, opts.projectId, opts.cloudRegion, opts.datasetId, opts.dicomStoreId, opts.uriPrefix);
+ };
+ getClient(opts.apiKey, opts.serviceAccount, cb);
+ }
+ )
+ .wrap(120)
+ .recommendCommands()
+ .epilogue(`For more information, see https://cloud.google.com/healthcare/docs`)
+ .help()
+ .strict()
+ .argv;
diff --git a/healthcare/dicom/dicomweb.js b/healthcare/dicom/dicomweb.js
new file mode 100644
index 0000000000..93cd4f471e
--- /dev/null
+++ b/healthcare/dicom/dicomweb.js
@@ -0,0 +1,243 @@
+/**
+ * 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 fs = require('fs');
+
+const BASE_URL = 'https://healthcare.googleapis.com/v1alpha';
+
+function 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(function (err, token) {
+ if (err) {
+ console.log('ERROR: ', err);
+ return;
+ }
+ cb(token);
+ });
+}
+
+// [START healthcare_dicomweb_store_instance]
+function dicomWebStoreInstance (token, projectId, cloudRegion, datasetId, dicomStoreId, dcmFile, boundary) {
+ // Token retrieved in callback
+ // getToken(serviceAccountJson, function(cb) {...});
+ // const cloudRegion = 'us-central1';
+ // const projectId = 'adjective-noun-123';
+ // const datasetId = 'my-dataset';
+ // const dicomStoreId = 'my-dicom-store';
+ // const dcmFile = 'IMG.dcm'
+ // const boundary = 'DICOMwebBoundary'
+ const parentName = `${BASE_URL}/projects/${projectId}/locations/${cloudRegion}`;
+
+ const dicomWebPath = `${parentName}/datasets/${datasetId}/dicomStores/${dicomStoreId}/dicomWeb/studies`;
+
+ const binaryData = fs.readFileSync(dcmFile);
+
+ const options = {
+ url: dicomWebPath,
+ headers: {
+ 'authorization': `Bearer ${token}`,
+ 'Content-Type': `multipart/related; type=application/dicom; boundary=${boundary}`
+ },
+ body: binaryData,
+ method: 'POST'
+ };
+
+ request(options)
+ .then(results => {
+ console.log('Stored instance:\n');
+ console.log(results);
+ })
+ .catch(err => {
+ console.error(err);
+ });
+}
+// [END healthcare_dicomweb_store_instance]
+
+// [START healthcare_dicomweb_search_instances]
+function dicomWebSearchInstances (token, projectId, cloudRegion, datasetId, dicomStoreId) {
+ // Token retrieved in callback
+ // getToken(serviceAccountJson, function(cb) {...});
+ // const cloudRegion = 'us-central1';
+ // const projectId = 'adjective-noun-123';
+ // const datasetId = 'my-dataset';
+ // const dicomStoreId = 'my-dicom-store';
+ const parentName = `${BASE_URL}/projects/${projectId}/locations/${cloudRegion}`;
+
+ const dicomWebPath = `${parentName}/datasets/${datasetId}/dicomStores/${dicomStoreId}/dicomWeb/instances`;
+
+ const options = {
+ url: dicomWebPath,
+ headers: {
+ 'authorization': `Bearer ${token}`,
+ 'Content-Type': 'application/dicom+json; charset=utf-8'
+ },
+ method: 'GET'
+ };
+
+ request(options)
+ .then(results => {
+ console.log('Instances:\n');
+ console.log(results);
+ })
+ .catch(err => {
+ console.error(err);
+ });
+}
+// [END healthcare_dicomweb_search_instances]
+
+// [START healthcare_dicomweb_retrieve_study]
+function dicomWebRetrieveStudy (token, projectId, cloudRegion, datasetId, dicomStoreId, studyUid) {
+ // Token retrieved in callback
+ // getToken(serviceAccountJson, function(cb) {...});
+ // const cloudRegion = 'us-central1';
+ // const projectId = 'adjective-noun-123';
+ // const datasetId = 'my-dataset';
+ // const dicomStoreId = 'my-dicom-store';
+ // const studyUid = '1.2.345.678901.2.345.6789.0123456.7890.1234567890.123'
+ const parentName = `${BASE_URL}/projects/${projectId}/locations/${cloudRegion}`;
+
+ const dicomWebPath = `${parentName}/datasets/${datasetId}/dicomStores/${dicomStoreId}/dicomWeb/studies/${studyUid}`;
+
+ const options = {
+ url: dicomWebPath,
+ headers: {
+ 'authorization': `Bearer ${token}`,
+ 'Content-Type': 'application/dicom+json; charset=utf-8'
+ },
+ method: 'GET'
+ };
+
+ request(options)
+ .then(results => {
+ console.log(`Retrieved study with UID: ${studyUid}`);
+ })
+ .catch(err => {
+ console.error(err);
+ });
+}
+// [END healthcare_dicomweb_retrieve_study]
+
+// [START healthcare_dicomweb_delete_study]
+function dicomWebDeleteStudy (token, projectId, cloudRegion, datasetId, dicomStoreId, studyUid) {
+ // Token retrieved in callback
+ // getToken(serviceAccountJson, function(cb) {...});
+ // const cloudRegion = 'us-central1';
+ // const projectId = 'adjective-noun-123';
+ // const datasetId = 'my-dataset';
+ // const dicomStoreId = 'my-dicom-store';
+ // const studyUid = '1.2.345.678901.2.345.6789.0123456.7890.1234567890.123'
+ const parentName = `${BASE_URL}/projects/${projectId}/locations/${cloudRegion}`;
+
+ const dicomWebPath = `${parentName}/datasets/${datasetId}/dicomStores/${dicomStoreId}/dicomWeb/studies/${studyUid}`;
+
+ const options = {
+ url: dicomWebPath,
+ headers: {
+ 'authorization': `Bearer ${token}`,
+ 'Content-Type': 'application/dicom+json; charset=utf-8'
+ },
+ method: 'DELETE'
+ };
+
+ request(options)
+ .then(results => {
+ console.log('Deleted study.');
+ })
+ .catch(err => {
+ console.error(err);
+ });
+}
+// [END healthcare_dicomweb_delete_study]
+
+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(
+ `dicomWebStoreInstance `,
+ `Handles the POST requests specified in the DICOMweb standard.`,
+ {},
+ (opts) => {
+ const cb = function (token) {
+ dicomWebStoreInstance(token, opts.projectId, opts.cloudRegion, opts.datasetId, opts.dicomStoreId, opts.dcmFile, opts.boundary);
+ };
+ getToken(opts.serviceAccount, cb);
+ }
+ )
+ .command(
+ `dicomWebSearchInstances `,
+ `Handles the GET requests specified in the DICOMweb standard.`,
+ {},
+ (opts) => {
+ const cb = function (token) {
+ dicomWebSearchInstances(token, opts.projectId, opts.cloudRegion, opts.datasetId, opts.dicomStoreId);
+ };
+ getToken(opts.serviceAccount, cb);
+ }
+ )
+ .command(
+ `dicomWebRetrieveStudy `,
+ `Handles the GET requests specified in the DICOMweb standard.`,
+ {},
+ (opts) => {
+ const cb = function (token) {
+ dicomWebRetrieveStudy(token, opts.projectId, opts.cloudRegion, opts.datasetId, opts.dicomStoreId, opts.studyUid);
+ };
+ getToken(opts.serviceAccount, cb);
+ }
+ )
+ .command(
+ `dicomWebDeleteStudy `,
+ `Handles DELETE requests.`,
+ {},
+ (opts) => {
+ const cb = function (token) {
+ dicomWebDeleteStudy(token, opts.projectId, opts.cloudRegion, opts.datasetId, opts.dicomStoreId, opts.studyUid);
+ };
+ 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/dicom/package.json b/healthcare/dicom/package.json
new file mode 100644
index 0000000000..605240d7a6
--- /dev/null
+++ b/healthcare/dicom/package.json
@@ -0,0 +1,38 @@
+{
+ "name": "nodejs-docs-samples-healthcare",
+ "version": "0.0.1",
+ "private": true,
+ "license": "Apache-2.0",
+ "author": "Google LLC",
+ "repository": "GoogleCloudPlatform/nodejs-docs-samples",
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "scripts": {
+ "test": "ava -T 1m --verbose system-test/*.test.js"
+ },
+ "devDependencies": {
+ "@google-cloud/nodejs-repo-tools": "^2.3.1",
+ "ava": "^0.25.0"
+ },
+ "dependencies": {
+ "googleapis": "^32.0.0",
+ "uuid": "^3.3.2",
+ "yargs": "^12.0.1",
+ "gtoken": "^2.3.0",
+ "request": "^2.87.0",
+ "request-promise": "^4.2.2"
+ },
+ "cloud-repo-tools": {
+ "requiresKeyFile": true,
+ "requiresProjectId": true,
+ "test": {
+ "build": {
+ "requiredEnvVars": [
+ "API_KEY",
+ "GCLOUD_PROJECT"
+ ]
+ }
+ }
+ }
+}
diff --git a/healthcare/dicom/resources/IM-0002-0001-JPEG-BASELINE-edited.dcm b/healthcare/dicom/resources/IM-0002-0001-JPEG-BASELINE-edited.dcm
new file mode 100644
index 0000000000..1ce38558fd
Binary files /dev/null and b/healthcare/dicom/resources/IM-0002-0001-JPEG-BASELINE-edited.dcm differ
diff --git a/healthcare/dicom/resources/IM-0002-0001-JPEG-BASELINE.dcm b/healthcare/dicom/resources/IM-0002-0001-JPEG-BASELINE.dcm
new file mode 100644
index 0000000000..3e0064f21b
Binary files /dev/null and b/healthcare/dicom/resources/IM-0002-0001-JPEG-BASELINE.dcm differ
diff --git a/healthcare/dicom/system-test/dicom_stores.test.js b/healthcare/dicom/system-test/dicom_stores.test.js
new file mode 100644
index 0000000000..4e4f4bafdb
--- /dev/null
+++ b/healthcare/dicom/system-test/dicom_stores.test.js
@@ -0,0 +1,89 @@
+/**
+ * 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.
+ */
+
+'use strict';
+
+const path = require(`path`);
+const test = require(`ava`);
+const tools = require(`@google-cloud/nodejs-repo-tools`);
+const uuid = require(`uuid`);
+
+const cmdDataset = `node datasets.js`;
+const cmd = `node dicom_stores.js`;
+const cwdDatasets = path.join(__dirname, `../../datasets`);
+const cwd = path.join(__dirname, `..`);
+const datasetId = `nodejs-docs-samples-test-${uuid.v4()}`.replace(/-/gi, '_');
+const dicomStoreId = `nodejs-docs-samples-test-dicom-store${uuid.v4()}`.replace(/-/gi, '_');
+const pubsubTopic = `nodejs-docs-samples-test-pubsub${uuid.v4()}`.replace(/-/gi, '_');
+
+const bucketName = process.env.GCLOUD_STORAGE_BUCKET;
+const dcmFileName = `IM-0002-0001-JPEG-BASELINE.dcm`;
+const contentUri = bucketName + '/' + dcmFileName;
+
+test.before(tools.checkCredentials);
+test.before(async () => {
+ return tools.runAsync(`${cmdDataset} createDataset ${datasetId}`, cwdDatasets)
+ .then((results) => {
+ console.log(results);
+ return results;
+ });
+});
+test.after.always(async () => {
+ try {
+ await tools.runAsync(`${cmdDataset} deleteDataset ${datasetId}`, cwdDatasets);
+ } catch (err) { } // Ignore error
+});
+
+test.serial(`should create a DICOM store`, async t => {
+ const output = await tools.runAsync(
+ `${cmd} createDicomStore ${datasetId} ${dicomStoreId}`, cwd);
+ t.regex(output, /Created DICOM store/);
+});
+
+test.serial(`should get a DICOM store`, async t => {
+ const output = await tools.runAsync(
+ `${cmd} getDicomStore ${datasetId} ${dicomStoreId}`, cwd);
+ t.regex(output, /Got DICOM store/);
+});
+
+test.serial(`should patch a DICOM store`, async t => {
+ const output = await tools.runAsync(
+ `${cmd} patchDicomStore ${datasetId} ${dicomStoreId} ${pubsubTopic}`, cwd);
+ t.regex(output, /Patched DICOM store with Cloud Pub\/Sub topic/);
+});
+
+test.serial(`should list DICOM stores`, async t => {
+ const output = await tools.runAsync(
+ `${cmd} listDicomStores ${datasetId}`, cwd);
+ t.regex(output, /DICOM stores/);
+});
+
+test.serial(`should export a DICOM instance`, async t => {
+ const output = await tools.runAsync(
+ `${cmd} exportDicomInstanceGcs ${datasetId} ${dicomStoreId} ${bucketName}`, cwd);
+ t.regex(output, /Exported DICOM instances to bucket/);
+});
+
+test.serial(`should import a DICOM object from GCS`, async t => {
+ const output = await tools.runAsync(
+ `${cmd} importDicomObject ${datasetId} ${dicomStoreId} ${contentUri}`, cwd);
+ t.regex(output, /Imported DICOM objects from bucket/);
+});
+
+test(`should delete a DICOM store`, async t => {
+ const output = await tools.runAsync(
+ `${cmd} deleteDicomStore ${datasetId} ${dicomStoreId}`, cwd);
+ t.regex(output, /Deleted DICOM store/);
+});
diff --git a/healthcare/dicom/system-test/dicomweb.test.js b/healthcare/dicom/system-test/dicomweb.test.js
new file mode 100644
index 0000000000..bd0f03187a
--- /dev/null
+++ b/healthcare/dicom/system-test/dicomweb.test.js
@@ -0,0 +1,77 @@
+/**
+ * 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.
+ */
+
+'use strict';
+
+const path = require(`path`);
+const test = require(`ava`);
+const tools = require(`@google-cloud/nodejs-repo-tools`);
+const uuid = require(`uuid`);
+
+const cmdDataset = `node datasets.js`;
+const cmdDicomStore = `node dicom_stores.js`;
+const cmd = `node dicomweb.js`;
+const cwdDatasets = path.join(__dirname, `../../datasets`);
+const cwd = path.join(__dirname, `..`);
+const datasetId = `nodejs-docs-samples-test-${uuid.v4()}`.replace(/-/gi, '_');
+const dicomStoreId = `nodejs-docs-samples-test-dicom-store${uuid.v4()}`.replace(/-/gi, '_');
+
+const dcmFile = `resources/IM-0002-0001-JPEG-BASELINE-edited.dcm`;
+const boundary = `DICOMwebBoundary`;
+// The studyUid is not assigned by the server and is part of the metadata
+// of dcmFile.
+const studyUid = `1.2.840.113619.2.176.3596.3364818.7819.1259708454.105`;
+
+test.before(tools.checkCredentials);
+test.before(async () => {
+ return tools.runAsync(`${cmdDataset} createDataset ${datasetId}`, cwdDatasets)
+ .then((results) => {
+ console.log(results);
+ return results;
+ });
+});
+test.after.always(async () => {
+ try {
+ await tools.runAsync(`${cmdDataset} deleteDataset ${datasetId}`, cwdDatasets);
+ } catch (err) { } // Ignore error
+});
+
+test.serial(`should store a DICOM instance`, async t => {
+ await tools.runAsync(`${cmdDicomStore} createDicomStore ${datasetId} ${dicomStoreId}`, cwd);
+ const output = await tools.runAsync(
+ `${cmd} dicomWebStoreInstance ${datasetId} ${dicomStoreId} ${dcmFile} ${boundary}`, cwd);
+ t.regex(output, /Stored instance/);
+});
+
+test.serial(`should search DICOM instances`, async t => {
+ const output = await tools.runAsync(
+ `${cmd} dicomWebSearchInstances ${datasetId} ${dicomStoreId}`, cwd);
+ t.regex(output, /Instances/);
+});
+
+test.serial(`should retrieve a DICOM study`, async t => {
+ const output = await tools.runAsync(
+ `${cmd} dicomWebRetrieveStudy ${datasetId} ${dicomStoreId} ${studyUid}`, cwd);
+ t.regex(output, /Retrieved study/);
+});
+
+test.serial(`should delete a DICOM study`, async t => {
+ const output = await tools.runAsync(
+ `${cmd} dicomWebDeleteStudy ${datasetId} ${dicomStoreId} ${studyUid}`, cwd);
+ t.regex(output, /Deleted study/);
+
+ // Clean up
+ await tools.runAsync(`${cmdDicomStore} deleteDicomStore ${datasetId} ${dicomStoreId}`, cwd);
+});