Gatsby Frontmatter Валидация

У меня есть несколько вопросов по настройке схемы.

данные/categories.json

[
    {
        "name": "Foo Bar",
        "slug": "foo-bar"
    },
    { 
        "name": "Fuz Baz",
        "slug": "fuz-baz"
    }
]

gatsby-config.js

  ...
  
  mapping: {
    "MarkdownRemark.frontmatter.author": `AuthorsJson.alias`,
    "MarkdownRemark.frontmatter.category": `CategoriesJson.name`
  }

gatsby-node.js

exports.createSchemaCustomization = ({ actions, schema }) => {
    const { createTypes } = actions;
    const typeDefs = [
        `type AuthorsJson implements Node @dontInfer {
            alias: String,
            name: String
            slug: String,
            bio: String,
            profile: String
            posts: [MarkdownRemark] @link(by: "frontmatter.author.alias", from: "alias")
        }`,
        `type CategoriesJson implements Node @dontInfer {
            name: String,
            slug: String,
            posts: [MarkdownRemark] @link(by: "frontmatter.category.name", from: "name")
        }`,
    ];

    createTypes(typeDefs);
}

Основной вопрос заключается в том, как мне выполнить валидацию переднего плана?

  1. Из вопроса выше, как мне сила для каждого сообщения предоставить категорию, И категория должна существовать в categories.json (например, они не могут создать свою собственную категорию)?
  2. Если передняя часть представляет собой массив, как мне убедиться, что в массиве существует не более 3 элементов?

Спасибо!

Опция 1:

Вот что у меня есть в gatsby-node.js:

var categories = [];
var aliases = [];

exports.onCreateNode = ({ node, getNode, actions }) => {
  const { createNodeField } = actions

  if (node.internal.type === `CategoriesJson`) {
      categories.push(node.name);
  }

  if (node.internal.type === `AuthorsJson`) {
      aliases.push(node.alias);
  }

  if (node.internal.type === `MarkdownRemark`) {
    const slug = createFilePath({ node, getNode, basePath: `pages` })

    createNodeField({
      node,
      name: `slug`,
      value: slug,
    })

    if (node.frontmatter.author === null || node.frontmatter.author === undefined) {
        throw "Page is missing alias: " + node.fileAbsolutePath;
    }

    if (aliases.indexOf(node.frontmatter.author) == -1) {
        throw "Page has invalid alias: " + node.fileAbsolutePath;
    }

    if (node.frontmatter.category === null || node.frontmatter.category === undefined) {
        throw "Page is missing category: " + node.fileAbsolutePath;
    }

    if (categories.indexOf(node.frontmatter.category) == -1) {
        throw "Page has invalid category ('" + node.frontmatter.category +"'): " + node.fileAbsolutePath;
    }
    
    if (node.frontmatter.tags.length > 3) {
        throw "Page has more than 3 tags: " + node.fileAbsolutePath;
    }
  }
}

Есть ли способ лучше?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Что такое Apollo Client и зачем он нужен?
Что такое Apollo Client и зачем он нужен?
Apollo Client - это полнофункциональный клиент GraphQL для JavaScript-приложений, который упрощает получение, управление и обновление данных в...
1
0
21
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете упростить все условия:

let categories = [];
let aliases = [];

exports.onCreateNode = ({ node, getNode, actions }) => {
  const { createNodeField } = actions

  if (node.internal.type === `CategoriesJson`) {
      categories.push(node.name);
  }

  if (node.internal.type === `AuthorsJson`) {
      aliases.push(node.alias);
  }

  if (node.internal.type === `MarkdownRemark`) {
    const slug = createFilePath({ node, getNode, basePath: `pages` })

    createNodeField({
      node,
      name: `slug`,
      value: slug,
    })

    if (!node.frontmatter.author || !aliases.includes(node.frontmatter.author)) {
        throw "Page is missing alias: " + node.fileAbsolutePath;
    }


    if (!node.frontmatter.category || !categories.includes(node.frontmatter.category)) {
        throw "Page is missing category: " + node.fileAbsolutePath;
    }

   
    if (node.frontmatter.tags.length > 3) {
        throw "Page has more than 3 tags: " + node.fileAbsolutePath;
    }
  }
}

Я также добавил let вместо var, что в настоящее время считается устаревшим. Проверьте разницу в https://www.javascripttutorial.net/es6/difference-between-var-and-let/ и замените indexOf == -1 на более семантический includes.

В остальном подход мне кажется вполне солидным, хороший способ.

If front matter is an array, how do I ensure that no more than 3 elements exist in the array?

По умолчанию (и так и должно быть) frontmatter всегда будет объектом.

Другие вопросы по теме