Skip to content

Class and Enum Typings for Handling Data with GraphQL

This article was written over 18 months ago and may contain information that is out of date. Some content may be relevant but please refer to the relevant official documentation or available resources for the latest information.

Intro

Today we’ll talk about class and enum typings for handling more complex data with GraphQL. The typings will be used on class objects to make them easier to read and understand. This blog will build on the concepts of another blog found here, in which I discussed wrapping and enhancing data, which talks about how to create a GraphQL Rest API wrapper, and how to enhance your data.

This article assumes you have a basic understanding of classes, typing, and enums. Here is the code repo if you want to review it while reading, or just skip ahead. With that said, we will look at the class structure we’re going to be using, the enums, and the type lookup for our customField enum with our mapper.

Class setup

This class we’re going to set up will be strictly for typing. We’re going to make a RestaurantGuest class as this data will be restaurant themed. So in our restaurant.ts file, we will name it RestaurantGuest, and include a few different items.

Basic starting class example

  class RestaurantGuest {
    id!: number;
    name!: string;
    email!: string;
    phoneNumber!: string;
    /** foodReservation */
    3249258!: { id: number, value: string } | undefined;
  }

After setting that up, we will add a type that will reference the above class.

Type example

type RestaurantGuestResponse= {
 [g in keyof RestaurantGuest ]: RestaurantGuest [g];
};

This type will be used later when we do the type lookup in conjunction with our mapper function. With the above finished, we can now move on to handling our enums.

Handling enums

We’ll now create our Enum to make dealing with our complex data easier. Since the above 3249258 represents FoodReservation, we will create an enum for it. Now you might be wondering why 3249258 represents FoodReservation. Unfortunately, this is an example of how data can be returned to us from a call. It could be due to the field id established in a CMS such as Contentful, or from another source that we don’t control. This isn’t readable, so we’re creating an Enum for the value.

Enum example

export enum FoodReservation {
  'Yes' = 53425867,
  'No' = 53425868,
}

This will be used later during our type look-up.

Type lookup

Now we can start combining the enum from above with our class type, and a look-up type that we’re about to create. So let's make another type called RestaurantGuestFieldLookup, which will have an id and value.

Look-up type example

export type RestaurantGuestFieldLookup<
 TId extends string | number | null,
 TValue extends string | null
> = {
 id: TId;
 value: TValue;
};

Perfect, now we’ll swap out
3249258?: {id: number, value: string} | undefined;

to be
 3249258?: RestaurantGuestFieldLookup<
   FoodReservation,
   keyof typeof FoodReservation
 >;

We can now move on to creating and using our mapper. In a separate file called mapper.ts, we will create our restaruantGuestMapper function.
export const restaruantGuestMapper = (guest: RestaurantGuestResponse) => {
 if (!guest) {
   return null;
 }

 return {
   id: guest.id,
   name: guest.name,
   phoneNumber: guest.phoneNumber,
   email: guest.email,
   reservation: guest.3249258.id === FoodReservation.Yes,
 };
};

Tada! Thanks to all the work above, we can easily understand and get back the data we need.

Conclusion

Today's article covered setting up a typing class, creating an enum, and type lookup with a mapper for more complex data handling with GraphQL. Hopefully, the class structure was straightforward and helpful, along with the enums and type lookup and formatting examples.

If you want to learn more about GraphQL, read up on our resources available at graphql.framework.dev.

This Dot is a consultancy dedicated to guiding companies through their modernization and digital transformation journeys. Specializing in replatforming, modernizing, and launching new initiatives, we stand out by taking true ownership of your engineering projects.

We love helping teams with projects that have missed their deadlines or helping keep your strategic digital initiatives on course. Check out our case studies and our clients that trust us with their engineering.

You might also like

Introducing the New Serverless, GraphQL, Apollo Server, and Contentful Starter kit cover image

Introducing the New Serverless, GraphQL, Apollo Server, and Contentful Starter kit

