Write a query parser. Continue to translate Apollo’s official website guide.
Learn how GraphQL changes modify data.
Apollo Starter – Directory:
- introduce
- Build the schema
- Connect to data source
- Write a query parser
- Write a change parser
- Connect the Apollo Studio
- Create Apollo client
- Obtain data by querying
- Modify data through changes
- Managing Local Status
Time to finish: 10 minutes
The previous article wrote all the parsers needed for query operations in the Schema field. Now go ahead and write the parser for the schema change. The process is basically the same.
The login
Start by writing a parser for Mutation. Login that allows users to login to the application. Add the following below the Query field in the parser map:
// Query: {
/ /...
// },
Mutation: {
login: async (_, { email }, { dataSources }) => {
const user = await dataSources.userAPI.findOrCreateUser({ email });
if (user) return Buffer.from(email).toString('base64'); }},Copy the code
The parser takes an email address and returns the login token for the corresponding user entity. If the email address does not have a user entity, one is created.
You’ll learn how to save this login token on the client in the next chapter.
Verifying a Login User
The authentication method used in the sample application is not completely secure and should not be used in a production environment. But you can apply the principles of the following example to secure token-based authentication methods.
The Mutation. Login parser returns a token that clients can use for authentication in the service. Now you need to add logic to the service for authentication.
In SRC /index.js, import the isEmail function and pass the context function to ApolloServer’s constructor:
const isEmail = require('isemail');
const server = new ApolloServer({
context: async ({ req }) => {
// Simple authentication per request
const auth = (req.headers && req.headers.authorization) || ' ';
const email = Buffer.from(auth, 'base64').toString('ascii');
if(! isEmail.validate(email))return { user: null };
// email Searches for users by email
const users = await store.users.findOrCreate({ where: { email } });
const user = (users && users[0) | |null;
return { user: { ...user.dataValues } };
},
// Optional constructor options
});
Copy the code
For every GraphQL operation sent by the client to our service, the context function defined above is called. The return value of this function becomes the context parameter, which is passed to each parser running with the corresponding operation.
Here’s what the context function does:
- Gets the value contained in the incoming request
Authorization
The value of the request header, if any. - decoding
Authorization
The value of the request header. - If the decoded value is
email
Address, the user details of the email address are obtained from the database and displayed in theuser
Field returns an object containing these details.
By creating this context object at the beginning of each operation execution, all parsers can access the details of the logged-in user and perform specific actions on that user.
bookTrips
和 cancelTrip
Add parsers for bookTrips and cancelTrip to the Mutation object below:
//Mutation: {
// login: ...
bookTrips: async (_, { launchIds }, { dataSources }) => {
const results = await dataSources.userAPI.bookTrips({ launchIds });
const launches = await dataSources.launchAPI.getLaunchesByIds({
launchIds,
});
return {
success: results && results.length === launchIds.length,
message:
results.length === launchIds.length
? 'Successfully booked journey'
: 'The following launches cannot be scheduled:${launchIds.filter( id => ! results.includes(id), )}`,
launches,
};
},
cancelTrip: async (_, { launchId }, { dataSources }) => {
const result = await dataSources.userAPI.cancelTrip({ launchId });
if(! result)return {
success: false.message: 'Cancelled trip failed'};const launch = await dataSources.launchAPI.getLaunchById({ launchId });
return {
success: true.message: 'Journey cancelled'.launches: [launch],
};
},
Copy the code
To match the schema, both parsers return an object that conforms to the TripUpdateResponse type structure. Fields of this type include a SUCCESS indicator, a status message, and a launcher array for booking or canceling a change.
The bookTrips parser needs to consider the possibility of partial success, in which some launches are booked successfully and others fail. The code in the message field above represents a partial success.
Test the change
Now you’re ready to test our changes! Restart the service, then open it in your browser to Apollo Studio Explorer or GraphQL Playground.
Obtaining a Login Token
The structure of the GraphQL change is exactly the same as the query, except that the mutation keyword is used. Paste the following change code and run it:
mutation LoginUser {
login(email: "[email protected]")
}
Copy the code
The service returns the following response:
"data": {
"login": "ZGFpc3lAYXBvbGxvZ3JhcGhxbC5jb20="
}
Copy the code
The string below is the token for the login (just Base64 encoding of the email address provided). Copy it for the next change operation.
ZGFpc3lAYXBvbGxvZ3JhcGhxbC5jb20=
Copy the code
itinerary
Now try booking some travel. Because only authenticated users are allowed to book trips, a login token will be included in the request.
First, paste the following changes into the tool’s query editor:
mutation BookTrips {
bookTrips(launchIds: [67, 68, 69]) {
success
message
launches {
id
}
}
}
Copy the code
Next, paste the following into the Headers panel of the tool:
{
"authorization": "ZGFpc3lAYXBvbGxvZ3JhcGhxbC5jb20="
}
Copy the code
Run the changes and you should see a success message and an array of ids for the trip you just booked.
Running changes manually in GraphQL Playground is a helpful way to test the API, but real applications need other tools to ensure that their data graphs are added and changed safely. In the next section, we connect the service to the Apollo Studio tool.
Front-end notepad, not regularly updated, welcome to pay attention to!
- Wechat official account: Lin Jingyi’s notepad
- Blog: Lin Jingyi’s notebook
- Nuggets column: Lin Jingyi’s notebook
- Zhihu column: Lin Jingyi’s notebook
- Github: MageeLin