如何为 Gatsby 页面查询创建自定义解析器?

How to create custom resolvers for Gatsby page queries?

我有一个 Gatsby 应用程序从 Sanity 中提取数据。 这是 course.js:

的 Sanity 架构
import video from './video'

export default {
    // Computer name
    name: `courses`,
    // Visible title
    title: `Courses`,
    type: `document`,
    fields: [
        {
            name: `title`,
            title: `Course title`,
            type: `string`,
            description: `Name of the course`
        },
        {
            name: `slug`,
            title: `slug`,
            type: `slug`,
            options: {
                source: `title`,
                maxLength: 100,
            }
        },
        {
            name: `price`,
            title: `Price`,
            type: `number`
        },
        {
            name: `thumbnail`,
            title: `Thumbnail`,
            type: `image`,
            options: {
                hotspot: true,
            }
        },
        {
            name: `playlist`,
            title: `Playlist`,
            type: `array`,
            of: [
                {
                    title: `Video`,
                    name: `video`,
                    type: `video`,
                }
            ]
        },
    ]
}

这是 video.js 的 Sanity 架构:

export default {
    // Computer name
    name: `video`,
    // Visible title
    title: `Video`,
    type: `object`,
    fields: [
        { name: `title`, type: `string`, title: `Video title` },
        { name: `url`, type: `url`, title: `URL` },
        { name: `public`, title: `public`, type: `boolean`, initialValue: false }
    ]
}

这个Gatsby页面查询:

{
  allSanityCourses {
    nodes {
      title
      price
      playlist {
        url
        title
        public
      }
    }
  }
}

结果:

{
  "data": {
    "allSanityCourses": {
      "nodes": [
        {
          "title": "Master VS Code",
          "price": 149,
          "playlist": [
            {
              "url": "https://www.youtube.com/watch?v=PRz1Nv9GUzs",
              "title": "Introduction",
              "public": true
            },
            {
              "url": "https://www.youtube.com/watch?v=PRz1Nv9GUzs",
              "title": "Philosophy",
              "public": false
            },
            {
              "url": "https://www.youtube.com/watch?v=PRz1Nv9GUzs",
              "title": "Tech and Tools",
              "public": false
            },
            {
              "url": "https://www.youtube.com/watch?v=PRz1Nv9GUzs",
              "title": "Integration",
              "public": true
            },
            {
              "url": "https://www.youtube.com/watch?v=PRz1Nv9GUzs",
              "title": "Extensions",
              "public": false
            }
          ]
        }
      ]
    }
  },
  "extensions": {}
}

为了防止 url 字段被注入运行此 Gatsby 页面查询的 React 组件(因为这些 urls 是付费的),我需要删除它,如果 public 字段设置为 false.

我试过将其插入 gastby-node.js:

exports.createSchemaCustomization = ({ actions, schema }) => {
    const { createTypes } = actions
    const typeDefs = [
        schema.buildObjectType({
            name: "SanityCourses",
            fields: {
                playlist: {
                    type: "[SanityVideo]",
                    url: {
                        type: "String",
                        resolve: (source) => "nope"
                    },
                },
            },
            interfaces: ["Node"],
        }),
    ]
    createTypes(typeDefs)
}

并且:

exports.createResolvers = ({ createResolvers }) => {
    const resolvers = {
        SanityCourses: {
            playlist: {
                type: "[SanityVideo]",
                url: {
                    type: "String",
                    resolve(source, args, context, info) {
                        return "nope"
                    },
                }
            },
        },
    }
    createResolvers(resolvers)
}

但这两个似乎都不起作用。 url 字段 returns url 一如既往。解析器甚至似乎都没有触发(我试过将 console.log() 放入其中)。

如果 public 字段设置为 false,或提供有关如何删除 url 字段的任何帮助,我们将不胜感激。

放弃 createSchemaCustomization 中的尝试,因为您不需要在此处自定义架构(尽管我相信有一种方法可以使用它来实现您想要的,但预计其中的数据不会来自现有节点,这种未声明的依赖关系会产生缓存问题。

然后将您的 createResolvers 函数更新为如下内容:

exports.createResolvers = ({ createResolvers }) => {
  createResolvers({
    SanityVideo: {
      safeUrl: {
        type: "String",
        resolve: (source, args, context, info) => source.public ? source.url : null
      },
    },
  })
}
  1. 我不相信解析器可以替换源自模式的节点(字段),因此使用 safeUrl 而不是 url
  2. 您要添加字段的类型是 SanityVideo,父节点是什么并不重要——这将应用于数据中 SanityVideo 的所有实例