| import { createClient } from "@api/services/supabase"; |
| import type { Session } from "@api/utils/auth"; |
| import { verifyAccessToken } from "@api/utils/auth"; |
| import { getGeoContext } from "@api/utils/geo"; |
| import type { Database } from "@midday/db/client"; |
| import { db } from "@midday/db/client"; |
| import type { SupabaseClient } from "@supabase/supabase-js"; |
| import { initTRPC, TRPCError } from "@trpc/server"; |
| import type { Context } from "hono"; |
| import superjson from "superjson"; |
| import { withPrimaryReadAfterWrite } from "./middleware/primary-read-after-write"; |
| import { withTeamPermission } from "./middleware/team-permission"; |
|
|
| type TRPCContext = { |
| session: Session | null; |
| supabase: SupabaseClient; |
| db: Database; |
| geo: ReturnType<typeof getGeoContext>; |
| teamId?: string; |
| forcePrimary?: boolean; |
| }; |
|
|
| export const createTRPCContext = async ( |
| _: unknown, |
| c: Context, |
| ): Promise<TRPCContext> => { |
| const accessToken = c.req.header("Authorization")?.split(" ")[1]; |
| const session = await verifyAccessToken(accessToken); |
| const supabase = await createClient(accessToken); |
|
|
| |
| const geo = getGeoContext(c.req); |
|
|
| |
| const forcePrimary = c.req.header("x-force-primary") === "true"; |
|
|
| return { |
| session, |
| supabase, |
| db, |
| geo, |
| forcePrimary, |
| }; |
| }; |
|
|
| const t = initTRPC.context<TRPCContext>().create({ |
| transformer: superjson, |
| }); |
|
|
| export const createTRPCRouter = t.router; |
| export const createCallerFactory = t.createCallerFactory; |
|
|
| const withPrimaryDbMiddleware = t.middleware(async (opts) => { |
| return withPrimaryReadAfterWrite({ |
| ctx: opts.ctx, |
| type: opts.type, |
| next: opts.next, |
| }); |
| }); |
|
|
| const withTeamPermissionMiddleware = t.middleware(async (opts) => { |
| return withTeamPermission({ |
| ctx: opts.ctx, |
| next: opts.next, |
| }); |
| }); |
|
|
| export const publicProcedure = t.procedure.use(withPrimaryDbMiddleware); |
|
|
| export const protectedProcedure = t.procedure |
| .use(withTeamPermissionMiddleware) |
| .use(withPrimaryDbMiddleware) |
| .use(async (opts) => { |
| const { teamId, session } = opts.ctx; |
|
|
| if (!session) { |
| throw new TRPCError({ code: "UNAUTHORIZED" }); |
| } |
|
|
| return opts.next({ |
| ctx: { |
| teamId, |
| session, |
| }, |
| }); |
| }); |
|
|