Skip to content

Tutorial step by step setting up graphql apollo server using express, postgres and sequelize. This step by step tutorial is based on my following on this article: https://www.robinwieruch.de/graphql-apollo-server-tutorial/#apollo-server-type-relationship

Notifications You must be signed in to change notification settings

bhirmbani/graphql-apollo-server-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

24 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

initial commit,add express,resolvers,schema graphql

πŸ“„ .gitignore

node_modules

πŸ“„ package.json

{
  "name": "graphql-tutorial-1",
  "version": "0.1.0",
  "description": "coba pakai graphql",
  "main": "app.js",
  "scripts": {
    "start": "node ./src/app.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "bm",
  "license": "ISC",
  "dependencies": {
    "apollo-server": "^2.0.5",
    "apollo-server-express": "^2.0.4",
    "cors": "^2.8.4",
    "express": "^4.16.3",
    "graphql": "^0.13.2"
  }
}

πŸ“„ src/app.js

const express = require('express');
const ApolloServer = require('apollo-server-express').ApolloServer;
const cors = require('cors');

const schema = require('./schema');
const resolvers = require('./resolvers');

const app = express();

app.use(cors());

const server = new ApolloServer({
  typeDefs: schema,
  resolvers,
});

server.applyMiddleware({ app, path: '/graphql' });

app.listen({ port: 8000 }, () => {
  console.log('Apollo Server on http://localhost:8000/graphql');
});

πŸ“„ src/resolvers.js

const resolvers = {
  Query: {
    me: () => {
      return {
        username: 'Robin Wieruch',
      };
    },
  },
};

module.exports = resolvers;

πŸ“„ src/schema.js

const gql = require('apollo-server-express').gql;

const schema = gql`
  type Query {
    me: User
  }

  type User {
    username: String!
  }
`;

module.exports = schema;

adding user query and field id to User type

πŸ“„ src/schema.js

  const schema = gql`
    type Query {
      me: User
+     user(id: ID!): User
    }
  
    type User {
      username: String!
+     id: ID!
    }
  `;
  

adding resolvers for query user based on id

πŸ“„ src/resolvers.js

+ const users = {
+   1: {
+     id: '1',
+     username: 'Robin Wieruch',
+   },
+   2: {
+     id: '2',
+     username: 'Dave Davids',
+   },
+ };
+ 
+ const me = users[1];
+ 
  const resolvers = {
    Query: {
      me: () => {
-       return {
-         username: 'Robin Wieruch',
-       };
+       return me;
+     },
+     user: (parent, { id }) => {
+       return users[id];
      },
    },
  };

adding get all user query and resolvers

πŸ“„ src/resolvers.js

      user: (parent, { id }) => {
        return users[id];
      },
+     users: () => {
+       return Object.values(users);
+     },
    },
  };
  

πŸ“„ src/schema.js

    type Query {
      me: User
      user(id: ID!): User
+     users: [User!]
    }
  
    type User {

adding fullname query on User type

πŸ“„ src/schema.js

  
    type User {
      username: String!
+     fullname: String
      id: ID!
    }
  `;

adding fullname resolver on User

πŸ“„ src/resolvers.js

  const users = {
    1: {
      id: '1',
-     username: 'Robin Wieruch',
+     username: 'robinw',
+     firstname: 'Robin',
+     lastname: 'Wieruch',
    },
    2: {
      id: '2',
-     username: 'Dave Davids',
+     username: 'daved',
+     firstname: 'Dave',
+     lastname: 'Davids',
    },
  };
  
        return Object.values(users);
      },
    },
+   User: {
+     fullname: user => `${user.firstname} ${user.lastname}`,
+     username: user => user.username
+   },
  };
  
  module.exports = resolvers;

adding context in ApolloServer

πŸ“„ src/app.js

  const server = new ApolloServer({
    typeDefs: schema,
    resolvers,
+   context: {
+     me: users[1],
+   },
  });
  
  server.applyMiddleware({ app, path: '/graphql' });

refactors to use context in resolvers

πŸ“„ src/resolvers.js

  
  const resolvers = {
    Query: {
-     me: () => {
+     me: (parent, args, { me }) => {
        return me;
      },
      user: (parent, { id }) => {

adding dev script using nodemon

πŸ“„ package.json

    "main": "app.js",
    "scripts": {
      "start": "node ./src/app.js",
+     "dev": "nodemon ./src/app.js",
      "test": "echo \"Error: no test specified\" && exit 1"
    },
    "author": "bm",

adding message Query and type

πŸ“„ src/schema.js

      me: User
      user(id: ID!): User
      users: [User!]
+     messages: [Message!]!
+     message(id: ID!): Message!
    }
  
    type User {
      fullname: String
      id: ID!
    }
+ 
+   type Message {
+     id: ID!
+     text: String!
+     user: User!
+   }
  `;
  
  module.exports = schema;

adding resolvers for message query and type

πŸ“„ src/resolvers.js

    },
  };
  
