# Serving NestJS via Firebase Functions

# Intro
This is a simple step-by-step guide/note of how to deploy NestJS in Firebase Functions to go serverless as of September 2021.
What I am writing here is almost entirely from the following link of  [Fireship.io](https://fireship.io). 

%[https://fireship.io/snippets/setup-nestjs-on-cloud-functions/]

It is an incredible source but I had to write this post (1) because I am amateur developer and I need a more _digestible_ details, and (2) I wanted to record some of the changes I made after a few failed tries.

# Details
I chose Option A of 'Point a function to Nest' from the site. It seemed to make NestJS and Firebase more decoupled than Option B of 'Add Nest to the Functions Source'.

### Prerequisites:
- You need to set up your project for 'Pay-as-you-go' tier in Firebase to use Functions.  It is a good idea to set up your Firebase project before Step 0.

### Step 0: Install Firebase tools and NestJS
You need both Firebase tools and NestJS installed on your machine.
```
$ npm i -g firebase-tools && npm i -g @nestjs/cli
```

### Step 1: Create a folder for Firebase Functions.
Note the directory structure:
- The parent directory has ```firebase.json``` and ```.firebaserc``` files, and a NestJS project directory is laid as its child.
```
$ mkdir my_functions_project && cd my_functions_project
```
- Inside the newly created ```my_functions_project``` directory, initialize for firebase functions.
```
$ firebase init functions
```
- You will need ```functions``` directory within the NestJS project directory (not immediately in ```my_functions_project```), so you can delete the ```functions``` directory now.
```
$ rm -rf functions
```

### Step2: Adjust firebase.json to the NestJS directory
- Inside the ```firebase.json``` file, add the line of ```"source": "my_nestjs_project"``` under ```functions```.
```{
  "functions": {
    "predeploy": "npm --prefix \"$RESOURCE_DIR\" run build",
    "source": "my_nestjs_project"
  }
}```

### Step3: Create a NestJS project.
- Inside ```my_functions_project``` directory, type in the following command:
```
$ nest new my_nestjs_project
```

### Step 4: Add Firebase and Express in NestJS Project.
- We need Firebase Functions and Firebase Admin in our NestJS project directory. 
- We also need to install Express and its adaptor for NestJS, so run the following commands: (I broke lines for improved readability.)
```
$ npm i firebase-functions firebase-admin 
$ npm i express @nestjs/platform-express
```

### Step 5: Create main.firebase-functions.ts in the NestJS project
- In ```my_functions_project/my_nestjs_project/src```, create ```main.firebase-functions.ts``` with the following content. 
- N.B. Yes, this is in addition to your ```main.ts```.  DO NOT DELETE IT.

```
import { NestFactory } from '@nestjs/core';
import { ExpressAdapter } from '@nestjs/platform-express';
import { AppModule } from './app.module';
import * as express from 'express';
import * as functions from 'firebase-functions';

const server = express();

export const createNestServer = async (expressInstance) => {
  const app = await NestFactory.create(
    AppModule,
    new ExpressAdapter(expressInstance),
  );

  return app.init();
};

createNestServer(server)
  .then((v) => console.log('Nest Ready'))
  .catch((err) => console.error('Nest broken', err));

export const api = 
  functions.region('asia-northeast3').https.onRequest(server);
```

- Note that I used ```asia-northeast3``` for region, but you can choose one that you may find more suitable.   [Visit this link for a list of available regions.](https://cloud.google.com/filestore/docs/regions).

### Step 6: Edit ```eslintrc.js``` to make eslint happier.
- VSCode can give an annoying error that ```import``` is wrong.  This can be corrected by changing ```parserOptions.project``` from ```tsconfig.json``` to ```my_nestjs_project/tsconfig.json```.

```
module.exports = {
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: 'my_nestjs_project/tsconfig.json',
    sourceType: 'module',
  },
```

### Step 7: Update ```package.json``` of your NestJS project.
- You need to add the following lines at the top level of ```package.json```.
```
  "main": "dist/main.firebase-functions.js",
  "engines": {
    "node": "14"
  },
```
- I have also added the following lines for convenience.
```
"scripts":{
  ...
    "serve:firebase": "nest build && firebase serve --only functions",
    "deploy:firebase": "nest build && firebase deploy --only functions",
  ...
}
```

### Step 8: Test to see if it works.
In the ```my_functions_project/my_nestjs_project```, run the following commands to see if everything works:

```
$ npm run serve:firebase
$ npm run deploy:firebase
$ npm run start:dev
```

## Conclusion
I wrote this post as a note to myself but for others who may benefit from it.  Leave your comments and/or questions how you like it.

### Versions info (as of Sept 19, 2021)
- Firebase: 9.18.0
- NestJS: 8.1.1
- NodeJS: 14.17.5
