Reading FILES as environment variables in nodejs
Tags: node, javascript, firebase
Published: 2021-10-21 06:35:12

###Introduction
Recently, I had to write push notification in nodejs for a project, and this took more time to implement considering the time it would have taken if somehow had documented it, hence this article.
In developing softwares, there are some variables that are particular to your environment say test, development, production, staging...and there are particularly some credentials sometimes for third-party apps that you don't want to push to Github, these credentials are usually stored as environment variables which are set to strings and ignored by git as they are listed in your *.gitgnore* file. 
They are usually something like this :

```
NODE_ENV = development
PORT = 3000
MONGO_URI = mongodb+srv://test-cruise:cruise666@cluster0.q1upa.mongodb.net/cruise-dev-DB?retryWrites=true&w=majority
```
[More on environment variables?](https://www.freecodecamp.org/news/what-are-environment-variables-and-how-can-i-use-them-with-gatsby-and-netlify/)

In writing push notifications with firebase cloud messaging, you are given a service-account.json file that stores all cloud messaging configurations, and you don't want your private keys from this file to be public.
Now most developers don't read files, as environment varibales but we're gonna do that, why? Cause we're superheroes and you know what...sh!t I forgot.

Create these files -
**convert.js** - this basically holds the script to convert files to base64 encoded string
**secrets.js** - this holds all the secrets of our software
**.env.development** - this holds all our environment variables for development environment
**push_notification.js** - script to send push notification to fcm

##Step One - Convert your JSON file to base64 encoded string
```js
//convert.js

const fs = require('fs');

//service_account.json is gitgnored
let buff = fs.readFileSync('service_account.json');
let base64data = buff.toString('base64');

console.log(base64data);
```
Run the following command to convert
```
node convert.js
```

##Step Two - Set service account variable
In your .env.development file, set SERVICE_ACCOUNT = your_encoded_string. Your encoded string is gotten from logging base64data.
```
SERVICE_ACCOUNT = Ly8gaW1wb3J0IGRvdGVudiBmcm9tICdkb3RlbnYnOwovLyBpbXBvcnQgZnMgZnJvbSAnZnMnOwovLyBkb3RlbnYuY29uZmlnKCk7CgovLyBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT0gJ3Rlc3QnKSB7Ci8vICAgdHJ5IHsKLy8gICAgIGxldCBkb3RlbnZ0ID0gZG90ZW52LnBhcnNlKGZzLnJlY...........
```

##Step Three
Add SERVICE_ACCOUNT to your secrets and export
```js
//secrets.js

const dotenv = require('dotenv');
const fs = require('fs');

dotenv.config();

if (process.env.NODE_ENV == 'development') {
  try {
    let dotenvt = dotenv.parse(fs.readFileSync('.env.development'));
    for (const k in dotenvt) {
      process.env[k] = dotenvt[k];
    }
    
  } catch (err) {
     console.log(err);
  }
}

const secrets = {
  .....
  port: process.env.PORT,
  serviceAccount: JSON.parse(Buffer.from(process.env.SERVICE_ACCOUNT, 'base64').toString('utf-8'))
}

export default secrets;
```
Step 3 - initialize the firebaseSDK, and you're set to go
```js
//push_notification.js

const admin = require('firebase-admin');
const secrets = require('./secrets.js');


admin.initializeApp({
    credential: admin.credential.cert(secrets.serviceAccount)
});


class PushNotification {
    
    //Replies on a user's comment
    commentReply = async (p) => {
        try {
            const { data, type } = p;     
            const user = await User.findOne({ _id: data.userId }); 
            let payload = {
                notification: {
                    title: 'New reply to your comment',
                    body: `${user.username} replied: ${data.reply}`,
......
```

##Conclusion
The process is convert to base64 => set to environment variable => convert to string
This article is subject to change.
[Github](https://github.com/theifedayo) || [Twitter](https://twitter.com/ifedayoadesiyan)