Firebase functions "in short"
Published: 2023-06-14 11:17:31

Firebase functions let you write the logic of your application on the servers of Google.

A function is like a callback that gets executed whenever *something happens* in your application, i.e. when a user is created/deleted, when your Firestore database changes, etc...

You can then execute anything that you want on these special events. 

## Source of truth

All the development you are doing on your local machine is considered source of truth. That means every time you need to augment the functionality of your application you have to develop your functions locally and push/deploy them on the cloud.
But the contrary is not true, for instance if you delete a function directly from the console there is no way to reflect the change locally. 

## Blaze Plan

If you want to use cloud functions you will need to upgrade your project to a Firebase *Blaze Plan* ([more details here](https://firebase.google.com/pricing)).
Don't worry you don't have to pay to switch to that plan because Spark plan is included (but I would still recommend you set a billing alert.)

## Google Cloud

Behind the scene Firebase is just a candy-wrapped and user-friendly platform for introducing new users to the Google Cloud world. For instance when you create a Firebase function, in reality the function is just installed on Google Cloud servers.
You can check installed functions and their details at any time going to the [cloud functions page](https://console.cloud.google.com/functions/list)

## Config

Configs let you pass environmental variables in your functions at runtime. There are few ways of doing that:

### functions.config

This is considered the old way, you can use the following command to register a runtime value
```
firebase functions:config:set MY_KEY="something"
```
*(note: This will save the value in the cloud directly and they will be included inside each deployed functions)*

Use `firebase functions:config:get > .runtimeconfig.json` to save the config object inside `functions` directory, and then you can retrieve values in your functions with the following:

```javascript
const {config} = require('firebase-functions/v1');

console.log(config().MY_KEY);
```

**But if your function is defined as a v2 function you should use v2 accessories**

### v2
In Firebase v2 you have 3 options:

- **Parameterized configuration**

```javascript
const {defineString, defineInt, ...} = require('firebase-functions/params');

const myParam = defineString('MY_PARAM');
console.log(myParam.values());
```
During emulation/deployment you'll be asked to enter a default value for your params, and a `.env.<project_id>` file will be created inside the `functions` directory ([more info there](https://firebase.google.com/docs/functions/config-env?gen=2nd#params))

- **dotenv**

To use this configuration pattern, create `.env` file in the `functions` directory.
Then you can access them in your functions using `process.env.<VAR>`.
you can have different `.env.<type>` file and use `firebase use` to use one or another ([more details there](https://firebase.google.com/docs/functions/config-env?gen=2nd#env-variables))

If you need to migrate from v1 to dotenv, you can use this command `firebase functions:config:export`. That will export the config values in appropriate dot env files.

- **secrets**

This is considered most secured and also convenient (but with convenience comes a cost?).

[More details here](https://firebase.google.com/docs/functions/config-env?gen=2nd#create-secret)

*([firestore-stripe-payments](https://github.com/stripe/stripe-firebase-extensions/tree/master/firestore-stripe-payments) create a GC secret during the installation)*

---
For more details about config please [read this](https://firebase.google.com/docs/functions/config-env?gen=2nd)

**Be aware**: [environment variables are not being loaded during deployment](https://github.com/firebase/firebase-functions/issues/1094#issuecomment-1595351596)
Here's a possible solution
```typescript
import {config} from 'dotenv';
config();
// now process.env.<VARNAME> will be available
```
*(note that `config()` only interprets values in `.env` by default)*


## Emulator

We can use `firebase` command tool to try out our functions before deployment using the emulator.

```
firebase emulators:start --only functions
```

## Deploying

Once you are done with the development phase, you can deploy your functions using

```
firebase deploy --only functions
```

Firebase will create an endpoint for all the exposed functions.

During deployment the JavaScript files are being packaged and sent to the cloud.

## Codebases

You can have different functions [codebases](https://firebase.google.com/docs/functions/organize-functions?gen=2nd) within your project. This allows you to organize functions into different directories/environments.  
It can also help for the deployment as you are able to filter and deploy only functions from a specified codebase, e.g.

```bash
firebase deploy --only functions:<codebase_name>
```

To create a new codebase just run `firebase init` and select "Functions" and follow the prompts.

## Logger

```typescript
import {logger} from 'firebase-functions';
```
You can also use the logger from gcloud package (TODO)

## Miscellaneous information

You can code split functions into various files as far as you import-export them inside the `index.js` file (which is the entry point defined in package.json)


**[ Article in Progress ]**