Comment créer un serveur GraphQL avec Node.js et Express

Un tutoriel simple sur la création d'un serveur GraphQL alimenté par Node.js et Express

Commencez par créer un nouveau projet Node.js, si vous n'en avez pas déjà configuré:

npm init --y

Cette commande crée lepackage.jsonfichier avec lequel nous devons travaillernpm.

Installez les packages npmexpress,graphqletexpress-graphql:

npm install express graphql express-graphql

Créé unapp.jsfichier, et commençons par l'initialisation duExpressserveur:

const express = require('express')

const app = express()

app.listen(3000, () => { console.log(‘App listening on port 3000’) })

Maintenant nous ajoutonsexpress-graphql. C'est unmiddleware, et nous l'appliquons uniquement à un itinéraire, le/graphqlroute:

const express = require('express')
const graphqlHTTP = require('express-graphql')

const app = express()

app.use(’/graphql’, graphqlHTTP())

app.listen(3000, () => { console.log(‘App listening on port 3000’) })

Il faut passer un objet qui contient leschemapropriété, qui doit contenir unschémadéfinition.

Il faut d'abord définir un schéma!

Créer unschema.jsfichier, et là-dedans, nous avons d'abord besoingraphql, puis en utilisant lesyntaxe de déstructuration d'objetnous obtenons leGraphQLSchema,GraphQLObjectTypeetGraphQLStringobjets dont nous aurons bientôt besoin:

const graphql = require('graphql')
const { GraphQLSchema, GraphQLObjectType, GraphQLString } = graphql

Ensuite, nous définissons la valeur du schéma en initialisant un nouveauGraphQLSchemainstance, en passant un objet qui contient unquerybiens. Cette propriété est une instance d'unGraphQLObjectTypeobjet:

const schema = new GraphQLSchema({
  query: new GraphQLObjectType({
    //...
  }),
})

module.exports = schema

À l'intérieur de ce nouvel objet, nous devons spécifier unname, et unfieldsparamètres. Cette dernière propriété est un objet qui contient un ensemble de propriétés, une pour chaque champ de notre schéma. Dans cet exemple, nous avons mis en place unhellodomaine:

const schema = new GraphQLSchema({
  query: new GraphQLObjectType({
    name: 'RootQueryType',
    fields: {
      hello: {
        type: GraphQLString,
        resolve() {
          return 'world'
        },
      },
    },
  }),
})

Leresolve()méthode renvoie la chaîneworld, ce qui signifie que lorsque nous demanderons lehellofield, nous récupérerons cette chaîne.

Voici le pleinschema.jscontenu du fichier:

const graphql = require('graphql')
const { GraphQLSchema, GraphQLObjectType, GraphQLString } = graphql

const schema = new GraphQLSchema({ query: new GraphQLObjectType({ name: ‘RootQueryType’, fields: { hello: { type: GraphQLString, resolve() { return ‘world’ }, }, }, }), })

module.exports = schema

Revenons maintenant à notreapp.jsdéposer.

Voici ce que nous avions:

const express = require('express')
const graphqlHTTP = require('express-graphql')

const app = express()

app.use(’/graphql’, graphqlHTTP())

app.listen(3000, () => { console.log(‘App listening on port 3000’) })

Nous avons maintenant besoin duschema.jsdéposer:

const schema = require('./schema.js')

et on ajoute que dans un objet on passe augraphqlHTTP()constructeur:

app.use(
  '/graphql',
  graphqlHTTP({
    schema: schema,
  })
)

D'accord!

Nous pouvons maintenant tester cela et voir si cela fonctionne. On peut utiliserGraphiQL, un excellent outil pour tester notre API GraphQL.

Il est déjà installé et pour permettre cela, nous devons passer une autre propriété augraphqlHTTPconstructeur:

app.use(
  '/graphql',
  graphqlHTTP({
    schema: schema,
    graphiql: true,
  })
)

Maintenant après avoir courunode app.js, en accédant auhttp://localhost:3000/graphqlURL avec le navigateur, vous verrez GraphiQL en action:

Et vous pouvez tester le premier appel d'API en passant cette requête:

{
  hello
}

Voici le résultat:

Construisons maintenant un schéma plus complexe.

Celui qui a des types imbriqués.

Un exemple que j'ai en tête est un article de blog.

Un article de blog a un titre, une description et un auteur. L'auteur a un nom.

Voyons cela.

