Creating our GraphQL backend server

Let's get started with the backend server:

  1. First, inside the apollo project (the one we created with create-react-app), we need to create a new directory called backend, initialize a package.json file, and create inside the src folder:
      cd apollo
mkdir backend
cd backend
npm init -y
mkdir src

  1. Now we need to install these dependencies:
      npm install cors express express-graphql graphql graphql-tools 
mongoose nodemon babel-preset-es2015


npm install -g babel-cli
  1. In our package.json file, we need to modify our start script to use nodemon:
      "scripts": {
"start": "nodemon src/app.js --watch src --exec babel-node
--presets es2015"
}
File: package.json
  1. Then we need to create our app.js file, in which we are going to create our GraphQL middleware:
  // Dependencies
import express from 'express';
import expressGraphQL from 'express-graphql';
import cors from 'cors';
import graphQLExpress from 'express-graphql';
import { makeExecutableSchema } from 'graphql-tools';

// Query
import { typeDefs } from './types/Query';
import { resolvers } from './types/Resolvers';

// Defining our schema with our typeDefs and resolvers
const schema = makeExecutableSchema({
typeDefs,
resolvers
});

// Intializing our express app
const app = express();

// Using cors
app.use(cors());

// GraphQL Middleware
app.use('/graphiql', graphQLExpress({
schema,
pretty: true,
graphiql: true
}));

// Listening port 5000
app.listen(5000);

console.log('Server started on port 5000');
File: src/app.js
  1. As you can see, we have included our typeDefs and resolvers from types folder, so let's create that directory and create our Query file:
  export const typeDefs = [`
# Scalar Types (custom type)
scalar DateTime

# Tweet Type (should match our Mongo schema)
type Tweet {
_id: String
tweet: String
author: String
createdAt: DateTime
}

# Query
type Query {
# This query will return a single Tweet
getTweet(_id: String): Tweet

# This query will return an array of Tweets
getTweets: [Tweet]
}

# Mutations
type Mutation {
# DateTime is a custom Type
createTweet(
tweet: String,
author: String,
createdAt: DateTime
): Tweet

# Mutation to delete a Tweet
deleteTweet(_id: String): Tweet

# Mutation to update a Tweet (! means mandatory).
updateTweet(
_id: String!,
tweet: String!
): Tweet
}

# Schema
schema {
query: Query
mutation: Mutation
}
`];
File: src/types/Query.js
  1. After we have created our Query file, we need to add our resolvers. These are the functions that are executed for each Query and Mutation. We are also going to define our custom DateTime type using GraphQLScalarType:
  // Dependencies
import { GraphQLScalarType } from 'graphql';
// TweetModel (Mongo Schema)
import TweetModel from '../model/Tweet';
// Resolvers
export const resolvers = {
Query: {
// Receives an _id and returns a single Tweet.
getTweet: _id => TweetModel.getTweet(_id),
// Gets an array of Tweets.
getTweets: () => TweetModel.getTweets()
},
Mutation: {
// Creating a Tweet passing the args (Tweet object), the _ is
// the root normally is undefined

createTweet: (_, args) => TweetModel.createTweet(args),
// Deleting a Tweet passing in the args the _id of the Tweet
// we want to remove

deleteTweet: (_, args) => TweetModel.deleteTweet(args),
// Updating a Tweet passing the new values of the Tweet we
// want to update

updateTweet: (_, args) => TweetModel.updateTweet(args)
},
// This DateTime will return the current date.
DateTime: new GraphQLScalarType({
name: 'DateTime',
description: 'Date custom scalar type',
parseValue: () => new Date(),
serialize: value => value,
parseLiteral: ast => ast.value
})
};
File: src/types/Resolvers.js

  1. Finally, we need to create our tweet model:
  // Dependencies
import mongoose from 'mongoose';

// Connecting to Mongo
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost:27017/twitter', {
useNewUrlParser: true
});

// Getting Mongoose Schema
const Schema = mongoose.Schema;

// Defining our Tweet schema
const tweetSchema = new Schema({
tweet: String,
author: String,
createdAt: Date,
});

// Creating our Model
const TweetModel = mongoose.model('Tweet', tweetSchema);

export default {
// Getting all the tweets and sorting descending
getTweets: () => TweetModel.find().sort({ _id: -1 }),
// Getting a single Tweet using the _id
getTweet: _id => TweetModel.findOne({ _id }),
// Saving a Tweet
createTweet: args => TweetModel(args).save(),
// Removing a Tweet by _id
deleteTweet: args => {
const { _id } = args;

TweetModel.remove({ _id }, error => {
if (error) {
console.log('Error Removing:', error);
}
});

// Even when we removed a tweet we need to return the object
// of the tweet

return args;
},
// Updating a Tweet (just the field tweet will be updated)
updateTweet: args => {
const { _id, tweet } = args;

// Searching by _id and then update tweet field.
TweetModel.update({ _id }, {
$set: {
tweet
}
},
{ upsert: true }, error => {
if (error) {
console.log('Error Updating:', error);
}
});

// This is hard coded for now
args.author = 'codejobs';
args.createdAt = new Date();

// Returning the updated Tweet
return args;
}
};
File: src/model/Tweet.js
You need to have MongoDB installed and running to use this project. If you don't know how to do this, you can look at Chapter 8, Creating an API with Node.js Using MongoDB and MySQL.
  1. Now for the moment of truth! If you followed all the steps correctly you should see the GraphiQL IDE working if you go to http://localhost:5000/graphiql, but it's possible you'll get this error:

  1. Usually, this error means that we are using graphql in two projects (frontend and backend) and npm does not know which version will use which. This is a tricky error, but I will show you how to fix it. First, we remove the node_modules folder from both of our projects (frontend and backend). Then we need to add a resolutions node in both of the package.json files:
  "resolutions": {
"graphql": "0.13.2"
}
  1. At the same time, we also need to remove the caret (^) from the graphql version in both package.json files.
  2. Now we must delete the package-lock.json and yarn.lock files (if you have them).
  3. Before we install the dependencies again, it's a good idea to update npm to the latest version:
     npm install -g npm
  1. After that, just to be safe, let's remove the npm cache:
    npm cache clean --force
  1. And now you run npm install again (first on the backend), and after you run the project with npm start, if everything works fine you should see the GraphiQL IDE working properly:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.217.134