How to run node js application programmatically using forever - javascript

I need to run the set of node js files which contains the configuration information where It has to run typically port number and IP address then using the forever in node.js I need to run the script in the terminal with the configuration without having any manual input.

For Programmatic approach , you can use Forever-Moniter
var forever = require('forever-monitor');
var child = new (forever.Monitor)('your-filename.js', {
max: 3,
silent: true,
options: []
});
child.on('exit', function () {
console.log('your-filename.js has exited after 3 restarts');
});
child.start();

You could make use of the child_process module. Check the doc, there're some useful information there: http://nodejs.org/api/child_process.html
To give a brief example
var exec = require('child_process').exec;
exec('forever', function callback(error, stdout, stderr){
// cb
});
If you don't need a callback / don't want to wait for the execution:
var exec = require('child_process').exec('forever').unref();
Was that helpful?
Best
Marc
Edit: Ok, not sure if I really got the point of your question, but my answer combined with https://stackoverflow.com/a/23871739/823851 might offer a good solution.

Usage:
forever start hello.js to start a process.
forever list to see list of all processes started by forever
forever stop hello.js to stop the process, or forever stop 0 to stop the process with index 0 (as shown by forever list).

node-config is a good module for managing different configurations of a Node.js app.
For example, to make a "production" config, /config/production.json would contain:
{
"port" : "3000",
"ip" : "192.168.1.1"
}
In one of your node application JS files:
config = require('config')
....
var port = config.port;
var ip = config.ip;
And to launch the app in this configuration, just first set your NODE_ENV to production from the shell before running your app.
export NODE_ENV=production
forever start app.js
Make additional config JSON files as needed for each of your environments. default.json is used when no environment is specified.

Related

differentiate between make and package in Electron Forge config

