How can I get the local IP address in Node.js? - node.js

I'm not referring to
127.0.0.1
But rather the one that other computers would use to access the machine e.g.
192.168.1.6

http://nodejs.org/api/os.html#os_os_networkinterfaces
var os = require('os');
var interfaces = os.networkInterfaces();
var addresses = [];
for (var k in interfaces) {
for (var k2 in interfaces[k]) {
var address = interfaces[k][k2];
if (address.family === 'IPv4' && !address.internal) {
addresses.push(address.address);
}
}
}
console.log(addresses);

https://github.com/indutny/node-ip
var ip = require("ip");
console.dir ( ip.address() );

$ npm install --save quick-local-ip
follwed by
var myip = require('quick-local-ip');
//getting ip4 network address of local system
myip.getLocalIP4();
//getting ip6 network address of local system
myip.getLocalIP6();

My version which was needed for a compact and single file script, hope to be useful for others:
var ifs = require('os').networkInterfaces();
var result = Object.keys(ifs)
.map(x => [x, ifs[x].filter(x => x.family === 'IPv4')[0]])
.filter(x => x[1])
.map(x => x[1].address);
Or to answer the original question:
var ifs = require('os').networkInterfaces();
var result = Object.keys(ifs)
.map(x => ifs[x].filter(x => x.family === 'IPv4' && !x.internal)[0])
.filter(x => x)[0].address;

https://github.com/dominictarr/my-local-ip
$ npm install -g my-local-ip
$ my-local-ip
or
$ npm install --save my-local-ip
$ node
> console.log(require('my-local-ip')())
A very small module that does just this.

savage one-liner incoming
based on accepted answer, this one will build an array of objects with conditional entries depending on address properties
[{name: {interface name}, ip: {ip address}}, ...]
const ips = Object.entries(require("os").networkInterfaces()).reduce((acc, iface) => [...acc, ...(iface[1].reduce((acc, address) => acc || (address.family === "IPv4" && !address.internal), false) ? [{name: iface[0], ip: iface[1].filter(address => address.family === "IPv4" && !address.internal).map(address => address.address)[0]}] : [])], []);
console.log(ips);
Explained :
const ips = Object.entries(require("os").networkInterfaces()) // fetch network interfaces
.reduce((acc, iface) => [ // reduce to build output object
...acc, // accumulator
...(
iface[1].reduce((acc, address) => acc || (address.family === "IPv4" && !address.internal), false) ? // conditional entry
[ // validate, insert it in output
{ // create {name, ip} object
name: iface[0], // interface name
ip: iface[1] // interface IP
.filter(address => address.family === "IPv4" && !address.internal) // check is IPv4 && not internal
.map(address => address.address)[0] // get IP
}
]
:
[] // ignore interface && ip
)
], []);
Output example :
Array(4) [Object, Object, Object, Object]
length:4
__proto__:Array(0) [, …]
0:Object {name: "vEthernet (WSL)", ip: "172.31.xxx.x"}
1:Object {name: "Ethernet", ip: "10.0.x.xx"}
2:Object {name: "VMware Network Adapter VMnet1", ip: "192.168.xxx.x"}
3:Object {name: "VMware Network Adapter VMnet8", ip: "192.168.xx.x"}

Ever since Node version 0.9.6 there is a simple way to get the server's IP address based on each request. This could be important if your machine has multiple IP addresses or even if you are doing something on localhost.
req.socket.localAddress will return the address of the machine node is running on based on the current connection.
If you have a public IP address of 1.2.3.4 and someone hits your node server from the outside then the value for req.socket.localAddress will be "1.2.3.4".
If you hit the same server from localhost then the address will be "127.0.0.1"
If your server has multiple public addresses then the value of req.socket.localAddress will be the correct address of the socket connection.

Modified a bit Ebrahim's answer with some es6 and module syntax, for leaner code:
import { networkInterfaces } from "os";
const netInterfaces = networkInterfaces();
const [{ address }] = Object.values(netInterfaces).flatMap((netInterface) =>
netInterface.filter((prop) => prop.family === "IPv4" && !prop.internal)
);
console.log(address) // -> '192.168...'

Related

localhost, 127.0.0.1 does not work between 2 containers in a kubernetes node