- const me = users[1];
+ let messages = {
+   1: {
+     id: '1',
+     text: 'Hello World',
+   },
+   2: {
+     id: '2',
+     text: 'By World',
+   },
+ };
  
  const resolvers = {
    Query: {
      users: () => {
        return Object.values(users);
      },
+     messages: () => {
+       return Object.values(messages);
+     },
+     message: (parent, { id }) => {
+       return messages[id];
+     },
    },
    User: {
      fullname: user => `${user.firstname} ${user.lastname}`,
      username: user => user.username
    },
+   Message: {
+     user: (parent, args, { me }) => {
+       return me;
+     },
+   },
  };
  
- module.exports = resolvers;
+ module.exports = { resolvers, users };

import users to app.js

πŸ“„ src/app.js

  const cors = require('cors');
  
  const schema = require('./schema');
- const resolvers = require('./resolvers');
+ const resolvers = require('./resolvers').resolvers;
+ const users = require('./resolvers').users;
  
  const app = express();
  
  
  const server = new ApolloServer({
    typeDefs: schema,
-   resolvers,
+   resolvers: resolvers,
    context: {
      me: users[1],
    },

adding Message type in User's type

πŸ“„ src/schema.js

      username: String!
      fullname: String
      id: ID!
+     messages: [Message!]
    }
  
    type Message {

adding resolvers for User and Message type relationship

πŸ“„ src/resolvers.js

      username: 'robinw',
      firstname: 'Robin',
      lastname: 'Wieruch',
+     messageIds: [1],
    },
    2: {
      id: '2',
      username: 'daved',
      firstname: 'Dave',
      lastname: 'Davids',
+     messageIds: [2],
    },
  };
  
    1: {
      id: '1',
      text: 'Hello World',
+     userId: '1'
    },
    2: {
      id: '2',
      text: 'By World',
+     userId: '2',
    },
  };
  
    },
    User: {
      fullname: user => `${user.firstname} ${user.lastname}`,
-     username: user => user.username
+     username: user => user.username,
+     messages: user => {
+       return Object.values(messages).filter(
+         message => message.userId === user.id,
+       );
+     },
    },
    Message: {
-     user: (parent, args, { me }) => {
-       return me;
+     user: message => {
+       return users[message.userId];
      },
    },
  };

adding create and delete message mutation

πŸ“„ src/schema.js

      message(id: ID!): Message!
    }
  
+   type Mutation {
+     createMessage(text: String!): Message!
+     deleteMessage(id: ID!): Boolean!
+   }
+ 
    type User {
      username: String!
      fullname: String

adding resolvers for create and delete message

πŸ“„ package.json

      "apollo-server-express": "^2.0.4",
      "cors": "^2.8.4",
      "express": "^4.16.3",
-     "graphql": "^0.13.2"
+     "graphql": "^0.13.2",
+     "uuid": "^3.3.2"
    }
  }

πŸ“„ src/resolvers.js