I have an Electron Forge config file set up with many options and it all works automagically and beautifully (thanks Forge team!!). But I have found certain situations where I might want to handle a bare npm run package differently than a full npm run make (which as I understand it runs the package script as part of its process). Is there any way to programmatically detect whether the package action was run direct from the command line rather than as part of the make process, so that I can invoke different Forge configuration options depending? For example sometimes I just want to do a quick build for local testing and skip certain unnecessary time-consuming steps such as notarizing on macOS and some prePackage/postPackage hook functions. Ideally I'm looking for a way to do something like this in my Forge config file:
//const isMake = ???
module.exports = {
packagerConfig: {
osxNotarize: isMake ? {appleId: "...", appleIdPassword: "..."} : undefined
},
hooks: {
prePackage: isMake ? someFunction : differentFunction
}
}
You can do it by process.argv[1]:
let isMake;
if (process.argv[1].endsWith('electron-forge-make.js') {
isMake = true;
} else {
isMake = false;
}
module.exports = {
// ...
}
When calling process.argv, it returns an array with two strings: The first one with node.js directory and the second one with electron forge module directory.
The make module ends with electron-forge-make.js and package module ends with electron-forge-package.js. So you can look at the end of it and determine whether it's package or make.

Environment variable is undefined in electron even it has been set inside webpack.DefinePlugin

I have a requirement where we need to set dll path based upon whether it is executing in production or in development environment. So I decided to place that value in environment variable and tried to achieve that using webpack.DefinePlugin({}).
Method 1:
webpack.config.json
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV' : JSON.stringify('production')
})
And then I tried to get that value in electron's main process, In my case elec.js
elec.js
const Electron = require("electron");
const app = require("electron");
var dllPath = "";
function createWindow() {
let win = new BrowserWindow({
width: 800,
height: 600,
title: "Test",
icon: "Test.ico"
});
win.setMenu(null);
win.loadURL(
url.format({
pathname: path.join(__dirname, "../renderer/index.html"),
protocol: "file:",
slashes: true
})
);
if (process.env.NODE_ENV ==='production') {
dllPath = path.join(
__dirname,
"./../../dll/test.dll"
);
} else {
dllPath = path.join(
__dirname,
"./../../../dll/test.dll"
);
}
}
app.on("ready", createWindow);
But problem is that when I try to access that value in createWindow() function it is undefined so flow always goes to else block.
Is there anything I am missing?
Method 2:
I tried to achieve the same using cross-env node package, but no luck. Please find below code block which I tried using cross-env.
package.json
"scripts": {
"build": "cross-env process.env.NODE_ENV=production && rimraf ./dist/ && webpack --progress && node-sass
./src/renderer/scss/ -o ./dist/renderer/ && rimraf ./dist/renderer/includes/"
}
The problem is multi-faceted.
First, your elec.js is executed by Electron before the app is loaded. Electron runs elec.js, which creates the Browser window (let win = new BrowserWindow(...)) and loads HTML file (win.loadURL(...)) into it inside the browser process, the HTML then loads your webpack'ed js. So none of the webpacked js code is available in the elec.js. The webpack'ed code is also running in another process than the elec.js.
Another thing to note is that webpack plugin does not create any assignment to the variable it points too. It is done by simple text search and replace, in your example, all instances of process.env.NODE_ENV will be replaced with "production" string in the source code that is webpack'ed. That is not too obvious, but messes up the expected results.
One last thing - webpack plugin does not change any code in elec.js file, as that file is not webpack'ed.
So all that makes process.env.NODE_ENV from the build/webpack time not available in the elec.js code.
Once the mechanisms are clear, there are few ways to solve the problem, I will give general ideas, as there are plenty of discussions on each, and depending on circumstances and desired use case, some are better than others:
Generate a js file with necessary assignments based on environment variable during build (e.g. copy one of env-prod.js / env-dev.js -> env.js), copy it next to the elec.js, and reference it (require(env.js)) in elec.js.
Pass environment variable from command line (e.g. NODE_ENV=1 electron .) - it will get to elec.js.
Include a file into webpack based on environment variable (e.g. copy one of env-prod.js / env-dev.js -> env.js) and peek into webpacked' files from elec.js, e.g. using asar commands.
Use different version in package.json depending on build (e.g. version: "1.0.0-DEBUG" for debug), and read & parse it by calling app.getVersion() in elec.js. It is tricky as package.json should be a single file, but OS commands could be used (e.g. in "scripts") to copy one of prepared package.json files before invoking npm.
Here are some links that could help too:
Electron issue #7714 - discussion on relevant features in Electron
electron-is-dev - module checking if it is in dev
Electron boilerplate - example boilerplate that uses config/env-prod/dev files
The insight provided by iva2k is what allowed me to come to a solution for this same problem.
Using dotenv to create a .env file for my config got me halfway to where I wanted to be (setting up a few environment variables for use in a production setting). The problem then became that Electron wasn't passing those from the Main process down to the Renderer process by default.
The work-around is simple: use Electron's own ipcMain and ipcRenderer modules to pass the dotenv object between the two.
In your main file (e.g. your elec.js file), place an ipcMain event listener after requiring the module:
const config = require('dotenv').config();
const electron = require('electron');
const { app, BrowserWindow, ipcMain } = electron;
...
ipcMain.on('get-env', (event) => {
event.sender.send('get-env-reply', config);
});
Elsewhere, in your application's rendering-side, place this anywhere necessary:
async function getConfig()
{
const { ipcRenderer } = window.require('electron');
let config = null;
ipcRenderer.on('get-env-reply', (event, arg) => {
// The dotenv config object should return an object with
// another object inside caled "parsed". Change this if need be.
config = arg.parsed;
});
ipcRenderer.send('get-env');
return config;
}
This basically allowed me to declare one event in the Main process file, and then re-use it in any process-side file I wanted, thus allowing me to obfuscate config variables in a file that goes with the build, but isn't accessible to end-users without opening up the dev-tools.
Maybe late but can use simple hack in elec.js
const isProduction = process.env.NODE_ENV === 'production' || (!process || !process.env || !process.env.NODE_ENV);
In your console
For Windows
set MY_VARIABLE=true
For linux
$ export MY_VARIABLE=true
window.process.env.MY_VARIABLE

Getting test results when creating a Karma server programmatically

