How to define const in nodejs in global scope? - node.js

I want to separate my app in to the parts to have something like MVC... Currently I figured out exports works and how to communicate between different files. The one thing i cant understand is that how to use constants in global scope? Currently i have something like this:
// start.js
const ROOT_DIR = __dirname;
const APP_DIR = ROOT_DIR + '/app/';
const MODULES_DIR = '/usr/local/lib/node_modules/';
const APP_PORT = 4935;
var server = require(APP_DIR + 'server.js');
server.start();
// server.js
exports.start = function() {
var express = require(MODULES_DIR + 'express'),
app = express(),
http = require('http'),
server = http.createServer(app),
io = require(MODULES_DIR + 'socket.io').listen(server),
fs = require('fs'),
path = require('path');
server.listen(APP_PORT);
app.use(express.static(ROOT_DIR + '/assets'));
app.get('/', function (req, res) {
res.sendfile(ROOT_DIR + '/views/index.html');
});
}
Is it possible to automatically assign this constants to server.js or i need to pass them as variables?

I think, you need create file with constants and use him as require file in begin a other module.
File consts.js
exports.CONST_1 = 42,
exports.CONST_2 = 123;
In the module where necessary:
var consts = require('path_to_consts.js');
var my_var = consts.CONST_1 + consts.CONST_2;
So all global variables will be in one place

Object.defineProperty(global, 'MY_CONST', { value : 123 })
P.S. Please, don't do this

Javascript constants won't work globally across files in Node.js. You need to pass them to the function.
// start.js
const ROOT_DIR = __dirname;
const APP_DIR = ROOT_DIR + '/app/';
const MODULES_DIR = '/usr/local/lib/node_modules/';
const APP_PORT = 4935;
var server = require(APP_DIR + 'server.js');
server.start(MODULES_DIR,APP_PORT,ROOT_DIR);
// server.js
exports.start = function(MODULES_DIR,APP_PORT,ROOT_DIR) {
var express = require(MODULES_DIR + 'express'),
app = express(),
http = require('http'),
server = http.createServer(app),
io = require(MODULES_DIR + 'socket.io').listen(server),
fs = require('fs'),
path = require('path');
server.listen(APP_PORT);
app.use(express.static(ROOT_DIR + '/assets'));
app.get('/', function (req, res) {
res.sendfile(ROOT_DIR + '/views/index.html');
});
}

This is method is same as suggested by #user3040347 but little different.
Here, you need create file with constants and use him as require file in begin of a module in which you want to use.
File consts.js
CONST_1 = 42,
CONST_2 = 123;
module.exports = {};
In the module where necessary:
var consts = require('path_to_consts.js');
var my_var = CONST_1 + CONST_2;
//Here you can access directly

Related

NodeJs says "ReferenceError: window is not defined" with jsPDF