+ const uuidv4 = require('uuid/v4');
+ 
  const users = {
    1: {
      id: '1',
        return messages[id];
      },
    },
+   Mutation: {
+     createMessage: (parent, { text }, { me }) => {
+       const id = uuidv4();
+       const message = {
+         id,
+         text,
+         userId: me.id,
+       };
+ 
+       messages[id] = message;
+       users[me.id].messageIds.push(id);
+ 
+       return message;
+     },
+     deleteMessage: (parent, { id }) => {
+       const { [id]: message, ...otherMessages } = messages;
+ 
+       if (!message) {
+         return false;
+       }
+ 
+       messages = otherMessages;
+ 
+       return true;
+     },
+   },
    User: {
      fullname: user => `${user.firstname} ${user.lastname}`,
      username: user => user.username,

adding eslint

πŸ“„ .eslintrc.json

{
    "extends": "airbnb-base"
}

πŸ“„ package.json

      "express": "^4.16.3",
      "graphql": "^0.13.2",
      "uuid": "^3.3.2"
+   },
+   "devDependencies": {
+     "eslint": "^5.4.0",
+     "eslint-config-airbnb-base": "^13.1.0",
+     "eslint-plugin-import": "^2.14.0"
    }
  }

refactoring resolvers

πŸ“„ src/resolvers.js

- const uuidv4 = require('uuid/v4');
- 
- const users = {
-   1: {
-     id: '1',
-     username: 'robinw',
-     firstname: 'Robin',
-     lastname: 'Wieruch',
-     messageIds: [1],
-   },
-   2: {
-     id: '2',
-     username: 'daved',
-     firstname: 'Dave',
-     lastname: 'Davids',
-     messageIds: [2],
-   },
- };
- 
- let messages = {
-   1: {
-     id: '1',
-     text: 'Hello World',
-     userId: '1'
-   },
-   2: {
-     id: '2',
-     text: 'By World',
-     userId: '2',
-   },
- };
- 
- const resolvers = {
-   Query: {
-     me: (parent, args, { me }) => {
-       return me;
-     },
-     user: (parent, { id }) => {
-       return users[id];
-     },
-     users: () => {
-       return Object.values(users);
-     },
-     messages: () => {
-       return Object.values(messages);
-     },
-     message: (parent, { id }) => {
-       return messages[id];
-     },
-   },
-   Mutation: {
-     createMessage: (parent, { text }, { me }) => {
-       const id = uuidv4();
-       const message = {
-         id,
-         text,
-         userId: me.id,
-       };
- 
-       messages[id] = message;
-       users[me.id].messageIds.push(id);
- 
-       return message;
-     },
-     deleteMessage: (parent, { id }) => {
-       const { [id]: message, ...otherMessages } = messages;
- 
-       if (!message) {
-         return false;
-       }
- 
-       messages = otherMessages;
- 
-       return true;
-     },
-   },
-   User: {
-     fullname: user => `${user.firstname} ${user.lastname}`,
-     username: user => user.username,
-     messages: user => {
-       return Object.values(messages).filter(
-         message => message.userId === user.id,
-       );
-     },
-   },
-   Message: {
-     user: message => {
-       return users[message.userId];
-     },
-   },
- };
- 
- module.exports = { resolvers, users };

πŸ“„ src/resolvers/index.js

const userResolvers = require('./user');
const messageResolvers = require('./message');

module.exports = [userResolvers, messageResolvers];

πŸ“„ src/resolvers/message.js

const uuidv4 = require('uuid/v4');

const messageResolvers = {
  Query: {
    messages: (parent, args, { models }) => {
      return Object.values(models.messages);
    },
    message: (parent, { id }, { models }) => {
      return models.messages[id];
    },
  },
  Mutation: {
    createMessage: (parent, { text }, { me, models }) => {
      const id = uuidv4();
      const message = {
        id,
        text,
        userId: me.id,
      };
      models.messages[id] = message;
      models.users[me.id].messageIds.push(id);

      return message;
    },
    deleteMessage: (parent, { id }, { models }) => {
      const { [id]: message, ...otherMessages } = models.messages;

      if (!message) {
        return false;
      }

      models.messages = otherMessages;

      return true;
    },
  },
  Message: {
    user: (message, args, { models }) => models.users[message.userId],
  },
};

