Thibault Mocellin

Thibault Mocellin

Développeur Full-Stack freelance basé à Annecy 🇫🇷

Utilisation de GraphQL avec Parse Server

Posted on June 20, 2017

Aujourd’hui nous allons voir comment utiliser GraphQL avec Parse Server. Pour ceux qui ne connaitraient pas, GraphQL est une spécification concernant un langage de requête qui a été initié par Facebook. Etant donné que GraphQL n’est pas un langage de requête pour bases de données, mais une spécification pour ce langage nous allons pouvoir l’utilisé avec Parse.

Dans cet article nous utiliserons Docker et nous partirons du principe que vous connaissez déjà les notions de base à propos de GraphQL sinon commencez par lire l’introduction à GraphQL.

Configuration

Nous allons commencer par configurer notre environnement Docker, créez un dossier parse-server-graphql et clonez le repository Parse Server Exemple :

mkdir parse-server-graphql && cd parse-server-graphql
git clone https://github.com/ParsePlatform/parse-server-example parse-server

Ensuite créez un dossier dashboard et ajoutez-y le Dockerfile suivant :

FROM node:6

ENV PARSE_DASHBOARD_VERSION 1.0.25
RUN npm install -g parse-dashboard@${PARSE_DASHBOARD_VERSION}
ENV PORT 4040
EXPOSE $PORT

CMD ["parse-dashboard"]

Enfin revenez à la racine du dossier parse-server-graphql et ajoutez le fichier docker-compose.yml suivant :

version: '2'
services:
  mongo:
    image: mongo:3
    container_name: 'mongo-db'
    volumes:
      - ./mongo/data:/db/data
    ports:
      - '27017:27017'
  api:
    build: ./parse-server
    container_name: 'parse-server'
    ports:
      - '1337:1337'
    environment:
      PORT: 1337
      DATABASE_URI: mongodb://mongo:27017
      APP_ID: 'parse-graphql'
      MASTER_KEY: 'master'
      PARSE_MOUNT: '/parse'
      SERVER_URL: 'http://192.168.99.100:1337/parse'
    volumes:
      - ./parse-server/cloud:/parse/cloud
      - ./parse-server/public:/parse/public
      - ./parse-server/graphql:/parse/graphql
    depends_on:
      - mongo
  dashboard:
    build: ./dashboard
    container_name: 'parse-dashboard'
    environment:
      PORT: 4040
      PARSE_DASHBOARD_ALLOW_INSECURE_HTTP: 'True'
      PARSE_DASHBOARD_SERVER_URL: 'http://192.168.99.100:1337/parse'
      PARSE_DASHBOARD_MASTER_KEY: 'master'
      PARSE_DASHBOARD_APP_ID: 'parse-graphql'
      PARSE_DASHBOARD_APP_NAME: 'GraphQL with Parse Server'
      PARSE_DASHBOARD_USER_ID: 'user'
      PARSE_DASHBOARD_USER_PASSWORD: 'password'
    ports:
      - '4040:4040'

Schéma

Maintenant que notre environnement Docker est configuré nous allons passer à la création du schéma GraphQL.

Dans le dossier parse-server créez un nouveau dossier nommé graphql et ajoutez-y le fichier schema.js :

mkdir graphql && cd graphql
touch schema.js

La première chose que nous allons faire est d’importer les différents types utilisés par notre schéma ainsi que Parse.

import {
  GraphQLBoolean,
  GraphQLFloat,
  GraphQLID,
  GraphQLInt,
  GraphQLList,
  GraphQLNonNull,
  GraphQLObjectType,
  GraphQLSchema,
  GraphQLString,
} from 'graphql'
import Parse from 'parse/node'

Type

Dans cet exemple nous allons déclarer un userType qui représentera l’objet User de Parse Server.

const userType = new GraphQLObjectType({
  name: 'User',
  description: 'A simple user',
  fields: () => ({
    id: {
      type: GraphQLID,
      resolve: obj => obj.id,
    },
    username: {
      type: GraphQLString,
      description: 'The username of the user.',
      resolve: obj => obj.get('username'),
    },
    emailVerified: {
      type: GraphQLBoolean,
      description: 'Define if the user has validate his email.',
      resolve: obj => obj.get('emailVerified'),
    },
    updatedAt: {
      type: GraphQLString,
      description: 'Last time user update data changes.',
      resolve: obj => obj.get('updatedAt').toString(),
    },
    createdAt: {
      type: GraphQLString,
      description: 'Date when the user was created',
      resolve: obj => obj.get('createdAt').toString(),
    },
  }),
})

