| | 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, |
| | }, |
| | }); |
| | }); |
| |
|