module.exports = messageResolvers;

πŸ“„ src/resolvers/user.js

const userResolvers = {
  Query: {
    users: (parent, args, { models }) => {
      return Object.values(models.users);
    },
    user: (parent, { id }, { models }) => {
      return models.users[id];
    },
    me: (parent, args, { me }) => {
      return me;
    },
  },
  User: {
    fullname: user => `${user.firstname} ${user.lastname}`,
    username: user => user.username,
    messages: (user, args, { models }) => {
      return Object.values(models.messages).filter(
        message => message.userId === user.id,
      );
    },
  },
};

module.exports = userResolvers;

refactoring schema

πŸ“„ src/schema.js

- const gql = require('apollo-server-express').gql;
- 
- const schema = gql`
-   type Query {
-     me: User
-     user(id: ID!): User
-     users: [User!]
-     messages: [Message!]!
-     message(id: ID!): Message!
-   }
- 
-   type Mutation {
-     createMessage(text: String!): Message!
-     deleteMessage(id: ID!): Boolean!
-   }
- 
-   type User {
-     username: String!
-     fullname: String
-     id: ID!
-     messages: [Message!]
-   }
- 
-   type Message {
-     id: ID!
-     text: String!
-     user: User!
-   }
- `;
- 
- module.exports = schema;

πŸ“„ src/schema/index.js

const gql = require('apollo-server-express').gql;
const userSchema = require('./user');
const messageSchema = require('./message');

const linkSchema = gql`
  type Query {
    _: Boolean
  }

  type Mutation {
    _: Boolean
  }

  type Subscription {
    _: Boolean
  }
`;

module.exports = [linkSchema, userSchema, messageSchema];

πŸ“„ src/schema/message.js

const gql = require('apollo-server-express').gql;

const messageSchema = gql`
  extend type Query {
    messages: [Message!]!
    message(id: ID!): Message!
  }

  extend type Mutation {
    createMessage(text: String!): Message!
    deleteMessage(id: ID!): Boolean!
  }

  type Message {
    id: ID!
    text: String!
    user: User!
  }
`;

module.exports = messageSchema;

πŸ“„ src/schema/user.js

const gql = require('apollo-server-express').gql;

const userSchema = gql`
  extend type Query {
    users: [User!]
    user(id: ID!): User
    me: User
  }

  type User {
    id: ID!
    fullname: String
    username: String!
    messages: [Message!]
  }
`;

module.exports = userSchema;

refactoring models

πŸ“„ src/models/index.js

const users = {
  1: {
    id: '1',
    username: 'robinw',
    firstname: 'Robin',
    lastname: 'Wieruch',
    messageIds: [1],
  },
  2: {
    id: '2',
    username: 'daved',
    firstname: 'Dave',
    lastname: 'Davids',
    messageIds: [2],
  },
};

const messages = {
  1: {
    id: '1',
    text: 'Hello World',
    userId: '1'
  },
  2: {
    id: '2',
    text: 'By World',
    userId: '2',
  },
};

module.exports = { users, messages };

refactoring app.js

πŸ“„ src/app.js

  const cors = require('cors');
  
  const schema = require('./schema');
- const resolvers = require('./resolvers').resolvers;
- const users = require('./resolvers').users;
+ const resolvers = require('./resolvers');
+ const models = require('./models');
  
  const app = express();
  
    typeDefs: schema,
    resolvers: resolvers,
    context: {
-     me: users[1],
+     models,
+     me: models.users[1],
    },
  });
  

About

Tutorial step by step setting up graphql apollo server using express, postgres and sequelize. This step by step tutorial is based on my following on this article: https://www.robinwieruch.de/graphql-apollo-server-tutorial/#apollo-server-type-relationship

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published