Nous ajoutons d'abord l'ensemble des articles et des auteurs:

const posts = [
  {
    title: 'First post',
    description: 'Content of the first post',
    author: 'Flavio',
  },
  {
    title: 'Second post',
    description: 'Content of the second post',
    author: 'Roger',
  },
]

const authors = { Flavio: { name: ‘Flavio’, age: 36, }, Roger: { name: ‘Roger’, age: 7, }, }

C'est de là que nous obtiendrons les données.

Next, we define 3 GraphQLObjectTypeles instances:

  • authorType, qui définit les données de l'auteur
  • postType, qui définit les données de publication
  • queryType, le principal

Commençons par l'auteur. Un auteur a un nom et un âge.

Nous utilisons leGraphQLInttype, qu'il faut ajouter au require:

const { GraphQLSchema, GraphQLObjectType, GraphQLString, GraphQLInt } = graphql

//… const authorType = new GraphQLObjectType({ name: ‘Author’, fields: { name: { type: GraphQLString, }, age: { type: GraphQLInt, }, }, })

Vient ensuitepostType. Un article a un titre, une description (les deux chaînes) et un auteur. Un auteur est de typeauthorType, que nous venons de définir, et il a un résolveur.

Nous obtenons le nom de l'auteur de lasourceparamètre, qui sont les paramètres passés à l'objet de publication, et nous recherchons les données de l'auteur en fonction de cela. Nous le rendons.

const postType = new GraphQLObjectType({
  name: 'Post',
  fields: {
    title: {
      type: GraphQLString,
    },
    description: {
      type: GraphQLString,
    },
    author: {
      type: authorType,
      resolve: (source, params) => {
        return authors[source.author]
      },
    },
  },
})

Notez qu'une fonction de résolution peut être asynchrone, vous pouvez donc utiliser async / await pour rechercher des ressources à partir d'une base de données ou du réseau.

Ensuite, il y a queryType, le type de racine que nous ajouterons au schéma. Ici, nous définissons 2 champs:

  • postun seul article de blog, identifié par un identifiant
  • postsla liste des articles

les deux ont une fonction de résolveur pour rechercher les données dans lepostsdéployer:

const queryType = new GraphQLObjectType({
  name: 'Query',
  fields: {
    post: {
      type: postType,
      args: {
        id: { type: GraphQLInt },
      },
      resolve: (source, { id }) => {
        return posts[id]
      },
    },
    posts: {
      type: new GraphQLList(postType),
      resolve: () => {
        return posts
      },
    },
  },
})

Remarquez le nouveauGraphQLListtype, que nous utilisons pour envelopperpostTypepour signifier que c'est une liste depostTypeobjets. Nous devons l'exiger en plus:

const {
  GraphQLSchema,
  GraphQLObjectType,
  GraphQLString,
  GraphQLList,
  GraphQLInt,
} = graphql

C'est tout. Nous devons l'ajouter à notreschemaet nous sommes fixés:

const schema = new GraphQLSchema({
  query: queryType,
})

Voici le code complet:

const graphql = require('graphql')
const {
  GraphQLSchema,
  GraphQLObjectType,
  GraphQLString,
  GraphQLList,
  GraphQLInt,
} = graphql

const posts = [ { title: ‘First post’, description: ‘Content of the first post’, author: ‘Flavio’, }, { title: ‘Second post’, description: ‘Content of the second post’, author: ‘Roger’, }, ]

const authors = { Flavio: { name: ‘Flavio’, age: 36, }, Roger: { name: ‘Roger’, age: 7, }, }

const authorType = new GraphQLObjectType({ name: ‘Author’, fields: { name: { type: GraphQLString, }, age: { type: GraphQLInt, }, }, })

const postType = new GraphQLObjectType({ name: ‘Post’, fields: { title: { type: GraphQLString, }, description: { type: GraphQLString, }, author: { type: authorType, resolve: (source, params) => { return authors[source.author] }, }, }, })

const queryType = new GraphQLObjectType({ name: ‘Query’, fields: { post: { type: postType, args: { id: { type: GraphQLInt }, }, resolve: (source, { id }) => { return posts[id] }, }, posts: { type: new GraphQLList(postType), resolve: () => { return posts }, }, }, })

const schema = new GraphQLSchema({ query: queryType, })

module.exports = schema

Voir le code complet sur Glitch.


Plus de tutoriels graphql: