Mercurius上下文内Prisma报Undefined错误求助
问题:Fastify + Mercurius 上下文传递Prisma为undefined
错误信息
{ "type": "GraphQLError", "message": "Cannot read properties of undefined (reading 'user')", "stack": "TypeError: Cannot read properties of undefined (reading 'user')" }
相关代码
上下文传递代码
import AltairFastify from "altair-fastify-plugin"; import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify"; import mercurius from "mercurius"; import mercuriusCodegen from "mercurius-codegen"; import { makeSchema } from "nexus"; import { schemaTypes } from "./graphql/index"; import path from "path"; const buildContext = (fastify: FastifyInstance) => async (req: FastifyRequest, _reply: FastifyReply) => ({ req, prisma: fastify.prisma, }); const schema = makeSchema({ types: schemaTypes, outputs: { schema: `${__dirname}/generated/schema.graphql`, typegen: `${__dirname}/generated/typings.ts`, }, contextType: { module: path.join(process.cwd(), "src", "graphql", "context.ts"), export: "Context", }, }); export async function initGraphql(app: FastifyInstance) { try { await app.register(mercurius, { schema, graphiql: false, ide: false, path: "/graphql", allowBatchedQueries: true, context: buildContext(app), }); await app.register(AltairFastify, { path: "/altair", baseURL: "/altair/", endpointURL: "/graphql", }); await mercuriusCodegen(app, { targetPath: `${__dirname}/generated/graphql.ts`, }); } catch (err: unknown) { app.log.error(err); } }
Prisma插件代码
import fp from "fastify-plugin"; import { PrismaClient } from "@prisma/client"; /** * Prisma plugin for Fastify. */ export default fp(async (fastify) => { // Initialize Prisma client const prisma = new PrismaClient(); // Decorate Fastify with Prisma client instance fastify.decorate("prisma", prisma); // Add a hook to close the Prisma client when Fastify is shutting down fastify.addHook("onClose", async (instance) => { await prisma.$disconnect(); }); fastify.log.info("Prisma started..."); });
Nexus Resolver代码
export const UserMutation = mutationType({ definition(t) { t.field("createUser", { type: UserType, args: { firstName: nonNull(stringArg()), lastName: nonNull(stringArg()), phoneNumber: nonNull(stringArg()), otp: nonNull(stringArg()), }, resolve: async (_parent, args, { req, prisma }) => { console.log(prisma); const { jwt } = req.server; const user = await prisma.user.create({ data: args, select: { id: true, // 更多字段 }, }); const token = jwt.signToken(user.id); return { ...user, token }; }, }); }, });
问题描述
Resolver中prisma始终为undefined,已确认Prisma插件内部实例化正常,直接在Resolver中实例化Prisma Client也能成功,但通过上下文传递失败,使用fastify-starter模板。
解决方案
1. 调整插件注册顺序(核心修复)
Fastify的装饰器仅在插件注册完成后生效,必须先注册Prisma插件,再初始化GraphQL。
在主入口文件(如app.ts)中确保顺序如下:
import fastify from "fastify"; import prismaPlugin from "./prisma-plugin"; import { initGraphql } from "./graphql/init"; const app = fastify(); // 第一步:注册Prisma插件 await app.register(prismaPlugin); // 第二步:初始化GraphQL await initGraphql(app); await app.listen({ port: 3000 });
若先初始化GraphQL再注册Prisma插件,buildContext执行时fastify.prisma还未被装饰,会直接返回undefined。
2. 验证Context类型定义(可选)
确保src/graphql/context.ts中的Context接口包含prisma字段,避免类型不匹配:
import type { FastifyRequest } from "fastify"; import type { PrismaClient } from "@prisma/client"; export interface Context { req: FastifyRequest; prisma: PrismaClient; }
3. 确认插件作用域配置
你的Prisma插件已使用fastify-plugin包装,这会将装饰器暴露到全局作用域,确保Mercurius能访问到fastify.prisma,这部分代码无需修改。
内容的提问来源于stack exchange,提问作者Blatzo
相关产品推荐
相关产品推荐

