DIV and Backend again. A TypeScript Tale: Part 3

Connecting Graphql to PostgreSQL with TypeORM

Object Relation Mappers transform SQL into classes, and provide an abstraction above database access.

Even you couldn't say no to that.

Oh yes we could! Spoiling nice SQL. Give it to us raw and unreadable!! You keep nasty ORM.

You're hopeless.


  1. Nx.dev- In Part 1, we setup an Nx workspace, with a NextJS front end.

  2. Type-GraphQL - In Part 2, we setup a graphql server that generates our graphql schema based on our types.

  3. YOU ARE HERE
    TypeORM
    - An excellent, battle tested, ORM with over 20k stars. TypeORM will be where the bulk of our actual types flow from. TypeORM can generate and run migrations as well as traditional ORM capabilities.

  4. GraphQL Code Generator- The type safe link between your front end and your back end. We will generate an SDK, which we can use on the front end to achieve complete type safety. We will use the apollo generator, but there are tons of options for common graphql tooling.

  5. Tying it all together - Lets put all our hard work to good use with some examples.

Prerequisites

You should have the following installed:

  1. Part 1 - Nx

  2. Part 2 - type-graphql.

  3. node: version 14 or greater. I recommend NVM if you need to switch versions between projects.

  4. yarn: You could use npm if you like, but this guide will be using yarn in it’s examples.

  5. Docker: We use docker to setup a development database. You can always install postgres directly on your machine if you don’t want to use Docker. Just make sure postgres is running on port 5432.

Part 3: Connecting GraphQL to PostgreSQL with TypeORM


Want to skip ahead? Check out the the Part 3 source on GitHub


Running a local version of PostgreSQL:

In order to skip lots of install instructions, we’re just going to use docker to spin up postgres.

Add a docker-compose.yml file at the root of your project:

Then run docker-compose up. You should have postgres available on port 5432. You can use docker-compose up -d to run the services in the background.

Initializing TypeORM


For our DB connection, we are going to use TypeORM, which will manage migrations, schemas, and types for us. All of our types will flow from our TypeORM classes.

First, add some dependencies:

yarn add typeorm pg ts-node

Add this script to your package.json

"typeorm": "ts-node -P ./tsconfig.base.json -O '{\"module\": \"commonjs\", \"experimentalDecorators\": true}' -r tsconfig-paths/register ./node_modules/typeorm/cli.js --config ormconfig.js",

W need to add a lib for all our database interactions.

yarn nx generate @nrwl/node:library --name=db

Now create a ormconfig.js in the root of your project, add the following to it:

Creating our Entities

Note: We are going to ignore validation, since it’s a bit out of scope. But Type-GraphQL provides a very elegant means of validation in the form of Class Validator.

Time to create our our TodoItem entity. These will map to tables in our database.

  1. Delete libs/db/src/lib/db.ts and libs/db/src/lib/db.spec.ts

  2. Create a file: libs/db/src/lib/entity/TodoItem.ts

  3. Create our first migration: yarn typeorm migration:create -n AddTodoItem. You should have a generated file called libs/db/src/lib/migration/<timestamp>-AddTodoItem.ts.

    There seems to be some bug with typeorm, with regards to migrations, but only on my windows machine using WSL2. I am still investigating. If your migration file comes out empty, while following this guide, reach out to me on twitter @ericwooley. Maybe we can figure it out together.

  4. We can run the migration, to create our initial schema:
    yarn typeorm migration:run

  5. If you use something like DBeaver, you can see that the underlying table.

  6. Follow the same flow for libs/db/src/lib/entity/List.ts:

  7. Before we add migrations, lets create our relationship first. This is a many to one relationship, where the list has many todo items, but a todo item only has one list. Lets add those relationships with TypeORM.

  8. Now if we generate our migrations again:
    yarn typeorm migration:generate -n AddList
    Then run our migrations
    yarn typeorm migration:run
    Our list table has been created, and our Todo Items now have a reference to our List. You should also have another migration file, similar to this.

  9. Export both List and TodoItem in libs/db/src/index.ts

Hooking our entities up to Type GraphQL

To make use of our entities on our server, we need to initialize the TypeORM connection, and let it know about our models. Update apps/api/src/main.ts to call to createConnection. It should look like this:

Now that we have type safe access to our database, we can use our entities with Type-GraphQL by adding ObjectType and Field decorators.

The beautiful things about Type-Graphql and TypeORM is that they decorators are compatible. So lets just stick em right in there.

The last thing we need to do is update libs/graphql/src/lib/list/list-resolver.ts:

You should now be able to get all your typeorm types straight from graphql:

Up Next

Man this is a lot of work! So many pieces, so much config! You are right, but don’t give up yet! It’s all down hill from here. Everything from this point out is going to be taking advantage of all the types we made. Starting with Part 4, GraphQL codegen. We will use graphql code generation to create a fully typed, ready to use SDK for our front end.

If you haven’t subscribed, make sure you do, so you don’t miss the next part in the series.