Recently, I was tasked with creating our API. I chose NestJS to experiment with since its tagline:

A progressive Node.js framework for building efficient, reliable and scalable server-side applications.

really jived with me. I was excited to tackle this problem and thought with my JavaScript background — learning a new library while also learning TypeScript couldn’t be that hard, could it? Well, 500+ searches and a pretty good API foundation later, NestJS has lived up to the excitement. This article takes you through my development hurdles and successes.

A selection of my searches will be displayed in the format: search🔎 as well as quick answers to some. Additionally, on the search itself, I’ve linked to specific articles or posts that solved those queries.

API requirements

Typescript, TypeORM, GraphQL Support

Basic Splash Page that shows ‘API Operational’ with CameraKit Logo/etc

User scheme to support sign-in, sign-up, portal access, and user settings

Doing Research

It starts with the nestjs🔎 search. One that I had used seven more times over the course of development, most assuredly to get to the main NestJS site — a great source of documentation and best practices. I quickly realized I needed to take a step back to see what NestJS does. nestjs explanation🔎landed me this great article from Auth0. The next search nestjs vs nextjs🔎 seems a bit out of place, but to make things a bit more confusing, the main CameraKit website began transitioning to NextJS for server-side rendered React; which, of course, has nothing in common with NestJS besides very similar pronunciation.

Constructing the Scaffold

I soon gained a bit of confidence as I started branching off to the beginning steps of making an API— nestjs user authentication🔎 which led me down the path of using nestjs passport🔎, and then getting a bit more serious with the keyword-shotgun approach scaffold nestjs typescript typeorm graphql🔎 — a surprisingly helpful search which pointed me towards this GitHub Repository. I will implement some of the ideas here, just to have them not work later, though, after an update changes the interfaces. I then realized I should include Linting; tslint airbnb rules🔎, tslint config json extend🔎, and tsconfig.json🔎 helped set up TsLint with my preferred Airbnb Config. This was not any harder than installing and adding a line in tslint.json .

Adding a Database

Apollo support was next on my todo list:

🔎

- scaffold tests typescript typeorm grapql

- apollo server express

- nestjs grapql scaffold

Though I ran into what I thought was a problem with a package version Module has no exported member ‘graphiqlexpress’🔎. I solved this by adding @types/grpahql . Only after some confusion: Removing carrots from dependencies🔎, What are carrots in package.json🔎.

After adding TypeORM (with the help of the docs), and deciding to use PostgreSQL as the database, I was ready to start writing some code.

🔎

- add typeorm to nestjs

- best db to use with typeorm

- what database to use with typeorm

- typeorm and mongodb

- set up postgresql server on windows

Making the Index Page

I like starting with a splash page for the API to have a quick and dirty way to confirm requests are being served. This involved getting the file system

🔎

- nestjs index example

- import path

- favicon

Including the favicon

🔎

- favicon

- favicon include in site

- Nestjs fastify “favicon”

As well as getting the image and font right

“CameraKit API Operational” on the index page

This search, and similar phrases, came up multiple times while developing with NestJS. An error might look something like:

[ExceptionHandler] Nest can't resolve dependencies of the UserController (UserService, ?). Please make sure that the argument at index [1] is available in the current context.

and I did not know where to look at first. I thought there was something I didn’t know about nestjs interface🔎 or typescript interface🔎, but there were some helpful clues. First, I looked inside the user.controller , and realized that (UserService, ?) points towards its constructor:

You can see NestJS knows about the UserService , and even though I believed I imported the SubscriptionService

nestjs imports exports providers🔎 showed me it both needs to be exported from subscription.module

As well as imported from the user.module

Using Different Development Environments

Because I develop on a Windows computer and Mac laptop, programs and services outside of the great NPM need to be installed: install postgres mac🔎, debugged: invalid active developer path🔎 and set up: create role postgresql🔎 postgresql mac service cli🔎 default postgres password🔎 create user postgres🔎. After getting back up to speed on the Mac side I begin implementing user registration and login. nest authentication login api🔎 and nestjs authentication🔎 kept pointing me towards nestjs/passport as well as the authentication technique in the NestJS docs. I eventually went with their “best practice”, and decided to follow the JWT approach.

