From 704cf70ab64afb22349c5b5c967569cec29865ad Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Tue, 15 Oct 2024 21:03:31 -0400 Subject: [PATCH 1/9] docker env vars --- .env | 7 +++ Dockerfile | 17 +++++- Dockerfile.dev | 22 ++++++- README.md | 3 +- dockerRunnerDev.sh | 57 ++++++++++++++----- dockerRunnerProd.sh | 12 ++++ frontend/config.json | 6 -- frontend/package.json | 1 + frontend/src/App.tsx | 2 +- .../src/views/DataViews/CaseCollection.tsx | 4 +- frontend/src/views/DataViews/Medications.tsx | 2 +- .../src/views/DataViews/MetRequirements.tsx | 6 +- frontend/src/views/Login.tsx | 5 +- frontend/vite.config.ts | 16 +++++- src/fhir/utilities.ts | 19 ++++--- 15 files changed, 131 insertions(+), 48 deletions(-) create mode 100755 dockerRunnerProd.sh delete mode 100644 frontend/config.json diff --git a/.env b/.env index 36730982..fe09fe6d 100644 --- a/.env +++ b/.env @@ -11,3 +11,10 @@ USE_HTTPS = false VSAC_API_KEY = changeMe WHITELIST = http://localhost, http://localhost:3005 SERVER_NAME = CodeX REMS Administrator Prototype + +#Frontend Vars +FRONTEND_PORT=9090 +VITE_REALM = ClientFhirServer +VITE_AUTH = http://localhost:8180 +VITE_CLIENT = app-login +VITE_SCOPE_ID = rems-admin \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 594e2cfd..f3e91c9d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,10 +4,21 @@ WORKDIR /rems-admin ARG PORT=8090 ENV PORT=${PORT} +ARG FRONTEND_PORT=9090 +ENV FRONTEND_PORT=${FRONTEND_PORT} + COPY --chown=node:node . . RUN npm install -EXPOSE 8090 -HEALTHCHECK --interval=30s --start-period=15s --timeout=10m --retries=10 CMD wget --no-verbose --tries=1 --spider http://localhost:${PORT} || exit 1 +WORKDIR /rems-admin/frontend +RUN npm install + +WORKDIR /rems-admin + +EXPOSE 8090 EXPOSE 8095 -CMD npm run start \ No newline at end of file +EXPOSE 9090 +EXPOSE 9095 + +HEALTHCHECK --interval=30s --start-period=15s --timeout=10m --retries=10 CMD (wget --no-verbose --tries=1 --spider http://localhost:${PORT} && wget --no-verbose --tries=1 --spider http://localhost:${FRONTEND_PORT}) || exit 1 +CMD ./dockerRunnerProd.sh \ No newline at end of file diff --git a/Dockerfile.dev b/Dockerfile.dev index 051e83bf..92b722c8 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -4,13 +4,31 @@ WORKDIR /rems-admin ARG PORT=8090 ENV PORT=${PORT} +ARG FRONTEND_PORT=9090 +ENV FRONTEND_PORT=${FRONTEND_PORT} + COPY --chown=node:node . . RUN npm install + +WORKDIR /rems-admin/frontend +RUN npm install + +WORKDIR /rems-admin + + EXPOSE 8090 EXPOSE 8091 -HEALTHCHECK --interval=30s --start-period=15s --timeout=10m --retries=10 CMD wget --no-verbose --tries=1 --spider http://localhost:${PORT} || exit 1 - EXPOSE 8095 EXPOSE 8096 + +EXPOSE 9090 +EXPOSE 9091 + +EXPOSE 9095 +EXPOSE 9096 + +HEALTHCHECK --interval=30s --start-period=15s --timeout=10m --retries=10 CMD (wget --no-verbose --tries=1 --spider http://localhost:${PORT} && wget --no-verbose --tries=1 --spider http://localhost:${FRONTEND_PORT}) || exit 1 + + CMD ./dockerRunnerDev.sh \ No newline at end of file diff --git a/README.md b/README.md index c68f5484..1d8cc90f 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Next, start the frontend with the following: ### `npm start` -Go to the UI running on http://localhost:5173/ (or whichever port it was run on) +Go to the UI running on http://localhost:9090/ (or whichever port it was run on) Still need to update docker to start the UI automatically. @@ -117,3 +117,4 @@ Following are a list of modifiable paths: | VSAC_API_KEY | `changeMe` | Replace with VSAC API key for pulling down ValueSets. Request an API Key from the [VSAC website](https://vsac.nlm.nih.gov/) | | WHITELIST | `http://localhost, http://localhost:3005` | List of valid URLs for CORS. Should include any URLs the server accesses for resources. | | SERVER_NAME | `CodeX REMS Administrator Prototype` | Name of the server that is returned in the card source. | +| FRONTEND_PORT | `9080` | Port that the frontend server should run on, change if there are conflicts with port usage. | \ No newline at end of file diff --git a/dockerRunnerDev.sh b/dockerRunnerDev.sh index c59845c0..7395bf61 100755 --- a/dockerRunnerDev.sh +++ b/dockerRunnerDev.sh @@ -1,44 +1,71 @@ #!/bin/sh # Handle closing application on signal interrupt (ctrl + c) -trap 'kill $CONTINUOUS_INSTALL_PID $SERVER_PID; gradle --stop; exit' INT +trap 'kill $CONTINUOUS_INSTALL_PID $SERVER_PID $BACKEND_SERVER_PID; exit' INT mkdir logs +touch ./logs/frontend_installer.log +touch ./logs/frontend_runner.log +touch ./logs/backend_installer.log +touch ./logs/backend_runner.log + # Reset log file content for new application boot -echo "*** Logs for continuous installer ***" > ./logs/installer.log -echo "*** Logs for 'npm run start' ***" > ./logs/runner.log +echo "*** Logs for continuous frontend installer ***" > ./logs/frontend_installer.log +echo "*** Logs for frontend 'npm run start' ***" > ./logs/frontend_runner.log + +echo "*** Logs for continuous backend installer ***" > ./logs/backend_installer.log +echo "*** Logs for backend 'npm run start' ***" > ./logs/backend_runner.log # Print that the application is starting in watch mode echo "starting application in watch mode..." # Start the continious build listener process -echo "starting continuous installer..." -npm install +echo "starting continuous installers..." + +cd frontend +npm install | tee ./logs/frontend_installer.log +cd .. +npm install | tee ./logs/backend_installer.log -( package_modify_time=$(stat -c %Y package.json) -package_lock_modify_time=$(stat -c %Y package-lock.json) +( package_modify_time=$(stat -c %Y frontend/package.json) +package_lock_modify_time=$(stat -c %Y frontend/package-lock.json) +backend_modify_time=$(stat -c %Y package.json) +backend_lock_modify_time=$(stat -c %Y package-lock.json) while sleep 1 do - new_package_modify_time=$(stat -c %Y package.json) - new_package_lock_modify_time=$(stat -c %Y package-lock.json) + new_package_modify_time=$(stat -c %Y frontend/package.json) + new_package_lock_modify_time=$(stat -c %Y frontend/package-lock.json) + new_backend_modify_time=$(stat -c %Y package.json) + new_backend_lock_modify_time=$(stat -c %Y package-lock.json) - if [[ "$package_modify_time" != "$new_package_modify_time" ]] || [[ "$package_lock_modify_time" != "$new_package_lock_modify_time" ]] + if [[ "$package_modify_time" != "$new_package_modify_time" ]] || [[ "$package_lock_modify_time" != "$new_package_lock_modify_time" ]] || [[ "$backend_lock_modify_time" != "$new_backend_lock_modify_time" ]]|| [[ "$backend_modify_time" != "$new_backend_modify_time" ]] then - echo "running npm install..." - npm install | tee ./logs/installer.log + echo "running frontent npm install..." + cd frontend + npm install | tee ./logs/frontend_installer.log + cd .. + elif [[ "$backend_lock_modify_time" != "$new_backend_lock_modify_time" ]]|| [[ "$backend_modify_time" != "$new_backend_modify_time" ]] + then + echo "running backend npm install..." + npm install | tee ./logs/backend_installer.log fi package_modify_time=$new_package_modify_time package_lock_modify_time=$new_package_lock_modify_time + backend_modify_time=$new_backend_modify_time + backend_lock_modify_time=$new_backend_lock_modify_time done ) & CONTINUOUS_INSTALL_PID=$! # Start server process once initial build finishes -( npm run start | tee ./logs/runner.log ) & SERVER_PID=$! +cd frontend +( npm run start | tee ./logs/frontend_runner.log ) & SERVER_PID=$! + +cd .. +( npm run start | tee ./logs/backend_runner.log ) & BACKEND_SERVER_PID=$! # Handle application background process exiting -wait $CONTINUOUS_INSTALL_PID $SERVER_PID +wait $CONTINUOUS_INSTALL_PID $SERVER_PID $BACKEND_SERVER_PID EXIT_CODE=$? echo "application exited with exit code $EXIT_CODE..." - diff --git a/dockerRunnerProd.sh b/dockerRunnerProd.sh new file mode 100755 index 00000000..bb91319d --- /dev/null +++ b/dockerRunnerProd.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +cd frontend +( npm run start ) & SERVER_PID=$! + +cd .. +( npm run start ) & BACKEND_SERVER_PID=$! + +# Handle application background process exiting +wait $SERVER_PID $BACKEND_SERVER_PID +EXIT_CODE=$? +echo "application exited with exit code $EXIT_CODE..." \ No newline at end of file diff --git a/frontend/config.json b/frontend/config.json deleted file mode 100644 index 2f2a382b..00000000 --- a/frontend/config.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "realm": "ClientFhirServer", - "client": "app-login", - "auth": "http://localhost:8180/", - "scopeId": "pims" -} diff --git a/frontend/package.json b/frontend/package.json index 7f694417..b5b2e347 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -15,6 +15,7 @@ "@mui/icons-material": "^6.1.0", "@mui/material": "^6.1.0", "axios": "^1.7.7", + "dotenv": "^16.4.5", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^6.26.2" diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 895151df..2d8b36bb 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -29,7 +29,7 @@ function App() { const resetDB = async () => { setOpen(false); await axios - .post('http://localhost:8090/etasu/reset') + .post(process.env.RESOURCE_SERVER + '/etasu/reset') .then(function (response: any) { console.log(response); setForceRefresh(true); diff --git a/frontend/src/views/DataViews/CaseCollection.tsx b/frontend/src/views/DataViews/CaseCollection.tsx index 96bdd422..2e2339d5 100644 --- a/frontend/src/views/DataViews/CaseCollection.tsx +++ b/frontend/src/views/DataViews/CaseCollection.tsx @@ -56,7 +56,7 @@ const CaseCollection = (props: { refresh: boolean }) => { }, []); const getAllRemsCase = async () => { - const url = 'http://localhost:8090/api/all/remscase'; + const url = process.env.RESOURCE_SERVER + '/api/all/remscase'; await axios .get(url) .then(function (response: { data: SetStateAction }) { @@ -70,7 +70,7 @@ const CaseCollection = (props: { refresh: boolean }) => { }; const deleteSingleRow = async (event: any, row: RemsCase) => { - const url = 'http://localhost:8090/api/remsCase/deleteOne'; + const url = process.env.RESOURCE_SERVER + '/api/remsCase/deleteOne'; await axios .post(url, { data: { params: row } }) .then(function (response: { data: any; status: number }) { diff --git a/frontend/src/views/DataViews/Medications.tsx b/frontend/src/views/DataViews/Medications.tsx index 373a734c..aa37011b 100644 --- a/frontend/src/views/DataViews/Medications.tsx +++ b/frontend/src/views/DataViews/Medications.tsx @@ -46,7 +46,7 @@ const Medications = (props: { refresh: boolean }) => { }, []); const getAllMedications = async () => { - const url = 'http://localhost:8090/api/all/medications'; + const url = process.env.RESOURCE_SERVER + '/api/all/medications'; await axios .get(url) .then(function (response: { data: SetStateAction }) { diff --git a/frontend/src/views/DataViews/MetRequirements.tsx b/frontend/src/views/DataViews/MetRequirements.tsx index 98e2d5fa..d544fcfc 100644 --- a/frontend/src/views/DataViews/MetRequirements.tsx +++ b/frontend/src/views/DataViews/MetRequirements.tsx @@ -44,7 +44,7 @@ const MetRequirements = (props: { refresh: boolean }) => { }, []); const getAllMetReqs = async () => { - const url = 'http://localhost:8090/api/all/metreqs'; + const url = process.env.RESOURCE_SERVER + '/api/all/metreqs'; await axios .get(url) .then(function (response: { data: any }) { @@ -58,7 +58,7 @@ const MetRequirements = (props: { refresh: boolean }) => { }; const deleteSingleRow = async (event: any, row: MetRequirements) => { - const url = 'http://localhost:8090/api/metreqs/deleteOne'; + const url = process.env.RESOURCE_SERVER + '/api/metreqs/deleteOne'; await axios .post(url, { data: { params: row } }) .then(function (response: { data: any; status: number }) { @@ -73,7 +73,7 @@ const MetRequirements = (props: { refresh: boolean }) => { }; const formattedQuestionnaire = (row: MetRequirements) => { - return row?.completedQuestionnaire?.questionnaire.split('http://localhost:8090/4_0_0/')[1]; + return row?.completedQuestionnaire?.questionnaire.split(process.env.RESOURCE_SERVER + '/4_0_0/')[1]; }; const formattedCompleted = (row: MetRequirements) => { return row?.completed === true ? 'Yes' : 'No'; diff --git a/frontend/src/views/Login.tsx b/frontend/src/views/Login.tsx index 15b7df6f..66a114f3 100644 --- a/frontend/src/views/Login.tsx +++ b/frontend/src/views/Login.tsx @@ -2,7 +2,6 @@ import { SetStateAction, useState } from 'react'; import axios from 'axios'; import { Avatar, Box, Button, Container, CssBaseline, TextField, Typography } from '@mui/material'; import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; -import config from '../../config.json'; const Login = props => { const [showMessage, setShowMessage] = useState(false); @@ -20,9 +19,9 @@ const Login = props => { params.append('username', user); params.append('password', pass); params.append('grant_type', 'password'); - params.append('client_id', config.client); + params.append('client_id', process.env.VITE_CLIENT!); axios - .post(`${config.auth}/realms/${config.realm}/protocol/openid-connect/token`, params, { + .post(`${process.env.VITE_AUTH}/realms/${process.env.VITE_REALM}/protocol/openid-connect/token`, params, { withCredentials: true }) .then( diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 65491824..d5d116bc 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -1,7 +1,19 @@ import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; -// https://vitejs.dev/config/ +import dotenv from 'dotenv'; + +dotenv.config({path : '../.env'}); // load env vars from .env export default defineConfig({ - plugins: [react()] + // depending on your application, base can also be "/" + base: '', + plugins: [react()], + define: { + 'process.env': process.env + }, + server: { + port: parseInt(process.env.FRONTEND_PORT!), + open: false, + host: true + } }); diff --git a/src/fhir/utilities.ts b/src/fhir/utilities.ts index 72d79676..fb08b49d 100644 --- a/src/fhir/utilities.ts +++ b/src/fhir/utilities.ts @@ -13,6 +13,7 @@ import ValueSetModel from '../lib/schemas/resources/ValueSet'; import { Model } from 'mongoose'; import { medicationCollection, metRequirementsCollection } from './models'; import { glob } from 'glob'; +import config from '../config' class ResourceExistsException extends Error {} @@ -135,7 +136,7 @@ export class FhirUtilities { resourceId: 'TuralioRemsPatientEnrollment', requiredToDispense: true, appContext: - 'questionnaire=http://localhost:8090/4_0_0/Questionnaire/TuralioRemsPatientEnrollment', + 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/TuralioRemsPatientEnrollment', questionnaire: null }, { @@ -146,7 +147,7 @@ export class FhirUtilities { resourceId: 'TuralioPrescriberEnrollmentForm', requiredToDispense: true, appContext: - 'questionnaire=http://localhost:8090/4_0_0/Questionnaire/TuralioPrescriberEnrollmentForm', + 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/TuralioPrescriberEnrollmentForm', questionnaire: null }, { @@ -157,7 +158,7 @@ export class FhirUtilities { resourceId: 'TuralioPrescriberKnowledgeAssessment', requiredToDispense: true, appContext: - 'questionnaire=http://localhost:8090/4_0_0/Questionnaire/TuralioPrescriberKnowledgeAssessment', + 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/TuralioPrescriberKnowledgeAssessment', questionnaire: null }, { @@ -178,7 +179,7 @@ export class FhirUtilities { resourceId: 'TuralioRemsPatientStatus', requiredToDispense: false, appContext: - 'questionnaire=http://localhost:8090/4_0_0/Questionnaire/TuralioRemsPatientStatus', + 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/TuralioRemsPatientStatus', questionnaire: null } ] @@ -196,7 +197,7 @@ export class FhirUtilities { resourceId: 'TIRFRemsPatientEnrollment', requiredToDispense: true, appContext: - 'questionnaire=http://localhost:8090/4_0_0/Questionnaire/TIRFRemsPatientEnrollment', + 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/TIRFRemsPatientEnrollment', questionnaire: null }, { @@ -207,7 +208,7 @@ export class FhirUtilities { resourceId: 'TIRFPrescriberEnrollmentForm', requiredToDispense: true, appContext: - 'questionnaire=http://localhost:8090/4_0_0/Questionnaire/TIRFPrescriberEnrollmentForm', + 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/TIRFPrescriberEnrollmentForm', questionnaire: null }, { @@ -218,7 +219,7 @@ export class FhirUtilities { resourceId: 'TIRFPrescriberKnowledgeAssessment', requiredToDispense: true, appContext: - 'questionnaire=http://localhost:8090/4_0_0/Questionnaire/TIRFPrescriberKnowledgeAssessment', + 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/TIRFPrescriberKnowledgeAssessment', questionnaire: null }, { @@ -256,7 +257,7 @@ export class FhirUtilities { resourceId: 'IPledgeRemsPatientEnrollment', requiredToDispense: true, appContext: - 'questionnaire=http://localhost:8090/4_0_0/Questionnaire/IPledgeRemsPatientEnrollment', + 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/IPledgeRemsPatientEnrollment', questionnaire: null }, { @@ -267,7 +268,7 @@ export class FhirUtilities { resourceId: 'IPledgeRemsPrescriberEnrollmentForm', requiredToDispense: true, appContext: - 'questionnaire=http://localhost:8090/4_0_0/Questionnaire/IPledgeRemsPrescriberEnrollmentForm', + 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/IPledgeRemsPrescriberEnrollmentForm', questionnaire: null }, { From 0cae96f20ea004e92e8cf4535e7ffc7f54b07d6d Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Tue, 15 Oct 2024 21:08:55 -0400 Subject: [PATCH 2/9] linting --- frontend/vite.config.ts | 2 +- src/fhir/utilities.ts | 38 ++++++++++++++++++++++++++++---------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index d5d116bc..5aa4da60 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -3,7 +3,7 @@ import react from '@vitejs/plugin-react'; import dotenv from 'dotenv'; -dotenv.config({path : '../.env'}); // load env vars from .env +dotenv.config({ path: '../.env' }); // load env vars from .env export default defineConfig({ // depending on your application, base can also be "/" base: '', diff --git a/src/fhir/utilities.ts b/src/fhir/utilities.ts index fb08b49d..7c92f816 100644 --- a/src/fhir/utilities.ts +++ b/src/fhir/utilities.ts @@ -13,7 +13,7 @@ import ValueSetModel from '../lib/schemas/resources/ValueSet'; import { Model } from 'mongoose'; import { medicationCollection, metRequirementsCollection } from './models'; import { glob } from 'glob'; -import config from '../config' +import config from '../config'; class ResourceExistsException extends Error {} @@ -136,7 +136,9 @@ export class FhirUtilities { resourceId: 'TuralioRemsPatientEnrollment', requiredToDispense: true, appContext: - 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/TuralioRemsPatientEnrollment', + 'questionnaire=' + + config.fhirServerConfig.resourceServer + + '/4_0_0/Questionnaire/TuralioRemsPatientEnrollment', questionnaire: null }, { @@ -147,7 +149,9 @@ export class FhirUtilities { resourceId: 'TuralioPrescriberEnrollmentForm', requiredToDispense: true, appContext: - 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/TuralioPrescriberEnrollmentForm', + 'questionnaire=' + + config.fhirServerConfig.resourceServer + + '/4_0_0/Questionnaire/TuralioPrescriberEnrollmentForm', questionnaire: null }, { @@ -158,7 +162,9 @@ export class FhirUtilities { resourceId: 'TuralioPrescriberKnowledgeAssessment', requiredToDispense: true, appContext: - 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/TuralioPrescriberKnowledgeAssessment', + 'questionnaire=' + + config.fhirServerConfig.resourceServer + + '/4_0_0/Questionnaire/TuralioPrescriberKnowledgeAssessment', questionnaire: null }, { @@ -179,7 +185,9 @@ export class FhirUtilities { resourceId: 'TuralioRemsPatientStatus', requiredToDispense: false, appContext: - 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/TuralioRemsPatientStatus', + 'questionnaire=' + + config.fhirServerConfig.resourceServer + + '/4_0_0/Questionnaire/TuralioRemsPatientStatus', questionnaire: null } ] @@ -197,7 +205,9 @@ export class FhirUtilities { resourceId: 'TIRFRemsPatientEnrollment', requiredToDispense: true, appContext: - 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/TIRFRemsPatientEnrollment', + 'questionnaire=' + + config.fhirServerConfig.resourceServer + + '/4_0_0/Questionnaire/TIRFRemsPatientEnrollment', questionnaire: null }, { @@ -208,7 +218,9 @@ export class FhirUtilities { resourceId: 'TIRFPrescriberEnrollmentForm', requiredToDispense: true, appContext: - 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/TIRFPrescriberEnrollmentForm', + 'questionnaire=' + + config.fhirServerConfig.resourceServer + + '/4_0_0/Questionnaire/TIRFPrescriberEnrollmentForm', questionnaire: null }, { @@ -219,7 +231,9 @@ export class FhirUtilities { resourceId: 'TIRFPrescriberKnowledgeAssessment', requiredToDispense: true, appContext: - 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/TIRFPrescriberKnowledgeAssessment', + 'questionnaire=' + + config.fhirServerConfig.resourceServer + + '/4_0_0/Questionnaire/TIRFPrescriberKnowledgeAssessment', questionnaire: null }, { @@ -257,7 +271,9 @@ export class FhirUtilities { resourceId: 'IPledgeRemsPatientEnrollment', requiredToDispense: true, appContext: - 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/IPledgeRemsPatientEnrollment', + 'questionnaire=' + + config.fhirServerConfig.resourceServer + + '/4_0_0/Questionnaire/IPledgeRemsPatientEnrollment', questionnaire: null }, { @@ -268,7 +284,9 @@ export class FhirUtilities { resourceId: 'IPledgeRemsPrescriberEnrollmentForm', requiredToDispense: true, appContext: - 'questionnaire=' + config.fhirServerConfig.resourceServer + '/4_0_0/Questionnaire/IPledgeRemsPrescriberEnrollmentForm', + 'questionnaire=' + + config.fhirServerConfig.resourceServer + + '/4_0_0/Questionnaire/IPledgeRemsPrescriberEnrollmentForm', questionnaire: null }, { From 8d22a72ecc6cb134ab88d7b1e84573a6b6ae5814 Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Tue, 15 Oct 2024 21:13:53 -0400 Subject: [PATCH 3/9] update env path --- src/fhir/utilities.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/fhir/utilities.ts b/src/fhir/utilities.ts index 7c92f816..9cb98ae2 100644 --- a/src/fhir/utilities.ts +++ b/src/fhir/utilities.ts @@ -137,7 +137,7 @@ export class FhirUtilities { requiredToDispense: true, appContext: 'questionnaire=' + - config.fhirServerConfig.resourceServer + + config.fhirServerConfig.auth.resourceServer + '/4_0_0/Questionnaire/TuralioRemsPatientEnrollment', questionnaire: null }, @@ -150,7 +150,7 @@ export class FhirUtilities { requiredToDispense: true, appContext: 'questionnaire=' + - config.fhirServerConfig.resourceServer + + config.fhirServerConfig.auth.resourceServer + '/4_0_0/Questionnaire/TuralioPrescriberEnrollmentForm', questionnaire: null }, @@ -163,7 +163,7 @@ export class FhirUtilities { requiredToDispense: true, appContext: 'questionnaire=' + - config.fhirServerConfig.resourceServer + + config.fhirServerConfig.auth.resourceServer + '/4_0_0/Questionnaire/TuralioPrescriberKnowledgeAssessment', questionnaire: null }, @@ -186,7 +186,7 @@ export class FhirUtilities { requiredToDispense: false, appContext: 'questionnaire=' + - config.fhirServerConfig.resourceServer + + config.fhirServerConfig.auth.resourceServer + '/4_0_0/Questionnaire/TuralioRemsPatientStatus', questionnaire: null } @@ -206,7 +206,7 @@ export class FhirUtilities { requiredToDispense: true, appContext: 'questionnaire=' + - config.fhirServerConfig.resourceServer + + config.fhirServerConfig.auth.resourceServer + '/4_0_0/Questionnaire/TIRFRemsPatientEnrollment', questionnaire: null }, @@ -219,7 +219,7 @@ export class FhirUtilities { requiredToDispense: true, appContext: 'questionnaire=' + - config.fhirServerConfig.resourceServer + + config.fhirServerConfig.auth.resourceServer + '/4_0_0/Questionnaire/TIRFPrescriberEnrollmentForm', questionnaire: null }, @@ -232,7 +232,7 @@ export class FhirUtilities { requiredToDispense: true, appContext: 'questionnaire=' + - config.fhirServerConfig.resourceServer + + config.fhirServerConfig.auth.resourceServer + '/4_0_0/Questionnaire/TIRFPrescriberKnowledgeAssessment', questionnaire: null }, @@ -272,7 +272,7 @@ export class FhirUtilities { requiredToDispense: true, appContext: 'questionnaire=' + - config.fhirServerConfig.resourceServer + + config.fhirServerConfig.auth.resourceServer + '/4_0_0/Questionnaire/IPledgeRemsPatientEnrollment', questionnaire: null }, @@ -285,7 +285,7 @@ export class FhirUtilities { requiredToDispense: true, appContext: 'questionnaire=' + - config.fhirServerConfig.resourceServer + + config.fhirServerConfig.auth.resourceServer + '/4_0_0/Questionnaire/IPledgeRemsPrescriberEnrollmentForm', questionnaire: null }, From c1750605621e76446955997c64134470c5a94eaf Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Wed, 16 Oct 2024 12:22:17 -0400 Subject: [PATCH 4/9] increase healthcheck time out --- Dockerfile | 2 +- Dockerfile.dev | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index f3e91c9d..a50d5b21 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,5 +20,5 @@ EXPOSE 8095 EXPOSE 9090 EXPOSE 9095 -HEALTHCHECK --interval=30s --start-period=15s --timeout=10m --retries=10 CMD (wget --no-verbose --tries=1 --spider http://localhost:${PORT} && wget --no-verbose --tries=1 --spider http://localhost:${FRONTEND_PORT}) || exit 1 +HEALTHCHECK --interval=45s --start-period=60s --timeout=10m --retries=10 CMD (wget --no-verbose --tries=1 --spider http://localhost:${PORT} && wget --no-verbose --tries=1 --spider http://localhost:${FRONTEND_PORT}) || exit 1 CMD ./dockerRunnerProd.sh \ No newline at end of file diff --git a/Dockerfile.dev b/Dockerfile.dev index 92b722c8..8bbff684 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -28,7 +28,7 @@ EXPOSE 9091 EXPOSE 9095 EXPOSE 9096 -HEALTHCHECK --interval=30s --start-period=15s --timeout=10m --retries=10 CMD (wget --no-verbose --tries=1 --spider http://localhost:${PORT} && wget --no-verbose --tries=1 --spider http://localhost:${FRONTEND_PORT}) || exit 1 +HEALTHCHECK --interval=45s --start-period=60s --timeout=10m --retries=10 CMD (wget --no-verbose --tries=1 --spider http://localhost:${PORT} && wget --no-verbose --tries=1 --spider http://localhost:${FRONTEND_PORT}) || exit 1 CMD ./dockerRunnerDev.sh \ No newline at end of file From 44e536ae9ccfc26d14290924441ddbe0929724d8 Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Wed, 23 Oct 2024 10:18:04 -0400 Subject: [PATCH 5/9] fix questionnaire paths --- src/fhir/utilities.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/fhir/utilities.ts b/src/fhir/utilities.ts index 9cb98ae2..de0cde9e 100644 --- a/src/fhir/utilities.ts +++ b/src/fhir/utilities.ts @@ -138,7 +138,7 @@ export class FhirUtilities { appContext: 'questionnaire=' + config.fhirServerConfig.auth.resourceServer + - '/4_0_0/Questionnaire/TuralioRemsPatientEnrollment', + '4_0_0/Questionnaire/TuralioRemsPatientEnrollment', questionnaire: null }, { @@ -151,7 +151,7 @@ export class FhirUtilities { appContext: 'questionnaire=' + config.fhirServerConfig.auth.resourceServer + - '/4_0_0/Questionnaire/TuralioPrescriberEnrollmentForm', + '4_0_0/Questionnaire/TuralioPrescriberEnrollmentForm', questionnaire: null }, { @@ -164,7 +164,7 @@ export class FhirUtilities { appContext: 'questionnaire=' + config.fhirServerConfig.auth.resourceServer + - '/4_0_0/Questionnaire/TuralioPrescriberKnowledgeAssessment', + '4_0_0/Questionnaire/TuralioPrescriberKnowledgeAssessment', questionnaire: null }, { @@ -187,7 +187,7 @@ export class FhirUtilities { appContext: 'questionnaire=' + config.fhirServerConfig.auth.resourceServer + - '/4_0_0/Questionnaire/TuralioRemsPatientStatus', + '4_0_0/Questionnaire/TuralioRemsPatientStatus', questionnaire: null } ] @@ -207,7 +207,7 @@ export class FhirUtilities { appContext: 'questionnaire=' + config.fhirServerConfig.auth.resourceServer + - '/4_0_0/Questionnaire/TIRFRemsPatientEnrollment', + '4_0_0/Questionnaire/TIRFRemsPatientEnrollment', questionnaire: null }, { @@ -220,7 +220,7 @@ export class FhirUtilities { appContext: 'questionnaire=' + config.fhirServerConfig.auth.resourceServer + - '/4_0_0/Questionnaire/TIRFPrescriberEnrollmentForm', + '4_0_0/Questionnaire/TIRFPrescriberEnrollmentForm', questionnaire: null }, { @@ -233,7 +233,7 @@ export class FhirUtilities { appContext: 'questionnaire=' + config.fhirServerConfig.auth.resourceServer + - '/4_0_0/Questionnaire/TIRFPrescriberKnowledgeAssessment', + '4_0_0/Questionnaire/TIRFPrescriberKnowledgeAssessment', questionnaire: null }, { @@ -273,7 +273,7 @@ export class FhirUtilities { appContext: 'questionnaire=' + config.fhirServerConfig.auth.resourceServer + - '/4_0_0/Questionnaire/IPledgeRemsPatientEnrollment', + '4_0_0/Questionnaire/IPledgeRemsPatientEnrollment', questionnaire: null }, { @@ -286,7 +286,7 @@ export class FhirUtilities { appContext: 'questionnaire=' + config.fhirServerConfig.auth.resourceServer + - '/4_0_0/Questionnaire/IPledgeRemsPrescriberEnrollmentForm', + '4_0_0/Questionnaire/IPledgeRemsPrescriberEnrollmentForm', questionnaire: null }, { From fafdc74fc797aaae3f3aeece04d9c089e2c1ff9e Mon Sep 17 00:00:00 2001 From: Patrick LaRocque Date: Fri, 10 Jan 2025 00:22:49 -0500 Subject: [PATCH 6/9] Include only a reference to the order (MedicationRequest) if configured. --- .env | 3 ++- README.md | 1 + src/config.ts | 3 ++- src/hooks/hookResources.ts | 9 ++++++++- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.env b/.env index fe09fe6d..cfe77825 100644 --- a/.env +++ b/.env @@ -11,10 +11,11 @@ USE_HTTPS = false VSAC_API_KEY = changeMe WHITELIST = http://localhost, http://localhost:3005 SERVER_NAME = CodeX REMS Administrator Prototype +FULL_RESOURCE_IN_APP_CONTEXT = false #Frontend Vars FRONTEND_PORT=9090 VITE_REALM = ClientFhirServer VITE_AUTH = http://localhost:8180 VITE_CLIENT = app-login -VITE_SCOPE_ID = rems-admin \ No newline at end of file +VITE_SCOPE_ID = rems-admin diff --git a/README.md b/README.md index 1d8cc90f..84cdb6ba 100644 --- a/README.md +++ b/README.md @@ -117,4 +117,5 @@ Following are a list of modifiable paths: | VSAC_API_KEY | `changeMe` | Replace with VSAC API key for pulling down ValueSets. Request an API Key from the [VSAC website](https://vsac.nlm.nih.gov/) | | WHITELIST | `http://localhost, http://localhost:3005` | List of valid URLs for CORS. Should include any URLs the server accesses for resources. | | SERVER_NAME | `CodeX REMS Administrator Prototype` | Name of the server that is returned in the card source. | +| FULL_RESOURCE_IN_APP_CONTEXT | 'false' | If true, the entire order resource will be included in the appContext, otherwise only a reference will be. | | FRONTEND_PORT | `9080` | Port that the frontend server should run on, change if there are conflicts with port usage. | \ No newline at end of file diff --git a/src/config.ts b/src/config.ts index 69fa1a4f..58745c61 100644 --- a/src/config.ts +++ b/src/config.ts @@ -23,7 +23,8 @@ export default { }, general: { resourcePath: 'src/cds-library/CRD-DTR', - VsacApiKey: env.get('VSAC_API_KEY').required().asString() + VsacApiKey: env.get('VSAC_API_KEY').required().asString(), + fullResourceInAppContext: env.get('FULL_RESOURCE_IN_APP_CONTEXT').required().asBool() }, database: { selected: 'mongo', diff --git a/src/hooks/hookResources.ts b/src/hooks/hookResources.ts index 1dd98dbf..9e462ca9 100644 --- a/src/hooks/hookResources.ts +++ b/src/hooks/hookResources.ts @@ -297,11 +297,18 @@ export function createSmartLink( appContext: string | null, request: MedicationRequest | undefined ) { + var order; + if (config.general.fullResourceInAppContext) { + order = JSON.stringify(request); + } else { + order = request?.resourceType + '/' + request?.id; + } + const newLink: Link = { label: requirementName + ' Form', url: new URL(config.smart.endpoint), type: 'smart', - appContext: `${appContext}&order=${JSON.stringify(request)}&coverage=${ + appContext: `${appContext}&order=${order}&coverage=${ request?.insurance?.[0].reference }` }; From c38e684da2c67782706affc5909ad490a252402c Mon Sep 17 00:00:00 2001 From: Patrick LaRocque Date: Fri, 10 Jan 2025 09:56:01 -0500 Subject: [PATCH 7/9] fix lint and prettier errors --- src/hooks/hookResources.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/hooks/hookResources.ts b/src/hooks/hookResources.ts index 9e462ca9..39f69671 100644 --- a/src/hooks/hookResources.ts +++ b/src/hooks/hookResources.ts @@ -297,20 +297,18 @@ export function createSmartLink( appContext: string | null, request: MedicationRequest | undefined ) { - var order; + let order; if (config.general.fullResourceInAppContext) { order = JSON.stringify(request); } else { - order = request?.resourceType + '/' + request?.id; + order = request?.resourceType + '/' + request?.id; } const newLink: Link = { label: requirementName + ' Form', url: new URL(config.smart.endpoint), type: 'smart', - appContext: `${appContext}&order=${order}&coverage=${ - request?.insurance?.[0].reference - }` + appContext: `${appContext}&order=${order}&coverage=${request?.insurance?.[0].reference}` }; return newLink; } From d22395f0c37a4ab3200f5a0c818b131fe5d13c81 Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Mon, 13 Jan 2025 18:28:22 -0500 Subject: [PATCH 8/9] cors policy --- src/server.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/server.ts b/src/server.ts index bfb47ef6..ff5fd520 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,4 +1,4 @@ -import cors from 'cors'; +import cors, { CorsOptions } from 'cors'; import bodyParser from 'body-parser'; import container from './lib/winston'; import morgan from 'morgan'; @@ -18,10 +18,11 @@ import bodyParserXml from 'body-parser-xml'; const logger = container.get('application'); + const initialize = (config: any) => { //const logLevel = _.get(config, 'logging.level'); return new REMSServer(config.fhirServerConfig) - .configureMiddleware() + .configureMiddleware(config.fhirServerConfig.server.corsOptions) .configureSession() .configureHelmet() .configurePassport() @@ -60,15 +61,15 @@ class REMSServer extends Server { * @method configureMiddleware * @description Enable all the standard middleware */ - configureMiddleware() { + configureMiddleware(corsOptions: CorsOptions) { super.configureMiddleware(); this.app.set('showStackError', true); this.app.set('jsonp callback', true); this.app.use(bodyParser.urlencoded({ limit: '50mb', extended: true })); this.app.use(bodyParser.json({ limit: '50mb' })); - this.app.use(cors()); - this.app.options('*', cors()); + this.app.use(cors(corsOptions)); + this.app.options('*', cors(corsOptions)); return this; } From 2eeec4e4a2e98e207b1f1c2659720e09522b7ee5 Mon Sep 17 00:00:00 2001 From: Sahil Malhotra Date: Tue, 14 Jan 2025 11:15:00 -0500 Subject: [PATCH 9/9] fix questionaire path for connectathon --- src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index 58745c61..ad1680aa 100644 --- a/src/config.ts +++ b/src/config.ts @@ -41,7 +41,7 @@ export default { fhirServerConfig: { auth: { // This server's URI - resourceServer: env.get('RESOURCE_SERVER').required().asUrlString() + resourceServer: env.get('RESOURCE_SERVER').required().asUrlString() + '/' // // if you use this strategy, you need to add the corresponding env vars to docker-compose //