如何在Nexus GraphQL关系字段的mutation中阻止/忽略指定字段被提交
你可以通过以下三种方式实现需求,可根据业务场景选择:
方案1:直接在crud mutation配置中使用computedInputs处理嵌套字段
和你单独创建帖子时的处理逻辑一致,直接在createUser的配置中添加嵌套字段校验逻辑,既可以抛出错误也可以直接忽略/覆盖用户传入的isPublished值:
const UserMutation = extendType({ type: "Mutation", definition(t) { t.crud.createOneUser({ alias: "createUser", inputs: { posts: { relateBy: "create", }, }, computedInputs: { posts: ({ args }) => { const postCreateData = args.data.posts?.create if (!postCreateData) return args.data.posts // 兼容单条/批量创建帖子的场景 const formatPost = (post) => { // 如果要抛出错误打开下面两行注释 // if ('isPublished' in post) { // throw new Error("创建关联帖子时不允许手动设置isPublished字段") // } // 直接删除用户传入的isPublished字段,强制设置默认值 delete post.isPublished return { ...post, isPublished: false } } return { create: Array.isArray(postCreateData) ? postCreateData.map(formatPost) : formatPost(postCreateData) } } } }); }, });
方案2:自定义输入类型,从根上移除isPublished字段
直接定义关联创建时的Post输入类型,不暴露isPublished字段,客户端在请求阶段就会因为类型校验不通过无法传入该字段,安全性最高:
// 定义不带isPublished的帖子创建输入类型 const PostCreateWithoutUserInput = inputObjectType({ name: "PostCreateWithoutUserInput", definition(t) { t.nonNull.string("content") // 不定义isPublished字段,客户端就无法传入 } }) // 定义用户创建输入类型,关联上面的帖子输入类型 const UserWithPostsCreateInput = inputObjectType({ name: "UserWithPostsCreateInput", definition(t) { t.nonNull.string("name") t.nonNull.string("email") t.list.field("posts", { type: PostCreateWithoutUserInput }) } }) // 自定义mutation实现创建逻辑 const UserMutation = extendType({ type: "Mutation", definition(t) { t.field("createUser", { type: "User", args: { data: nonNull(UserWithPostsCreateInput) }, resolve: async (_, { data }, { prisma }) => { return prisma.user.create({ data: { name: data.name, email: data.email, posts: { create: data.posts.map(post => ({ ...post, isPublished: false // 强制设置默认值 })) } } }) } }) } })
方案3:使用Prisma中间件全局拦截校验
如果有多处需要关联创建帖子的场景,可以直接用Prisma中间件做全局校验,不用每个mutation单独写逻辑:
// 初始化Prisma后添加中间件 const prisma = new PrismaClient() prisma.$use(async (params, next) => { // 拦截所有用户创建操作 if (params.model === "User" && params.action === "create") { const postCreateList = params.args.data.posts?.create if (!postCreateList) return next(params) const posts = Array.isArray(postCreateList) ? postCreateList : [postCreateList] posts.forEach(post => { if ("isPublished" in post) { throw new Error("不允许手动设置帖子发布状态") // 需要忽略的话直接执行 delete post.isPublished 即可 } post.isPublished = false }) } return next(params) })
内容的提问来源于stack exchange,提问作者user1945290
相关产品推荐
相关产品推荐