🔎

- jwt passport persistent sessions

- express session

- nestjs passport session

- passport session

- passport jwt session

- debugging nestjs

- auto attach vs option

Out of those searches, I realized I did not want to use express session as well as learning how to debug from here. For Visual Studio Code users turn on Auto Attach:

Visual Studio Code settings — search for “auto attach” and flip it on

and create nodemon.json which runs with nodemon .

Adding custom Configuration and Security

A few searches later,

🔎

- what passport strategy to use for logins local vs jwt

- what’s the point of jwt

- saving jwt in local storage

- nestjs middleware cookie session login authentication

- passport extend strategy

- nestjs guard passport

- use guards nestjs

I had the API hooked up to the web client in what I thought was a working state. I realized later that the nice comments in the example GitHub repository would need to be followed and implemented. After some worrying: authentication with jwt secure🔎 jwt brute force🔎 generate good jwt secret🔎 I needed a place to store my newly generated secret . I turned to dotenv🔎 to handle configuration files, and of course had to search how to name something starting with a dot in finder🔎. I started off with using purely environment variables and accessing them within the code from process.env.ENVIRONMENT_VARIABLE , but soon after nestjs configuration documentation🔎, I found my way back to the NestJS documentation which suggests using joi npm🔎 for validation. I followed the advanced configuration and made a global module nestjs global modules🔎. To round out my “security audit” I read and implemented nestjs force ssl🔎 for production

After quite a few searches

began to add CSRF protection csurf🔎 until I decided it was unnecessary at this time.

Deploying to Heroku

The next step was deployment to Heroku. Of course it did not work on the first try. I fixed bcrypt failing heroku🔎 by installing a new version, same with ts-node not found🔎, and an error that stumped me for a while — web process failed to bind to $PORT within 60 seconds of launch wait longer🔎. I originally thought I might need more time, but I actually needed to dynamically set the port according to the environment variable that Heroku assigns. When that still did not fix the problem app.listen string or number🔎 nestjs heroku port🔎 nestjs heroku deploy🔎 showed me the host was required to be set to 0.0.0.0 .

I was then back to errors that I had seen before! This time concerning the environment variables. I was confused how the variables worked on Heroku, and realized after a bit of searching:

🔎

- heroku dotenv

- push file to heroku

- put dotenv file in Heroku

- “Dotenv” “heroku” site:stackoverflow.com

- dotenv parse current process env variables

- “Get all” environment variables dotenv

dotenv does not work with Heroku because the .env file should never be committed. This is for good reason since your secrets would not be secret. Therefore, I solved the problem by either using the file (if found) or checking for environment variables that are already set and then validating them.

🔎

- get keys from object into different object specific

- get variables out of process.env

- assign specific object properties to new object

- reduce mdn

With that done, more errors came up that looked like a typescript compilation problem, but with weird errors like cannot find global type ‘Boolean’ .

Almost everyone pointed towards fixes through tsconfig.json , yet suggestions to change the lib to X would remove Y error, but add Z error. I ended up with a tsconfig.json that worked, but unfortunately I could not tell you why.

Still, TypeORM was throwing errors, and it was at this time I realized the TypeORM entities

were correctly found during development in the /src directory, but since production moves the files to the /dist directory, the entities were not correctly found. I changed where TypeORM looks for the entity files by changing src/**/*.entity.ts to dist/**/*.entity.js .

Conclusion

To great relief, the server successfully deployed and started serving requests. I have since gone on to add more functionality as well as run into more problems, but that’s development! Thanks for reading, and if you’re interested: a full list of my searches!

CameraKit helps implement reliable Android camera into your mobile app easily. Open-source, performant, and optimized for tackling the complex Camera APIs on Android.