GraphQL + TypeScript + PostgreSQL API

wonder2210

Wonder2210

Posted on June 8, 2020

GraphQL + TypeScript + PostgreSQL API

Introduction

In the current year, one of the most popular stacks is GraphQl and Typescript (and for a while, I think). I started recently a new project, using this stack, I did some GraphQL API's using good Vanilla Javascript before, but even I'm using Typescript for few times. I've never used it for this purpose but I didn't find a tutorial who fits with my requirements, I get it done, then I ask to my self. Why not do a guide?. Here we go

before we are starting :

Why GraphQL ?:

GraphQL provides a complete description of the data in your API, giving clients the power to ask for exactly what they need and nothing more when you have to deal with a great amount of data this is a very nice choice, you can have all the data required with just Running one Query.

Why typescript? :

Typescript is a superset of Javascript that compiles to plain JavaScript.
As JavaScript code grows it gets messier to maintain and reuse, and don't have strong type checking and compile-time error checks, that's where Typescript comes in

Why PostgreSQL?

PostgreSQL is a personal preference, is widely used, open-source, and has a great community, but I'm not going to go deep about it, You can read more about why use it here

Prerequisites

  • yarn you can use NPM no matter
  • node: v.10 or superior
  • postgresql = 12
  • some typescript knowledge

1) Folder Structure

This is how's going to be structured the project

   graphql_api/
       ...
        dist/
          bundle.js
        src/
         database/
              knexfile.ts
              config.ts
              migrations/
              models/
                User.ts
                Pet.ts
          __generated__/
          schema/
              resolvers/
                  user.ts
                  pet.ts
                  index.ts

              graphql/
                  schema.ts
              index.ts/
          index.ts       
Enter fullscreen mode Exit fullscreen mode

2) Main Dependencies

  • Apollo server: Apollo Server is a community-maintained open-source GraphQL server. It works with pretty much all Node.js HTTP server frameworks

  • Objection: i used to use sequelize but i really like objection.js because it is an ORM that embraces SQL

    Development

  • Webpack : webpack is used to compile JavaScript modules, node.js by its own doesn't accept files .gql or .graphql , that's where webpack comes in

First, we are going to install

yarn add graphql apollo-server-express express body-parser objection pg knex
Enter fullscreen mode Exit fullscreen mode

and some dev dependencies

yarn add -D typescript @types/graphql @types/express @types/node  graphql-tag concurrently nodemon ts-node webpack webpack-cli webpack-node-external
Enter fullscreen mode Exit fullscreen mode

3) Configurations

tsconfig

Webpack

4) Hello World

Add the next scripts to your package.json


Enter fullscreen mode Exit fullscreen mode


json
"scripts":{
"dev": "concurrently \" nodemon ./dist/bundle.js \" \" webpack --watch\" "
}


Enter fullscreen mode Exit fullscreen mode

index.ts

5) Server config

For this project we are gone to use , Executable schema from graphql-tools wich allow us to generate a GraphQLSchema instance from GraphQL schema language beside this you can also combine types and resolvers from multiple files

src/index.ts


Enter fullscreen mode Exit fullscreen mode


typescript
...
const config : Config = {
schema:schema,// schema definition from schema/index.ts
introspection: true,//these lines are required to use

playground: true,// playground

}

const server : ApolloServer = new ApolloServer(config);

server.applyMiddleware({
app,
path: '/graphql'
});
...


Enter fullscreen mode Exit fullscreen mode

schema/index.ts


Enter fullscreen mode Exit fullscreen mode


typescript
import { makeExecutableSchema} from 'graphql-tools';
import schema from './graphql/schema.gql';
import {user,pet} from './resolvers';

const resolvers=[user,pet];

export default makeExecutableSchema({typeDefs:schema, resolvers: resolvers as any});


Enter fullscreen mode Exit fullscreen mode

6) Database

Now we will be working based in the next database diagram, It will be just a register of Users and their pets.
capture
Migration file
For creating the database in Postgres , we'll be using the migrations of knex



and generate the first migration running:


Enter fullscreen mode Exit fullscreen mode


bash
npx knex --knexfile ./src/database/knexfile.ts migrate:make -x ts initial


Enter fullscreen mode Exit fullscreen mode

And your migration file should look's like this



Then run the migration


Enter fullscreen mode Exit fullscreen mode


bash
npx knex --knexfile ./src/database/knexfile.ts migrate:latest


Enter fullscreen mode Exit fullscreen mode

Now we have two tables then we need the models for each table to start executing queries
src/database/models:



then we need to instantiate Knex and give the instance to Objection


Enter fullscreen mode Exit fullscreen mode


typescript

import dbconfig from './database/config';
const db = Knex(dbconfig["development"]);

Model.knex(db);


Enter fullscreen mode Exit fullscreen mode

7) Schema

8) generating types

we need the following packages for better type safeting the resolvers :


Enter fullscreen mode Exit fullscreen mode


bash
yarn add -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/
typescript-resolvers @graphql-codegen/typescript-operations


Enter fullscreen mode Exit fullscreen mode

create the config file for generate types :

/codegen.yml
Enter fullscreen mode Exit fullscreen mode

Enter fullscreen mode Exit fullscreen mode


yml
overwrite: true
schema: "http://localhost:3000/graphql"
documents: null
generates:
src/generated/generated-types.ts:
config:
mappers:
User:'./src/database/User.ts'
UpdateUserInput:'./src/database/User.ts'
Pet:'./src/database/Pet.ts'
plugins:
- "typescript"
- "typescript-resolvers"


Enter fullscreen mode Exit fullscreen mode

add the follow script to packages.json :


Enter fullscreen mode Exit fullscreen mode


json
...
"generate:types": "graphql-codegen --config codegen.yml"
...


Enter fullscreen mode Exit fullscreen mode

once your server is up , then run :


Enter fullscreen mode Exit fullscreen mode


bash
yarn run generate:types


Enter fullscreen mode Exit fullscreen mode

if you want to go deep generating types from graphql you can read more about here, I highly suggest to do

9) resolvers

schema/resolvers/



Now you should be able to execute all the operations defined before

BONUS:

you can see two errors from typescript

errors

it's not terrible at all, but I would prefer to don't have them

then

the first one I get it solved splitting knexfile.ts and put the configuration that is required for knex in a standalone file

And the second one, from the import of the schema , I get it solved with this useful post
and finally, you should have working your own graphql api

Conclusion

Congratulations ! Now you have a GraphQL API
if you get stucked at any of the steps here is the repo on github , In this tutorial we learned about, how to generate types for Typescript from graphql , solve some issues , I hope you enjoyed this post , if is it the case, please follow me here on DEV and also on twitter I'll be posting more often soon , if you have any suggestion for me I would love to know it , leave it below in the comments box ,Thanks!

💖 💪 🙅 🚩
wonder2210
Wonder2210

Posted on June 8, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related