Introducing the new Serverless, GraphQL, Apollo Server, and Contentful Starter kit The team at This Dot Labs has released a brand new starter kit which includes the Serverless Framework, GraphQL, Apollo Server and Contentful configured and ready to go. This article will walk through how to set up the new kit, the key technologies used, and reasons why you would consider using this kit. Table of Contents - How to get started setting up the kit - Generate the project - Setup Contentful access - Setting up Docker - Starting the local server - How to Create the Technology Model in Contentful - How to seed the database with demo data - How to work with the migration scripts - Technologies included in this starter kit - Why use GraphQL? - Why use Contentful? - Why use Amazon Simple Queue Service (SQS)? - Why use Apollo Server? - Why use the Serverless Framework? - Why use Redis? - Why use the Jest testing framework? - Project structure - How to deploy your application - What can this starter kit be used for? - Conclusion How to get started setting up the kit Generate the project In the command line, you will need to start the starter.dev CLI by running the npx @this-dot/create-starter command. You can then select the Serverless Framework, Apollo Server, and Contentful CMS kit and name your new project. Then you will need to cd into your new project directory and install the dependencies using the tool of your choice (npm, yarn, or pnpm). Next, you will need to Run cp .env.example .env to copy the contents of the .env.example file into the .env file. Setup Contentful access You will first need to create an account on Contentful, if you don't have one already. Once you are logged in, you will need to create a new space. From there, go to Settings -> API keys and click on the Content Management Tokens tab. Next, click on the Generate personal token button and give your token a name. Copy your new Personal Access Token, and add it to the CONTENTFUL_CONTENT_MANAGEMENT_API_TOKEN variable. Then, go to Settings -> General settings to get the CONTENTFUL_SPACE_ID. The last step is to add those CONTENTFUL_CONTENT_MANAGEMENT_API_TOKEN and CONTENTFUL_SPACE_ID values to your .env file. Setting up Docker You will first need to install Docker Desktop if you don't have it installed already. Once installed, you can start up the Docker container with the npm run infrastructure:up command. Starting the local server While the Docker container is running, open up a new tab in the terminal and run npm run dev to start the development server. Open your browser to http://localhost:3000/dev/graphql to open up Apollo server. How to Create the Technology Model in Contentful To get started with the example model, you will first need to create the model in Contentful. 1. Log into your Contentful account 2. Click on the Content Model tab 3. Click on the Design your Content Modal button if this is your first modal 4. Create a new model called Technology 5. Add three new text fields called displayName, description and url 6. Save your new model How to seed the database with demo data This starter kit comes with a seeding script that pre-populates data for the Technology Content type. In the command line, run npm run db:seed which will add three new data entries into Contentful. If you want to see the results from seeding the database, you can execute a small GraphQL query using Apollo server. First, make sure Docker, and the local server(npm run dev) are running, and then navigate to http://localhost:3000/dev/graphql. Add the following query: ` When you run the query, you should see the following output. ` How to work with the migration scripts Migrations are a way to make changes to your content models and entries. This starter kit comes with a couple of migration scripts that you can study and run to make changes to the demo Technology model. These migration scripts are located in the scripts/migration directory. To get started, you will need to first install the contentful-cli. ` You can then login to Contentful using the contentful-cli. ` You will then need to choose the Contentful space where the Technology model is located. ` If you want to modify the existing demo content type, you can run the second migration script from the starter kit. ` If you want to build out more content models using the CLI, you can study the example code in the /scripts/migrations/01-create-technology-contentType.js file. From there, you can create a new migration file, and run the above contentful space migration command. If you want to learn more about migration in Contentful, then please check out the documentation. Technologies included in this starter kit Why use GraphQL? GraphQL is a query language for your API and it makes it easy to query all of the data you need in a single request. This starter kit uses GraphQL to query the data from our Contentful space. Why use Contentful? Contentful is a headless CMS that makes it easy to create and manage structured data. We have integrated Contentful into this starter kit to make it easy for you to create new entries in the database. Why use Amazon Simple Queue Service (SQS)? Amazon Simple Queue Service (SQS) is a queuing service that allows you to decouple your components and process and store messages in a scalable way. In this starter kit, an SQS message is sent by the APIGatewayProxyHandler using the sendMessage function, which is then stored in a queue called DemoJobQueue. The SQS handler sqs-handler polls this queue, and processes any message received. ` Why use Apollo Server? Apollo Server is a production-ready GraphQL server that works with any GraphQL client, and data source. When you run npm run dev and open the browser to http://localhost:3000/dev/graphql, you will be able to start querying your Contentful data in no time. Why use the Serverless Framework? The Serverless Framework is used to help auto-scale your application by using AWS Lambda functions. In the starter kit, you will find a serverless.yml file, which acts as a configuration for the CLI and allows you to deploy your code to your chosen provider. This starter kit also includes the following plugins: - serverless-offline - allows us to deploy our application locally to speed up development cycles. - serverless-plugin-typescript - allows the use of TypeScript with zero-config. - serverless-dotenv-plugin - preloads function environment variables into the Serverless Framework. Why use Redis? Redis is an open-source in-memory data store that stores data in the server memory. This starter kit uses Redis to cache the data to reduce the API response times and rate limiting. When you make a new request, those new requests will be retrieved from the Redis cache. Why use the Jest testing framework? Jest is a popular testing framework that works well for creating unit tests. You can see some example test files under the src/schema/technology directory. You can use the npm run test command to run all of the tests. Project structure Inside the src directory, you will find the following structure: ` This given structure makes it easy to find all of the code and tests related to that specific component. This structure also follows the single responsibility principle which means that each file has a single purpose. How to deploy your application The Serverless Framework needs access to your cloud provider account so that it can create and manage resources on your behalf. You can follow the guide to get started. Steps to get started: 1. Sign up for an AWS account 2. Create an IAM User and Access Key 3. Export your AWS_ACCESS_KEY_ID & AWS_SECRET_ACCESS_KEY credentials. ` 4. Deploy your application on AWS Lambda: ` 5. To deploy a single function, run: ` To stop your Serverless application, run: ` For more information on Serverless deployment, check out this article. What can this starter kit be used for? This starter kit is very versatile, and can be used with a front-end application for a variety of situations. Here are some examples: - personal developer blog - small e-commerce application Conclusion In this article, we looked at how we can get started using the Serverless, GraphQL, Apollo Server, and Contentful Starter kit. We also looked at the different technologies used in the kit, and why they were chosen. Lastly, we looked at how to deploy our application using AWS. I hope you enjoy working with our new starter kit!...

