Basic Apollo Express GraphQL API with TypeScript

In this article we are going to learn how to build a Basic Apollo Express GraphQL API with TypeScript. I’ve been looking for a dead simple tutorial to get started and didn’t find any so I decided to write my first article on Medium with this topic!

⚠️Disclaimer: This is obviously not a production ready project, this is an illustration of a basic setup with TypeScript, don’t use it in production if you don’t know what you are doing.

🏎️ If you do not have the time to read this because there are 27 more articles waiting for you in your browser’s tabs, here is the full code.

For those, like me, that weren’t used to build Node.js app with TypeScript, the first chapter is for you even though you should be already convinced if you are here.

Why use Typescript?

TL;DR TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. It’s awesome, really.

TypeScript is for JavaScript development at application scale. As JavaScript code grows, it gets messier, making it more and more difficult to maintain and reuse the code. That’s true for both Front End and Back End Applications. JavaScript fails to embrace strong type checking and compile-time error checks and TypeScript was presented to bridge this gap.

Pros and cons

🚀 JavaScript super-set: Rename your .js file into a .ts file and 💥it’s already TypeScript! TypeScript has an easy learning curve, you can learn it step by step, but still use it in your project.

🚀Javascript of tomorrow: Many of TS features became part of ECMA specification. Get ready for the future, today.

🚀 Compilation: TypeScript compiles and generate compilation errors if it finds some sort of syntax errors. It helps to highlight errors before the script actually runs and fails.

🚀Strong Static Typing: TypeScript comes with an optional static typing and type inference system through the TLS (TypeScript Language Service). Also, it provides code analysis and auto-completion for IDEs.

🤷‍♂️ No cons.


Let’s actually build the thing you are here for…

Creating a basic TypeScript configuration

So you didn’t come here to learn why TypeScript is awesome, did you?

Setting up the project

Create a new folder for the project and create a package.json file with the help of the CLI.

$ mkdir typescript-apollo-express-graphql-api
$ cd typescript-apollo-express-graphql-api
$ npm init --yes

Install & Initialize TypeScript

Install Typescript and generate a tsconfig.json file using npx.

We will also need nodemon to compile our code on change, and ts-node to exec TypeScript files.

$ npm i typescript nodemon ts-node --save-dev
$ npx tsc --init --rootDir src --outDir dist --lib dom,es6 --module commonjs --removeComments

Hello World 👋 with a TypeScript configuration

Create a/src directory with a server.ts file.

$ mkdir src && cd src && touch server.ts

Put some content in that file for testing purpose

// server.ts
console.log('Hey 👋');

Last step is to adjust scripts in the package.json file as below:

"scripts": {
"start:dev": "npm run build:dev",
"build:dev": "nodemon 'src/server.ts' --exec 'ts-node' src/server.ts -e ts,graphql"
}

With that, you should be able to type npm run start:dev in your terminal to start nodemon and see our console.log. Nodemon should also recompile if you change the code in the server.ts file.

Hello world 👋

Setting up Express, Apollo and creating a simple GraphQL API

If you are new to GraphQL, I won’t cover the concept here as it’s not the topic but here is a link introducing GraphQL.

Installing moar dependencies…

$ npm i apollo-server-express compression cors express graphql http ncp
$ npm i @types/compression @types/express @types/graphql @types/graphql-depth-limit @types/node graphql-depth-limit graphql-import graphql-import-node --save-dev

Creating the Apollo Server with basic options

Change the content of server.ts to this:

import express from 'express';
import { ApolloServer } from 'apollo-server-express';
import depthLimit from 'graphql-depth-limit';
import { createServer } from 'http';
import compression from 'compression';
import cors from 'cors';
import schema from './schema';
const app = express();
const server = new ApolloServer({
schema,
validationRules: [depthLimit(7)],
});
app.use('*', cors());
app.use(compression());
server.applyMiddleware({ app, path: '/graphql' });
const httpServer = createServer(app);
httpServer.listen(
{ port: 3000 },
(): void => console.log(`\n🚀 GraphQL is now running on http://localhost:3000/graphql`));

🗒️Notes about configuration
schema: Will will create it in a second👌,
depthLimit: It’s well documented in the package’s README but to sum that up, it puts boundaries to a query and limits its depth to 7 (in our case) 📉,
compression: Gzip compressing can greatly decrease the size of the response body and hence increase the speed of a web app. See more

Creating GraphQL schema and resolvers

First, let’s create our GraphQL Schema. In the /src folder, create a /schema folder and 1file inside: schema.graphql.

$ mkdir schema && cd schema && touch schema.graphql

Declare a Query type in it:

// schema.graphql
type Query {
helloWorld: String!
}

Then let’s quickly create a resolverMap file in the /src folder:

$ cd ../ && touch resolverMap.ts
// resolverMap.ts
import { IResolvers } from 'graphql-tools';
const resolverMap: IResolvers = {
Query: {
helloWorld(_: void, args: void): string {
return `👋 Hello world! 👋`;
},
},
};
export default resolverMap;

Finally create a schema file in the /src folder that will be in charge of making an Executable GraphQL Schema:

$ touch schema.ts
// schema.ts
import 'graphql-import-node';
import * as typeDefs from './schema/schema.graphql';
import { makeExecutableSchema } from 'graphql-tools';
import resolvers from './resolverMap';
import { GraphQLSchema } from 'graphql';
const schema: GraphQLSchema = makeExecutableSchema({
typeDefs,
resolvers,
});
export default schema;

Aaaaand… That’s it! You try try to Query the helloWorld query we created and it should be working!

Last step: Compile the code

Adjust the script in your package.json file as below:

"scripts": {
"start": "node 'dist/server.js'",
"build": "tsc -p . && ncp src/schema dist/schema",
"start:dev": "npm run build:dev",
"build:dev": "nodemon 'src/server.ts' --exec 'ts-node' src/server.ts -e ts,graphql"
}

Running npm run build in your terminal will compile your code and put it in the /dist folder. You can run the compiled code with npm start.

Here is the repo with all the code.