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.