I am trying to run multiple Karma test files in parallel from inside a Node script and get to know which tests are passing or failing. Right now what I have is this:
const exec = require("child_process").exec;
exec("karma start " + filename, (error, stdout, stderr) => {
// handle errors and test results...
});
The code above works well, and I can get the information on tests passed or failed from stdout. However, it requires having installed Karma and all of the associated dependencies (reporters, browser launchers, etc.) globally. I am looking for a solution that doesn't require me to install all dependencies globally.
My first thought was this:
const karma = require("karma");
const server = new karma.Server(config, () => {
// some logic
});
However, when trying this other approach, I have been unable to gather the test results programmatically.
When using new karma.Server(), is there any way in which I could know which tests have passed or failed (and, ideally, a stack trace of the error)? Alternatively, is there any other way in which I can execute my tests and get the desired information programmatically without the need to install dependencies globally?
Actually, changing the exec line to this seems to do the trick:
exec("node node_modules/karma/bin/karma start " + filename, (error, stdout, stderr) => {
It turns out I'd only need to run the locally installed version of Karma instead of the global one. :-)

Debugging gf3/sandbox module

I'm doing my baby steps in node.js, and i'm trying to understand sandbox mechanism.
Currently i'm using node v4.0.0 and node-inspector v0.12.3.
I've installed gf3/sandbox module and run it with this simple code:
var s = new Sandbox();
s.run('1 + 1 + " apples"',function(output) {
console.log(output.result);
});
In order to debug easily, i've also commented the timeout function in sandbox.js file:
// timer = setTimeout(function() {
// self.child.stdout.removeListener('output', output);
// stdout = JSON.stringify({ result: 'TimeoutError', console: [] });
// self.child.kill('SIGKILL');
// }, self.options.timeout);
The issue is that debug DOESN'T break on ANY line code of shovel.js, and i'm 100% sure the module is using its code.
Why is that ? And what can I do in order to debug shovel.js?
sandbox.js is spawning shovel.js as child process without debugging enabled(e.g. no --debug option). So the child process executes normally and your breakpoints are simply ignored. You need to start child process in debug mode too.
If you want to debug both sandbox.js and shovel.js at the same time, then use different debug ports. I'm not sure about node-inspector, but here is an example of how you can do it with the debugger module. I'm sure you can tweak a bit to make it work with node-inspector.
Comment the timeout code like you already did
Pass debug option while spawning child process in sandbox.js. Note the port is 5859:
self.child = spawn(this.options.node, ['--debug-brk=5859',this.options.shovel], { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] });
start example.js in debug mode. By default, it starts at 5858 port:
node --debug-brk example.js
Now debug sandbox.js by connecting to 5858:
node debug localhost:5858
Once the child process starts, you can fire up separate terminal and start debugging shovel.js on port 5859:
node debug localhost:5859
For node-inspector, I think you need to use node-debug command instead of this.options.node for child process. Also there are options to set debug port explicitly.
From above, These could be the steps for node-inspector. Note: I haven't tested it:
Same as above
Open sandbox.js file and change this line like following to pass debug option while spawning child process. Note the port is 5859:
self.child = spawn('node-debug', ['--debug-port=5859',this.options.shovel], { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] });
start example.js in debug mode. By default, it starts at 5858 port:
node-debug example.js
Now head to the browser to debug parent process:
http://127.0.0.1:8080/?ws=127.0.0.1:8080&port=5858
Once the child process starts, open up another browser window to debug shovel.js:
http://127.0.0.1:8080/?ws=127.0.0.1:8080&port=5859

How can I run multiple node.js scripts from a main node.js scripts?

I am totally new to node.js .I have two node.js script that I want to run . I know I can run them separately but I want to create a node.js script that runs both the scripts .What should be the code of the main node.js script?
All you need to do is to use the node.js module format, and export the module definition for each of your node.js scripts, like:
//module1.js
var colors = require('colors');
function module1() {
console.log('module1 started doing its job!'.red);
setInterval(function () {
console.log(('module1 timer:' + new Date().getTime()).red);
}, 2000);
}
module.exports = module1;
and
//module2.js
var colors = require('colors');
function module2() {
console.log('module2 started doing its job!'.blue);
setTimeout(function () {
setInterval(function () {
console.log(('module2 timer:' + new Date().getTime()).blue);
}, 2000);
}, 1000);
}
module.exports = module2;
The setTimeout and setInterval in the code are being used just to show you that both are working concurrently. The first module once it gets called, starts logging something in the console every 2 second, and the other module first waits for one second and then starts doing the same every 2 second.
I have also used npm colors package to allow each module print its outputs with its specific color(to be able to do it first run npm install colors in the command). In this example module1 prints red logs and module2 prints its logs in blue. All just to show you that how you could easily have concurrency in JavaScript and Node.js.
At the end to run these two modules from a main Node.js script, which here is named index.js, you could easily do:
//index.js
var module1 = require('./module1'),
module2 = require('./module2');
module1();
module2();
and execute it like:
node ./index.js
Then you would have an output like:
You can use child_process.spawn to start up each of node.js scripts in one. Alternatively, child_process.fork might suit your need too.
Child Process Documentation

Categories

Resources