How to Resolve Nested Queries in Apollo Server cover image

How to Resolve Nested Queries in Apollo Server

When working with relational data, there will be times when you will need to access information within nested queries. But how would this work within the context of Apollo Server? In this article, we will take a look at a few code examples that explore different solutions on how to resolve nested queries in Apollo Server. I have included all code examples in CodeSandbox if you are interested in trying them out on your own. Prerequisites This article assumes that you have a basic knowledge of GraphQL terminology. Table of Contents - How to resolve nested queries: An approach using resolvers and the filter method - A refactored approach using Data Loaders and Data Sources - What are Data Loaders - How to setup a Data Source - Setting up our schemas and resolvers - Resolving nested queries when microservices are involved - Conclusion How to resolve nested queries: An approach using resolvers and the filter method In this first example, we are going to be working with two data structures called musicBrands and musicAccessories. musicBrands is a collection of entities consisting of id and name. musicAccessories is a collection of entities consisting of the product name, price, id and an associated brandId. You can think of the brandId as a foreign key that connects the two database tables. We also need to set up the schemas for the brands and accessories. ` The next step is to set up a resolver for our Query to return all of the music accessories. ` When we run the following query and start the server, we will see this JSON output: ` ` As you can see, we are getting back the value of null for the brands field. This is because we haven't set up that relationship yet in the resolvers. Inside our resolver, we are going to create another query for the MusicAccessories and have the value for the brands key be a filtered array of results for each brand. ` When we run the query, this will be the final result: ` ` This single query makes it easy to access the data we need on the client side as compared to the REST API approach. If this were a REST API, then we would be dealing with multiple API calls and a Promise.all which could get a little messy. You can find the entire code in this CodeSandbox example. A refactored approach using Data Loaders and Data Sources Even though our first approach does solve the issue of resolving nested queries, we still have an issue fetching the same data repeatedly. Let’s look at this example query: ` If we take a look at the results, we are making additional queries for the brand each time we request the information. This leads to the N+1 problem in our current implementation. We can solve this issue by using Data Loaders and Data Sources. What are Data Loaders Data Loaders are used to batch and cache fetch requests. This allows us to fetch the same data and work with cached results, and reduce the number of API calls we have to make. To learn more about Data Loaders in GraphQL, please read this helpful article. How to setup a Data Source In this example, we will be using the following packages: - apollo-datasource - apollo-server-caching - dataloader We first need to create a BrandAccessoryDataSource class which will simulate the fetching of our data. ` We will then set up a constructor with a custom Dataloader. ` Right below our constructor, we will set up the context and cache. ` We then want to set up the error handling and cache keys for both the accessories and brands. To learn more about how caching works with GraphQL, please read through this article. ` Next, we are going to set up an asynchronous function called get which takes in an id. The goal of this function is to first check if there is anything in the cached results and if so return those cached results. Otherwise, we will set that data to the cache and return it. We will set the ttl(Time to Live in cache) value to 15 seconds. ` Below the get function, we will create another asynchronous function called getByBrand which takes in a brand. This function will have a similar setup to the get function but will filter out the data by brand. ` Setting up our schemas and resolvers The last part of this refactored example includes modifying the resolvers. We first need to add an accessory key to our Query schema. ` Inside the resolver, we will add the accessories key with a value for the function that returns the data source we created earlier. ` We also need to refactor our Brand resolver to include the data source we set up earlier. ` Lastly, we need to modify our ApolloServer object to include the BrandAccessoryDataSource. ` Here is the entire CodeSandbox example. When the server starts up, click on the Query your server button and run the following query: ` Resolving nested queries when microservices are involved Microservices is a type of architecture that will split up your software into smaller independent services. All of these smaller services can interact with a single API data layer. In this case, this data layer would be GraphQL. The client will interact directly with this data layer, and will consume API data from a single entry point. You would similarly resolve your nested queries as before because, at the end of the day, there are just functions. But now, this single API layer will reduce the number of requests made by the client because only the data layer will be called. This simplifies the data fetching experience on the client side. Conclusion In this article, we looked at a few code examples that explored different solutions on how to resolve nested queries in Apollo Server. The first approach involved creating custom resolvers and then using the filter method to filter out music accessories by brand. We then refactored that example to use a custom DataLoader and Data Source to fix the "N+1 problem". Lastly, we briefly touched on how to approach this solution if microservices were involved. If you want to get started with Apollo Server and build your own nested queries and resolvers using these patterns, check out our serverless-apollo-contentful starter kit!...

