Skip to main content
Glama
conditionUtils.ts11.4 kB
import { Condition, CodeableConcept, OperationOutcome, Reference, Patient, Encounter, Period, Age, Practitioner, } from '@medplum/fhirtypes'; import { medplum, MedplumClient, ensureAuthenticated } from '../config/medplumClient'; /** * The clinical status of the condition. * From http://hl7.org/fhir/R4/valueset-condition-clinical.html */ export const ConditionClinicalStatusCodes = { ACTIVE: { system: 'http://terminology.hl7.org/CodeSystem/condition-clinical', code: 'active', display: 'Active', }, RECURRENCE: { system: 'http://terminology.hl7.org/CodeSystem/condition-clinical', code: 'recurrence', display: 'Recurrence', }, RELAPSE: { system: 'http://terminology.hl7.org/CodeSystem/condition-clinical', code: 'relapse', display: 'Relapse', }, INACTIVE: { system: 'http://terminology.hl7.org/CodeSystem/condition-clinical', code: 'inactive', display: 'Inactive', }, REMISSION: { system: 'http://terminology.hl7.org/CodeSystem/condition-clinical', code: 'remission', display: 'Remission', }, RESOLVED: { system: 'http://terminology.hl7.org/CodeSystem/condition-clinical', code: 'resolved', display: 'Resolved', }, } as const; /** * The verification status to support or refute the clinical status of the condition. * From http://hl7.org/fhir/R4/valueset-condition-ver-status.html */ export const ConditionVerificationStatusCodes = { UNCONFIRMED: { system: 'http://terminology.hl7.org/CodeSystem/condition-ver-status', code: 'unconfirmed', display: 'Unconfirmed', }, PROVISIONAL: { system: 'http://terminology.hl7.org/CodeSystem/condition-ver-status', code: 'provisional', display: 'Provisional', }, DIFFERENTIAL: { system: 'http://terminology.hl7.org/CodeSystem/condition-ver-status', code: 'differential', display: 'Differential', }, CONFIRMED: { system: 'http://terminology.hl7.org/CodeSystem/condition-ver-status', code: 'confirmed', display: 'Confirmed', }, REFUTED: { system: 'http://terminology.hl7.org/CodeSystem/condition-ver-status', code: 'refuted', display: 'Refuted', }, 'ENTERED-IN-ERROR': { system: 'http://terminology.hl7.org/CodeSystem/condition-ver-status', code: 'entered-in-error', display: 'Entered in Error', }, } as const; export interface CreateConditionArgs { subject: Reference<Patient>; code: CodeableConcept; clinicalStatus?: CodeableConcept; verificationStatus?: CodeableConcept; category?: CodeableConcept[]; encounter?: Reference<Encounter>; onsetDateTime?: string; onsetAge?: Age; onsetPeriod?: Period; onsetString?: string; recordedDate?: string; // ISO 8601 date string asserter?: Reference<Patient | Practitioner>; } export interface UpdateConditionArgs { id: string; clinicalStatus?: CodeableConcept; verificationStatus?: CodeableConcept; code?: CodeableConcept; onsetDateTime?: string | null; // null to remove onsetString?: string | null; recordedDate?: string | null; } export interface ConditionSearchArgs { subject?: string; // Patient ID patient?: string; // Patient ID (alternative to subject) category?: string; // e.g., 'encounter-diagnosis' 'clinical-status'?: string; // e.g., 'active' code?: string; // e.g., 'http://snomed.info/sct|44054006' 'asserter.identifier'?: string; } /** * Creates a new Condition resource. * @param args The arguments for creating the condition. * @returns The created Condition resource or an OperationOutcome in case of an error. */ export async function createCondition( args: CreateConditionArgs, client?: MedplumClient, ): Promise<Condition | OperationOutcome> { const medplumClient = client || medplum; await ensureAuthenticated(); try { if (!args.subject || !args.subject.reference) { throw new Error('Patient subject reference is required.'); } if (!args.code || !args.code.coding || args.code.coding.length === 0) { throw new Error('Condition code with at least one coding is required.'); } const conditionResource: Condition = { resourceType: 'Condition', subject: args.subject, code: args.code, clinicalStatus: args.clinicalStatus || { coding: [ConditionClinicalStatusCodes.ACTIVE] }, verificationStatus: args.verificationStatus || { coding: [ConditionVerificationStatusCodes.CONFIRMED] }, category: args.category, encounter: args.encounter, onsetDateTime: args.onsetDateTime, onsetAge: args.onsetAge, onsetPeriod: args.onsetPeriod, onsetString: args.onsetString, recordedDate: args.recordedDate, asserter: args.asserter, }; // Remove undefined fields to create a clean resource object Object.keys(conditionResource).forEach( (key) => (conditionResource as any)[key] === undefined && delete (conditionResource as any)[key], ); const createdCondition = (await medplumClient.createResource( conditionResource, )) as Condition; console.log('Condition created successfully:', createdCondition.id); return createdCondition; } catch (error: any) { console.error('Error creating Condition:', error); const outcome: OperationOutcome = { resourceType: 'OperationOutcome', issue: [ { severity: 'error', code: 'exception', diagnostics: `Error creating Condition: ${error.message || 'Unknown error'}`, }, ], }; if (error.outcome) { console.error('Server OperationOutcome:', JSON.stringify(error.outcome, null, 2)); return error.outcome as OperationOutcome; } return outcome; } } /** * Retrieves a Condition resource by its ID. * @param conditionId The ID of the Condition to retrieve. * @returns The Condition resource or null if not found, or an OperationOutcome on error. */ export async function getConditionById( conditionId: string, client?: MedplumClient, ): Promise<Condition | null | OperationOutcome> { const medplumClient = client || medplum; await ensureAuthenticated(); try { if (!conditionId) { throw new Error('Condition ID is required.'); } const condition = (await medplumClient.readResource( 'Condition', conditionId, )) as Condition | null; if (condition) { console.log('Condition retrieved:', condition.id); } return condition; } catch (error: any) { if (error.outcome && error.outcome.issue && error.outcome.issue[0]?.code === 'not-found') { console.log(`Condition with ID "${conditionId}" not found.`); return null; } console.error(`Error retrieving Condition with ID "${conditionId}":`, error); const outcome: OperationOutcome = { resourceType: 'OperationOutcome', issue: [ { severity: 'error', code: 'exception', diagnostics: `Error retrieving Condition: ${error.message || 'Unknown error'}`, }, ], }; if (error.outcome) { console.error('Server OperationOutcome:', JSON.stringify(error.outcome, null, 2)); return error.outcome as OperationOutcome; } return outcome; } } /** * Updates an existing Condition resource. * @param args The arguments for updating the condition. * @returns The updated Condition resource or an OperationOutcome on error. */ export async function updateCondition( args: UpdateConditionArgs, client?: MedplumClient, ): Promise<Condition | OperationOutcome> { const medplumClient = client || medplum; await ensureAuthenticated(); try { const { id, ...updates } = args; if (!id) { throw new Error('Condition ID is required for update.'); } if (Object.keys(updates).length === 0) { throw new Error('No updates provided for Condition.'); } const existingCondition = (await medplumClient.readResource( 'Condition', id, )) as Condition; const updatedResource: Condition = { ...existingCondition, ...(updates as any) }; // Handle null values for removal if (updates.onsetDateTime === null) delete updatedResource.onsetDateTime; if (updates.onsetString === null) delete updatedResource.onsetString; if (updates.recordedDate === null) delete updatedResource.recordedDate; const result = (await medplumClient.updateResource(updatedResource)) as Condition; console.log('Condition updated successfully:', result.id); return result; } catch (error: any) { console.error('Error updating Condition:', error); const outcome: OperationOutcome = { resourceType: 'OperationOutcome', issue: [ { severity: 'error', code: 'exception', diagnostics: `Error updating Condition: ${error.message || 'Unknown error'}`, }, ], }; if (error.outcome) { console.error('Server OperationOutcome:', JSON.stringify(error.outcome, null, 2)); return error.outcome as OperationOutcome; } return outcome; } } /** * Searches for Condition resources based on specified criteria. * @param args The search criteria. * @returns An array of Condition resources matching the criteria or an OperationOutcome on error. */ export async function searchConditions( args: ConditionSearchArgs, client?: MedplumClient, ): Promise<Condition[] | OperationOutcome> { const medplumClient = client || medplum; await ensureAuthenticated(); try { const searchCriteria: string[] = []; const patientId = args.subject || args.patient; if (patientId) { // Medplum search needs the full reference, but the arg might just be an ID searchCriteria.push(`subject=${patientId.startsWith('Patient/') ? patientId : `Patient/${patientId}`}`); } if (args.category) { searchCriteria.push(`category=${args.category}`); } if (args['clinical-status']) { searchCriteria.push(`clinical-status=${args['clinical-status']}`); } if (args.code) { searchCriteria.push(`code=${args.code}`); } if(args['asserter.identifier']){ searchCriteria.push(`asserter.identifier=${args['asserter.identifier']}`); } if (searchCriteria.length === 0) { return { resourceType: 'OperationOutcome', issue: [ { severity: 'error', code: 'invalid', diagnostics: 'At least one search criterion (subject, patient, category, clinical-status, or code) must be provided.', }, ], }; } const query = searchCriteria.join('&'); console.log('Searching conditions with query:', query); const searchResult = await medplumClient.searchResources('Condition', query); const conditions = searchResult as Condition[]; console.log(`Found ${conditions.length} conditions.`); return conditions; } catch (error: any) { console.error('Error searching Conditions:', error); const outcome: OperationOutcome = { resourceType: 'OperationOutcome', issue: [ { severity: 'error', code: 'exception', diagnostics: `Error searching Conditions: ${error.message || 'Unknown error'}`, }, ], }; if (error.outcome) { console.error('Server OperationOutcome:', JSON.stringify(error.outcome, null, 2)); return error.outcome as OperationOutcome; } return outcome; } }

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rkirkendall/medplum-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server