Circle V2 API Docs
    Preparing search index...

    Module @repo/trpc

    @repo/trpc

    tRPC v11 API layer. The server export provides the appRouter (composed from domain routers: patients, patientSessions, profiles, orgMembers, facilities, templates, auditTemplates) and a fetch adapter. The client export provides TRPCProvider, useTRPC, useTRPCClient, and api for React Query–integrated procedure calls. It also exports authenticatedProcedure and Zod-based input schemas.

    %%{init:{"theme":"dark"}}%% graph TD trpc["@repo/trpc"] auth["@repo/auth"] db["@repo/db"] legacy["@repo/legacy"] logger["@repo/logger"] safe["@repo/safe"] react_query["@repo/react-query"] typescript_config["@repo/typescript-config"] vitest_config["@repo/vitest-config"] services["@repo/services"] utils["@repo/utils"] trpc -.-> auth trpc -.-> db trpc -.-> legacy trpc -.-> logger trpc -.-> safe trpc -.-> react_query trpc -.-> typescript_config trpc -.-> vitest_config trpc -.-> services trpc -.-> utils
    %%{init:{"theme":"default"}}%% graph TD trpc["@repo/trpc"] auth["@repo/auth"] db["@repo/db"] legacy["@repo/legacy"] logger["@repo/logger"] safe["@repo/safe"] react_query["@repo/react-query"] typescript_config["@repo/typescript-config"] vitest_config["@repo/vitest-config"] services["@repo/services"] utils["@repo/utils"] trpc -.-> auth trpc -.-> db trpc -.-> legacy trpc -.-> logger trpc -.-> safe trpc -.-> react_query trpc -.-> typescript_config trpc -.-> vitest_config trpc -.-> services trpc -.-> utils
    graph TD
      trpc["@repo/trpc"]
      auth["@repo/auth"]
      db["@repo/db"]
      legacy["@repo/legacy"]
      logger["@repo/logger"]
      safe["@repo/safe"]
      react_query["@repo/react-query"]
      typescript_config["@repo/typescript-config"]
      vitest_config["@repo/vitest-config"]
      services["@repo/services"]
      utils["@repo/utils"]
      trpc -.-> auth
      trpc -.-> db
      trpc -.-> legacy
      trpc -.-> logger
      trpc -.-> safe
      trpc -.-> react_query
      trpc -.-> typescript_config
      trpc -.-> vitest_config
      trpc -.-> services
      trpc -.-> utils

    Each procedure lives in its own file (*.query.ts or *.mutation.ts). Define a Zod input schema, export inferred types, and use authenticatedProcedure:

    // src/routers/patients/get-patient-by-id.query.ts
    import { TRPCError } from "@trpc/server";
    import { z } from "zod";

    import { patientsRepo } from "@repo/db";
    import { zPatientId } from "@repo/db/schema";

    import { authenticatedProcedure } from "../../procedures";

    export type GetPatientByIdInput = z.infer<typeof getPatientByIdInputSchema>;
    export type GetPatientByIdOutput = Awaited<ReturnType<typeof getPatientById>>;

    export const getPatientByIdInputSchema = z.object({
    id: zPatientId,
    });

    export const getPatientById = authenticatedProcedure
    .input(getPatientByIdInputSchema)
    .query(async ({ input }) => {
    const { data, error } = await patientsRepo.getById(input.id);

    if (error) {
    throw new TRPCError({
    code: "BAD_REQUEST",
    message: error.message || "Unknown error",
    });
    }

    return data;
    });

    Mutations follow the same pattern but use .mutation(...). The ctx object provides the authenticated user:

    // src/routers/patients/create-patient.mutation.ts
    export const createPatientInputSchema = z.object({
    firstName: z.string().min(1, "First name is required"),
    lastName: z.string().min(1, "Last name is required"),
    facilityId: zFacilityId.optional(),
    email: z.email().optional().or(z.literal("")),
    // ...
    });

    export type CreatePatientInput = z.infer<typeof createPatientInputSchema>;

    export const createPatient = authenticatedProcedure
    .input(createPatientInputSchema)
    .mutation(async ({ ctx, input }) => {
    const { data, error } = await patientsRepo.create({
    first_name: input.firstName,
    last_name: input.lastName,
    entity_id: ctx.user.entity_id,
    // ...
    });

    if (error) {
    throw new TRPCError({ code: "BAD_REQUEST", message: error.message || "Unknown error" });
    }

    return data;
    });

    Each domain has an index.ts that composes individual procedures into a router. Types are re-exported with export type *:

    // src/routers/patients/index.ts
    import { trpc } from "../../trpc";
    import { createPatient } from "./create-patient.mutation";
    import { getPatientById } from "./get-patient-by-id.query";
    import { listInOrganization } from "./list-in-organization.query";
    import { updatePatient } from "./update-patient.mutation";

    export type * from "./create-patient.mutation";
    export type * from "./get-patient-by-id.query";
    // ...

    export const patientsRouter = trpc.router({
    createPatient,
    getPatientById,
    listInOrganization,
    updatePatient,
    });

    Domain routers are then merged into the appRouter:

    // src/routers/app.router.ts
    export const appRouter = trpc.router({
    patients: patientsRouter,
    patientSessions: patientSessionsRouter,
    profiles: profilesRouter,
    // ...
    });

    For access-control checks that load and validate a resource, define composable middleware that can be chained onto a procedure with .concat:

    // src/middleware/auth/can-access-audit-template.middleware.ts
    export function canAccessAuditTemplate({ getId }: CanAccessAuditTemplateOptions) {
    return authenticatedProcedure.use(async (opts) => {
    const id = getId(opts.input as Record<string, unknown>);
    const { data: template, error } = await auditTemplatesRepo.getById(id);

    if (error) throw new TRPCError({ code: "NOT_FOUND" });
    if (!hasAccessToAuditTemplate(template, opts.ctx.user)) throw new TRPCError({ code: "FORBIDDEN" });

    return opts.next({ ctx: { auditTemplate: template } });
    });
    }

    Then use .concat to attach it after .input:

    export const getById = authenticatedProcedure
    .input(getAuditTemplateByIdInputSchema)
    .concat(canAccessAuditTemplate({ getId: (input) => input.id as AuditTemplateId }))
    .query(async ({ input, ctx }) => {
    // ctx.auditTemplate is now available and typed
    });

    Use useTRPC() to get the typed proxy, then pass queryOptions into TanStack Query's useQuery:

    import { useTRPC } from "@repo/trpc/client";
    import { useQuery } from "@repo/react-query";

    function PatientList({ search }: { search: string }) {
    const trpc = useTRPC();

    const { data, isLoading, error } = useQuery(
    trpc.patients.listInOrganization.queryOptions({
    sortBy: "name",
    sortOrder: "asc",
    limit: 25,
    offset: 0,
    patientSearch: search || undefined,
    }),
    );
    }

    Pass TanStack Query options like enabled as the second argument to queryOptions:

    function SessionDetail({ sessionId }: { sessionId: SessionId }) {
    const trpc = useTRPC();

    const { data } = useQuery(
    trpc.patientSessions.getById.queryOptions(
    { id: sessionId },
    { enabled: !!sessionId },
    ),
    );
    }

    Use mutationOptions with useMutation. Invalidate related queries in onSuccess using queryKey():

    import { useTRPC } from "@repo/trpc/client";
    import { useMutation, useQueryClient } from "@repo/react-query";

    function useCreateClient(options?: { onSuccess?: () => void }) {
    const trpc = useTRPC();
    const queryClient = useQueryClient();

    return useMutation(
    trpc.patients.createPatient.mutationOptions({
    onSuccess: () => {
    queryClient.invalidateQueries({
    queryKey: trpc.patients.listInOrganization.queryKey(),
    });
    options?.onSuccess?.();
    },
    }),
    );
    }

    Use the fetch adapter to mount the router in a Next.js route handler:

    import { createTRPCFetchAdapter } from "@repo/trpc/server";

    const handler = createTRPCFetchAdapter({
    endpoint: "/api/trpc",
    createContext: ({ req }) => createContext(req),
    });

    export { handler as GET, handler as POST };
    Script Description
    check-types Typecheck with tsc --noEmit

    Modules

    client
    routers/app.router
    routers/audit-runs/create-response-trail.mutation
    routers/audit-runs/get-by-id.query
    routers/audit-runs/index
    routers/audit-runs/list-for-patient.query
    routers/audit-runs/list-recent-for-patient.query
    routers/audit-templates/create.mutation
    routers/audit-templates/delete.mutation
    routers/audit-templates/duplicate.mutation
    routers/audit-templates/get-by-id.query
    routers/audit-templates/index
    routers/audit-templates/list.query
    routers/audit-templates/toggle-sharing.mutation
    routers/audit-templates/update.mutation
    routers/chart-review-triggers/create.mutation
    routers/chart-review-triggers/delete.mutation
    routers/chart-review-triggers/index
    routers/chart-review-triggers/list.query
    routers/chart-review-triggers/update.mutation
    routers/contact-types/create-contact-type.mutation
    routers/contact-types/delete-contact-type.mutation
    routers/contact-types/get-contact-type.query
    routers/contact-types/index
    routers/contact-types/list-contact-types.query
    routers/contact-types/update-contact-type.mutation
    routers/contacts/create-contact.mutation
    routers/contacts/delete-contact.mutation
    routers/contacts/get-contact.query
    routers/contacts/index
    routers/contacts/list-contacts.query
    routers/contacts/update-contact.mutation
    routers/facilities/create.mutation
    routers/facilities/delete.mutation
    routers/facilities/index
    routers/facilities/list-in-organization.query
    routers/facilities/list-with-integrations.query
    routers/facilities/list-with-levels-of-care.query
    routers/facilities/update.mutation
    routers/integrations/get-integration-locations.query
    routers/integrations/index
    routers/integrations/sync-admissions.mutation
    routers/integrations/sync-patients.mutation
    routers/integrations/update.mutation
    routers/metrics/criteria-assistants.query
    routers/metrics/criteria-detail.query
    routers/metrics/filters
    routers/metrics/index
    routers/metrics/metrics-facilities.query
    routers/metrics/metrics-grouped.query
    routers/org-members/create-invite.mutation
    routers/org-members/index
    routers/org-members/list-pending-invites.query
    routers/org-members/list-roles.query
    routers/org-members/list-users.query
    routers/patient-charts/index
    routers/patient-charts/list-for-patient.query
    routers/patient-sessions/delete.mutation
    routers/patient-sessions/get-by-id.query
    routers/patient-sessions/get-recent-sessions.query
    routers/patient-sessions/index
    routers/patient-sessions/list-for-current-user.query
    routers/patient-sessions/list-for-patient.query
    routers/patient-sessions/modify-ai-note.mutation
    routers/patient-sessions/switch-template.mutation
    routers/patient-sessions/update-ai-summarized-note.mutation
    routers/patient-sessions/update-private-note.mutation
    routers/patient-sessions/update-session-time.mutation
    routers/patients/create-patient.mutation
    routers/patients/delete-patient.mutation
    routers/patients/get-patient-by-id.query
    routers/patients/get-patient-detail.query
    routers/patients/get-patient-overview.query
    routers/patients/index
    routers/patients/list-in-organization.query
    routers/patients/update-patient.mutation
    routers/profiles/index
    routers/profiles/list-in-organization.query
    routers/profiles/update-profile.mutation
    routers/review-dashboard/filters
    routers/review-dashboard/index
    routers/review-dashboard/review-dashboard-grouped.query
    routers/review-dashboard/review-dashboard-list.query
    routers/teams/add-team-members.mutation
    routers/teams/create-team.mutation
    routers/teams/index
    routers/teams/list-teams.query
    routers/teams/remove-team-member.mutation
    routers/templates/create.mutation
    routers/templates/delete.mutation
    routers/templates/duplicate.mutation
    routers/templates/get-by-id.query
    routers/templates/index
    routers/templates/list.query
    routers/templates/toggle-sharing.mutation
    routers/templates/update.mutation
    routers/user-prompts/create.mutation
    routers/user-prompts/delete.mutation
    routers/user-prompts/index
    routers/user-prompts/list.query
    routers/user-prompts/toggle-pin.mutation
    server
    tests