diff --git a/.eslintcache b/.eslintcache deleted file mode 100644 index b9f20cc..0000000 --- a/.eslintcache +++ /dev/null @@ -1 +0,0 @@ -[{"/u01/code/shared-health-record/src/lib/hl7MllpSender.ts":"1","/u01/code/shared-health-record/src/workflows/labWorkflowsBw.ts":"2","/u01/code/shared-health-record/src/workflows/__tests__/labWorkflowsBw.ts":"3"},{"size":1599,"mtime":1691536925750,"results":"4","hashOfConfig":"5"},{"size":30252,"mtime":1691536926174},{"size":3190,"mtime":1691537800246},{"filePath":"6","messages":"7","suppressedMessages":"8","errorCount":0,"fatalErrorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},"h0u5wi","/u01/code/shared-health-record/src/lib/hl7MllpSender.ts",["9","10","11"],[],{"ruleId":"12","severity":1,"message":"13","line":19,"column":40,"nodeType":"14","messageId":"15","endLine":19,"endColumn":43,"suggestions":"16"},{"ruleId":"12","severity":1,"message":"13","line":25,"column":75,"nodeType":"14","messageId":"15","endLine":25,"endColumn":78,"suggestions":"17"},{"ruleId":"12","severity":1,"message":"13","line":25,"column":89,"nodeType":"14","messageId":"15","endLine":25,"endColumn":92,"suggestions":"18"},"@typescript-eslint/no-explicit-any","Unexpected any. Specify a different type.","TSAnyKeyword","unexpectedAny",["19","20"],["21","22"],["23","24"],{"messageId":"25","fix":"26","desc":"27"},{"messageId":"28","fix":"29","desc":"30"},{"messageId":"25","fix":"31","desc":"27"},{"messageId":"28","fix":"32","desc":"30"},{"messageId":"25","fix":"33","desc":"27"},{"messageId":"28","fix":"34","desc":"30"},"suggestUnknown",{"range":"35","text":"36"},"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct.","suggestNever",{"range":"35","text":"37"},"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of.",{"range":"38","text":"36"},{"range":"38","text":"37"},{"range":"39","text":"36"},{"range":"39","text":"37"},[453,456],"unknown","never",[752,755],[766,769]] diff --git a/src/app.ts b/src/app.ts index c2249d3..87c3389 100644 --- a/src/app.ts +++ b/src/app.ts @@ -3,7 +3,6 @@ import logger from './lib/winston' import { run } from './server/kafkaWorkers' import MllpAdapter from './server/mllpAdapter' import { ShrMediator } from './server/shrMediator' -import { LabWorkflowsBw } from './workflows/labWorkflowsBw' if (require.main === module) { if (config.get('app:port')) { diff --git a/src/lib/kafkaConsumerUtil.ts b/src/lib/kafkaConsumerUtil.ts index 8ccbf99..b928b4e 100644 --- a/src/lib/kafkaConsumerUtil.ts +++ b/src/lib/kafkaConsumerUtil.ts @@ -1,4 +1,4 @@ -import { Kafka, Consumer, EachBatchPayload, Transaction, Message, KafkaConfig, EachMessagePayload } from 'kafkajs'; +import { Consumer, EachBatchPayload, Kafka, KafkaConfig, Message } from 'kafkajs'; import logger from './winston'; export type EachMessageCallback = (topic: string, partition: number, message: Message) => Promise; diff --git a/src/lib/kafkaProducerUtil.ts b/src/lib/kafkaProducerUtil.ts index 755c7fe..11d7ebb 100644 --- a/src/lib/kafkaProducerUtil.ts +++ b/src/lib/kafkaProducerUtil.ts @@ -1,5 +1,4 @@ -import { Kafka, KafkaConfig, Producer, ProducerConfig, ProducerRecord, Transaction } from 'kafkajs'; -import config from './config' +import { Kafka, KafkaConfig, Producer, ProducerRecord, Transaction } from 'kafkajs'; import logger from './winston'; type DeliveryReportCallback = (report: any) => void; diff --git a/src/lib/validate.ts b/src/lib/validate.ts new file mode 100644 index 0000000..d87b5f3 --- /dev/null +++ b/src/lib/validate.ts @@ -0,0 +1,163 @@ + +export enum FHIR_R4_RESOURCES { + Account = "Account", + ActivityDefinition = "ActivityDefinition", + AdverseEvent = "AdverseEvent", + AllergyIntolerance = "AllergyIntolerance", + Appointment = "Appointment", + AppointmentResponse = "AppointmentResponse", + AuditEvent = "AuditEvent", + Basic = "Basic", + Binary = "Binary", + BiologicallyDerivedProduct = "BiologicallyDerivedProduct", + BodyStructure = "BodyStructure", + Bundle = "Bundle", + CapabilityStatement = "CapabilityStatement", + CarePlan = "CarePlan", + CareTeam = "CareTeam", + CatalogEntry = "CatalogEntry", + ChargeItem = "ChargeItem", + ChargeItemDefinition = "ChargeItemDefinition", + Claim = "Claim", + ClaimResponse = "ClaimResponse", + ClinicalImpression = "ClinicalImpression", + CodeSystem = "CodeSystem", + Communication = "Communication", + CommunicationRequest = "CommunicationRequest", + CompartmentDefinition = "CompartmentDefinition", + Composition = "Composition", + ConceptMap = "ConceptMap", + Condition = "Condition", + Consent = "Consent", + Contract = "Contract", + Coverage = "Coverage", + CoverageEligibilityRequest = "CoverageEligibilityRequest", + CoverageEligibilityResponse = "CoverageEligibilityResponse", + DetectedIssue = "DetectedIssue", + Device = "Device", + DeviceDefinition = "DeviceDefinition", + DeviceMetric = "DeviceMetric", + DeviceRequest = "DeviceRequest", + DeviceUseStatement = "DeviceUseStatement", + DiagnosticReport = "DiagnosticReport", + DocumentManifest = "DocumentManifest", + DocumentReference = "DocumentReference", + DomainResource = "DomainResource", + EffectEvidenceSynthesis = "EffectEvidenceSynthesis", + Encounter = "Encounter", + Endpoint = "Endpoint", + EnrollmentRequest = "EnrollmentRequest", + EnrollmentResponse = "EnrollmentResponse", + EpisodeOfCare = "EpisodeOfCare", + EventDefinition = "EventDefinition", + Evidence = "Evidence", + EvidenceVariable = "EvidenceVariable", + ExampleScenario = "ExampleScenario", + ExplanationOfBenefit = "ExplanationOfBenefit", + FamilyMemberHistory = "FamilyMemberHistory", + Flag = "Flag", + Goal = "Goal", + GraphDefinition = "GraphDefinition", + Group = "Group", + GuidanceResponse = "GuidanceResponse", + HealthcareService = "HealthcareService", + ImagingStudy = "ImagingStudy", + Immunization = "Immunization", + ImmunizationEvaluation = "ImmunizationEvaluation", + ImmunizationRecommendation = "ImmunizationRecommendation", + ImplementationGuide = "ImplementationGuide", + InsurancePlan = "InsurancePlan", + Invoice = "Invoice", + Library = "Library", + Linkage = "Linkage", + List = "List", + Location = "Location", + Measure = "Measure", + MeasureReport = "MeasureReport", + Media = "Media", + Medication = "Medication", + MedicationAdministration = "MedicationAdministration", + MedicationDispense = "MedicationDispense", + MedicationKnowledge = "MedicationKnowledge", + MedicationRequest = "MedicationRequest", + MedicationStatement = "MedicationStatement", + MedicinalProduct = "MedicinalProduct", + MedicinalProductAuthorization = "MedicinalProductAuthorization", + MedicinalProductContraindication = "MedicinalProductContraindication", + MedicinalProductIndication = "MedicinalProductIndication", + MedicinalProductIngredient = "MedicinalProductIngredient", + MedicinalProductInteraction = "MedicinalProductInteraction", + MedicinalProductManufactured = "MedicinalProductManufactured", + MedicinalProductPackaged = "MedicinalProductPackaged", + MedicinalProductPharmaceutical = "MedicinalProductPharmaceutical", + MedicinalProductUndesirableEffect = "MedicinalProductUndesirableEffect", + MessageDefinition = "MessageDefinition", + MessageHeader = "MessageHeader", + MolecularSequence = "MolecularSequence", + NamingSystem = "NamingSystem", + NutritionOrder = "NutritionOrder", + Observation = "Observation", + ObservationDefinition = "ObservationDefinition", + OperationDefinition = "OperationDefinition", + OperationOutcome = "OperationOutcome", + Organization = "Organization", + OrganizationAffiliation = "OrganizationAffiliation", + Parameters = "Parameters", + Patient = "Patient", + PaymentNotice = "PaymentNotice", + PaymentReconciliation = "PaymentReconciliation", + Person = "Person", + PlanDefinition = "PlanDefinition", + Practitioner = "Practitioner", + PractitionerRole = "PractitionerRole", + Procedure = "Procedure", + Provenance = "Provenance", + Questionnaire = "Questionnaire", + QuestionnaireResponse = "QuestionnaireResponse", + RelatedPerson = "RelatedPerson", + RequestGroup = "RequestGroup", + ResearchDefinition = "ResearchDefinition", + ResearchElementDefinition = "ResearchElementDefinition", + ResearchStudy = "ResearchStudy", + ResearchSubject = "ResearchSubject", + Resource = "Resource", + RiskAssessment = "RiskAssessment", + RiskEvidenceSynthesis = "RiskEvidenceSynthesis", + Schedule = "Schedule", + SearchParameter = "SearchParameter", + ServiceRequest = "ServiceRequest", + Slot = "Slot", + Specimen = "Specimen", + SpecimenDefinition = "SpecimenDefinition", + StructureDefinition = "StructureDefinition", + StructureMap = "StructureMap", + Subscription = "Subscription", + Substance = "Substance", + SubstanceNucleicAcid = "SubstanceNucleicAcid", + SubstancePolymer = "SubstancePolymer", + SubstanceProtein = "SubstanceProtein", + SubstanceReferenceInformation = "SubstanceReferenceInformation", + SubstanceSourceMaterial = "SubstanceSourceMaterial", + SubstanceSpecification = "SubstanceSpecification", + SupplyDelivery = "SupplyDelivery", + SupplyRequest = "SupplyRequest", + Task = "Task", + TerminologyCapabilities = "TerminologyCapabilities", + TestReport = "TestReport", + TestScript = "TestScript", + ValueSet = "ValueSet", + VerificationResult = "VerificationResult", + VisionPrescription = "VisionPrescription" +} + +export function getResourceTypeEnum(resourceType: string): FHIR_R4_RESOURCES { + if(isValidResourceType(resourceType)) { + return resourceType + } else { + throw new Error(`Invalid resource type ${resourceType}`) + } +} + +export function isValidResourceType(resourceType: string): boolean { + return resourceType in FHIR_R4_RESOURCES +} \ No newline at end of file diff --git a/src/routes/fhir.ts b/src/routes/fhir.ts index 79c0e49..1cf6be6 100644 --- a/src/routes/fhir.ts +++ b/src/routes/fhir.ts @@ -6,6 +6,7 @@ import config from '../lib/config' import { invalidBundle, invalidBundleMessage } from '../lib/helpers' import logger from '../lib/winston' import { generateSimpleIpsBundle } from '../workflows/ipsWorkflows' +import { getResourceTypeEnum } from '../lib/validate' export const router = express.Router() @@ -85,7 +86,7 @@ router.post('/', async (req, res) => { const uri = URI(config.get("fhirServer:baseURL")); - let ret = await got.post(uri.toString(), { json: resource }) + const ret = await got.post(uri.toString(), { json: resource }) res.status(ret.statusCode).json(ret.body) @@ -114,11 +115,14 @@ async function saveResource(req: any, res: any) { resource.id = id } - logger.info('Received a request to add resource type ' + resourceType) + logger.info('Received a request to add resource type ' + resourceType + ' with id ' + id) - let ret = await got.post(config.get('fhirServer:baseURL') + '/' + resourceType, { json: resource }) + const ret = await got.post(config.get('fhirServer:baseURL') + '/' + getResourceTypeEnum(resourceType).toString, { json: resource }) res.status(ret.statusCode).json(ret.body) } + + + export default router diff --git a/src/server/kafkaWorkers.ts b/src/server/kafkaWorkers.ts index b638a5f..b842d10 100644 --- a/src/server/kafkaWorkers.ts +++ b/src/server/kafkaWorkers.ts @@ -1,4 +1,4 @@ -import { KafkaConfig, logLevel, Message } from 'kafkajs' +import { KafkaConfig, Message, logLevel } from 'kafkajs' import logger from '../lib/winston' import { LabWorkflowsBw, topicList } from '../workflows/labWorkflowsBw' import { config } from '../lib/config' diff --git a/src/server/shrMediator.ts b/src/server/shrMediator.ts index 8dbc6c5..b00fd34 100644 --- a/src/server/shrMediator.ts +++ b/src/server/shrMediator.ts @@ -4,7 +4,6 @@ import shrApp from '../lib/shr' import logger from '../lib/winston' import medUtils from 'openhim-mediator-utils' -import { error } from 'console' import { LabWorkflowsBw } from '../workflows/labWorkflowsBw'