T3 - app dir - tRPC + Prisma + Custom auth
Hello!
Is there an alternative to using the createAction function for mutations and deletions on the client? I'm implementing it in a new app directory, and while fetching data is smooth, creating or editing data is challenging. I can't get the req in
Is there an alternative to using the createAction function for mutations and deletions on the client? I'm implementing it in a new app directory, and while fetching data is smooth, creating or editing data is challenging. I can't get the req in
createInnerTRPCContextcreateInnerTRPCContext, so I can't access the cookie to verify authentication. Can I use createTRPCContextcreateTRPCContext instead of createInnerTRPCContextcreateInnerTRPCContext for actions?interface CreateContextOptions {
headers: Headers;
prisma: typeof prisma;
user: User | null;
}
export const createInnerTRPCContext = async (opts: CreateContextOptions) => ({
headers: opts.headers,
prisma,
user: opts.user,
});
export const createTRPCContext = async (opts: FetchCreateContextFnOptions) => {
const { req } = opts;
const reqWithCookies = req as NextRequest;
const token = await getTokens(reqWithCookies.cookies, AUTH_CONFIG);
return createInnerTRPCContext({
headers: opts.req.headers,
prisma,
user: token ? mapFirebaseTokensToUser(token) : null,
});
};
const t = initTRPC.context<typeof createTRPCContext>().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError: error.cause instanceof ZodError ? error.cause.flatten() : null,
},
};
},
});
export const createAction = experimental_createServerActionHandler(t, {
async createContext() {
const ctx = await createInnerTRPCContext({
headers: headers(),
user: null,
prisma,
});
return ctx;
},
});
export const createTRPCRouter = t.router;
export const publicProcedure = t.procedure;
const enforceUserIsAuthed = t.middleware(async ({ ctx, next }) => {
if (!ctx.user) {
throw new TRPCError({
});
}
return next({
ctx: {
prisma: ctx.prisma,
user: ctx.user,
},
});
});
export const privateProcedure = t.procedure.use(enforceUserIsAuthed);interface CreateContextOptions {
headers: Headers;
prisma: typeof prisma;
user: User | null;
}
export const createInnerTRPCContext = async (opts: CreateContextOptions) => ({
headers: opts.headers,
prisma,
user: opts.user,
});
export const createTRPCContext = async (opts: FetchCreateContextFnOptions) => {
const { req } = opts;
const reqWithCookies = req as NextRequest;
const token = await getTokens(reqWithCookies.cookies, AUTH_CONFIG);
return createInnerTRPCContext({
headers: opts.req.headers,
prisma,
user: token ? mapFirebaseTokensToUser(token) : null,
});
};
const t = initTRPC.context<typeof createTRPCContext>().create({
transformer: superjson,
errorFormatter({ shape, error }) {
return {
...shape,
data: {
...shape.data,
zodError: error.cause instanceof ZodError ? error.cause.flatten() : null,
},
};
},
});
export const createAction = experimental_createServerActionHandler(t, {
async createContext() {
const ctx = await createInnerTRPCContext({
headers: headers(),
user: null,
prisma,
});
return ctx;
},
});
export const createTRPCRouter = t.router;
export const publicProcedure = t.procedure;
const enforceUserIsAuthed = t.middleware(async ({ ctx, next }) => {
if (!ctx.user) {
throw new TRPCError({
});
}
return next({
ctx: {
prisma: ctx.prisma,
user: ctx.user,
},
});
});
export const privateProcedure = t.procedure.use(enforceUserIsAuthed);