How can I access command options in separate files? - node.js

I'm using commander to specify some commands and options for my global node module in the index.js file of the project (like shown in the example).
I know that I can easily check if a command was used by using the following code:
if (program.peppers) {
console.log('-peppers was used')
}
But how can I check those properties in other files? I've already tried exporting program and requiring it in those other files, but it doesn't seem to work.
Let's say I want to check if an option was used in a different file than in the one in which I've defined them. How should I do that?

You could pass the parsed program to the files/functions that need the parsed arguments or you can export the parsed arguments program instance
File index.js
var program = require('./program');
if (program.peppers) {
console.log('-peppers was used')
}
File program.js
var program = require('commander');
program
.version('0.0.1')
.option('-p, --peppers', 'Add peppers')
.option('-P, --pineapple', 'Add pineapple')
.option('-b, --bbq-sauce', 'Add bbq sauce')
.option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')
.parse(process.argv);
module.exports = program;
Invoking index.js from command line:
> node index.js -p
Yields the output
-peppers was used

Related

Is it possible to run a node JS program in a console-like environment?

What I want is very simple, to run code while typing, just like enter node and run things like this:
% node
Welcome to Node.js v17.0.1.
Type ".help" for more information.
> var a=5; var b=6;
> console.log(a+b);
11
But in this case, I have to copy and paste my code again and again.
Is it possible to "include" the code from an eternal .js file, then let me stay in the console-like environment to run the code?
Store these in the app.js:
var a=5;
var b=6;
function addNumber(x,y){console.log(x+y);}
In node console:
% node
Welcome to Node.js v17.0.1.
Type ".help" for more information.
> include "app.js" //- This is what I'm looking for
> addNumber(a,b);
11
You can require files in the REPL just as easily as you can in a standard Node script.
For example, inside a directory, create a file, foo.js:
module.exports = () => 'foo';
And inside that directory, enter Node:
PS D:\Directory> node
Welcome to Node.js v14.17.6.
Type ".help" for more information.
> const foo = require('./foo');
undefined
> console.log(foo())
foo
undefined
>
require('./foo') will return the exports of the foo file in the same directory.
require('../foo') will return the exports of the foo file in the parent directory.
Absolute paths work too. And so on.

Create a persistent bash shell session in Node.js, know when commands finish, and read and modify sourced/exported variables

Imagine this contrived scenario:
./main.sh
source ./config.sh
SOME_CONFIG="${SOME_CONFIG}bar"
./output.sh
./config.sh
export SOME_CONFIG='foo'
./output.sh
echo "Config is: ${SOME_CONFIG}"
I am trying to replace ./main.sh with a Node.js powered ./main.js WITHOUT replacing the other shell files. The exported ./config.sh functions/variables must also be fully available to ./output.sh
Here is a NON working ./main.js. I have written this for the sole purpose to explain what I want the final code to look like:
const terminal = require('child_process').spawn('bash')
terminal.stdin.write('source ./config.sh\n')
process.env.SOME_CONFIG = `${process.env.SOME_CONFIG}bar` // this must be done in JS
terminal.stdin.write('./output.sh\n') // this must be able to access all exported functions/variables in config.sh, including the JS modified SOME_CONFIG
How can I achieve this? Ideally if there's a library that can do this I'd prefer that.
While this doesn't fully answer my question, it solves the contrived problem I had at hand and could help others if need be.
In general, if bash scripts communicate with each other via environment variables (eg. using export/source), this will allow you to start moving bash code to Node.js.
./main.js
const child_process = require("child_process");
const os = require("os");
// Source config.sh and print the environment variables including SOME_CONFIG
const sourcedConfig = child_process
.execSync(". ./config.sh > /dev/null 2>&1 && env")
.toString();
// Convert ALL sourced environment variables into an object
const sourcedEnvVars = sourcedConfig
.split(os.EOL)
.map((line) => ({
env: `${line.substr(0, line.indexOf("="))}`,
val: `${line.substr(line.indexOf("=") + 1)}`,
}))
.reduce((envVarObject, envVarEntry) => {
envVarObject[envVarEntry.env] = envVarEntry.val;
return envVarObject;
}, {});
// Make changes
sourcedEnvVars["SOME_CONFIG"] = `${sourcedEnvVars["SOME_CONFIG"]}bar`;
// Run output.sh and pass in the environment variables we got from the previous command
child_process.execSync("./output.sh", {
env: sourcedEnvVars,
stdio: "inherit",
});