I am creating a sample project with NodeJs and jsPDF. When I run, it echos ReferenceError: window is not defined. I also used John Gordon answer from here, but again also same problem.
I tried with
var express = require('express');
var jsPDF = require('jspdf');
var app = express();
app.get('/', function(req, res)
{
global.window = {document: {createElementNS: () => {return {}} }};
global.navigator = {};
global.btoa = () => {};
var fs = require('fs');
var jsPDF = require('jspdf');
var jsPDFTable = require('jspdf-autotable');
var doc = new jsPDF();
doc.text("Hello", 10, 10);
var data = doc.output();
fs.writeFileSync('./tmp/storage/pdf/document.pdf', data);
delete global.window;
delete global.navigator;
delete global.btoa;
});
var port = process.env.PORT || 8080;
app.listen(port);
console.log('Server started');
module.exports = app;
All you need to do is to remove your var jsPDF = require('jspdf'); at the top and to have the similar declaration inside your app.get.. (which you already have) function like this,
var express = require('express');
var app = express();
app.get('/', function(req, res)
{
global.window = {document: {createElementNS: () => {return {}} }};
global.navigator = {};
global.btoa = () => {};
var fs = require('fs');
var jsPDF = require('jspdf');
var jsPDFTable = require('jspdf-autotable');
var doc = new jsPDF();
doc.text("Hello", 10, 10);
var data = doc.output();
fs.writeFileSync('./document.pdf', data);
delete global.window;
delete global.navigator;
delete global.btoa;
});
var port = process.env.PORT || 8080;
app.listen(port);
console.log('Server started');
module.exports = app;
Hope this helps!
The specified package jspdf is a client only library and need to be used in a browser environment to work properly.
The description is clear in the package home page:
A library to generate PDFs in client-side JavaScript.
Now, the reason an npm package is available is because bundlers like Webpack and Browserify can load npm packages and convert them into a proper browser compatible script. The require() is not defined in a browser environment and will not work without these bundlers.
So, either choose a library that supports NodeJS like
https://www.npmjs.com/package/pdfkit or shift your PDF related code to browser and work with it.
EDIT:
https://github.com/MrRio/jsPDF/issues/566#issuecomment-382039316
shows that you can use the library in NodeJS env by making the following changes.
In that case, you need to define the global variables before requireing the module.
global.window = {document: {createElementNS: () => {return {}} }};
global.navigator = {};
global.btoa = () => {};
var fs = require('fs');
var jsPDF = require('jspdf');
var jsPDFTable = require('jspdf-autotable');
var app = require('express')();
app.get('/', function(req, res)
{
var doc = new jsPDF();
// ...
}
You can place the script tag either in the head or body tag in the html page, either one is fine. To decide where to place, this answer might be of help

Separating modules in NodeJS for use with a single object

I have a NodeJS + ExpressJS + Socket.IO server and I am trying to divide my different namespaces into different modules.
Essentially I want to require the socket.io library in server.js, but have access to the io variable from my modules like this:
server.js
var app = require('express')();
var jwt = require('jsonwebtoken');
var server = require('http').Server(app);
var fs = require('fs');
var io = require('socket.io')(server);
var bodyParser = require('body-parser');
var _log = require('./logging/loggly.js').Client();
// Global NS
var SK = {
Namespaces:{}
};
var Migrations = require('./sockets/migrations');
var Backups = require('./sockets/backups');
var Cloudmanager = require('./sockets/cloudmanager');
SK.Namespaces[Migrations.NS] = Migrations;
SK.Namespaces[Backups.NS] = Backups;
SK.Namespaces[Cloudmanager.NS] = Cloudmanager;
....
....
migrations.js
var exports = module.exports = {};
///////////////////////////////////////////////
//
// Migrations Namespace
//
///////////////////////////////////////////////
exports.NS = 'migrations';
exports.socket = io.of('/'+exports.NS); // PROBLEM IS 'io' IS UNDEFINED HERE
exports.socket.on('connection', function(socket){
});
I have basically the same code in all 3 of my socket.io namespaces, but I don't have access to the io variable that is used in server.js. Is there a way to have access here? Do I just use a require()? Whats the best way to achieve this functionality?
Thank you
You can export a function from migrations.js that accepts the io value as a parameter:
module.exports = function (io) {
var socket = io.of('/'+exports.NS);
socket.on('connection', function(socket){});
return {
NS: 'migrations',
socket: socket,
};
};
Then simply require and invoke this function in your server.js:
var Migrations = require('./sockets/migrations')(io);

zip and download from nodejs

I am trying to zip the file and download from server using easy-zip module. But now I can write into a server using following code but how can i make it downloadable???
var app = require('express')();
var easyzip = require('easy-zip');
app.get('/api/downloadFile',function(req,res){
console.log("inside req");
var data = "<html><body><h1>Inside new Html</h1></body></html>";
var zip2 = new easyzip.EasyZip();
var jsFolder = zip2.folder('data');
jsFolder.file('app.js','alert("hello world")');
jsFolder.file('index.html',data);
zip2.writeToFile('folder.zip');
});
Try zip2.writeToResponse(res,'folder.zip'); instead of zip2.writeToFile('folder.zip');
Instead of write into a file write into a response
var app = require('express')();
var easyzip = require('easy-zip');
app.get('/api/downloadFile',function(req,res){
console.log("inside req");
var data = "<html><body><h1>Inside new Html</h1></body></html>";
var zip2 = new easyzip.EasyZip();
var jsFolder = zip2.folder('data');
jsFolder.file('app.js','alert("hello world")');
jsFolder.file('index.html',data);
zip2.writeToResponse(res,'folder');
res.end();
})

How to access io instance in a third part file?

I need to access my socket.io instance in some differents files, how do you make it works?
Here is what i tried:
main.js
var app = express();
var sockets = require('./sockets');
sockets.listen(app)
sockets.js
var io = require('socket.io');
exports.listen = function(app) {
io = io.listen(app);
//...
}
exports.io = io;
SomeClass.js
var io = require('./sockets').io;
var SomeClass = function() {
var Clients = io.sockets.clients('room');
//io is undefined...
}
exports.SomeClass = SomeClass;
In your file, io.sockets is undefined because you are starting your server incorrectly. Socket.IO expects a HTTP server instance, and you are instead passing an Express instance. You are also trying to change a variable after it has been exported, and that does not work. This is what you should be doing:
var http = require('http');
var express = require('express');
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server):
server.listen(80);
If you still wanted to split this up into files, you would have to put your Socket.IO instance in your main application, and pass it to other modules when requiring them.

Node.js + Express passing an object

I'm building a small node.js/express project and have a function in configure.js that sets configuration options in my express app. For example:
server.js
var express = require('express');
var server = ('./configure');
var app = express();
server.configure(app);
configure.js
exports.configure = function(app) {
app.set('title', 'Server');
};
This doesn't work but I hope it explains what I'm trying to do. I want to make changes to the app instance in server.js. How do I do this?
EDIT:
Okay I think i can get this all working if i understand why this isn't working. Is it to do with timing of the callback? The second console.log() isn't called.
configure.js
var fs = require('fs');
var StringDecoder = require('string_decoder').StringDecoder;
var decoder = new StringDecoder('utf8');
function configure(app) {
var config = module.exports = {};
fs.readFile('config.txt', function (err, data) {
if (err) throw err;
config.title = decoder.write(data)
console.log(config.title)
});
if(config.title) console.log(config.title);
//app.set('title', config.title)
}
module.exports = function (app) {
configure(app);
};
server.js
var express = require('express');
var cfg = require('./configure');
var fs = require('fs');
var app = express()
cfg(app)
(config.txt is echo 'server' > config.txt)
What you have should actually work.
As for your question about using multiple functions, you can export and call each separately. This can be useful when timing is important (such as if other setup steps need to occur that aren't specified in configure.js):
// configure.js
exports.configure = function (app) {
// ...
};
exports.attachMiddlware = function (app) {
// ...
};
// server.js
var express = require('express');
var server = require('./configure');
var app = express();
server.configure(app);
server.attachMiddlware(app);
You can also define a single entry function as the exported object which calls the functions needed within configure.js. This can possibly keep server.js cleaner by isolating the maintenance within configure.js:
function configure(app) {
// ...
}
function attachMiddleware(app) {
// ...
}
module.exports = function (app) {
configure(app);
attachMiddleware(app)
};
var express = require('express');
var configure = require('./configure');
var app = express();
configure(app);
I would avoid that and just do a json object:
app.js
var cfg = require('./config');
app.set('title', cfg.title);
config.js
var config = module.exports = {};
config.title = 'Server';

Resources