Уф, это полный рот. В первой части серии мы рассмотрим настройку экспресс-схем и схем GraphQL.

Если вы хотите узнать больше о том, почему выбрать GraphQL вместо архитектуры REST, вот ссылка, по которой вы можете перейти, чтобы узнать больше.

Https://dev-blog.apollodata.com/graphql-vs-rest-5d425123e34b

Давайте начнем.

mkdir server
cd server
touch app.js
npm init

Мы хотим запустить новый пустой проект и init. Вы можете просто нажать Enter после npm init или дать проекту имя.

npm install express graphql express-graphql

Наши пакеты для настройки express, и нам нужен express-graphql, потому что обычный экспресс не знает, как обрабатывать запросы graphql.

// app.js
const express = require('express')
const graphqlHTTP = require('express-graphql')
const app = express()
// binding graphql to express
app.use('/graphql', graphqlHTTP({
}));
app.listen(4000, () => {
  console.log('now listening for requests on port 4000');
});

Теперь мы говорим express, что хотим использовать localhost: 4000 / graphql для обработки всех наших запросов. Но если вы пойдете туда сейчас, то увидите ошибку. Убедитесь, что вы запускаете приложение в терминале! Если у вас нет nodemon, я настоятельно рекомендую npm i -g nodemon. Он следит за вашими файлами на предмет изменений, поэтому это отличный инструмент для разработки.

nodemon app.js

Нам нужно сообщить express-graphql о схеме данных, чтобы он знал, как данные выглядят, и как их обслуживать и разрешать. Итак, давайте спроектируем схему!

mkdir schema
cd schema
touch schema.js

Здесь мы создадим файл схемы.

// schema.js
const graphql = require('graphql')
const { 
  GraphQLObjectType,
  GraphQLString,
  GraphQLInt,
  GraphQLBoolean,
  GraphQLSchema
} = graphql
const TaskType = new GraphQLObjectType({
  name: 'Task',
  fields: () => ({
    id: { type: GraphQLInt },
    name: { type: GraphQLString },
    completed: { type: GraphQLBoolean }
  })
})
const RootQuery = new GraphQLObjectType({
    name: 'RootQueryType',
    fields: {
      task: {
        type: TaskType,
        args: { id: { type: GraphQLInt } },
        resolve(parent, args) {
        // code to get data from db
      }
    }
  }
})
module.exports = new GraphQLSchema({
  query: RootQuery
})

Много чего только что произошло. Мы определяем очень простой тип задачи или, если хотите, «модель». Все, что он знает, - это то, какие данные он хранит. Следующая часть - это наш корневой запрос, с помощью которого мы переходим в структуру графа и находим что-то. Аргумент «поля» - это термин запроса. Нам обязательно нужно будет его расширить, так как это только один. Может быть, что-то вроде «задач», которое вернет список всех задач. Давайте рассмотрим этот запрос, который мы написали выше. «Задача» - это то, что мы будем запрашивать, и нам нужно передать аргумент «id», который затем вернет все, что найдено в базе данных с этим идентификатором. Если это не имеет смысла, я думаю, что в следующем разделе будет показан пример.

Но сначала давайте добавим эту схему в наше экспресс-приложение.

// app.js
const schema = require('./schema/schema')
const express = require('express')
const graphqlHTTP = require('express-graphql')
const app = express()
app.use('/graphql', graphqlHTTP({
  schema: schema
}))
...

Хороший! Мы успешно подключили схему и все, что нам нужно, чтобы поиграть! А пока давайте воспользуемся фиктивными данными и настроим сервер в следующем руководстве. Нам также понадобится способ проанализировать эти данные и получить идентификатор.

// schema.js 
...
const tasks = [
  { name: 'Go to the grocery store', completed: false, id: 1 },
  { name: 'Pick up dry cleaning', completed: true, id: 2 },
  { name: 'Write GraphQL tutorial', completed: false, id: 3 },
  { name: 'Clean up garage', completed: false, id: 4 },
  { name: 'Make a really good sandwich', completed: true, id: 5 }
]
function find(collection, id){
  for (const key of Object.keys(collection)) {
    if (collection[key].id === id) return collection[key]
  }
}
const TaskType = new GraphQLObjectType({
  name: 'Task',
  fields: () => ({
    id: { type: GraphQLInt },
    name: { type: GraphQLString },
    completed: { type: GraphQLBoolean }
  })
})
const RootQuery = new GraphQLObjectType({
  name: 'RootQueryType',
  fields: {
    task: {
      type: TaskType,
      args: { id: { type: GraphQLInt } },
      resolve(parent, args) {
        return find(tasks, args.id)
      }
    }
  }
})
module.exports = new GraphQLSchema({
  query: RootQuery
})

Итак, теперь все, что нам нужно сделать, это протестировать! К счастью, в graphql есть отличный инструмент под названием «graphiql», который представляет собой игровую площадку для тестирования ваших запросов. Давайте добавим этот инструмент.

// app.js
const express = require('express')
const graphqlHTTP = require('express-graphql')
const app = express()
const schema = require('./schema/schema')
app.use('/graphql', graphqlHTTP({
  schema: schema,
  graphiql: true
}))
app.listen(4000, () => {
  console.log('now listening for requests on port 4000')
})

Посмотрите http: // localhost: 4000 / graphql, и вы увидите экран, показанный ниже!

Слева есть несколько полезных советов о том, как начать работу с запросами, а справа - самодокументированный дизайн схемы. Это так круто! Вы также можете изучить документацию справа, чтобы узнать, какие данные ожидаются и как использовать запрос. Давайте попробуем наш единственный запрос.

query {
  task(id: 1) {
    id
    name
    completed
  }
}

И ответ ...

{
  "data": {
    "task": {
      "id": 1,
      "name": "Go to the grocery store",
      "completed": false
    }
  }
}

Хорошо! Мы работаем с express и graphql. Не так уж сложно, правда? В следующем руководстве мы рассмотрим другие запросы и настройку базы данных. А пока попробуйте добавить свои собственные запросы!