Ici nous avons défini notre userType qui est un objet GraphQLObjectType, nous avons aussi défini son nom, sa description ainsi que l’ensemble des champs qu’il contient. Pour chaque champs on définit aussi le type, la description et le plus important la fonction resolve.

La fonction resolve va nous permettre de définir comment récupérer la valeur pour le champ en question. Dans notre cas obj représentera une classe Parse.Object donc on récupère la valeur de son champ de la manière suivante :

obj.get('nom_du_champ')

Query

Maintenant nous allons définir les requêtes de notre schéma. Nous définissons deux requêtes :

  • user : Renvoie un utilisateur en fonction de son Id.
  • users : Renvoie la liste des utilisateurs.
const user = {
  type: userType,
  args: {
    id: {
      description: 'The id of the user',
      type: new GraphQLNonNull(GraphQLString),
    },
  },
  resolve: (root, { id }) => {
    return new Parse.Query(Parse.User).equalTo('objectId', id).first()
  },
}

const users = {
  type: new GraphQLList(userType),
  resolve: root => {
    return new Parse.Query(Parse.User).find()
  },
}

Pour chaque requêtes on définit le type de résultat renvoyé par la requête :

  • user : userType
  • users : GraphQLList(userType)

Ensuite pour la requête user on définit un paramètre qui sera obligatoire qui est l’id de l’utilisateur.

Enfin comme pour les champs de userType on définit la fonction resolve, ici on renvoie simplement le résultat d’une Parse.Query.

Mutation

Afin de pouvoir ajouter de nouveaux utilisateurs nous allons définir une mutation :

const createUser = {
  type: userType,
  description: 'Create a new user',
  args: {
    username: {
      type: GraphQLString,
      description: 'The username of the user.',
    },
    email: {
      type: GraphQLString,
      description: 'The email adress of the user.',
    },
    password: {
      type: GraphQLString,
      description: 'The password of the user.',
    },
  },
  resolve: (value, { username, email, password }) => {
    var user = new Parse.User()
    user.set('username', username)
    user.set('password', password)
    user.set('email', email)
    return user.signUp()
  },
}

De la même façon que pour une requête nous définissons le type, ensuite on définit les différents paramètres nécessaires à la création de l’utilisateur. Enfin on définit la fonction resolve, Parse permet d’ajouter un nouvelle utilisateur de la manière suivante :

  • Déclaration d’une nouvelle objet User
  • Définition des valeurs des attributs
  • Exécution de la fonction signUp

Pour terminer on retourne le résultat user.signUp.

Définition du schéma

Avant de créer le schéma nous allons ajouter deux derniers types qui seront la racine de notre requête, et les points d’entrée dans notre schéma. Nous déterminons queryType qui prendra comme fields chacune des requêtes que nous avons défini auparavant et un mutationType qui prendra comme fields la mutation que nous avons créé.

var queryType = new GraphQLObjectType({
  name: 'queries',
  description: 'all qqueries',
  fields: () => ({
    // Queries goes here
    user,
    users,
  }),
})
var mutationType = new GraphQLObjectType({
  name: 'mutation',
  description: 'all mutations',
  fields: () => ({
    // Mutations goes here
    createUser,
  }),
})

Enfin nous définissons le schéma

export default new GraphQLSchema({
  query: queryType,
  mutation: mutationType,
})

Ajout de GraphQL à Parse

Nous avons défini le schéma, il ne nous reste plus qu’à ajouter GraphQL à notre serveur Parse avant de pouvoir tester.

Nous allons avoir besoin de plusieurs packages supplémentaires pour utiliser GraphQL :

yarn add express-graphql graphql
yarn add babel-cli babel-preset-es2015 --dev

Ensuite dans le fichier index.js de Parse ajoutez les imports suivants :

import GraphQLHTTP from 'express-graphql'
import schema from './graphql/schema'
import Parse from 'parse/node'

Enfin juste avant la déclaration du serveur HTTP ajoutez le code suivant :

//Initialize Parse
Parse.initialize(process.env.APP_ID || 'myAppId')
Parse.serverURL = process.env.SERVER_URL || 'http://localhost:1337/parse'

//GraphQL
app.use(
  '/graphql',
  GraphQLHTTP(request => {
    return {
      graphiql: true,
      pretty: true,
      schema: schema,
    }
  })
)

Premièrement on initialise Parse et ensuite on déclare notre serveur graphQL sur la route ‘/graphql’ on passe le schéma que nous avons défini, et on active graphiql.

Graphiql est une interface qui vous permettra de tester l’ensemble de vos requêtes et mutations.

Tout est prêt il ne reste plus qu’a lancer Docker :

docker-compose up

Et se rendre sur l’url votre-docker-machine-ip:1337/graphql.

Le code source est disponible ici.