I have 2 containers in a Kubernetes node.
microk8s kubectl exec -it worker-statefulset-name-0 -c worker-container bash
To connect to the first. It is a python container with a socket interface, not http. Observe the IP address
python
>>> import socket
>>> socket.gethostbyname(socket.gethostname())
'10.1.56.41'
The second is a nodejs container. Opening a socket between these 2 containers works as expected when using the ip address:
microk8s kubectl exec -it worker-statefulset-name-0 -c worker-health-monitor bash
nodejs
socket_utilities.promise_open_socket_send_get_ack('10.1.56.41', 55001, data)
.then((result)=>{console.log(result)})
> { result: 'got work' }
but fails if I use localhost or 127.0.0.1
socket_utilities.promise_open_socket_send_get_ack('127.0.0.1', 55001, data).then((result)=>{console.log(result)})
> 1661547443715ECONNREFUSED
(node:21) UnhandledPromiseRejectionWarning: Error: connect ECONNREFUSED 127.0.0.1:55001
> socket_utilities.promise_open_socket_send_get_ack('localhost', 55001, data).then((result)=>{console.log(result)})
> 1661547509627ECONNREFUSED
(node:21) UnhandledPromiseRejectionWarning: Error: connect ECONNREFUSED 127.0.0.1:55001
The promise_open_socket_send_get_act is simply a wrapper around net.createConnection
function promise_open_socket_send_get_ack(host, port, data) {
return new Promise((resolve, reject) => {
try {
//console.log("createConnection host=" + host + ", port:" + port + ", my ip is " + get_my_IPv4_addresses())
const client = net.createConnection({ host: host, port: port })
let data_from_server = null
let to = null
client.on("error", (e) => {
if (e.errno == "ECONNREFUSED") {
console.log(new Date().getTime()+"ECONNREFUSED")
}
clearTimeout(to)
reject(e)
})
....
I know the nodejs container is on the same node as the python container. They are created as part of the same StatefulSet, but to be sure:
> socket_utilities.get_my_IPv4_addresses()
[ '10.1.56.41', eth0: [] ]
function get_my_IPv4_addresses(){
const nets = os.networkInterfaces();
const results = []
for (const name of Object.keys(nets)) {
for (const net of nets[name]) {
// Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses
if (net.family === 'IPv4' && !net.internal) {
if (!results[name]) {
results[name] = [];
}
results.push(net.address);
}
}
}
return results
}
So a kludgy solution is to use get_my_IPv4_addresses and open the socket with this.
Aside from being kludgy, I fear I do not understand something and will run into problems in the future.
So how do I get 127.0.0.1 to work correctly in a kubernetes nodejs container?

Discord.JS ReferenceError: stopTyping is not Defined

I'm trying to get our announce command to work but it keeps throwing the following error:
#Nimbi, An error occurred while running the command: ReferenceError: stopTyping is not defined
You shouldn't ever receive an error like this.
Please contact Nimbi#4961.
Here is my announce.js code:
const stripIndents = require('common-tags').stripIndents;
const { Command } = require('discord.js-commando');
require('dotenv').config();
ANNOUNCE_CHANNEL_NAME = process.env.ANNOUNCEMENT_CHANNEL;
NEWS_CHANNEL_NAME = process.env.NEWS_CHANNEL;
MODLOG_CHANNEL_NAME = process.env.MODLOG_CHANNEL;
module.exports = class NewsCommand extends Command {
constructor (client) {
super(client, {
name: 'announce',
memberName: 'announce',
group: 'mod',
aliases: ['news', 'ann', 'a'],
description: 'Make an announcement in the news channel',
format: 'Announcement',
examples: ['announce John Appleseed reads the news'],
guildOnly: true,
throttling: {
usages: 2,
duration: 3
},
args: [
{
key: 'body',
prompt: 'What do you want me to announce?',
type: 'string'
}
],
userPermissions: ['MANAGE_MESSAGES'],
clientPermissions: ['MANAGE_MESSAGES']
});
}
run (msg, {body}) {
try {
startTyping(msg);
let announce = body,
newsChannel = null;
const announceEmbed = new MessageEmbed(),
modlogChannel = msg.guild.settings.get('modLogChannel',
msg.guild.channels.find(c => c.name === MODLOG_CHANNEL) ? msg.guild.channels.find(c => c.name === MODLOG_CHANNEL).id : null);
if (msg.guild.settings.get('announcechannel')) {
newsChannel = msg.guild.channels.find(c => c.id === msg.guild.settings.get('announcechannel'));
} else {
msg.guild.channels.find(c => c.name === 'announcements')
? newsChannel = msg.guild.channels.find(c => c.name === ANNOUNCEMENT_CHANNEL)
: newsChannel = msg.guild.channels.find(c => c.name === NEWS_CHANNEL);
}
if (!newsChannel) throw new Error('nochannel');
if (!newsChannel.permissionsFor(msg.guild.me).has(['SEND_MESSAGES', 'VIEW_CHANNEL'])) throw new Error('noperms');
newsChannel.startTyping(1);
announce.slice(0, 4) !== 'http' ? announce = `${body.slice(0, 1).toUpperCase()}${body.slice(1)}` : null;
msg.attachments.first() && msg.attachments.first().url ? announce += `\n${msg.attachments.first().url}` : null;
announceEmbed
.setColor('#AAEFE6')
.setAuthor(msg.author.tag, msg.author.displayAvatarURL())
.setDescription(stripIndents`**Action:** Made an announcement`)
.setTimestamp();
newsChannel.msg.say(announce);
newsChannel.stopTyping(true);
if (msg.guild.settings.get('mod-logs', true)) {
if (!msg.guild.settings.get('hasSentModLogMessage', false)) {
msg.reply(oneLine`📃 I can keep a log of moderator actions if you create a channel named **${MODLOG_CHANNEL_NAME}**
(or some other name configured by the ${msg.guild.commandPrefix}setmodlogs command) and give me access to it.
This message will only show up this one time and never again after this so if you desire to set up mod logs make sure to do so now.`);
msg.guild.settings.set('hasSentModLogMessage', true);
}
modlogChannel && msg.guild.settings.get('mod-logs', false) ? msg.guild.channels.get(modlogChannel).msg.say('', {embed: announceEmbed}) : null;
}
stopTyping(msg);
return msg.embed(announceEmbed);
} catch (err) {
stopTyping(msg);
if ((/(?:nochannel)/i).test(err.toString())) {
return msg.reply(`there is no channel for me to make the announcement in. Create channel named either ${ANNOUNCE_CHANNEL_NAME} or ${NEWS_CHANNEL_NAME}`);
} else if ((/(?:noperms)/i).test(err.toString())) {
return msg.reply(`I do not have permission to send messages to the ${ANNOUNCE_CHANNEL_NAME} or ${NEWS_CHANNEL_NAME} channel. Better go fix that!`);
}
return msg.reply(oneLine`An error occurred but I notified ${this.client.owners[0].username}
Want to know more about the error? Join the support server by getting an invite by using the \`${msg.guild.commandPrefix}invite\` command `);
}
}
};
My discord.js version is: ^12.5.1
My discord.js-commando version is: ^0.11.1
My node.js version is: ^12.0.0
I've already tried defining it with:
const {startTyping, stopTypeing } = require('discord.js');
and
const {startTyping, stopTypeing } = require('util');
however, both simply threw the startTyping is not a function error.
Any help would be much appreciated.
Note: this is in discord.js#13 and onwards
startTyping
// like 101arrowz said, startTyping (or now sendTyping) is a method of the TextChannel, which you can get by msg.channel
message.channel.sendTyping()
Discord.js and commando (which is by the same people) works great, but if you have any problems I suggest you read the docs or ask at their discord server (they do actually help)

Open up terminal/shell on remote server via tcp request

I have this:
const http = require('http');
const cp = require('child_process');
const server = http.createServer((req,res) => {
const bash = cp.spawn('bash');
req.pipe(bash.stdin, {end:false);
bash.stdout.pipe(res);
bash.stderr.pipe(res);
});
server.listen('4004');
when I hit the server with:
curl localhost:4004
and I type bash commands, nothing gets outputed to my console, anybody know why?
Note: To address security I plan to run this in a docker container, use https/ssl, and implement authentication (any recommendations on auth schemes lmk).
More importantly, I am looking for shell prompts to appear ... apparently bash by itself doesn't open up a shell/prompt?
It is possible to do this "over the web" so to speak. However, your approach will not work, because you are mixing paradigms (batch vs. interactive), and you are missing large chunks of setup that's needed to run terminal applications.
Normally I would show you how to program this, however, that's really involved. Have a look at:
https://github.com/chjj/tty.js
and,
https://github.com/xtermjs/xterm.js
as starting points to create your solution.
Both are usable directly from node.js to serve up terminal applications over HTTP.
This is a partial answer, but I started a bounty because I am looking for something better. I was able to create something rudimentary with TCP like so:
const net = require('net'); // !use net package not http
const cp = require('child_process');
const server = net.createServer(s => {
const bash = cp.spawn('bash');
s.pipe(bash.stdin, {end:false});
bash.stdout.pipe(s);
bash.stderr.pipe(s);
});
server.listen('4004');
not sure why it won't work with HTTP though. I connect to it using netcat:
nc localhost 4004
but this isn't opening a terminal, just a bash process. the experience is not ideal, as described here:
https://unix.stackexchange.com/questions/519364/bash-shell-modes-how-to-pipe-request-to-shell-on-remote-server
however I am looking to replicate the shell experience you have when you do something like:
docker exec -ti <container> /bin/bash
when I run my script it "works", but I don't get any shell prompts or anything like that. (One way to solve this might be with ssh, but I am trying to figure out a different way).
You can connect to an http server with telnet. It depends on how you're starting the http server. Here's an example
Start an http server with the npm package http-server
npm install -g http-server
cd ~/ <Any directory>
http-server
Now seperately start a telnet session
telnet localhost 8080
OR
nc localhost 8080
And then type something like GET /
Use the telnet client instead of nc
Check this: https://www.the-art-of-web.com/system/telnet-http11/
Update: Running an ssh server over nodejs. It allows you to run an ssh server
I found this at https://github.com/mscdex/ssh2
var fs = require('fs');
var crypto = require('crypto');
var inspect = require('util').inspect;
var ssh2 = require('ssh2');
var utils = ssh2.utils;
var allowedUser = Buffer.from('foo');
var allowedPassword = Buffer.from('bar');
var allowedPubKey = utils.parseKey(fs.readFileSync('foo.pub'));
new ssh2.Server({
hostKeys: [fs.readFileSync('host.key')]
}, function(client) {
console.log('Client connected!');
client.on('authentication', function(ctx) {
var user = Buffer.from(ctx.username);
if (user.length !== allowedUser.length
|| !crypto.timingSafeEqual(user, allowedUser)) {
return ctx.reject();
}
switch (ctx.method) {
case 'password':
var password = Buffer.from(ctx.password);
if (password.length !== allowedPassword.length
|| !crypto.timingSafeEqual(password, allowedPassword)) {
return ctx.reject();
}
break;
case 'publickey':
var allowedPubSSHKey = allowedPubKey.getPublicSSH();
if (ctx.key.algo !== allowedPubKey.type
|| ctx.key.data.length !== allowedPubSSHKey.length
|| !crypto.timingSafeEqual(ctx.key.data, allowedPubSSHKey)
|| (ctx.signature && !allowedPubKey.verify(ctx.blob, ctx.signature))) {
return ctx.reject();
}
break;
default:
return ctx.reject();
}
ctx.accept();
}).on('ready', function() {
console.log('Client authenticated!');
client.on('session', function(accept, reject) {
var session = accept();
session.once('exec', function(accept, reject, info) {
console.log('Client wants to execute: ' + inspect(info.command));
var stream = accept();
stream.stderr.write('Oh no, the dreaded errors!\n');
stream.write('Just kidding about the errors!\n');
stream.exit(0);
stream.end();
});
});
}).on('end', function() {
console.log('Client disconnected');
});
}).listen(0, '127.0.0.1', function() {
console.log('Listening on port ' + this.address().port);
});
Your approaches are quite mixed, nonetheless, when ever you finally connect to the remote server do not use 'bash' as a method to start the connection, BASH is just born again shell with other commands & stuff in it,
Rather use some of the following program, command-line names: i.e :
~ $ 'gnome-terminal'
~ $ 'xterm'
there you will now be referencing a true program in the system, even kernel level C code has its own recognition of these, if not changed.

Cloud9: Could not find an open port

I'm new to NodeJS and trying to set up an existing project (developed by someone else) in Cloud9 IDE (I'm using an older Cloud9 account; so not running on AWS). I've pulled the git and installed everything. This all seemed to go without problems.
To run the app locally, outside of Cloud9, you would start the server with npm run start (I know from the person who developed the app, this works for him). But I want to set it up in Cloud9, and in Cloud9 it is necessary to set some variables first (if I don't define the host first, it gives the error "Invalid Host header"). Therefore, I use the following two commands:
export HOST=$C9_HOSTNAME && export PORT=8080
npm run start
The npm run start produces the error:
Could not find an open port at appname-username.c9users.io.
Network error message: listen EADDRNOTAVAIL 35.189.252.103
I believe I have the port correct, considering https://docs.c9.io/docs/run-an-application. I’ve also tried the values 8081, 8082 and $PORT but none of these work.
Any ideas how I could get the Cloud9 local preview working?
Upon request some lines from start.js:
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
const HOST = process.env.HOST || '0.0.0.0';
console.log(`1. The host is ${HOST} on port ${DEFAULT_PORT}`); //ADDED
choosePort(HOST, DEFAULT_PORT)
.then(port => {
console.log(`2. The host is ${HOST} on port ${DEFAULT_PORT}`); //ADDED
if (port == null) {
// We have not found a port.
return;
}
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
const appName = require(paths.appPackageJson).name;
const urls = prepareUrls(protocol, HOST, port);
// Create a webpack compiler that is configured with custom messages.
const compiler = createCompiler(webpack, config, appName, urls, useYarn);
// Load proxy config
const proxySetting = require(paths.appPackageJson).proxy;
const proxyConfig = prepareProxy(proxySetting, paths.appPublic);
// Serve webpack assets generated by the compiler over a web sever.
const serverConfig = createDevServerConfig(
proxyConfig,
urls.lanUrlForConfig
);
const devServer = new WebpackDevServer(compiler, serverConfig);
// Launch WebpackDevServer.
devServer.listen(port, HOST, err => {
if (err) {
return console.log(err);
}
if (isInteractive) {
clearConsole();
}
console.log(chalk.cyan('Starting the development server...\n'));
openBrowser(urls.localUrlForBrowser);
});
})
.catch(err => {
if (err && err.message) {
console.log(err.message);
}
process.exit(1);
});
netstat --listen responds with the following information:
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp6 0 0 [::]:ssh [::]:* LISTEN
Active UNIX domain sockets (only servers)
Proto RefCnt Flags Type State I-Node Path
unix 2 [ ACC ] STREAM LISTENING 1533837857 /home/ubuntu/.c9/6614254/collab.sock
unix 2 [ ACC ] STREAM LISTENING 1533835235 /home/ubuntu/.c9/bridge.socket
unix 2 [ ACC ] STREAM LISTENING 1533836998 /tmp/tmux-1000/cloud92.2
The function choosePort is part of the node module "react-dev-utils" and reads as follows:
function choosePort(host, defaultPort) {
return detect(defaultPort, host).then(
port => new Promise(resolve => {
if (port === defaultPort) {
return resolve(port);
}
if (isInteractive) {
clearConsole();
const existingProcess = getProcessForPort(defaultPort);
const question = {
type: 'confirm',
name: 'shouldChangePort',
message: chalk.yellow(
`Something is already running on port ${defaultPort}.` +
`${existingProcess ? ` Probably:\n ${existingProcess}` : ''}`
) + '\n\nWould you like to run the app on another port instead?',
default: true,
};
inquirer.prompt(question).then(answer => {
if (answer.shouldChangePort) {
resolve(port);
} else {
resolve(null);
}
});
} else {
console.log(
chalk.red(`Something is already running on port ${defaultPort}.`)
);
resolve(null);
}
}),
err => {
throw new Error(
chalk.red(`Could not find an open port at ${chalk.bold(host)}.`) +
'\n' +
('Network error message: ' + err.message || err) +
'\n'
);
}
);
}
I did some googling on this and I think the issue might be with the host value you are setting. Per this Cloud9 support thread which references a similar error:
...You need to use 0.0.0.0 instead since c9user.io is the public address of the proxy. Or modify your /etc/hosts file. echo "0.0.0.0 $C9_HOSTNAME" | sudo tee -a /etc/hosts
So, try setting the host to 0.0.0.0 instead of the public hostname:
export HOST=0.0.0.0 && export PORT=8080 && npm run start
Also just found this on the support page you linked to:
If you're developing a server application, please note that you need to listen to 0.0.0.0 ($IP) and 8080 ($PORT). Listening to this port will enable your app to be viewable at http://-.c9users.io
Listening on 0.0.0.0 should resolve the issue.
Edit (in response to additional error being returned):
For the "Invalid host header" error, I think you're on the right track with setting disableHostCheck to true, but your npm script command isn't likely adhering to the flag from.the CLI. There are probably a few ways to get that flag passed, but the simplest might be to update your code to set the option when creating the dev server. Keep in mind this is just a quick fix to see if we can get it to work. It would be better to update the createDevServerConfig function to set the option:
const devServer = new WebpackDevServer(compiler, { ...serverConfig, disableHostCheck: true});
Another edit:
The disableHostCheck option is insecure and can open you up to vulnerabilities. It's considered a quick fix when testing locally and should only be used in a closed network. To fix the"Invalid host header" in an exposed environment, use the public option, where public is your DNS host name or public IP address:
const devServer = new WebpackDevServer(compiler, { ...serverConfig, public: process.env.PUBLIC_HOST }
You can then have this value passed in via the CLI environment like your other vars:
export HOST=0.0.0.0 && export PORT=8080 && export PUBLIC_HOST=$C9_HOSTNAME:8080 && npm run start
Disclaimer: I don't think the changes above are the best way to go about doing this (it would likely be better to update the createDevServerConfig function, but they should resolve your issues. More information on the disableHostCheck option can be found here, here, and here.

Issue with Node require in class

I'm fairly new to Node, and writing an app with tests, I faced a scenario, where I don't need to load 2 packages for testing (as it will fail to load the packages as they require some binaries, which won't be present in testing environment). I set an environment variable TEST to true to let the app know that it should't load those 2 packages, and the tests run perfectly. However, for production, I get that the package was not loaded.
This is my class code:
"use strict";
const config = require('../../config/mainConfigs');
...Other constants...
if (typeof process.env.TEST === 'undefined' || process.env.TEST === null){
const mssql = require('mssql');
const oracle = require('oracledb');
if (process.env.DB_PASS && process.env.DB_PASS != '') var db_pass = process.env.DB_PASS;
else if (config.Logging.DB.password != '') var db_pass = config.Logging.DB.password;
else {
console.error(`There's no database password set. Use either Enviroment Variable "DB_PASS" or set "password" under "Logging" > "DB" in configuration file.`);
process.exit(1);
}
}
class db {
constructor(){
this._pool = null;
}
get_pool(){
if (process.env.TEST) return new Promise((resolve)=>resolve());
if (config.Logging.DB.type == 'mssql'){
if (!this._pool) {
this._pool = new mssql.ConnectionPool(sqlDbOptions);
}
if (!this._pool.connected){
return this._pool.connect();
}
else{
return new Promise((resolve, reject) => {
resolve(this._pool);
})
}
}else if (config.Logging.DB.type == 'oracle'){
if (!this._pool || this._pool.connectionsOpen == 0){
return this._pool = oracle.getConnection(oracleDbOptions);
}
else{
return new Promise((resolve, reject) => {
resolve(this._pool);
})
}
}
}
... MORE CLASS OPERATIONS...
}
module.exports = db;
Then I use the DB in my app like this:
const db = require('./db_class');
const db_instance = new db();
When starting the app, I call the get_pool() method to establish the connection prior starting the server.
But for some reason, I am getting:
ReferenceError: mssql is not defined
at db.get_pool (C:\Users...\src\db.js:122:34)
If I move the requires outside the if (the one that checks if the env variable is set) it works just fine.
Aren't the requires synchronous?
Any idea how to solve this?
const is block scoped so your two const variables defined within the if statement block will only be defined and usable within that if statement block.
Basically, you can't conditionally assign to a const like you're trying to do and have the variable available outside the scope of the block. So, you have to settle for using a non-const type (var or let). I recommend using let so you can decide exactly which scope you want it declared in and declaring the variable in that explicit scope. You can then assign to the previously declared variable within your if block.
Here's one usual work-around:
let mssql, oracle;
if (typeof process.env.TEST === 'undefined' || process.env.TEST === null){
mssql = require('mssql');
oracle = require('oracledb');
if (process.env.DB_PASS && process.env.DB_PASS != '') var db_pass = process.env.DB_PASS;
else if (config.Logging.DB.password != '') var db_pass = config.Logging.DB.password;
else {
console.error(`There's no database password set. Use either Enviroment Variable "DB_PASS" or set "password" under "Logging" > "DB" in configuration file.`);
process.exit(1);
}
}

Resources