Config File in NodeJS using npm config - javascript

I have a on-cloud SAAS application built on Angular/NodeJS/Postgres+MongoDB stack that can connect to customer DB, cloud warehouses, S3 buckets etc to load information. Once I get the connection information from Angular front-end I need to store this information for future retrieval .
Example :
Angular Front-end
<form>
Database Type :
Host :
Port :
Username:
Password :
S3Bucket :
Region :
bucket-name :
Access key :
</form>
etc.
I need this information saved for later access. As suggested by Abdullah Deliogullari in the original question, I am trying to use config module npm config. But how do I use package config to write config file and load it in a running application.
ie While my application is running I need to write the (say S3) bucket info to a customer.config file (from frontend JSON) and later when required to retrieve data use the customer.config to connect to S3 bucket.
The "get" portion I am able to understand but the write portion (adding a new section dynamically) is what I am not able to figure out.
Example from frontend when I pass in the values like
["ct_postgres":
{"host":"3.15.xxx.xxx",
"port":"5132",
"dbname":"wcdb"
}]
this should be written to the config file. So something like config.put/write I am looking for. Next time I want to make connection to the customer postgresdb I do config.get() and it provides me the connection details.
Original question

First you should install this package
npm install config
After that create config file into your project directory(name "config" is a must).
In this file create development.json and production.json files(these names are optional). Content of development.json could be like this
{
"SERVER" : {
"port" : 5000
},
"PASSWORDHASH" : {
"saltRounds" : 10
}
}
In your javascript file for example in app.js file, first you should include the library, and then you can get configuration informations via this module
const config = require('config');
const port = config.get("SERVER.port");
app.listen(port);
Last step should be add this development.json file name to NODE_ENV variable
NODE_ENV=development node app.js
So if you want to update your json file based on new data coming from your frontend, you can basically do this
var fs = require('fs');
var file_content = fs.readFileSync("development.json");
var content = JSON.parse(file_content);
content.SERVER.port = 6000;
fs.writeFileSync("development.json", JSON.stringify(content));

Related

Autodesk Forge web application - from visual studio code to close .exe file

I have a working forge application ( bim360 hub sidebar with forge viewer and some charts).
It is currently running from Visual Studio Code IDE only. I want to build the app into an .exe file in order to be able to send it to a user, upload it to a server with IIS, etc..
General details:
I used Petr Broz tutorial to set up the backend of the viewer and hub
(Forge online training - view your models https://www.youtube.com/watch?v=-O1e3gXCOEQ&t=8986s )
The app is running on Node.js
I tried to use 'nexe' module and build executable file. With this method, I need to specify index.js file ("an entry point") and define a 'nexe.config.js' file. I used the entry point start.js.
Eventually, I managed to create an exe file - and when I run it from the command line, I get an error
Missing FORGE_CLIENT_ID or FORGE_CLIENT_SECRET env. variables.
although I have them in the config.js
Main questions:
Is there another way to build a close exe file from visual studio code - for a forge web application?
Am i doing something wrong with the processes I mention above?
Is it even possible to deploy a web application to IIS using an exe file?? all of the documentation points toward Azur, AWS and heroku..
Relevant files:
1) start.js:
const path = require('path');//bringing in built in node js modeules ( to resulve file system path )
const express = require('express');//module to create the express server
const cookieSession = require('cookie-session');
//any piece of code would have an opportunity to handle the request
const PORT = process.env.PORT || 3000;
const config = require('./config.js');
if (config.credentials.client_id == null || config.credentials.client_secret == null) {
console.error('Missing FORGE_CLIENT_ID or FORGE_CLIENT_SECRET env. variables.');
return;
}
let app = express();
//static middlewere to check for the front end files (html,js,css)
app.use(express.static(path.join(__dirname, 'public')));//method inside express module: a middlewere for serving static files this line will check in 'public' folder if the request
//that is sent (specific file) is in there. if so - it will ignore the rest of the stack(the rest of the code)
app.use(cookieSession({
// create 2 cookies that stores the name and encripted key
name: 'forge_session',
keys: ['forge_secure_key'],//takes cater of decipher the encription for the forge key for us
maxAge: 14 * 24 * 60 * 60 * 1000 // 14 days, same as refresh token
}));
app.use(express.json({ limit: '50mb' }));//middlewere that looks at the title of the request - and if its .json it will look at the body of the request and parese it to javascript object
app.use('/api/forge', require('./routes/oauth.js'));//adding our custom express routers that will handle the different endpoints.
app.use('/api/forge', require('./routes/datamanagement.js'));
app.use('/api/forge', require('./routes/user.js'));
app.use((err, req, res, next) => {
console.error(err);
res.status(err.statusCode).json(err);
});
app.listen(PORT, () => { console.log(`Server listening on port ${PORT}`); });
2) config.js:
// Autodesk Forge configuration
module.exports = {
// Set environment variables or hard-code here
credentials: {
client_id: process.env.FORGE_CLIENT_ID,
client_secret: process.env.FORGE_CLIENT_SECRET,
callback_url: process.env.FORGE_CALLBACK_URL
},
scopes: {
// Required scopes for the server-side application-->privliges for our internal opperation in the server side ("back end")
internal: ['bucket:create', 'bucket:read', 'data:read', 'data:create', 'data:write'],
// Required scope for the client-side viewer-->priveliges for the client ("front end")
public: ['viewables:read']
}
};
Author of the tutorial here :)
I'm not sure how nexe works exactly but please note that the sample app expects input parameters such as FORGE_CLIENT_ID or FORGE_CLIENT_SECRET to be provided as environment variables.
As a first step, try running your *.exe file after setting the env. variables in your command prompt.
If that doesn't work, try hard-coding the input parameters directly into the config.js file (replacing any of the process.env.* references), and then bundle everything into an *.exe file. This is just for debugging purposes, though! You shouldn't share your credentials with anyone, not even inside an *.exe file. So as an alternative I'd suggest that you update the sample app to read the input parameters from somewhere else, perhaps from a local file.
after trying a lot of solutions, i got to the conclusion that the reason that nothing happened was that the oathantication files ( with the clint_id and clint_password) was not embedded in the .exe file.
the way to include those files with the nexe module is to use the flag -r "Foldername/subfoldername/filename.js".
first, crate a nexe.config.js file that would contain the entry point file name to the app. ( in my case, the file name is " start.js")
second, write the following commands in the command line:
cd C:\Projects\MyAppFolder
npm install -g nexe
// specify all the files you want to include inside the exe file
nexe start.js -r "config.js" -r "nexe.config.js" -r "routes/common/oauth.js" -r "routes/*.js" -r "public//." -r ".vscode/**/." -r "package-lock.json" -r "package.json" --build --output "AppName.exe"