How to Integrate Mailchimp Forms in a React Project cover image

How to Integrate Mailchimp Forms in a React Project

Intro Today we will cover how to set up an email signup form using React and Mailchimp. This blog will be using the starter.dev cra-rxjs-styled-components template to expedite the process. This article assumes you have a basic understanding of React, and have set up a Mailchimp account. Here is the code repo if you want to review it while reading, or just skip ahead. We will start with setting up our React project using Starter.dev for simplicity, and then finish it up by integrating the two for our signup form. To start, we will be using the command yarn create @this-dot/starter --kit cra-rxjs-styled-components, which can be found here. We’ll go ahead, and give the project a name. I will be calling mine react-mailchimp. Now we will navigate into the project and do a yarn install. Then we can run yarn run dev to get it up and running locally on localhost:3000. This should have us load up on the React App, RxJS, and styled-components Starter kit page. With that all set, we’ll also need to install jsonp by using yarn add jsonp. We’ll be using jsonp instead of fetch to avoid any CORS issues we may run into. This also makes for an easy and quick process by not relying on their API, which can’t be utilized by the client. Now that we have our project set up, we will go ahead and go and grab our form action URL from MailChimp. This can be found by going to your Audience > Signup Forms > Embedded Forms > Continue and then grabbing the form action URL found in the Embedded Form Code. We need to make a small change to the URL and swap /post? with /post-json?. We can now start setting up our form input, and our submit function. I will add a simple form input and follow it up, and a submit function. Inside the submit function, we will use our imported jsonp to invoke our action URL. ` We’ll also add a quick alert to let the user know that it was successful and that’s it! We’ve now successfully added the email to our MailChimp account. Conclusion Today, we covered how to integrate Mailchimp with a react app using the cra-rxjs-styled-components template from starter.dev. I highly recommend using starter.dev to get your project up and running quickly. Here is the code repo again for you to check out....

The simplicity of deploying an MCP server on Vercel cover image

The simplicity of deploying an MCP server on Vercel

The current Model Context Protocol (MCP) spec is shifting developers toward lightweight, stateless servers that serve as tool providers for LLM agents. These MCP servers communicate over HTTP, with OAuth handled clientside. Vercel’s infrastructure makes it easy to iterate quickly and ship agentic AI tools without overhead. Example of Lightweight MCP Server Design At This Dot Labs, we built an MCP server that leverages the DocuSign Navigator API. The tools, like `get_agreements`, make a request to the DocuSign API to fetch data and then respond in an LLM-friendly way. ` Before the MCP can request anything, it needs to guide the client on how to kick off OAuth. This involves providing some MCP spec metadata API endpoints that include necessary information about where to obtain authorization tokens and what resources it can access. By understanding these details, the client can seamlessly initiate the OAuth process, ensuring secure and efficient data access. The Oauth flow begins when the user's LLM client makes a request without a valid auth token. In this case they’ll get a 401 response from our server with a WWW-Authenticate header, and then the client will leverage the metadata we exposed to discover the authorization server. Next, the OAuth flow kicks off directly with Docusign as directed by the metadata. Once the client has the token, it passes it in the Authorization header for tool requests to the API. ` This minimal set of API routes enables me to fetch Docusign Navigator data using natural language in my agent chat interface. Deployment Options I deployed this MCP server two different ways: as a Fastify backend and then by Vercel functions. Seeing how simple my Fastify MCP server was, and not really having a plan for deployment yet, I was eager to rewrite it for Vercel. The case for Vercel: * My own familiarity with Next.js API deployment * Fit for architecture * The extremely simple deployment process * Deploy previews (the eternal Vercel customer conversion feature, IMO) Previews of unfamiliar territory Did you know that the MCP spec doesn’t “just work” for use as ChatGPT tooling? Neither did I, and I had to experiment to prove out requirements that I was unfamiliar with. Part of moving fast for me was just deploying Vercel previews right out of the CLI so I could test my API as a Connector in ChatGPT. This was a great workflow for me, and invaluable for the team in code review. Stuff I’m Not Worried About Vercel’s mcp-handler package made setup effortless by abstracting away some of the complexity of implementing the MCP server. It gives you a drop-in way to define tools, setup https-streaming, and handle Oauth. By building on Vercel’s ecosystem, I can focus entirely on shipping my product without worrying about deployment, scaling, or server management. Everything just works. ` A Brief Case for MCP on Next.js Building an API without Next.js on Vercel is straightforward. Though, I’d be happy deploying this as a Next.js app, with the frontend features serving as the documentation, or the tools being a part of your website's agentic capabilities. Overall, this lowers the barrier to building any MCP you want for yourself, and I think that’s cool. Conclusion I'll avoid quoting Vercel documentation in this post. AI tooling is a critical component of this natural language UI, and we just want to ship. I declare Vercel is excellent for stateless MCP servers served over http....

Let's innovate together!

We're ready to be your trusted technical partners in your digital innovation journey.

Whether it's modernization or custom software solutions, our team of experts can guide you through best practices and how to build scalable, performant software that lasts.

Prefer email? hi@thisdot.co