Why is my function running twice in command line but not in vscode

I am using a function from one file, in another file, and calling it there. This is causing the function to run twice at the same time when run from the command line, but not when I run it in VSCode.
Here is an example:
// fileOne
async function task() {
console.log('Hello')
}
module.exports = { task }
// fileTwo
const fileOne = require('./fileOne');
fileOne.task();
Output when ran in VSCode:
Hello
Output when ran in Command Line:
Hello
Hello
I'm not sure why this is happening... No I am not calling it in fileOne by accident because then it would also run twice in VSCode.
Thanks.
If your fileOne and fileTwo look exactly as in your problem statement, i.e.:
fileOne.js:
async function task() {
console.log('Hello')
}
module.exports = { task }
fileTwo.js:
const fileOne = require('./fileOne');
fileOne.task();
the output is 1 single 'Hello' when run in the following ways:
in Command Prompt
node fileTwo.js
in Windows PowerShell
node .\fileTwo.js
in Linux Bash Terminal
$ nodejs fileTwo.js
The same applies if you run the script having both files within 1 file (as you mention in the comments).
There were some cases where Node.js would print the output twice, but those were different scenarios.
You can try running just the fileTwo.js separately, but as already mentioned, it worked well also under a common file (e.g. your my_program_here.js in case it is just a combination of fileOne.js and fileTwo.js).
const fileOne = require('./fileOne');
This is based on the './' in different command lines.

Unable to use variables in fs functions when using brfs

I use browserify in order to be able to use require. To use fs functions with browserify i need to transform it with brfs but as far as I understood this results in only being able to input static strings as parameters inside my fs function. I want to be able to use variables for this.
I want to search for xml files in a specific directory and read them. Either by searching via text field or showing all of their data at once. In order to do this I need fs and browserify in order to require it.
const FS = require('fs')
function lookForRoom() {
let files = getFileNames()
findSearchedRoom(files)
}
function getFileNames() {
return FS.readdirSync('../data/')
}
function findSearchedRoom(files) {
const SEARCH_FIELD_ID = 'room'
let searchText = document.getElementById(SEARCH_FIELD_ID).value
files.forEach((file) => {
const SEARCHTEXT_FOUND = file.includes(searchText.toLowerCase())
if (SEARCHTEXT_FOUND) loadXML(file)
})
}
function loadXML(file) {
const XML2JS = require('xml2js')
let parser = new XML2JS.Parser()
let data = FS.readFile('../data/' + file)
console.dir(data);
}
module.exports = { lookForRoom: lookForRoom }
I want to be able to read contents out of a directory containing xml files.
Current status is that I can only do so when I provide a constant string to the fs function
The brfs README contains this gotcha:
Since brfs evaluates your source code statically, you can't use dynamic expressions that need to be evaluated at run time.
So, basically, you can't use brfs in the way you were hoping.
I want to be able to read contents out of a directory containing xml files
If by "a directory" you mean "any random directory, the name of which is determined by some form input", then that's not going to work. Browsers don't have direct access to directory contents, either locally or on a server.
You're not saying where that directory exists. If it's local (on the machine the browser is running on): I don't think there are standardized API's to do that, at all.
If it's on the server, then you need to implement an HTTP server that will accept a directory-/filename from some clientside code, and retrieve the file contents that way.

How to define the property file in node js?

I have found an article about properties file reader in node js here:
https://www.npmjs.com/package/properties-reader
There is a module as 'properties-reader'. But, I'm unable to understand how to define the property file. Should it be a json?
It's an ini format, as described here:
# contents of properties file
[main]
some.thing = foo
[blah]
some.thing = bar
Its not a Json format, but in ini format.
Steps to set up properties file and to read it from your node module:
make any properties file such as app.properties inside your project directory. The file may contain data like:
\#comment(ignored)
sever.port=3000
Run the following command to install properties-reader locally:
npm i properties-reader
once done use the properties-reader like this:
const PropertiesReader = require('properties-reader');
const prop = PropertiesReader('path/to/app.properties');
/*gets property from path/to/app.properties
You can also export this function using module.exports*/
getProperty = (pty) => {return prop.get(pty);}
//call the getProperty method
console.log(getProperty('server.port')); //3000
Easy as that!

Resources