Can I check if my API key is sufficiently hidden in node.js to push to github?

I have a small web app I'm creating by following a node.js tutorial and would like to push to github. I'm using the requests package along with dotenv to hide my API key in a .env file and I've put .env into my gitignore. This is the code for the app.js file:
const request = require('request');
require('dotenv').config();
const api_key = process.env.API_KEY;
const url = `https://api.darksky.net/forecast/${api_key}/37.8267,-122.4233`;
request({ url: url }, (error, response) => {
const data = JSON.parse(response.body);
console.log(data.currently);
});
Question
Have I sufficiently hidden my API key? If I pushed this and someone were to clone my repo, would the API key be exposed at all in the process object or anywhere else? Is there a way to check this before a commit/push?
If the key is only in your .env and your .env isn't in github, you're fine. This is very standard practice.
You can verify that you're not about to push it up by running git status on your command line after git committing your changes.

Why will my MEAN app only (partially) run when I set the Angular build directory to /src/ instead of /dist/?

I'm following Heroku's tutorial to create a contact list using the MEAN stack (Heroku's running example here). I'm able to deploy it to Heroku and it works there. But when I run it locally on my machine, the browser (Chrome 67.0.3396.87 on macOS High Sierra) only displays a "Cannot GET /" message.
I believe it's related to how the Angular build directory /dist/ referenced in line 12 of server.js does not exist (as far as I can tell). The beginning of server.js looks like this:
var express = require("express");
var bodyParser = require("body-parser");
var mongodb = require("mongodb");
var ObjectID = mongodb.ObjectID;
var CONTACTS_COLLECTION = "contacts";
var app = express();
app.use(bodyParser.json());
// Create link to Angular build directory
var distDir = __dirname + "/dist/";
app.use(express.static(distDir));
// Create a database variable outside of the database connection callback to reuse the connection pool in your app.
var db;
I looked into it and found that Angular deletes the /dist/ directory upon ng serve. I also found that there is a flag --delete-output-path whose default is true.
I set the --delete-output-path flag to false in .angular-cli.json as recommended by this answer as well as in /node_modules/#angular/cli/lib/config/schema.json. Despite those changes (trying to set the flag in one file, or the other file, or both files at the same time), I'm still getting the "Cannot GET /" message and the /dist/ directory still doesn't appear to be there.
The only way I've been able to even run part of the app is to change server.js's line 12 reference from /dist/ to /src/. This allows /src/index.html to begin loading at localhost:5000/ (the browser displays the text "Loading..." as specified in line 16 of index.html) and gets the contacts API up and running at localhost:5000/api/contacts/. But the Angular components (the list of contacts that is the purpose of the tutorial) don't load. Maybe because I changed the build directory to a totally different location.
Is there something with the /dist/ directory that I'm missing? Or does my issue with getting the app to run locally have nothing to do with /dist/ at all?
Notice that you don't have a way of handling requests to the route '/' since the line:
app.use(express.static(distDir));
only ensures that all bundled files generated in your "dist" folder are accessible when your index.html requires them, but you still have to serve the index.html itself. When using the MEAN stack one normally would do something like this:
app.use ('/api', yourApiRouter);
//and for everything else let the client-side routing handle the route:
app.get ('*', function(req, res) {
res.sendFile(distDir + 'index.html');
}
I recommend to use the native "path" module to join your __dirname with your "dist" folder and your index.html location rather than simple concatenation.
You can use an arrow function instead of a callback when using app.get function if you are using ES6

How to host json-server in azure

I am new in the software field, please have patience with my question and mistakes of technical terms:
Premises:-
I have developed an front-end application using Angular4. The baseURL define in angular application is 'http://localhost:3000/'. My application uses restangular api to interact with json-server (I created a folder named json-server and it has db.json and public folder ). It is working perfectly fine when i start the json-server using command:
json-server json-server --watch db.json
My application is finalized and thus I created a production build. Thereafter I moved all my files from dist folder to public folder of json-server. When i start the json-server, my application works fine.
Actual problem:-
Now I wanted to host in azure. I simply copied all file/folder (db.json and public folder) from json-server folder as it is and put them in azure cloud. When azure hosting is done and I open the url in browser I got an error- "you don't have permission to view".
To rectify above error I deleted all files from azure and then I copied all files of dist folder and put them in azure cloud. Using this I could able to see the application in the browser but no images. At image there is an error- Response with status: 0 for URL: null
When I start json-server locally, everything works fine but of course when same web page open from other machines I got the same error- Response with status: 0 for URL: null
Is there any way to run json-server in azure so that all machines/mobile when accessing the url, can see proper web page without any error.
Step to step to run json-server on Azure Web App:
Open your browser and go to App Service Editor (https://<your-app-name>.scm.azurewebsites.net/dev/wwwroot/)
Run the command in the Console (Ctrl+Shift+C)
npm install json-server --save-dev
Put all file/folder (db.json and public folder) into wwwroot folder
Create a server.js with the following content
const jsonServer = require('json-server')
const server = jsonServer.create()
const router = jsonServer.router('db.json')
const middlewares = jsonServer.defaults()
server.use(middlewares)
server.use(router)
server.listen(process.env.PORT, () => {
console.log('JSON Server is running')
})
Click Run (Ctrl+F5), this will generate web.config file automatically and open your website in the browser.
You can use the following to quickly setup a mock service which can serve REST APIs off static JSON files.
json-server
Just install the NodeJS module ($npm install -g json-server). Populate a static json file in the format attached and then run the JSON server ($ json-server --watch db.json --port 3000)

Meteor environment variables invalid in production

I am using Meteor UP for deployment and have set the environment variable both in the mup.json file and a file server/lib/env.js which contains them.
Here is where its being accessed:
Meteor.startup(function() {
// Remove configuration entries in case service is already configured
Accounts.loginServiceConfiguration.remove({
service: "facebook"
});
// Add Facebook configuration entry
Accounts.loginServiceConfiguration.insert({
"service": "facebook",
"appId": process.env.FACEBOOK_1,
"secret": process.env.FACEBOOK_2
});
});
However in the browser I'm getting "Invalid app id: null", but it works in development, any ideas?
Use Meteor.settings.
Development
Define settings in .config/development/settings.json.
Create shell script (dev.sh) in root of your meteor project:
#!/bin/bash
meteor --settings .config/development/settings.json
Instead using command meteor run ./dev.sh
Production (deploy using mup)
mup init creates 'deployment directory' with generated files mup.json and settings.json.
It is important to execute mup init outside of your meteor app directory, so deployment configuration will not be stored on app server.
Usage
Example of settings.json:
{
"service_id":"...",
"service_secret":"...",
"public":{
"service_name":"..."
}
}
If the settings object contains a key named public, then
Meteor.settings.public will be available on the client as well as the
server. All other properties of Meteor.settings are only defined on
the server.
server only:
Meteor.settings.service_id
Meteor.settings.service_secret
server and client :
Meteor.settings.public.service_name
Update:
Changed paths accordingly to Hubert OG's comment

Categories

Resources