diff --git a/apps/expo/app.config.ts b/apps/expo/app.config.ts index 2b4c1b8b..3b8f8951 100644 --- a/apps/expo/app.config.ts +++ b/apps/expo/app.config.ts @@ -4,7 +4,7 @@ const defineConfig = (): ExpoConfig => ({ name: "PatientX Starter", slug: "canvas-fhir", scheme: "expo", - version: "0.1.0", + version: "0.1.1", orientation: "portrait", icon: "./assets/icon.png", userInterfaceStyle: "light", @@ -20,7 +20,7 @@ const defineConfig = (): ExpoConfig => ({ ios: { bundleIdentifier: "com.trusttheprocess.patientx", supportsTablet: true, - buildNumber: "3", + buildNumber: "2", }, android: { package: "com.trusttheprocess.patientx", diff --git a/apps/expo/src/app/(main)/portal/(tabs)/index.tsx b/apps/expo/src/app/(main)/portal/(tabs)/index.tsx index 1f5cb0b0..c34f0e88 100644 --- a/apps/expo/src/app/(main)/portal/(tabs)/index.tsx +++ b/apps/expo/src/app/(main)/portal/(tabs)/index.tsx @@ -1,4 +1,4 @@ -import { Text, View } from "react-native"; +import { ScrollView, Text, View } from "react-native"; import { useAtom } from "jotai"; import { patientIdAtom, patientNameAtom } from "~/app/(main)"; @@ -33,29 +33,31 @@ export default function Home() { } return ( - - {/* Welcome message */} - - - Good to see you, {patientName.firstName || "User"} - - + + + {/* Welcome message */} + + + Good to see you, {patientName.firstName || "User"} + + - {/* Next appointment */} - - - Your next appointment - - - - {/* Submenu buttons */} - - - - {/* Tasks */} - - + {/* Next appointment */} + + + Your next appointment + + + + {/* Submenu buttons */} + + + + {/* Tasks */} + + + - + ); } diff --git a/apps/expo/src/components/next-appointment.tsx b/apps/expo/src/components/next-appointment.tsx index 5e916235..40bdf003 100644 --- a/apps/expo/src/components/next-appointment.tsx +++ b/apps/expo/src/components/next-appointment.tsx @@ -1,11 +1,20 @@ import React, { useMemo } from "react"; import { Text, TouchableOpacity, View } from "react-native"; +import { Calendar } from "react-native-calendars"; import { useRouter } from "expo-router"; import { useAtom } from "jotai"; import { patientIdAtom } from "~/app/(main)"; import { AppointmentCard } from "~/components/ui/cards/appointment-card"; import { LoaderComponent } from "~/components/ui/loader"; +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from "~/components/ui/rn-ui/components/ui/card"; import { api } from "~/utils/api"; import { mapPractitionerIdsToNames } from "~/utils/scheduling"; @@ -45,7 +54,7 @@ export default function NextAppointment() { }, [appointmentQuery.data?.entry]); if (isLoading) { - return ; + return ; } if (isError) { @@ -72,7 +81,13 @@ export default function NextAppointment() { practitionerInfo={practitionerInfo} /> ) : ( - {`No appointments found.`} + + + + You do not have any appointments scheduled at this time + + + )} ); diff --git a/apps/expo/src/components/tasks.tsx b/apps/expo/src/components/tasks.tsx index 0e6aca19..1ba9a453 100644 --- a/apps/expo/src/components/tasks.tsx +++ b/apps/expo/src/components/tasks.tsx @@ -67,7 +67,7 @@ export default function Tasks() { - + {item.resource.description} {item.resource.status !== "completed" && ( diff --git a/apps/expo/src/components/ui/home-svg.tsx b/apps/expo/src/components/ui/home-svg.tsx index 10c96c07..1e8b2f5b 100644 --- a/apps/expo/src/components/ui/home-svg.tsx +++ b/apps/expo/src/components/ui/home-svg.tsx @@ -1,53 +1,65 @@ import * as React from "react"; +import { Dimensions, View } from "react-native"; import type { SvgProps } from "react-native-svg"; import Svg, { Path } from "react-native-svg"; +const originalWidth = 692.68; +const originalHeight = 520.455; +const aspectRatio = originalWidth / originalHeight; + const SvgComponent = (props: SvgProps) => ( - - - - - - - - - - - - - + + + + + + + + + + + + + + + ); export default SvgComponent; diff --git a/package.json b/package.json index 769f1641..a9d049dd 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "create-t3-turbo", + "name": "patientx-fhir-starter", "private": true, "engines": { "node": ">=18.18.2" diff --git a/packages/api/src/canvas/canvas-client.ts b/packages/api/src/canvas/canvas-client.ts index c5f7b766..21dcd092 100644 --- a/packages/api/src/canvas/canvas-client.ts +++ b/packages/api/src/canvas/canvas-client.ts @@ -24,6 +24,10 @@ import { readConditionResponseSchema, searchConditionResponseSchema, } from "@acme/shared/src/validators/condition"; +import { + readConsentResponseSchema, + searchConsentResponseSchema, +} from "@acme/shared/src/validators/consent"; import { readCoverageResponseSchema, searchCoverageResponseSchema, @@ -65,6 +69,10 @@ import { searchObservationResponseSchema, } from "@acme/shared/src/validators/observation"; import { postOrPutResponseSchema } from "@acme/shared/src/validators/operation-outcome"; +import { + readPatientResponseSchema, + searchPatientResponseSchema, +} from "@acme/shared/src/validators/patient"; import { readPaymentNoticeResponseSchema, searchPaymentNoticeResponseSchema, @@ -1051,72 +1059,7 @@ export const get_SearchConsent = { period: z.string().optional(), }), }), - response: z.object({ - entry: z - .array( - z.object({ - resource: z - .object({ - category: z - .array( - z.object({ - coding: z - .array( - z.object({ - display: z.string().optional(), - system: z.string().optional(), - }), - ) - .optional(), - }), - ) - .optional(), - dateTime: z.string().optional(), - id: z.string().optional(), - patient: z - .object({ - reference: z.string().optional(), - }) - .optional(), - provision: z - .object({ - period: z - .object({ - end: z.string().optional(), - start: z.string().optional(), - }) - .optional(), - }) - .optional(), - resourceType: z.string().optional(), - scope: z - .object({ - coding: z - .array( - z.object({ - code: z.string().optional(), - system: z.string().optional(), - }), - ) - .optional(), - }) - .optional(), - sourceAttachment: z - .object({ - data: z.string().optional(), - url: z.string().optional(), - }) - .optional(), - status: z.string().optional(), - }) - .optional(), - }), - ) - .optional(), - resourceType: z.string().optional(), - total: z.number(), - type: z.string().optional(), - }), + response: searchConsentResponseSchema, }; export type post_CreateConsent = typeof post_CreateConsent; @@ -1179,66 +1122,7 @@ export const get_ReadConsent = { consent_id: z.string(), }), }), - response: z.object({ - category: z - .array( - z.object({ - coding: z - .array( - z.object({ - code: z.string().optional(), - display: z.string().optional(), - system: z.string().optional(), - }), - ) - .optional(), - }), - ) - .optional(), - dateTime: z.string().optional(), - id: z.string().optional(), - meta: z - .object({ - lastUpdated: z.string().optional(), - versionId: z.string().optional(), - }) - .optional(), - patient: z - .object({ - reference: z.string().optional(), - }) - .optional(), - provision: z - .object({ - period: z - .object({ - end: z.string().optional(), - start: z.string().optional(), - }) - .optional(), - }) - .optional(), - resourceType: z.string().optional(), - scope: z - .object({ - coding: z - .array( - z.object({ - code: z.string().optional(), - system: z.string().optional(), - }), - ) - .optional(), - }) - .optional(), - sourceAttachment: z - .object({ - data: z.string().optional(), - url: z.string().optional(), - }) - .optional(), - status: z.string().optional(), - }), + response: readConsentResponseSchema, }; export type get_SearchCoverage = typeof get_SearchCoverage; @@ -2159,176 +2043,7 @@ export const get_SearchPatient = { _sort: z.string().optional(), }), }), - response: z.object({ - entry: z - .array( - z.object({ - resource: z - .object({ - active: z.boolean().optional(), - address: z - .array( - z.object({ - city: z.string().optional(), - country: z.string().optional(), - id: z.string().optional(), - line: z.array(z.string()).optional(), - period: z - .object({ - start: z.string().optional(), - }) - .optional(), - postalCode: z.string().optional(), - state: z.string().optional(), - type: z.string().optional(), - use: z.string().optional(), - }), - ) - .optional(), - birthDate: z.string().optional(), - communication: z - .array( - z.object({ - language: z - .object({ - coding: z - .array( - z.object({ - code: z.string().optional(), - display: z.string().optional(), - system: z.string().optional(), - }), - ) - .optional(), - text: z.string().optional(), - }) - .optional(), - }), - ) - .optional(), - contact: z - .array( - z.object({ - extension: z - .array( - z.object({ - url: z.string().optional(), - valueBoolean: z.boolean().optional(), - }), - ) - .optional(), - id: z.string().optional(), - name: z - .object({ - text: z.string().optional(), - }) - .optional(), - relationship: z - .array( - z.object({ - text: z.string().optional(), - }), - ) - .optional(), - telecom: z - .array( - z.object({ - system: z.string().optional(), - value: z.string().optional(), - }), - ) - .optional(), - }), - ) - .optional(), - deceasedBoolean: z.boolean().optional(), - extension: z - .array( - z.object({ - extension: z - .array( - z.object({ - url: z.string().optional(), - valueString: z.string().optional(), - }), - ) - .optional(), - url: z.string().optional(), - valueCode: z.string().optional(), - valueString: z.string().optional(), - }), - ) - .optional(), - gender: z.string().optional(), - id: z.string().optional(), - identifier: z - .array( - z.object({ - assigner: z - .object({ - display: z.string().optional(), - }) - .optional(), - id: z.string().optional(), - period: z - .object({ - end: z.string().optional(), - start: z.string().optional(), - }) - .optional(), - system: z.string().optional(), - type: z - .object({ - coding: z - .array( - z.object({ - code: z.string().optional(), - system: z.string().optional(), - }), - ) - .optional(), - }) - .optional(), - use: z.string().optional(), - value: z.string().optional(), - }), - ) - .optional(), - name: z - .array( - z.object({ - family: z.string().optional(), - given: z.array(z.string()).optional(), - use: z.string().optional(), - }), - ) - .optional(), - resourceType: z.string().optional(), - telecom: z - .array( - z.object({ - id: z.string().optional(), - system: z.string().optional(), - use: z.string().optional(), - value: z.string().optional(), - }), - ) - .optional(), - text: z - .object({ - div: z.string().optional(), - status: z.string().optional(), - }) - .optional(), - }) - .optional(), - }), - ) - .optional(), - resourceType: z.string().optional(), - total: z.number().optional(), - type: z.string().optional(), - }), + response: searchPatientResponseSchema, }; export type post_CreatePatient = typeof post_CreatePatient; @@ -2472,176 +2187,7 @@ export const get_ReadPatient = { patient_id: z.string(), }), }), - response: z.object({ - active: z.boolean().optional(), - address: z - .array( - z.object({ - city: z.string().optional(), - country: z.string().optional(), - id: z.string().optional(), - line: z.array(z.string()).optional(), - period: z - .object({ - start: z.string().optional(), - }) - .optional(), - postalCode: z.string().optional(), - state: z.string().optional(), - type: z.string().optional(), - use: z.string().optional(), - }), - ) - .optional(), - birthDate: z.string().optional(), - communication: z - .array( - z.object({ - language: z - .object({ - coding: z - .array( - z.object({ - code: z.string().optional(), - display: z.string().optional(), - system: z.string().optional(), - }), - ) - .optional(), - text: z.string().optional(), - }) - .optional(), - }), - ) - .optional(), - contact: z - .array( - z.object({ - extension: z - .array( - z.object({ - url: z.string().optional(), - valueBoolean: z.boolean().optional(), - }), - ) - .optional(), - id: z.string().optional(), - name: z - .object({ - text: z.string().optional(), - }) - .optional(), - relationship: z - .array( - z.object({ - text: z.string().optional(), - }), - ) - .optional(), - telecom: z - .array( - z.object({ - system: z.string().optional(), - value: z.string().optional(), - }), - ) - .optional(), - }), - ) - .optional(), - deceasedBoolean: z.boolean().optional(), - extension: z - .array( - z.object({ - extension: z - .array( - z.object({ - url: z.string().optional(), - valueString: z.string().optional(), - }), - ) - .optional(), - url: z.string().optional(), - valueCode: z.string().optional(), - valueString: z.string().optional(), - }), - ) - .optional(), - gender: z.string().optional(), - id: z.string().optional(), - identifier: z - .array( - z.object({ - assigner: z - .object({ - display: z.string().optional(), - }) - .optional(), - id: z.string().optional(), - period: z - .object({ - end: z.string().optional(), - start: z.string().optional(), - }) - .optional(), - system: z.string().optional(), - type: z - .object({ - coding: z - .array( - z.object({ - code: z.string().optional(), - system: z.string().optional(), - }), - ) - .optional(), - }) - .optional(), - use: z.string().optional(), - value: z.string().optional(), - }), - ) - .optional(), - meta: z - .object({ - lastUpdated: z.string().optional(), - versionId: z.string().optional(), - }) - .optional(), - name: z - .array( - z.object({ - family: z.string().optional(), - given: z.array(z.string()).optional(), - use: z.string().optional(), - }), - ) - .optional(), - photo: z - .array( - z.object({ - url: z.string().optional(), - }), - ) - .optional(), - resourceType: z.string().optional(), - telecom: z - .array( - z.object({ - id: z.string().optional(), - system: z.string().optional(), - use: z.string().optional(), - value: z.string().optional(), - }), - ) - .optional(), - text: z - .object({ - div: z.string().optional(), - status: z.string().optional(), - }) - .optional(), - }), + response: readPatientResponseSchema, }; export type put_UpdatePatient = typeof put_UpdatePatient; diff --git a/packages/api/src/lib/utils.ts b/packages/api/src/lib/utils.ts index 47a47b72..686da263 100644 --- a/packages/api/src/lib/utils.ts +++ b/packages/api/src/lib/utils.ts @@ -1,34 +1,7 @@ import { TRPCError } from "@trpc/server"; import type { z } from "zod"; -import type { - OperationOutcome, - OperationOutcomeIssue, -} from "@acme/shared/src/validators/operation-outcome"; - -// TODO: Utility functions for response validation and error handling. Will have to refactor more before we can use them. - -function handleCanvasApiResponse( - responseSchema: Z, - data: Z, -): z.infer { - const parsedData = responseSchema.parse(data); - - if (parsedData?.resourceType === "OperationOutcome") { - const issues = parsedData.issue - .map( - (issue: OperationOutcomeIssue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } - - return parsedData; -} +import { operationOutcomeSchema } from "@acme/shared/src/validators/operation-outcome"; /** * Checks if the response data is an OperationOutcome and throws an error if it is. @@ -37,48 +10,14 @@ function handleCanvasApiResponse( * @returns - The validated data if not an OperationOutcome, with the correct TypeScript type. * @throws {TRPCError} - Throws an error if the data is an OperationOutcome or validation fails. */ -function handleOperationOutcomeError( - data: any, - schema: Z, -): z.infer { - // Validate the data against the provided schema - const result = schema.safeParse(data); - - if (!result.success) { - if (data?.resourceType === "OperationOutcome" && data.issue) { - const issues = data.issue - .map( - (issue) => `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } else { - // If not an OperationOutcome, throw a generic error - throw new TRPCError({ - code: "INTERNAL_SERVER_ERROR", - message: "An error occurred while processing the request", - }); - } - } - - // Return the validated data with the correct type - return result.data; -} - -// Utility function to validate API response data -function validateApiResponse( - data: any, +function handleFhirApiResponse( + data: unknown, schema: Z, ): z.infer { - // Validate the response data against the provided Zod schema - const validatedData = schema.parse(data); - - // Check for special case 'OperationOutcome' - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue + // Check if the response data is an OperationOutcome + const operationOutcomeResult = operationOutcomeSchema.safeParse(data); + if (operationOutcomeResult.success) { + const issues = operationOutcomeResult.data.issue .map( (issue) => `${issue.severity}: ${issue.code}, ${issue.details?.text}`, ) @@ -89,11 +28,17 @@ function validateApiResponse( }); } - return validatedData; + // If not an OperationOutcome, validate the data against the provided schema + const result = schema.safeParse(data); + if (!result.success) { + throw new TRPCError({ + code: "INTERNAL_SERVER_ERROR", + message: "An error occurred while processing the request", + }); + } + + // Return the validated data with the correct type + return result.data as z.infer; } -export { - handleCanvasApiResponse, - handleOperationOutcomeError, - validateApiResponse, -}; +export { handleFhirApiResponse }; diff --git a/packages/api/src/router/allergy-intolerance.ts b/packages/api/src/router/allergy-intolerance.ts index cac46793..5a2b77a2 100644 --- a/packages/api/src/router/allergy-intolerance.ts +++ b/packages/api/src/router/allergy-intolerance.ts @@ -1,9 +1,8 @@ -import { TRPCError } from "@trpc/server"; - import { get_SearchAllergen, post_CreateAllergyintolerance, } from "../canvas/canvas-client"; +import { handleFhirApiResponse } from "../lib/utils"; import { createTRPCRouter, protectedCanvasProcedure } from "../trpc"; export const allergyIntoleranceRouter = createTRPCRouter({ @@ -18,25 +17,12 @@ export const allergyIntoleranceRouter = createTRPCRouter({ body, }); - // Validate response - const validatedData = post_CreateAllergyintolerance.response.parse( + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( allergyIntoleranceData, + post_CreateAllergyintolerance.response, ); - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } - return validatedData; }), searchAllergens: protectedCanvasProcedure @@ -50,22 +36,11 @@ export const allergyIntoleranceRouter = createTRPCRouter({ query, }); - // Validate response - const validatedData = get_SearchAllergen.response.parse(allergenData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + allergenData, + get_SearchAllergen.response, + ); return validatedData; }), diff --git a/packages/api/src/router/care-team.ts b/packages/api/src/router/care-team.ts index e244110b..a699edc8 100644 --- a/packages/api/src/router/care-team.ts +++ b/packages/api/src/router/care-team.ts @@ -1,10 +1,9 @@ -import { TRPCError } from "@trpc/server"; - import { get_ReadCareteam, get_SearchCareteam, put_UpdateCareteam, } from "../canvas/canvas-client"; +import { handleFhirApiResponse } from "../lib/utils"; import { createTRPCRouter, protectedCanvasProcedure } from "../trpc"; export const careTeamRouter = createTRPCRouter({ @@ -19,21 +18,11 @@ export const careTeamRouter = createTRPCRouter({ path: { care_team_id: path.care_team_id }, }); - // Validate response - const validatedData = get_ReadCareteam.response.parse(careTeamData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; ")}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + careTeamData, + get_ReadCareteam.response, + ); return validatedData; }), @@ -48,21 +37,11 @@ export const careTeamRouter = createTRPCRouter({ query: query, }); - // Validate response - const validatedData = get_SearchCareteam.response.parse(careTeamData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; ")}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + careTeamData, + get_SearchCareteam.response, + ); return validatedData; }), @@ -78,21 +57,11 @@ export const careTeamRouter = createTRPCRouter({ body: body, }); - // Validate response - const validatedData = put_UpdateCareteam.response.parse(careTeamData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; ")}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + careTeamData, + put_UpdateCareteam.response, + ); return validatedData; }), diff --git a/packages/api/src/router/communication.ts b/packages/api/src/router/communication.ts index 327f1b41..28618f6c 100644 --- a/packages/api/src/router/communication.ts +++ b/packages/api/src/router/communication.ts @@ -1,4 +1,3 @@ -import { TRPCError } from "@trpc/server"; import { compareDesc } from "date-fns"; import { @@ -7,6 +6,7 @@ import { get_SearchCommunicationSender, post_CreateCommunication, } from "../canvas/canvas-client"; +import { handleFhirApiResponse } from "../lib/utils"; import { createTRPCRouter, protectedCanvasProcedure } from "../trpc"; export const communicationRouter = createTRPCRouter({ @@ -21,23 +21,11 @@ export const communicationRouter = createTRPCRouter({ body, }); - // Validate response - const validatedData = - post_CreateCommunication.response.parse(communicationData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + communicationData, + post_CreateCommunication.response, + ); return validatedData; }), @@ -52,23 +40,11 @@ export const communicationRouter = createTRPCRouter({ query, }); - // Validate resposne - const validatedData = - get_SearchCommunicationSender.response.parse(communicationData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + communicationData, + get_SearchCommunicationSender.response, + ); return validatedData; }), @@ -88,23 +64,11 @@ export const communicationRouter = createTRPCRouter({ }, ); - // Validate response - const validatedData = - get_ReadCommunication.response.parse(communicationData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + communicationData, + get_ReadCommunication.response, + ); return validatedData; }), @@ -117,23 +81,11 @@ export const communicationRouter = createTRPCRouter({ // Reuse the searchCommunications logic const communicationData = await api.get("/Communication", { query }); - // Validate response - const validatedData = - get_SearchCommunicationSender.response.parse(communicationData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + communicationData, + get_SearchCommunicationSender.response, + ); // Define a structure to store chat previews interface ChatPreview { @@ -171,23 +123,11 @@ export const communicationRouter = createTRPCRouter({ }, }, ); - // validate providerDetails - const validatedProviderDetails = - get_ReadPractitioner.response.parse(providerDetails); - - // Check if response is OperationOutcome - if (validatedProviderDetails?.resourceType === "OperationOutcome") { - const issues = validatedProviderDetails.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedProviderDetails = handleFhirApiResponse( + providerDetails, + get_ReadPractitioner.response, + ); chatPreviews[recipientId] = { recipient: { @@ -220,31 +160,15 @@ export const communicationRouter = createTRPCRouter({ query: { sender: query.recipient, recipient: query.sender }, }); - // Validate responses - const validatedSenderMsgs = - get_SearchCommunicationSender.response.parse(senderMsgsResponse); - const validatedRecipientMsgs = - get_SearchCommunicationSender.response.parse(recipientMsgsResponse); - - // Check if responses are OperationOutcome - if ( - validatedSenderMsgs?.resourceType === "OperationOutcome" || - validatedRecipientMsgs?.resourceType === "OperationOutcome" - ) { - const issues = [ - ...(validatedSenderMsgs?.issue || []), - ...(validatedRecipientMsgs?.issue || []), - ] - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate responses and check for OperationOutcome + const validatedSenderMsgs = handleFhirApiResponse( + senderMsgsResponse, + get_SearchCommunicationSender.response, + ); + const validatedRecipientMsgs = handleFhirApiResponse( + recipientMsgsResponse, + get_SearchCommunicationSender.response, + ); // Process a single message async function fetchPersonDetails(api, reference) { diff --git a/packages/api/src/router/condition.ts b/packages/api/src/router/condition.ts index c2d46ccd..9f1d49a2 100644 --- a/packages/api/src/router/condition.ts +++ b/packages/api/src/router/condition.ts @@ -1,9 +1,8 @@ -import { TRPCError } from "@trpc/server"; - import { get_SearchCondition, post_CreateCondition, } from "../canvas/canvas-client"; +import { handleFhirApiResponse } from "../lib/utils"; import { createTRPCRouter, protectedCanvasProcedure } from "../trpc"; export const conditionRouter = createTRPCRouter({ @@ -18,22 +17,11 @@ export const conditionRouter = createTRPCRouter({ body, }); - // Validate response - const validatedData = post_CreateCondition.response.parse(conditionData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + conditionData, + post_CreateCondition.response, + ); return validatedData; }), @@ -48,22 +36,11 @@ export const conditionRouter = createTRPCRouter({ query, }); - // Validate response - const validatedData = get_SearchCondition.response.parse(medicationData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + medicationData, + get_SearchCondition.response, + ); return validatedData; }), diff --git a/packages/api/src/router/consent.ts b/packages/api/src/router/consent.ts index bbcdbc4b..a85dabb1 100644 --- a/packages/api/src/router/consent.ts +++ b/packages/api/src/router/consent.ts @@ -1,7 +1,7 @@ -import { TRPCError } from "@trpc/server"; import { z } from "zod"; import { get_ReadConsent, post_CreateConsent } from "../canvas/canvas-client"; +import { handleFhirApiResponse } from "../lib/utils"; import { createTRPCRouter, protectedCanvasProcedure } from "../trpc"; export const consentRouter = createTRPCRouter({ @@ -16,16 +16,11 @@ export const consentRouter = createTRPCRouter({ path: { consent_id: id }, }); - // Validate response - const validatedData = get_ReadConsent.response.parse(consentData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `${JSON.stringify(validatedData)}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + consentData, + get_ReadConsent.response, + ); return validatedData; }), @@ -40,16 +35,11 @@ export const consentRouter = createTRPCRouter({ body, }); - // Validate response - const validatedData = post_CreateConsent.response.parse(consentData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `${JSON.stringify(validatedData)}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + consentData, + post_CreateConsent.response, + ); return validatedData; }), diff --git a/packages/api/src/router/coverage.ts b/packages/api/src/router/coverage.ts index 381cf235..2207c138 100644 --- a/packages/api/src/router/coverage.ts +++ b/packages/api/src/router/coverage.ts @@ -1,6 +1,5 @@ -import { TRPCError } from "@trpc/server"; - import { post_CreateCoverage } from "../canvas/canvas-client"; +import { handleFhirApiResponse } from "../lib/utils"; import { createTRPCRouter, protectedCanvasProcedure } from "../trpc"; export const coverageRouter = createTRPCRouter({ @@ -16,22 +15,11 @@ export const coverageRouter = createTRPCRouter({ body, }); - // Validate response - const validatedData = post_CreateCoverage.response.parse(coverageData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + coverageData, + post_CreateCoverage.response, + ); return validatedData; }), diff --git a/packages/api/src/router/diagnostic-report.ts b/packages/api/src/router/diagnostic-report.ts index 441f4bc7..a5b3e62f 100644 --- a/packages/api/src/router/diagnostic-report.ts +++ b/packages/api/src/router/diagnostic-report.ts @@ -1,7 +1,7 @@ -import { TRPCError } from "@trpc/server"; import { z } from "zod"; import { get_ReadDiagnosticreport } from "../canvas/canvas-client"; +import { handleFhirApiResponse } from "../lib/utils"; import { createTRPCRouter, protectedCanvasProcedure } from "../trpc"; export const diagnosticReportRouter = createTRPCRouter({ @@ -19,23 +19,11 @@ export const diagnosticReportRouter = createTRPCRouter({ }, ); - // Validate response - const validatedData = - get_ReadDiagnosticreport.response.parse(diagnosticreportData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + diagnosticreportData, + get_ReadDiagnosticreport.response, + ); return validatedData; }), diff --git a/packages/api/src/router/document.ts b/packages/api/src/router/document.ts index a7fcef5f..ebbd7daa 100644 --- a/packages/api/src/router/document.ts +++ b/packages/api/src/router/document.ts @@ -1,9 +1,8 @@ -import { TRPCError } from "@trpc/server"; - import { get_ReadDocumentreference, get_SearchDocumentreference, } from "../canvas/canvas-client"; +import { handleFhirApiResponse } from "../lib/utils"; import { createTRPCRouter, protectedCanvasProcedure } from "../trpc"; export const documentRouter = createTRPCRouter({ @@ -22,19 +21,12 @@ export const documentRouter = createTRPCRouter({ }, ); - // Validate response - const validatedData = get_ReadDocumentreference.response.parse( + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( documentReferenceData, + get_ReadDocumentreference.response, ); - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `${JSON.stringify(validatedData)}`, - }); - } - return validatedData; }), searchBillDocument: protectedCanvasProcedure @@ -54,23 +46,11 @@ export const documentRouter = createTRPCRouter({ }, }); - // Validate response - const validatedData = - get_SearchDocumentreference.response.parse(documentsData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + documentsData, + get_SearchDocumentreference.response, + ); return validatedData; }), diff --git a/packages/api/src/router/medication.ts b/packages/api/src/router/medication.ts index 23604836..6fa26ac0 100644 --- a/packages/api/src/router/medication.ts +++ b/packages/api/src/router/medication.ts @@ -1,10 +1,9 @@ -import { TRPCError } from "@trpc/server"; - import { get_ReadMedication, get_SearchMedication, post_CreateMedicationstatement, } from "../canvas/canvas-client"; +import { handleFhirApiResponse } from "../lib/utils"; import { createTRPCRouter, protectedCanvasProcedure } from "../trpc"; export const medicationRouter = createTRPCRouter({ @@ -20,25 +19,12 @@ export const medicationRouter = createTRPCRouter({ body, }); - // Validate response - const validatedData = post_CreateMedicationstatement.response.parse( + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( medicationStatementData, + post_CreateMedicationstatement.response, ); - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } - return validatedData; }), @@ -54,22 +40,11 @@ export const medicationRouter = createTRPCRouter({ query, }); - // Validate response - const validatedData = get_SearchMedication.response.parse(medicationData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + medicationData, + get_SearchMedication.response, + ); return validatedData; }), @@ -79,28 +54,16 @@ export const medicationRouter = createTRPCRouter({ const { api } = ctx; const { path } = input; - // search /Medication + // get /Medication{id} const medicationData = await api.get("/Medication/{medication_id}", { path: { medication_id: path.medication_id }, }); - // console.log(medicationData); - - // Validate response - const validatedData = get_ReadMedication.response.parse(medicationData); - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + medicationData, + get_ReadMedication.response, + ); return validatedData; }), diff --git a/packages/api/src/router/observation.ts b/packages/api/src/router/observation.ts index 430a1e71..5a1b814e 100644 --- a/packages/api/src/router/observation.ts +++ b/packages/api/src/router/observation.ts @@ -1,7 +1,7 @@ -import { TRPCError } from "@trpc/server"; import { z } from "zod"; import { get_ReadObservation } from "../canvas/canvas-client"; +import { handleFhirApiResponse } from "../lib/utils"; import { createTRPCRouter, protectedCanvasProcedure } from "../trpc"; export const observationRouter = createTRPCRouter({ @@ -16,16 +16,11 @@ export const observationRouter = createTRPCRouter({ path: { observation_id: id }, }); - // Validate response - const validatedData = get_ReadObservation.response.parse(observationData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `${JSON.stringify(validatedData)}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + observationData, + get_ReadObservation.response, + ); return validatedData; }), diff --git a/packages/api/src/router/patient-medical-history.ts b/packages/api/src/router/patient-medical-history.ts index 5e4d9f96..35104f38 100644 --- a/packages/api/src/router/patient-medical-history.ts +++ b/packages/api/src/router/patient-medical-history.ts @@ -1,4 +1,3 @@ -import { TRPCError } from "@trpc/server"; import { z } from "zod"; import { @@ -13,6 +12,7 @@ import { get_SearchObservation, get_UpdateQuestionnaireresponse, } from "../canvas/canvas-client"; +import { handleFhirApiResponse } from "../lib/utils"; import { createTRPCRouter, protectedCanvasProcedure } from "../trpc"; export const patientMedicalHistoryRouter = createTRPCRouter({ @@ -29,23 +29,11 @@ export const patientMedicalHistoryRouter = createTRPCRouter({ }, }); - // Validate response - const validatedData = - get_SearchAllergyintolerance.response.parse(allergiesData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + allergiesData, + get_SearchAllergyintolerance.response, + ); return validatedData; }), @@ -62,22 +50,11 @@ export const patientMedicalHistoryRouter = createTRPCRouter({ }, }); - // Validate response - const validatedData = get_SearchCondition.response.parse(conditionsData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + conditionsData, + get_SearchCondition.response, + ); return validatedData; }), @@ -94,16 +71,11 @@ export const patientMedicalHistoryRouter = createTRPCRouter({ }, }); - // Validate response - const validatedData = get_SearchConsent.response.parse(consentsData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `${JSON.stringify(validatedData)}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + consentsData, + get_SearchConsent.response, + ); return validatedData; }), @@ -120,22 +92,11 @@ export const patientMedicalHistoryRouter = createTRPCRouter({ }, }); - // Validate response - const validatedData = get_SearchGoal.response.parse(goalsData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + goalsData, + get_SearchGoal.response, + ); return validatedData; }), @@ -156,25 +117,12 @@ export const patientMedicalHistoryRouter = createTRPCRouter({ }, ); - // Validate response - const validatedData = get_UpdateQuestionnaireresponse.response.parse( + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( questionnaireResponsesData, + get_UpdateQuestionnaireresponse.response, ); - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } - return validatedData; }), getPatientImmunizations: protectedCanvasProcedure @@ -190,23 +138,11 @@ export const patientMedicalHistoryRouter = createTRPCRouter({ }, }); - // Validate response - const validatedData = - get_SearchImmunization.response.parse(immunizationsData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + immunizationsData, + get_SearchImmunization.response, + ); return validatedData; }), @@ -223,17 +159,11 @@ export const patientMedicalHistoryRouter = createTRPCRouter({ }, }); - // Validate response - const validatedData = - get_SearchMedicationstatement.response.parse(medicationsData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `${JSON.stringify(validatedData)}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + medicationsData, + get_SearchMedicationstatement.response, + ); return validatedData; }), @@ -250,25 +180,12 @@ export const patientMedicalHistoryRouter = createTRPCRouter({ }, }); - // Validate response - const validatedData = get_SearchDiagnosticreport.response.parse( + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( diagnosticReportsData, + get_SearchDiagnosticreport.response, ); - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } - return validatedData; }), getPatientDocuments: protectedCanvasProcedure @@ -285,23 +202,11 @@ export const patientMedicalHistoryRouter = createTRPCRouter({ }, }); - // Validate response - const validatedData = - get_SearchDocumentreference.response.parse(documentsData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + documentsData, + get_SearchDocumentreference.response, + ); return validatedData; }), @@ -319,23 +224,11 @@ export const patientMedicalHistoryRouter = createTRPCRouter({ }, }); - // Validate response - const validatedData = - get_SearchObservation.response.parse(observationsData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + observationsData, + get_SearchObservation.response, + ); return validatedData; }), diff --git a/packages/api/src/router/patient.ts b/packages/api/src/router/patient.ts index 7ea79b54..494e77da 100644 --- a/packages/api/src/router/patient.ts +++ b/packages/api/src/router/patient.ts @@ -6,6 +6,7 @@ import { post_CreatePatient, } from "../canvas/canvas-client"; import { env } from "../env.mjs"; +import { handleFhirApiResponse } from "../lib/utils"; import { createTRPCRouter, protectedCanvasProcedure } from "../trpc"; export const patientRouter = createTRPCRouter({ @@ -18,16 +19,11 @@ export const patientRouter = createTRPCRouter({ // search /Patient const patientsData = await api.get("/Patient", { query }); - // Validate response - const validatedData = get_SearchPatient.response.parse(patientsData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `${JSON.stringify(validatedData)}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + patientsData, + get_SearchPatient.response, + ); return validatedData; }), @@ -42,16 +38,11 @@ export const patientRouter = createTRPCRouter({ path: { patient_id: path.patient_id }, }); - // Validate response - const validatedData = get_ReadPatient.response.parse(patientData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `${JSON.stringify(validatedData)}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + patientData, + get_ReadPatient.response, + ); return validatedData; }), diff --git a/packages/api/src/router/payment.ts b/packages/api/src/router/payment.ts index fcb8e0d4..0676f49d 100644 --- a/packages/api/src/router/payment.ts +++ b/packages/api/src/router/payment.ts @@ -1,9 +1,8 @@ -import { TRPCError } from "@trpc/server"; - import { get_SearchPaymentnotice, post_CreatePaymentnotice, } from "../canvas/canvas-client"; +import { handleFhirApiResponse } from "../lib/utils"; import { createTRPCRouter, protectedCanvasProcedure } from "../trpc"; export const paymentRouter = createTRPCRouter({ @@ -29,23 +28,11 @@ export const paymentRouter = createTRPCRouter({ }, }); - // Validate response - const validatedData = - post_CreatePaymentnotice.response.parse(paymentData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + paymentData, + post_CreatePaymentnotice.response, + ); return validatedData; }), @@ -61,22 +48,11 @@ export const paymentRouter = createTRPCRouter({ }, }); - // Validate response - const validatedData = get_SearchPaymentnotice.response.parse(paymentData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + paymentData, + get_SearchPaymentnotice.response, + ); return validatedData; }), diff --git a/packages/api/src/router/practitioner.ts b/packages/api/src/router/practitioner.ts index 8a2a3b42..e01fb83c 100644 --- a/packages/api/src/router/practitioner.ts +++ b/packages/api/src/router/practitioner.ts @@ -1,9 +1,8 @@ -import { TRPCError } from "@trpc/server"; - import { get_ReadPractitioner, get_SearchPractitioner, } from "../canvas/canvas-client"; +import { handleFhirApiResponse } from "../lib/utils"; import { createTRPCRouter, protectedCanvasProcedure } from "../trpc"; export const practitionerRouter = createTRPCRouter({ @@ -18,22 +17,11 @@ export const practitionerRouter = createTRPCRouter({ query: query, }); - // Validate response - const validatedData = - get_SearchPractitioner.response.parse(practitionerData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; ")}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + practitionerData, + get_SearchPractitioner.response, + ); return validatedData; }), @@ -53,22 +41,11 @@ export const practitionerRouter = createTRPCRouter({ }, ); - // Validate response - const validatedData = - get_ReadPractitioner.response.parse(practitionerData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; ")}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + practitionerData, + get_ReadPractitioner.response, + ); return validatedData; }), diff --git a/packages/api/src/router/questionnaire.ts b/packages/api/src/router/questionnaire.ts index 88024c38..68d7c6df 100644 --- a/packages/api/src/router/questionnaire.ts +++ b/packages/api/src/router/questionnaire.ts @@ -1,4 +1,3 @@ -import { TRPCError } from "@trpc/server"; import { z } from "zod"; import { @@ -7,6 +6,7 @@ import { get_SearchQuestionnaire, post_CreateQuestionnaireresponse, } from "../canvas/canvas-client"; +import { handleFhirApiResponse } from "../lib/utils"; import { createTRPCRouter, protectedCanvasProcedure } from "../trpc"; export const questionnaireRouter = createTRPCRouter({ @@ -25,17 +25,11 @@ export const questionnaireRouter = createTRPCRouter({ }, ); - // Validate response - const validatedData = - get_ReadQuestionnaire.response.parse(questionnaireData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `${JSON.stringify(validatedData)}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + questionnaireData, + get_ReadQuestionnaire.response, + ); return validatedData; }), @@ -50,23 +44,11 @@ export const questionnaireRouter = createTRPCRouter({ query, }); - // Validate response - const validatedData = - get_SearchQuestionnaire.response.parse(questionnaireData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + questionnaireData, + get_SearchQuestionnaire.response, + ); return validatedData; }), @@ -86,19 +68,12 @@ export const questionnaireRouter = createTRPCRouter({ }, ); - // Validate response - const validatedData = get_ReadQuestionnaireresponse.response.parse( + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( questionnaireResponseData, + get_ReadQuestionnaireresponse.response, ); - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `${JSON.stringify(validatedData)}`, - }); - } - return validatedData; }), submitQuestionnaireResponse: protectedCanvasProcedure @@ -115,25 +90,12 @@ export const questionnaireRouter = createTRPCRouter({ }, ); - // Validate response - const validatedData = post_CreateQuestionnaireresponse.response.parse( + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( questionnaireResponseData, + post_CreateQuestionnaireresponse.response, ); - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } - return validatedData; }), }); diff --git a/packages/api/src/router/scheduling.ts b/packages/api/src/router/scheduling.ts index 3853d525..1a2da95c 100644 --- a/packages/api/src/router/scheduling.ts +++ b/packages/api/src/router/scheduling.ts @@ -1,4 +1,3 @@ -import { TRPCError } from "@trpc/server"; import { z } from "zod"; import { @@ -9,6 +8,7 @@ import { post_CreateAppointment, put_UpdateAppointment, } from "../canvas/canvas-client"; +import { handleFhirApiResponse } from "../lib/utils"; import { createTRPCRouter, protectedCanvasProcedure } from "../trpc"; export const schedulingRouter = createTRPCRouter({ @@ -25,21 +25,11 @@ export const schedulingRouter = createTRPCRouter({ }, }); - // Validate response - const validatedData = get_SearchCareteam.response.parse(careTeamData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; ")}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + careTeamData, + get_SearchCareteam.response, + ); return validatedData; }), @@ -49,21 +39,11 @@ export const schedulingRouter = createTRPCRouter({ // search /Schedule const scheduleData = await api.get("/Schedule"); - // Validate response - const validatedData = get_SearchSchedule.response.parse(scheduleData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; ")}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + scheduleData, + get_SearchSchedule.response, + ); return validatedData; }), @@ -78,21 +58,11 @@ export const schedulingRouter = createTRPCRouter({ query, }); - // Validate response - const validatedData = get_SearchSlot.response.parse(slotData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; ")}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + slotData, + get_SearchSlot.response, + ); return validatedData; }), @@ -107,23 +77,11 @@ export const schedulingRouter = createTRPCRouter({ body, }); - // Validate response - const validatedData = - post_CreateAppointment.response.parse(appointmentData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + appointmentData, + post_CreateAppointment.response, + ); return validatedData; }), @@ -139,23 +97,11 @@ export const schedulingRouter = createTRPCRouter({ body, }); - // Validate response - const validatedData = - put_UpdateAppointment.response.parse(appointmentData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + appointmentData, + put_UpdateAppointment.response, + ); return validatedData; }), @@ -170,22 +116,11 @@ export const schedulingRouter = createTRPCRouter({ query, }); - // Validate response - const validatedData = - get_SearchAppointment.response.parse(appointmentData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; ")}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + appointmentData, + get_SearchAppointment.response, + ); return validatedData; }), diff --git a/packages/api/src/router/task.ts b/packages/api/src/router/task.ts index 098bebc7..e9dadb6e 100644 --- a/packages/api/src/router/task.ts +++ b/packages/api/src/router/task.ts @@ -1,10 +1,9 @@ -import { TRPCError } from "@trpc/server"; - import { get_SearchTask, post_CreateTask, put_UpdateTask, } from "../canvas/canvas-client"; +import { handleFhirApiResponse } from "../lib/utils"; import { createTRPCRouter, protectedCanvasProcedure } from "../trpc"; export const taskRouter = createTRPCRouter({ @@ -43,22 +42,11 @@ export const taskRouter = createTRPCRouter({ }, }); - // Validate response - const validatedData = post_CreateTask.response.parse(taskData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + taskData, + post_CreateTask.response, + ); return validatedData; }), @@ -73,22 +61,11 @@ export const taskRouter = createTRPCRouter({ query, }); - // Validate response - const validatedData = get_SearchTask.response.parse(taskData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + taskData, + get_SearchTask.response, + ); return validatedData; }), @@ -104,22 +81,11 @@ export const taskRouter = createTRPCRouter({ body, }); - // Validate response - const validatedData = put_UpdateTask.response.parse(taskData); - - // Check if response is OperationOutcome - if (validatedData?.resourceType === "OperationOutcome") { - const issues = validatedData.issue - .map( - (issue) => - `${issue.severity}: ${issue.code}, ${issue.details?.text}`, - ) - .join("; "); - throw new TRPCError({ - code: "BAD_REQUEST", - message: `FHIR OperationOutcome Error: ${issues}`, - }); - } + // Validate response and check for OperationOutcome + const validatedData = handleFhirApiResponse( + taskData, + put_UpdateTask.response, + ); return validatedData; }), diff --git a/packages/shared/src/validators/allergen.ts b/packages/shared/src/validators/allergen.ts index 9585a3d3..1698431b 100644 --- a/packages/shared/src/validators/allergen.ts +++ b/packages/shared/src/validators/allergen.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const linkSchema = z.object({ relation: z.string(), url: z.string(), @@ -39,11 +37,8 @@ export const allergenBundleSchema = z.object({ entry: z.array(entrySchema).optional(), }); -export const readAllergenResponseSchema = createUnionSchemaWithOperationOutcome( - allergenResourceSchema, -); +export const readAllergenResponseSchema = allergenResourceSchema; -export const searchAllergenResponseSchema = - createUnionSchemaWithOperationOutcome(allergenBundleSchema); +export const searchAllergenResponseSchema = allergenBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/allergy-intolerance.ts b/packages/shared/src/validators/allergy-intolerance.ts index ba878769..537730b8 100644 --- a/packages/shared/src/validators/allergy-intolerance.ts +++ b/packages/shared/src/validators/allergy-intolerance.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const codingSchema = z.object({ system: z.string(), code: z.string(), @@ -85,9 +83,9 @@ export const allergyIntoleranceBundleSchema = z.object({ }); export const readAllergyIntoleranceResponseSchema = - createUnionSchemaWithOperationOutcome(allergyIntoleranceResourceSchema); + allergyIntoleranceResourceSchema; export const searchAllergyIntoleranceResponseSchema = - createUnionSchemaWithOperationOutcome(allergyIntoleranceBundleSchema); + allergyIntoleranceBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/appointment.ts b/packages/shared/src/validators/appointment.ts index e5ce8b38..9c32a61f 100644 --- a/packages/shared/src/validators/appointment.ts +++ b/packages/shared/src/validators/appointment.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const linkSchema = z.object({ relation: z.string(), url: z.string(), @@ -78,10 +76,8 @@ export const appointmentBundleSchema = z.object({ entry: z.array(entrySchema).optional(), }); -export const readAppointmentResponseSchema = - createUnionSchemaWithOperationOutcome(appointmentResourceSchema); +export const readAppointmentResponseSchema = appointmentResourceSchema; -export const searchAppointmentResponseSchema = - createUnionSchemaWithOperationOutcome(appointmentBundleSchema); +export const searchAppointmentResponseSchema = appointmentBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/care-team.ts b/packages/shared/src/validators/care-team.ts index deaa9f8c..3b0ac108 100644 --- a/packages/shared/src/validators/care-team.ts +++ b/packages/shared/src/validators/care-team.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const linkSchema = z.object({ relation: z.string(), url: z.string(), @@ -55,11 +53,8 @@ export const careTeamBundleSchema = z.object({ }); export type CareTeamBundle = z.infer; -export const readCareTeamResponseSchema = createUnionSchemaWithOperationOutcome( - careTeamResourceSchema, -); +export const readCareTeamResponseSchema = careTeamResourceSchema; -export const searchCareTeamResponseSchema = - createUnionSchemaWithOperationOutcome(careTeamBundleSchema); +export const searchCareTeamResponseSchema = careTeamBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/communication.ts b/packages/shared/src/validators/communication.ts index b8c83f71..58d8380e 100644 --- a/packages/shared/src/validators/communication.ts +++ b/packages/shared/src/validators/communication.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const linkSchema = z.object({ relation: z.string(), url: z.string(), @@ -41,10 +39,8 @@ export const communicationBundleSchema = z.object({ entry: z.array(entrySchema).optional(), }); -export const readCommunicationResponseSchema = - createUnionSchemaWithOperationOutcome(communicationResourceSchema); +export const readCommunicationResponseSchema = communicationResourceSchema; -export const searchCommunicationResponseSchema = - createUnionSchemaWithOperationOutcome(communicationBundleSchema); +export const searchCommunicationResponseSchema = communicationBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/condition.ts b/packages/shared/src/validators/condition.ts index d17d6169..d2e14563 100644 --- a/packages/shared/src/validators/condition.ts +++ b/packages/shared/src/validators/condition.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const codingSchema = z.object({ system: z.string(), code: z.string(), @@ -67,10 +65,8 @@ export const conditionBundleSchema = z.object({ .optional(), }); -export const readConditionResponseSchema = - createUnionSchemaWithOperationOutcome(conditionResourceSchema); +export const readConditionResponseSchema = conditionResourceSchema; -export const searchConditionResponseSchema = - createUnionSchemaWithOperationOutcome(conditionBundleSchema); +export const searchConditionResponseSchema = conditionBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/consent.ts b/packages/shared/src/validators/consent.ts index a3e97d60..beaf0d74 100644 --- a/packages/shared/src/validators/consent.ts +++ b/packages/shared/src/validators/consent.ts @@ -1,51 +1,74 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; +const linkSchema = z + .object({ + relation: z.string().optional(), + url: z.string().optional(), + }) + .optional(); -const linkSchema = z.object({ - relation: z.string(), - url: z.string(), -}); +const codingSchema = z + .object({ + code: z.string().optional(), + system: z.string().optional(), + display: z.string().optional(), + }) + .optional(); -const codingSchema = z.object({ - system: z.string(), - display: z.string(), -}); +const categorySchema = z + .object({ + coding: z.array(codingSchema).optional(), + }) + .optional(); -const categorySchema = z.object({ - coding: z.array(codingSchema), -}); +const referenceSchema = z + .object({ + reference: z.string().optional(), + type: z.string().optional(), + }) + .optional(); -const referenceSchema = z.object({ - reference: z.string(), - type: z.string(), -}); +const periodSchema = z + .object({ + start: z.string().optional(), + end: z.string().optional(), + }) + .optional(); -const periodSchema = z.object({ - start: z.string(), - end: z.string().optional(), -}); +const provisionSchema = z + .object({ + period: periodSchema.optional(), + }) + .optional(); -const provisionSchema = z.object({ - period: periodSchema.optional(), -}); - -const scopeSchema = z.object({ - text: z.string(), -}); +const scopeSchema = z + .object({ + coding: z.array(codingSchema).optional(), + text: z.string().optional(), + }) + .optional(); -const sourceAttachmentSchema = z.object({ - url: z.string(), -}); +const sourceAttachmentSchema = z + .object({ + data: z.string().optional(), + url: z.string().optional(), + }) + .optional(); const consentResourceSchema = z.object({ resourceType: z.literal("Consent"), - id: z.string(), - status: z.string(), + id: z.string().optional(), + status: z.string().optional(), scope: scopeSchema, - category: z.array(categorySchema), + category: z.array(categorySchema).optional(), + meta: z + .object({ + lastUpdated: z.string().optional(), + versionId: z.string().optional(), + }) + .optional(), patient: referenceSchema, - dateTime: z.string(), + dateTime: z.string().optional(), sourceAttachment: sourceAttachmentSchema.optional(), provision: provisionSchema.optional(), }); @@ -62,11 +85,8 @@ export const consentBundleSchema = z.object({ entry: z.array(entrySchema).optional(), }); -export const readConsentResponseSchema = createUnionSchemaWithOperationOutcome( - consentResourceSchema, -); +export const readConsentResponseSchema = consentResourceSchema; -export const searchConsentResponseSchema = - createUnionSchemaWithOperationOutcome(consentBundleSchema); +export const searchConsentResponseSchema = consentBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/coverage.ts b/packages/shared/src/validators/coverage.ts index c54e5c44..6156887e 100644 --- a/packages/shared/src/validators/coverage.ts +++ b/packages/shared/src/validators/coverage.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const linkSchema = z.object({ relation: z.string(), url: z.string(), @@ -54,11 +52,8 @@ export const coverageBundleSchema = z.object({ entry: z.array(entrySchema).optional(), }); -export const readCoverageResponseSchema = createUnionSchemaWithOperationOutcome( - coverageResourceSchema, -); +export const readCoverageResponseSchema = coverageResourceSchema; -export const searchCoverageResponseSchema = - createUnionSchemaWithOperationOutcome(coverageBundleSchema); +export const searchCoverageResponseSchema = coverageBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/diagnostic-report.ts b/packages/shared/src/validators/diagnostic-report.ts index e125848d..49cddc7c 100644 --- a/packages/shared/src/validators/diagnostic-report.ts +++ b/packages/shared/src/validators/diagnostic-report.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const linkSchema = z.object({ relation: z.string(), url: z.string(), @@ -57,9 +55,9 @@ export const diagnosticReportBundleSchema = z.object({ }); export const readDiagnosticReportResponseSchema = - createUnionSchemaWithOperationOutcome(diagnosticReportResourceSchema); + diagnosticReportResourceSchema; export const searchDiagnosticReportResponseSchema = - createUnionSchemaWithOperationOutcome(diagnosticReportBundleSchema); + diagnosticReportBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/document-reference.ts b/packages/shared/src/validators/document-reference.ts index 788e4806..b63f1fb1 100644 --- a/packages/shared/src/validators/document-reference.ts +++ b/packages/shared/src/validators/document-reference.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const codingSchema = z.object({ system: z.string().optional(), code: z.string().optional(), @@ -85,9 +83,9 @@ export const documentReferenceBundleSchema = z.object({ }); export const readDocumentReferenceResponseSchema = - createUnionSchemaWithOperationOutcome(documentReferenceResourceSchema); + documentReferenceResourceSchema; export const searchDocumentReferenceResponseSchema = - createUnionSchemaWithOperationOutcome(documentReferenceBundleSchema); + documentReferenceBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/encounter.ts b/packages/shared/src/validators/encounter.ts index 027286ef..a4d09178 100644 --- a/packages/shared/src/validators/encounter.ts +++ b/packages/shared/src/validators/encounter.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const linkSchema = z.object({ relation: z.string(), url: z.string(), @@ -84,10 +82,8 @@ export const encounterBundleSchema = z.object({ entry: z.array(entrySchema).optional(), }); -export const readEncounterResponseSchema = - createUnionSchemaWithOperationOutcome(encounterResourceSchema); +export const readEncounterResponseSchema = encounterResourceSchema; -export const searchEncounterResponseSchema = - createUnionSchemaWithOperationOutcome(encounterBundleSchema); +export const searchEncounterResponseSchema = encounterBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/goal.ts b/packages/shared/src/validators/goal.ts index 9e56e1b5..c83b63c3 100644 --- a/packages/shared/src/validators/goal.ts +++ b/packages/shared/src/validators/goal.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const linkSchema = z.object({ relation: z.string(), url: z.string(), @@ -62,10 +60,8 @@ export const goalBundleSchema = z.object({ entry: z.array(entrySchema).optional(), }); -export const readGoalResponseSchema = - createUnionSchemaWithOperationOutcome(goalResourceSchema); +export const readGoalResponseSchema = goalResourceSchema; -export const searchGoalResponseSchema = - createUnionSchemaWithOperationOutcome(goalBundleSchema); +export const searchGoalResponseSchema = goalBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/immunization.ts b/packages/shared/src/validators/immunization.ts index 614367af..fad10a40 100644 --- a/packages/shared/src/validators/immunization.ts +++ b/packages/shared/src/validators/immunization.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const codingSchema = z.object({ system: z.string(), code: z.string(), @@ -47,10 +45,8 @@ export const immunizationsBundleSchema = z.object({ .optional(), }); -export const readImmunizationResponseSchema = - createUnionSchemaWithOperationOutcome(immunizationResourceSchema); +export const readImmunizationResponseSchema = immunizationResourceSchema; -export const searchImmunizationResponseSchema = - createUnionSchemaWithOperationOutcome(immunizationsBundleSchema); +export const searchImmunizationResponseSchema = immunizationsBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/medication-request.ts b/packages/shared/src/validators/medication-request.ts index 0cfec166..62abf831 100644 --- a/packages/shared/src/validators/medication-request.ts +++ b/packages/shared/src/validators/medication-request.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const codingSchema = z.object({ system: z.string(), code: z.string(), @@ -105,9 +103,9 @@ export const medicationRequestBundleSchema = z.object({ }); export const readMedicationRequestResponseSchema = - createUnionSchemaWithOperationOutcome(medicationRequestResourceSchema); + medicationRequestResourceSchema; export const searchMedicationRequestResponseSchema = - createUnionSchemaWithOperationOutcome(medicationRequestBundleSchema); + medicationRequestBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/medication-statement.ts b/packages/shared/src/validators/medication-statement.ts index 9ce58592..8c5688b5 100644 --- a/packages/shared/src/validators/medication-statement.ts +++ b/packages/shared/src/validators/medication-statement.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const referenceSchema = z.object({ reference: z.string(), display: z.string().optional(), @@ -61,9 +59,9 @@ export const medicationStatementBundleSchema = z.object({ }); export const readMedicationStatementResponseSchema = - createUnionSchemaWithOperationOutcome(medicationStatementResourceSchema); + medicationStatementResourceSchema; export const searchMedicationStatementResponseSchema = - createUnionSchemaWithOperationOutcome(medicationStatementBundleSchema); + medicationStatementBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/medication.ts b/packages/shared/src/validators/medication.ts index 834499b5..8c2c6bb6 100644 --- a/packages/shared/src/validators/medication.ts +++ b/packages/shared/src/validators/medication.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const codingSchema = z.object({ system: z.string(), code: z.string(), @@ -44,10 +42,8 @@ export const medicationBundleSchema = z.object({ .optional(), }); -export const readMedicationResponseSchema = - createUnionSchemaWithOperationOutcome(medicationResourceSchema); +export const readMedicationResponseSchema = medicationResourceSchema; -export const searchMedicationResponseSchema = - createUnionSchemaWithOperationOutcome(medicationBundleSchema); +export const searchMedicationResponseSchema = medicationBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/observation.ts b/packages/shared/src/validators/observation.ts index 36b32da4..1fa155d1 100644 --- a/packages/shared/src/validators/observation.ts +++ b/packages/shared/src/validators/observation.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const linkSchema = z.object({ relation: z.string(), url: z.string(), @@ -68,10 +66,8 @@ export const observationBundleSchema = z.object({ entry: z.array(entrySchema).optional(), }); -export const readObservationResponseSchema = - createUnionSchemaWithOperationOutcome(observationResourceSchema); +export const readObservationResponseSchema = observationResourceSchema; -export const searchObservationResponseSchema = - createUnionSchemaWithOperationOutcome(observationBundleSchema); +export const searchObservationResponseSchema = observationBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/operation-outcome.ts b/packages/shared/src/validators/operation-outcome.ts index 803b4c75..a704f87e 100644 --- a/packages/shared/src/validators/operation-outcome.ts +++ b/packages/shared/src/validators/operation-outcome.ts @@ -9,7 +9,7 @@ const operationOutcomeIssueSchema = z.object({ }); export type OperationOutcomeIssue = z.infer; -const operationOutcomeSchema = z.object({ +export const operationOutcomeSchema = z.object({ resourceType: z.literal("OperationOutcome"), issue: z.array(operationOutcomeIssueSchema), }); diff --git a/packages/shared/src/validators/patient.ts b/packages/shared/src/validators/patient.ts index 7531ddf9..c84d1195 100644 --- a/packages/shared/src/validators/patient.ts +++ b/packages/shared/src/validators/patient.ts @@ -1,27 +1,32 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const linkSchema = z.object({ - relation: z.string(), - url: z.string(), + relation: z.string().optional(), + url: z.string().optional(), }); const codingSchema = z.object({ - system: z.string(), - code: z.string(), - display: z.string(), + system: z.string().optional(), + code: z.string().optional(), + display: z.string().optional(), }); const textSchema = z.object({ - status: z.string(), - div: z.string(), + status: z.string().optional(), + div: z.string().optional(), }); const extensionSchema = z .object({ + extension: z + .array( + z.object({ + url: z.string().optional(), + valueString: z.string().optional(), + }), + ) + .optional(), url: z.string(), - // The value could be different types; you may need to adjust based on your data valueCode: z.string().optional(), valueCodeableConcept: z .object({ @@ -41,17 +46,18 @@ const extensionSchema = z .optional(); const identifierSchema = z.object({ + id: z.string().optional(), use: z.string().optional(), type: z .object({ - coding: z.array(codingSchema), + coding: z.array(codingSchema).optional(), }) .optional(), system: z.string().optional(), - value: z.string(), + value: z.string().optional(), assigner: z .object({ - display: z.string(), + display: z.string().optional(), }) .optional(), period: z @@ -75,16 +81,22 @@ const nameSchema = z.object({ }); const telecomSchema = z.object({ - system: z.string(), - value: z.string(), + system: z.string().optional(), + value: z.string().optional(), use: z.string().optional(), rank: z.number().optional(), }); const addressSchema = z.object({ + id: z.string().optional(), use: z.string().optional(), type: z.string().optional(), line: z.array(z.string()).optional(), + period: z + .object({ + start: z.string().optional(), + }) + .optional(), city: z.string().optional(), state: z.string().optional(), postalCode: z.string().optional(), @@ -92,6 +104,15 @@ const addressSchema = z.object({ }); const contactSchema = z.object({ + extension: z + .array( + z.object({ + url: z.string().optional(), + valueBoolean: z.boolean().optional(), + }), + ) + .optional(), + id: z.string().optional(), relationship: z.array( z.object({ coding: z.array(codingSchema), @@ -113,10 +134,9 @@ const communicationSchema = z.object({ }), }); -// TODO - check with generated code const patientResourceSchema = z.object({ resourceType: z.literal("Patient"), - id: z.string(), + id: z.string().optional(), text: textSchema, extension: z.array(extensionSchema).optional(), identifier: z.array(identifierSchema).optional(), @@ -143,11 +163,8 @@ export const patientBundleSchema = z.object({ entry: z.array(entrySchema).optional(), }); -export const readPatientResponseSchema = createUnionSchemaWithOperationOutcome( - patientResourceSchema, -); +export const readPatientResponseSchema = patientResourceSchema; -export const searchPatientResponseSchema = - createUnionSchemaWithOperationOutcome(patientBundleSchema); +export const searchPatientResponseSchema = patientBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/payment.ts b/packages/shared/src/validators/payment.ts index 15cefd92..ba7d578c 100644 --- a/packages/shared/src/validators/payment.ts +++ b/packages/shared/src/validators/payment.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const linkSchema = z.object({ relation: z.string(), url: z.string(), @@ -50,10 +48,8 @@ const paymentNoticeBundleSchema = z.object({ entry: z.array(entrySchema).optional(), }); -export const readPaymentNoticeResponseSchema = - createUnionSchemaWithOperationOutcome(paymentNoticeResourceSchema); +export const readPaymentNoticeResponseSchema = paymentNoticeResourceSchema; -export const searchPaymentNoticeResponseSchema = - createUnionSchemaWithOperationOutcome(paymentNoticeBundleSchema); +export const searchPaymentNoticeResponseSchema = paymentNoticeBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/practitioner.ts b/packages/shared/src/validators/practitioner.ts index 9af9c847..b276bf98 100644 --- a/packages/shared/src/validators/practitioner.ts +++ b/packages/shared/src/validators/practitioner.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const identifierSchema = z.object({ system: z.string(), value: z.string(), @@ -76,10 +74,8 @@ export const practitionerBundleSchema = z.object({ }); export type PractitionerBundle = z.infer; -export const readPractitionerResponseSchema = - createUnionSchemaWithOperationOutcome(practitionerResourceSchema); +export const readPractitionerResponseSchema = practitionerResourceSchema; -export const searchPractitionerResponseSchema = - createUnionSchemaWithOperationOutcome(practitionerBundleSchema); +export const searchPractitionerResponseSchema = practitionerBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/questionnaire-response.ts b/packages/shared/src/validators/questionnaire-response.ts index d672daa5..edf160af 100644 --- a/packages/shared/src/validators/questionnaire-response.ts +++ b/packages/shared/src/validators/questionnaire-response.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const linkSchema = z.object({ relation: z.string(), url: z.string(), @@ -66,9 +64,9 @@ export const questionnaireResponseBundleSchema = z.object({ }); export const readQuestionnaireResponseResponseSchema = - createUnionSchemaWithOperationOutcome(questionnaireResponseResourceSchema); + questionnaireResponseResourceSchema; export const searchQuestionnaireResponseResponseSchema = - createUnionSchemaWithOperationOutcome(questionnaireResponseBundleSchema); + questionnaireResponseBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/questionnaire.ts b/packages/shared/src/validators/questionnaire.ts index b04bcfdb..1494a94e 100644 --- a/packages/shared/src/validators/questionnaire.ts +++ b/packages/shared/src/validators/questionnaire.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const codingSchema = z.object({ system: z.string(), code: z.string(), @@ -56,10 +54,8 @@ export const questionnaireBundleSchema = z.object({ entry: z.array(entrySchema).optional(), }); -export const readQuestionnaireResponseSchema = - createUnionSchemaWithOperationOutcome(questionnaireResourceSchema); +export const readQuestionnaireResponseSchema = questionnaireResourceSchema; -export const searchQuestionnaireResponseSchema = - createUnionSchemaWithOperationOutcome(questionnaireBundleSchema); +export const searchQuestionnaireResponseSchema = questionnaireBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/schedule.ts b/packages/shared/src/validators/schedule.ts index 93eda3d3..6374c372 100644 --- a/packages/shared/src/validators/schedule.ts +++ b/packages/shared/src/validators/schedule.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const textSchema = z.object({ status: z.string(), div: z.string(), @@ -31,11 +29,8 @@ export const scheduleBundleSchema = z.object({ entry: z.array(entrySchema).optional(), }); -export const readScheduleResponseSchema = createUnionSchemaWithOperationOutcome( - scheduleResourceSchema, -); +export const readScheduleResponseSchema = scheduleResourceSchema; -export const searchScheduleResponseSchema = - createUnionSchemaWithOperationOutcome(scheduleBundleSchema); +export const searchScheduleResponseSchema = scheduleBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/slot.ts b/packages/shared/src/validators/slot.ts index 174851fd..cd350a09 100644 --- a/packages/shared/src/validators/slot.ts +++ b/packages/shared/src/validators/slot.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const scheduleReferenceSchema = z.object({ reference: z.string(), type: z.enum(["Schedule"]), @@ -27,10 +25,8 @@ export const slotBundleSchema = z.object({ entry: z.array(slotEntrySchema).optional(), }); -export const readSlotResponseSchema = - createUnionSchemaWithOperationOutcome(slotResourceSchema); +export const readSlotResponseSchema = slotResourceSchema; -export const searchSlotResponseSchema = - createUnionSchemaWithOperationOutcome(slotBundleSchema); +export const searchSlotResponseSchema = slotBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject) diff --git a/packages/shared/src/validators/task.ts b/packages/shared/src/validators/task.ts index b1752374..ae8fd0bd 100644 --- a/packages/shared/src/validators/task.ts +++ b/packages/shared/src/validators/task.ts @@ -1,7 +1,5 @@ import { z } from "zod"; -import { createUnionSchemaWithOperationOutcome } from "./operation-outcome"; - const linkSchema = z.object({ relation: z.string(), url: z.string(), @@ -73,10 +71,8 @@ export const taskBundleSchema = z.object({ entry: z.array(entrySchema).optional(), }); -export const readTaskResponseSchema = - createUnionSchemaWithOperationOutcome(taskResourceSchema); +export const readTaskResponseSchema = taskResourceSchema; -export const searchTaskResponseSchema = - createUnionSchemaWithOperationOutcome(taskBundleSchema); +export const searchTaskResponseSchema = taskBundleSchema; // Usage: Validate data with responseSchema.parse(yourDataObject)