The funny part is about to begin.
In this section we are going to set our graphql queries, and schemas so them matches the sql models created on the first part, and the authentication setted on the second part.
Now we can create a folder graphql
to wrap the users and messages schemas.
./graphql/schemas/messages.schema.js
const MESSAGE_TYPES = `
type Message { id: String, text: String, date: String, usr: String }
`;
module.exports = { MESSAGE_TYPES };
./graphql/schemas/users.schema.js
const USERS_TYPES = `
type User { usr: String, name: String, type: String, password_digested:String, token: String }
`;
module.exports = { USERS_TYPES };
This schemas are only objects that matches the types defined in the sql section for the messages and users.
Now we can use these schemas to implement mutations and queries with the graphql api apollo.
./graphql/index.js
const { USERS_TYPES } = require("./schemas/users.schema");
const { MESSAGE_TYPES } = require("./schemas/messages.schema");
const { getMessages, addMessage } = require("../data/sql/messages");
const { signin, signup, findUser } = require("../data/sql/users");
const { gql } = require("apollo-server-express");
const { PubSub } = require("apollo-server");
First lets take a look to these weird graphqlrequires.
gql
query parser, it allows us to write queries in string format.
PubSub
is the magic package that will help us to get the real time functionality. It uses socket subscriptions under the hood to achive that.
Now let's create the mutations!
const pubsub = new PubSub();
const QUERY = gql`
type Query {
user(usr: String): User
messages: [Message]
}
`;
const MUTATION = gql`
type Mutation {
createMessage(text: String, date: String, usr: String): Message
signInUser(usr: String, password: String): User
signUpUser(usr: String, name: String, password: String, type: String): User
}
`;
const SUBSCRIPTION = gql`
type Subscription {
messageAdded: Message
}
`;
const typeDefs = [QUERY, MUTATION, SUBSCRIPTION, USERS_TYPES, MESSAGE_TYPES];
Let's analize this code:
We create a new instance of the PubSub object.
The
QUERY
constant is a graphql query that defines how our server is going to search for users and messages.The
MUTATION
constant is a graphql mutation that defines 3 functionscreateMessage
,signInUser
,signUpUser
, and the parameters these functions requires.The
SUBSCRIPTION
constant is a graphql subscription that will be our connection to the real time messages stream.The
typeDefs
is an object required by the graphql server in order to show documentation, and basically this is how the server knows what it can query and mutate.
Now we can actually add funcionality to those things defined before:
const resolvers = {
Subscription: {
messageAdded: {
subscribe: () => {
return pubsub.asyncIterator(["MESSAGE_ADDED"]);
},
},
},
Mutation: {
signInUser: async (parent, args) => {
return await signin({ ...args });
},
signUpUser: async (parent, args) => {
return await signup({ ...args });
},
createMessage: async (parent, args) => {
pubsub.publish("MESSAGE_ADDED", {
messageAdded: { ...args },
});
return await addMessage({ ...args });
},
},
Query: {
messages: async () => {
return await getMessages();
},
user: async (paretn, args) => {
return await findUser(args.usr);
},
},
};
module.exports = { typeDefs, resolvers };
The
resolvers
object is, as the typeDefs object, used by the server. Basically are the functions executed by the server.The
Subscription
object is composed by a subscription to the 'MESSAGE_ADDED' topic. This means each time this topic is used for something (like adding a new message), themessageAdded
subscription will notice.The
Mutation
object is composed by the 3 functions defined on thetypeDefs
. These functions in turn use the functions of signin, signup, and addMessage. The args parameter should match the defined on thetypeDefs
.
3.1 ThecreateMessage
function is using the pubsub object to subscribe into a topic called 'MESSAGE_ADDED'.The
Query
object is returning whatever that is on the messages table and the user info given an username.Finally we can export the
typeDefs
and theresolvers
so we can start our server.
In the next part we'll be setting up the final details to start our server and run some manual tests to check if everything is ok.
Top comments (0)