I am building a simple command line app in node using commander js. The problem is, when I run a particular command, it outputs the result of an other command as well.
I've tried multiple things but nothing seems to be working out.
I have two crawler objects as below in crawler.js file
var f = new Crawler({
//code here
});
var c = new Crawler({
//code here
});
c.queue("http://www.someurl.com")
f.queue("http://www.someurl.com")
module.exports = {
c,
f
};
My index.js file looks like this
const x =() => {
crawler.c;
}
const y =() => {
crawler.f
}
program
.command("x")
.action(()=>{
x();
});
program
.command("y")
.action(()=>{
y();
});
Whenever I call the command x, it fires y as well and vice versa.
I need to show command specific outputs. Please help.
Related
I have some code in a web worker that is working perfectly locally, but as soon as I build and deploy (which minifies the code) it no longer works.
The unminified code looks like this:
const mapSourceCode = (treeNode, mfi, {objectType, types, fileType, templateType}) => {
let sourceCodeMap = new Map();
let ownerMap = new Map();
let sourceCodeList = [];
let ownerList = [];
let mfiMap = new Map();
mfi.forEach(row => mfiMap.set(row.uuid, row));
let sourceCodeObjects = mfi.filter(row => types.includes(row.objectTypeUuid));
if(sourceCodeObjects.length < 1)
return {sourceCodeMap, sourceCodeTree: undefined};
try {
sourceCodeObjects.forEach(sourceObj => {
let owner = findOwner(sourceObj, sourceObj, mfiMap, {...treeNode.data}, objectType);
The minified code is this:
i = function(e, t, n) {
var c = n.objectType
, o = n.types
, i = n.fileType
, u = n.templateType
, l = new Map
, s = new Map
, f = []
, p = []
, m = new Map;
t.forEach((function(e) {
return m.set(e.uuid, e)
}
));
var h = t.filter((function(e) {
return o.includes(e.objectTypeUuid)
}
));
if (h.length < 1)
return {
sourceCodeMap: l,
sourceCodeTree: void 0
};
try {
if (h.forEach((function(n) {
var r = a(n, n, m, Object(d.a)({}, e.data), c);
The line it's erroring out on is {...treeNode.data} on the last line.
The error is ReferenceError: d is not defined
I can't figure out what the issue could be? Like I said everything runs great on locally. Any help is greatly appreciated
I found the issue, in case anybody runs into this same thing.
Normally when using web workers you need to tell your builder (webpack) to build / compile workers separately. I'm using the default create-react-app configuration which doesn't give access to that part of webpack. unless you eject from create-react-app completely (which I'm currently not ready to do)
I'm using the react hook called useWorker, where I pass the function I want to allocate to the worker.
When your code is optimized and minified variable names are replaced with smaller names (mostly 1 or 2 letters from what I've seen). Because I didn't have any custom loaders to load my worker code, it used variables from the global scope assuming it would have access. When the code was extracted to a separate thread outside the main thread it no longer had access to those variables and thus didn't work.
The fix is to
Add a loader (you can either eject from create-react-app, or there may be some npm libraries that will give you access to that particular part of webpack)
Or my solution was to create the function in a string and create a function using the Function constructor like so
const generateFunction = new Function('treeNode', 'mfi', 'types', 'action', generateFunctionString);
Where the generateFunctionString was a string like: "return a + b"
I then passed that function into my useWorker hook:
const [generatorWorker] = useWorker(generateFunction);
as an example of what I'm trying to achieve, consider launching VS Code from the terminal. The code <file-name> command opens an instance of vs code if not only running, or tells it to open a file otherwise. Also, once opened, the user can use the terminal session for other tasks again (as if the process was disowned).
My script needs to interact with my electron app in the same way, with the only difference being that my app will be in the tray and not visible in the dock.
.
The solution only needs to work on linux
Use a unix socket server for inter-process-communication.
In electron
const handleIpc = (conn) => {
conn.setEncoding('utf8');
conn.on('data',(line) => {
let args = line.split(' ');
switch(args[0]) {
case 'hey':
conn.write('whatsup\n');
break;
default: conn.write('new phone who this?\n');
}
conn.end();
})
}
const server = net.createServer(handleIpc);
server.listen('/tmp/my-app.sock');
Then your CLI is:
#!/usr/bin/node
const net = require('net');
let args = process.argv;
args.shift(); // Drop /usr/bin/node
args.shift(); // Drop script path
let line = args.join(' ');
net.connect('/tmp/my-app.sock',(conn)=>{
conn.setEncoding('utf8');
conn.on('data',(response)=>{
console.log(response);
process.exit(0);
});
conn.write(line+'\n');
}).on('error',(err)=>{
console.error(err);
process.exit(1);
});
If I understand correctly, you want to keep only one instance of your app and to handle attempts to launch another instance. In old versions of Electron, app.makeSingleInstance(callback) was used to achieve this. As for Electron ...v13 - v15, app.requestSingleInstanceLock() with second-instance event is used. Here is an example how to use it:
const { app } = require('electron');
let myWindow = null;
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
} else {
app.on('second-instance', (event, commandLine, workingDirectory) => {
// Someone tried to run a second instance
// Do the stuff, for example, focus the window
if (myWindow) {
if (myWindow.isMinimized()) myWindow.restore()
myWindow.focus()
}
})
// Create myWindow, load the rest of the app, etc...
app.whenReady().then(() => {
myWindow = createWindow();
})
}
So when someone will launch ./app arg1 arg2 at the second time, the callback will be called. By the way, this solution is cross-platform.
I have a javascript file the that I'm running some node tasks in, and would like to be able to run them separately based on the terminal command I trigger.
For instance, my nodejs file myFile code could look like this:
const mysql = require('mysql');
const fs = require('fs');
const getDbData = () => {
...
...
}
const fileTransform = () => {
file transformation functionality
}
I'd like to be able to run each function separately, so that I can say node myFile.js getDbData in terminal. Do I need to export each of the functions to be able to do this?
You can supply command-line arguments to your script on the node command line. You receive them in the process.argv array. Your arguments start at index 2 (0 is the full path to node, 1 is the full path to your script).
So for instance:
switch (process.argv[2]) {
case "getData":
getData();
break;
case "etlData":
etlData();
break;
// ...
}
Note that it's true that your arguments start at index 2 even if a Node argument precedes your script on the actual command line. For instance:
node --use-strict your-script.js
...will still have the full path to node in process.argv[0] and the full path to your script in process.argv[1]. The --use-strict argument isn't in the array at all.
Or you can put your functions on an object and use the argument as a key:
function getData() {
// ...
}
function getData() {
// ...
}
const functions = {
getData,
etlData
};
const fn = functions[process.argv[2]] || () => { console.log("Invalid option"); };
fn();
Try using process.argv.
https://stackabuse.com/command-line-arguments-in-node-js/
parse the command line arguments and, for example, evaluate them with eval()
I'm having issues with node.js, I'm not that familiar with it.
I have a JavaScript file that I need to load the file into node.js by using .load "filename.js".
when I run the command I just get a print out of the code that is in the file.
here is my code for the file I'm trying to load. I have made the changes suggested to me. but I'm still getting an entire print out of code.
class ArithmeticTaskRunner
{
constructor()
{
this.tasks = [];
}
addNegationTask()
{
const negationTask = (x) => -x;
this.tasks.push(negationTask)
return this;
}
addAdditionTask(y)
{
const additionByY = (x) => x + y;
this.tasks.push(additionByY)
return this;
}
addMultiplicationTask(y)
{
const multiplyByY = (x) => x * y;
this.tasks.push(multiplyByY)
return this;
}
taskCount()
{
return this.tasks.length;
}
execute(n)
{
let currentResult = n;
for(let task of this.tasks)
{
currentResult = task(currentResult)
}
return currentResult;
}
}
let taskRunner = new ArithmeticTaskRunner()
taskRunner.addAdditionTask(10)
taskRunner.addNegationTask()
taskRunner.addMultiplicationTask()
taskRunner.execute(2)
here are examples of the output and the input that is needed on this task
1.
let taskRunner = new ArithmeticTaskRunner()
undefined
taskRunner.addAdditionTask(2)
undefined
taskRunner.addMultiplicationTask(4)
undefined
taskRunner.addAdditionTask(10)
undefined
taskRunner.execute(2)
26
taskRunner.execute(-2)
10
2.
taskRunner.execute()
-5
taskRunner.execute(10)
-10
taskRunner.taskCount
3
If you want to have a REPL session and run the commands in command line you can use repl module.
const repl = require('repl');
class ArithmeticTaskRunner {
... // Your class definition
}
// This starts the REPL session with the ArithmeticTaskRunner defined
repl.start().context.ArithmeticTaskRunner = ArithmeticTaskRunner;
Then in terminal:
node filename.js
And when you have node running:
let taskRunner = new ArithmeticTaskRunner()
taskRunner.addAdditionTask(2)
taskRunner.addMultiplicationTask(4)
taskRunner.addAdditionTask(10)
taskRunner.execute(2)
taskRunner.execute(-2)
If you want to run the code completely and output the result use console.log in the code and run node filename.js:
class ArithmeticTaskRunner {
... // Your class definition
}
let taskRunner = new ArithmeticTaskRunner()
taskRunner.addAdditionTask(2)
taskRunner.addMultiplicationTask(4)
taskRunner.addAdditionTask(10)
console.log(taskRunner.execute(2))
console.log(taskRunner.execute(-2))
In terminal:
node filename.js
I'm assuming you've done basically the following on the command line:
node
.load ArithmeticTaskRunner.js
The reason you're only seeing the code printed out is because you just have a class definition. You don't have an instance of TaskRunner. If that's your intent, at the bottom of your code add something like this:
const taskRunner = new TaskRunner();
console.log(taskRunner);
Then when you try those command line steps again, it will print out an instance of TaskRunner with your methods on it.
However, the entire purpose of the .load command is to put your script into the Node.js REPL. Alternatively you can instead do the following in the command line:
node
.load ArithmeticTaskRunner.js
const taskRunner = new TaskRunner();
console.log(taskRunner);
This will let you do work on the command line without hard-coding it into your script.
Update
If your intent is to execute the code without printing it out, you can do the following:
node ArithmeticTaskRunner.js
But you won't be making your code available to the global instance. You'd have to add code into that script that creates a 'TaskRunner` instance and make use of it, like I did initially and save it into that file.
class ArithmeticTaskRunner
{
constructor()
{
this.tasks = [];
}
addNegationTask()
{
const negationTask = (x) => -x;
this.tasks.push(negationTask)
return this;
}
addAdditionTask(y)
{
const additionByY = (x) => x + y;
this.tasks.push(additionByY)
return this;
}
addMultiplicationTask(y)
{
const multiplyByY = (x) => x * y;
this.tasks.push(multiplyByY)
return this;
}
taskCount()
{
return this.tasks.length;
}
execute(n)
{
let currentResult = n;
for(let task of this.tasks)
{
currentResult = task(currentResult)
}
return currentResult;
}
}
const arithmeticTaskRunner = new ArithmeticTaskRunner ();
console.log(arithmeticTaskRunner );
After this then try doing the steps on the command line:
node
.load ArithmeticTaskRunner.js
Update 2
This should open the Node REPL (leading '>` should appear). Afterwards do these commands one line at a time:
let taskRunner = new ArithmeticTaskRunner()
taskRunner.addAdditionTask(2)
taskRunner.addMultiplicationTask(4)
taskRunner.addAdditionTask(10)
taskRunner.execute(2)
This should print 26.
taskRunner.execute(-2)
This should print 10.
I am calling a batch file from Javascript in this fashion:
function runBatch(){
var exe = Components.classes['#mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
exe.initWithPath("C:\\test.bat");
var run = Components.classes['#mozilla.org/process/util;1'].createInstance(Components.interfaces.nsIProcess);
run.init(exe);
var parameters = ["hi"];
run.run(false, parameters,parameters.length);
}
my test batch file is:
echo on
echo %1
pause
exit
Each time I call a batch file, however, the command prompt is not displayed, as it would be if I simply ran the batch file from the desktop. How can I remedy this and display a command prompt for the batch file?
Edit
To be clear, the cmd.exe process is launched - I can see it in the task bar. But no window gets displayed. This snippet behaves similarly:
function runCmd(){
var exe = Components.classes['#mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
exe.initWithPath("C:\\WINDOWS\\system32\\cmd.exe");
var run = Components.classes['#mozilla.org/process/util;1'].createInstance(Components.interfaces.nsIProcess);
run.init(exe);
run.run(false, null,0);
}
The only solution I've heard so far (that should work, although I haven't done it yet, comes from Mook in the Mozilla xulrunner IRC channel:
create a temporary batch file, writing in the batch file to call and arguments to pass it. then execute the temporary batch file.
e.g psuedocode:
f = fopen("temp.bat");
fprintf(f, "other.bat 1 2 3 4 5");
fclose(f);
exec("temp.bat");
not very elegant but it should work.
Did you try using the launch method of nsiLocalFile?
function runBatch(){
var exe = Components.classes['#mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
exe.initWithPath("C:\\test.bat");
exe.launch();
}
This should have "the same effect as if you double-clicked the file."
This code snippet seems to work fine. Of course, you have to change D:\Windows\system32\ to path to cmd.exe in your operation system.
const FileFactory = new Components.Constructor("#mozilla.org/file/local;1","nsILocalFile","initWithPath");
var str_LocalProgram = "D:\\Windows\\system32\\cmd.exe";
var obj_Program = new FileFactory(str_LocalProgram);
var process = Components.classes["#mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess);
process.init(obj_Program);
var args = ["/C", "regedit.exe"];
process.run(true, args, args.length);
I had to launch a batch file and pass in an argument. This is how I did it:
let file = uri.QueryInterface(Components.interfaces.nsIFileURL).file;
let run = Components.classes['#mozilla.org/process/util;1']
.createInstance(Components.interfaces.nsIProcess);
let path = file.path;
if(file.exists())
{
// quick security check
if(file.isExecutable())
{
// show error message
return;
}
let localfile = file.QueryInterface(Components.interfaces.nsILocalFile);
if(localfile != null)
{
if (app == "app1")
{
localfile.initWithPath("C:\\app1.bat");
}
else
{
localfile.initWithPath("C:\\app2.bat");
}
run.init(localfile);
var parameters = [path];
run.run(false, parameters, parameters.length);
}
else
{
// show error message
}
}
else
{
// show error message
}
and in my Window batch file I did:
#ECHO OFF
START "application.exe" %1
using START, allowed me to launch the application and close the command line window
You are doing right but repair this:
function runBatch(){
var exe = Components.classes['#mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
exe.initWithPath("***C:\ \test.bat***");
var run = Components.classes['#mozilla.org/process/util;1'].createInstance(Components.interfaces.nsIProcess);
run.init(exe);
var parameters = ["hi"];
run.run(false, parameters,parameters.length);
}
If you do this???
function runBatch(){
var exe = Components.classes['#mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
exe.initWithPath("***C:\test.bat***");
var run = Components.classes['#mozilla.org/process/util;1'].createInstance(Components.interfaces.nsIProcess);
run.init(exe);
var parameters = ["hi"];
run.run(false, parameters,parameters.length);
}
An put #echo off at init???
Thanks
Pfft, very ugly code..
A much nicer trick is to use Win.com to spawn a 16bit subsystem of the command prompt.
Win.com will send the console to the right virtual terminal, showing you the output.
var lPath = getWorkingDir.path + "\\..\\..\\WINDOWS\\system32\\win.com";
lFile.initWithPath(lPath);
var process = Components.classes["#mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess);
process.init(lFile);
var args = ["cmd.exe"];
process.run(false, args, args.length);
Nicer, and works :)
For Linux:
<script>
function callLight2()
{
netscape.security.PrivilegeManager.enablePrivilege(
'UniversalXPConnect'
);
var exe = Components.classes['#mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
// exe.initWithPath(C:\\Windows\\system32\\cmd.exe"");
exe.initWithPath("/usr/bin/gnome-terminal");
var run = Components.classes['#mozilla.org/process/util;1'].createInstance(Components.interfaces.nsIProcess);
run.init(exe);
var parameters = ["-e", "/usr/bin/ip_connect_up.sh 2 2 3 4 5 6"];
// var parameters = ["/C", "regedit.exe"];
// var parameters = ["hi"];
run.run(true, parameters,parameters.length);
}
</script>
start