This holiday weekend I decided that it would be a great idea to build my own bookmarks service.

This bookmarks service starts with the Inbox Service would receive an email from SES, categorise that email and output JSON to a specific folder in a bucket.

Then there’s another service that gets triggered when that file has been saved and will process the data from the JSON and then store that processed data in DynamoDB.

In this article, I’m going to be building a new GraphQL API layer, this layer will provide us with a platform to retrieve and update the bookmarks.

You can find the full code for my Bookmarks Service here: https://github.com/nicholasgriffintn/Bookmarks-Service

Updating our Serverless definition

The first step in making our new GraphQL API is to update the Serverless definition that we made in part one to include our new GraphQL API.

This is done like so:

1functions:
2  process:
3    handler: processor.process
4    description: Process Bookmark emails to DynamoDB
5    timeout: 15
6    events:
7      - s3:
8          bucket: email.nicholasgriffin.dev
9          event: s3:ObjectCreated:*
10          rules:
11            - prefix: processed/bookmarks/
12            - suffix: .json
13          existing: true
14  graphql:
15    handler: api.graphql
16    description: GraphQL Service for interacting with the bookmarks data
17    timeout: 15
18    events:
19      - http:
20          path: graphql
21          method: post
22          cors: true
23      - http:
24          path: graphql
25          method: get
26          cors: true
27

If you read the previous article, you may have also noticed that I have moved the processor and the API into their own files to keep things a little tidier.

Aside from what we did in part 1, that should be all you need to do here.

Setting up the API

Next up, in our api file, we need to import a few packages that will help us along the way, these are:

1const { ApolloServer, gql } = require('apollo-server-lambda');
2const { unmarshall } = require('@aws-sdk/util-dynamodb');
3const { DynamoDBClient, ScanCommand } = require('@aws-sdk/client-dynamodb');
4

We also need to define our DynamoDB Client which will be used for grabbing the bookmarks data.

1const client = new DynamoDBClient({ region: config.region });
2

Now that’s done, let’s define our schema for GraphQL to use, at the moment, I’m defining everything as a string for the sake of time, but I’m going to need to change the bookmark to a proper object when I have the time.

For now, our schema is this:

1const typeDefs = gql'
2  scalar JSON
3  type Bookmark {
4    id: String!
5    status: String
6    subject: String
7    recieved: String
8    bookmark: String
9    toName: String
10    toAddress: String
11    fromName: String
12    fromAddress: String
13  }
14  type Query {
15    bookmarks: [Bookmark]
16  }
17';
18

Next up are the resolvers, this is quite simple for now as we are only adding a retrieve function, we’ll want to update this with our mutations later.

1const resolvers = {
2  Query: {
3    bookmarks: () => {
4      return getBookmarks();
5    }
6  }
7};
8

The getBookmarks function that we are returning is this:

1const getBookmarks = async () => {
2  const params = {
3    TableName: config.tableName,
4  };
5
6  try {
7    const results = await client.send(new ScanCommand(params));
8    const bookmarks = [];
9    results.Items.forEach((item) => {
10      const newRecord = unmarshall(item);
11
12      bookmarks.push(newRecord);
13    });
14    return bookmarks;
15  } catch (err) {
16    console.error(err);
17    return err;
18  }
19};
20

Now that’s done, we just need to create the server and export the handler that Serverless will be using:

1const gqlServer = new ApolloServer({
2  typeDefs,
3  resolvers,
4  introspection: false,
5});
6
7module.exports.graphql = gqlServer.createHandler({
8  cors: {
9    origin: true,
10    credentials: true,
11  },
12});
13

And that’s about it, we now have a GraphQL server that can output the data from our Bookmarks in DynamoDB!

In the next part, I’ll be expanding this service while I build a frontend for this service that will display all of the verified bookmarks and allow me to verify bookmarks that have not yet been verified from my Cognito login.

So stay tuned for that.

Stay Tuned!