GraphQL + TypeScript + PostgreSQL API
Tags: graphql, typescript, javascript, webpack
Published: 2020-06-08 01:53:41

###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](https://www.compose.com/articles/what-postgresql-has-over-other-open-source-sql-databases/) 

## 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       
```


###2) Main Dependencies

* [Apollo server](https://github.com/apollographql/apollo-server/tree/master/packages/apollo-server-express): Apollo Server is a community-maintained open-source GraphQL server. It works with pretty much all Node.js HTTP server frameworks

* [Objection](https://github.com/Vincit/objection.js/): i used to use sequelize but i really like objection.js because it is an [ORM that embraces SQL](https://www.jakso.me/blog/objection-to-orm-hatred)
####Development 

* [Webpack](https://webpack.js.org/) : 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
```
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
```
###3) Configurations
**tsconfig**
 {% gist https://gist.github.com/Wonder2210/1fdab079504b8b7be752776404759ec4 %}

**Webpack** 
{% gist https://gist.github.com/Wonder2210/ee0c1be1a9d3e3ff34f6d067d6b52beb %}

###4) Hello World
Add the next scripts to your package.json
<code>
```json
"scripts":{
     "dev": "concurrently \" nodemon ./dist/bundle.js \" \" webpack --watch\" "
}
```
</code>
#### index.ts
{% gist https://gist.github.com/Wonder2210/e1195083396b3d8c52d0b0ea95f71010 %}
###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**
<code>
```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'
  });
...
```
</code>

**schema/index.ts**
<code>
```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});
```
</code>
###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](https://user-images.githubusercontent.com/29363763/83218089-46220b00-a13b-11ea-8441-64338ab730c9.JPG)
Migration file
For creating the database in Postgres , we'll be using the migrations of knex 
{% gist https://gist.github.com/Wonder2210/5fdb77172286962633b2bc8ae8a683e6 %}
and generate the first migration running:
<code>
```bash
npx knex --knexfile ./src/database/knexfile.ts migrate:make -x ts initial
```
</code>
And your migration file should look's like this
{% gist https://gist.github.com/Wonder2210/654dcf4f1a5dfee94499634d9d90aa3b %}
Then run the migration
<code>
```bash
npx knex --knexfile ./src/database/knexfile.ts migrate:latest
```
</code>
Now we have two tables then we need the models for each table to start executing queries
src/database/models:
{% gist https://gist.github.com/Wonder2210/bb5d7feab96552d608959d2319b387b0 %}
then we need to instantiate Knex and give the instance to Objection
<code>
```typescript

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

Model.knex(db);
```
</code>
###7) Schema

{% gist https://gist.github.com/Wonder2210/76200ff85da74ff0ba1ea574dce3c248 %}

###8) generating types
we need the following packages for better type safeting the resolvers :
<code>
```bash
 yarn add -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/
typescript-resolvers @graphql-codegen/typescript-operations 
```
</code>
create the config file for generate types :
```
/codegen.yml
```
<code>
```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"

```
</code>
add the follow script to packages.json :
<code>
```json
...
"generate:types": "graphql-codegen --config codegen.yml"
...
```
</code>
once your server is up , then run :
<code>
```bash
yarn run generate:types
```
</code>
if you want to go deep generating types from graphql you can read more about [here](https://the-guild.dev/blog/better-type-safety-for-resolvers-with-graphql-codegen), I highly suggest to do
###9) resolvers
schema/resolvers/
{% gist https://gist.github.com/Wonder2210/c014ca374ce4d6ccd7e94c4726c96771 %}
Now you should be able to execute all the operations defined before
**BONUS:**
you can see two errors from typescript 
![errors](https://user-images.githubusercontent.com/29363763/83219548-9f3f6e00-a13e-11ea-8e32-b56e21b42ead.png)
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 
{% gist https://gist.github.com/Wonder2210/dd426019f2195dcc99a171f9f28ff02a %}

And the second one, from the import of the schema , I get it solved with this [useful post](https://dev.to/open-graphql/how-to-resolve-import-for-the-graphql-file-with-typescript-and-webpack-35lf) 
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](https://github.com/Wonder2210/graphql-typescript-pg-server) , 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!