In my previous article, I talked about how to get Now up and running with multiple environments. We used a boilerplate Next.js app and added a single environment variable to show our intended deployment on the landing page. Today, I’d like to take that app a bit further and show how to integrate Next.js serverless API functions with TypeORM and Postgres. While this still won’t cover everything, by the end we will be able to:
What this won’t cover:
I’ll be continuing the series hoping to address the above as this tech stack progresses. For now, let’s get this app running with some data.
Note: As stated in the previous article, ZEIT is still a moving target. I’ve been keeping watch over threads. While this is an example of a current setup, I am aware they are still actively adding features and sifting through requests. Should this setup change I’ll create a follow-up post. This is not the single and only way to do things.
If you’ve worked with an ORM you should be good here. The main benefit of using this one was out of the box TypeScript support. I’m not going to dive into the specifics of TypeORM but we will be covering the config setup and I’ll have a few examples along the way. I am going to go ahead and define some terms here as I’ll be using them throughout this post.
Entity: (Model) A class that maps to a database table. This also provides typescript annotations to our app.
Migrations: TypeORM will compare your Entities to Postgres and auto-create a migration file. Running the generate command will create a timestamped file with the needed up and down SQL. 90% of the time this will be all you need. However, I will note I’ve seen some edge cases when trying to update fields to something new, say an enum type, where this SQL may be off. Regardless, these files are generated but not set in stone. You can edit at will if something needs to be added. It’s always good to double-check.
TypeORM has a lot of built-in helpers for generating the core entities and migration files. You can install this dependency globally, but we would like to use these commands in our yarn scripts in pair with dotenv and keep our package versions under control.
To start we are going to look at a couple of setup scripts that will leave us with a base User model.
So we have a script that creates our databases and scripts to create an entity and create a new migration file. However, if you run any of the generate commands now, things will begin to break. TypeORM isn’t aware of your database just yet.
You have the normal DB setup here with connection type, host, db, port, etc. but we also have some ENV’s set for Entities Migrations and their respective directories. TypeORM will look to these files when making a comparison for migrations and use the directories when we generate new content. If you look into the root of our project you’ll see a folder set for both.
Taking a closer look you’ll notice that Column takes an object of keys that are database specific. Underneath each of these, you’ll also see the field is defined as a public field for typescript. A quick note, you can define different field names within Column if you would like to map to something different. eg. first_name maps to firstName. We’ll see how this all plays out in a second but for now, let’s keep going.
Enums. At some point, you’ll want to add a field that has limited values. For this example, we are going to add a role to the user. Similar to the other fields we will still use Column, but expand on the type options for Postgres. We’ve also defined this as a constant type to use within our application code.
Finally, you’ll notice I’ve used TypeORM’s utils for timestamps and primary keys. I’ve also brought in a before insert helper to set the primary id to a UUID rather than the Postgres default of 1, 2, 3. I know this is a lot but you altogether you should be looking at something like this.
Adding more of these lines we can attempt to run this seed file within our yarn scripts and add some users. Feel free to be creative.
I also mentioned at the beginning of this post it does not cover testing. There are still a few topics I’d like to cover regarding Next.js and Now. Namely testing your API with end-to-end tests, expanding on CI/CD, and Database pooling. Stay tuned, hopefully as I learn, so will you.
Matt Thompson is a lead engineer at Echobind, mentor, and content creator. Matt spends most of his time finding ways to improve the process for others. When he’s not building software, you’ll find him enjoying time with family, unplugging with a book, and woodworking.