// server.jsconstexpress=require('express')constserver=express()server.get('/',(req,res)=>{res.send('hello world!')})server.listen(3001,()=>{console.log('test server on port 3001')})
Перед тем как сервер сможет отдавать какие-либо данные клиенту ему нужно указать с какими данными придется работать. За описание данных отвечает схема.
// api/schema.jsconst{buildSchema}=require('graphql')// в type Query необходимо прописать запросы, которые сможет принимть сервер// pet - запрос на сервере; String - отдаем, к примеру, тип Stringmodule.exports=buildSchema(` type Query { pet: String }`)
Далее при запросу на http://localhost:3001/api вы сможете увидеть редактор graphiql.
Нам требуется научить GraphQL отдавать данные при, например, запросе на pet. Для этого используются резолверы - реализация запросов в свойстве rootValue.
1 2 3 4 5 6 7 8 9101112131415161718192021
// api/index.jsconstexpress=require('express')constgraphqlMiddleWare=require('express-graphql')// импортируем схему в файле index.jsconstschema=require('./schema.js')constapi=express()api.all('/api',graphqlMiddleWare({schema,graphiql:true,rootValue:{// 1 - название запроса; 2 - ф-я (реализация схемы)pet:()=>'test',},}))module.exports=api
Теперь при запросе в graphiQL (если graphiql: true) на:
Для изменения данных используются изменения или mutation. В schema.js добавим еще один тип - mutation, в нем определим функции, которые будут изменять данные.
Данные (например, пришедшие на изменение) в GraphQL называют input.
1234567
// НЕВЕРНО, так как **
// api/schema.js
type Mutation {
createPet(input: Pet!): Pet
updatePet(id: ID!, input: Pet!): Pet
deletePet(id: ID!): ID
}
Далее необходимо описать вышеприведенные функции как резолверы.
Для входных данных (а они в GraphQL называются словом input) нельзя ** использовать типы данных, которые мы определили ранее, например, Pet и которые мы используем в type Query.
В input-ах мы можем указывать значения по умолчанию.
Для каждого входного input нужно определить свой тип данных через ключевой слово input:
// api/index.jsconstexpress=require('express')constgraphqlMiddleWare=require('express-graphql')// импортируем схему в файле index.jsconstschema=require('./schema.js')letpets=require('./data').petsconstapi=express()// класс Pet будет отвечать за корректную инициализацию экземпляра PetclassPet{constructor({name,species='dog',steps=[],birthYear=2019,}={}){this.name=namethis.species=speciesthis.birthYear=birthYearthis.steps=stepsthis.id=pets.length+1}}api.all('/api',graphqlMiddleWare({schema,graphiql:true,rootValue:{// 1 - название запроса; 2 - ф-я (реализация схемы)pet:({id})=>{returnpets.find(function(pet){returnpet.id==id})},pets:()=>pets,createPet:({input})=>{letpet=newPet(input)pets.push(pet)returnpet},updatePet:({id,input})=>{constpet=pets.find(function(pet){returnpet.id==id})Object.assign(pet,input)returnpet},deletePet:({id})=>{constpet=pets.find(function(pet){returnpet.id==id})pets=pets.filter(function(pet){returnpet.id!=id})returnpet.id},},}))module.exports=api
Запросы в GrapiQL (getPets и updatePet это кастомные названия, чтобы GrapiQL мог выбрать query/mutation):
В папке api создадим файл model.js, в котором мы опишем модель для mongoose:
1 2 3 4 5 6 7 8 910111213141516171819202122232425
// api/model.jsconstmongoose=require('mongoose')constPet=newmongoose.Schema({//id: - за id будет отвечать MongoDBname:{type:String,required:true,},species:{type:String,required:true,},favFoods:[String],birthYear:Number,photo:String,steps:[{title:String,completed:Boolean,},],})module.exports=mongoose.model('Pet',Pet)
В файле index.js подключим mongoose, модель mongoose (реализованную ранее), подключимся к MongoDB и реализуем работу с запросами и mongoose:
// api/index.jsconstexpress=require('express')constgraphqlMiddleWare=require('express-graphql')// импортируем схему в файле index.jsconstschema=require('./schema.js')constmongoose=require('mongoose')mongoose.Promise=Promisemongoose.connect('mongodb://localhost:27017/graphql-intro')mongoose.connection.once('open',()=>console.log('connect to MongoDB'))// импортируем модель (mongoose)constPet=require('./model')constapi=express()api.all('/api',graphqlMiddleWare({schema,graphiql:true,rootValue:{// 1 - название запроса; 2 - ф-я (реализация схемы)pet:({id})=>Pet.findById(id),pets:()=>Pet.find({}),createPet:({input})=>{// метод mongoose create возвращает PromisereturnPet.create(input)},updatePet:({id,input})=>{returnPet.findByIdAndUpdate(id,input,{new:true,// то есть вернуть новый объект})},deletePet:({id})=>{returnPet.deleteOne({_id:id}).then(()=>{returnid})},},}))module.exports=api
Три запроса на создание, редактирование и удаление питомцев:
На данный момент схема описана через шаблонные строки в файле api/schema.js при вызове метода buildSchema. Но схему можно поместить в специальный файл - schema.graphql: