NodeJs says "ReferenceError: window is not defined" with jsPDF - node.js

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

Related

Nodejs TypeError "is not a constructor"

I am working through the course "Build a Blockchain and Cryptocurrency From Scratch from Udemy. I have no prior experience with NodeJS I have been following along with the instructor's code, but recently hit a snag that I cannot resolve. When trying to build the project to run test scripts via npm run dev, I get the following error:
/home/OnlyDean/Workspace/udemy_blockchain_course_1/app/index.js:13
const p2pServer = new P2pServer(bc);
^
TypeError: P2pServer is not a constructor
Answers I've found online seem to indicate that I'm calling an instance of the class P2pServer rather than the constructor of the class itself. This is borne out by the output of console.log(P2pServer);, which returns [Object object]. I have scoured the code for errors, and compared my code to what the instructor has on the screen. I can't seem to find any differences. Below are my index.js and p2p-server.js classes, which I think are the only relevant files.
index.js
const express = require('express');
const bodyParser = require('body-parser');
const Blockchain = require('../blockchain');
const P2pServer = require('./p2p-server');
const HTTP_PORT = process.env.HTTP_PORT || 3001;
const app = express();
const bc = new Blockchain();
//console.log(`Blockchain = ${Blockchain}`)
console.log(`P2pServer = ${P2pServer}`)
console.log(bc)
const p2pServer = new P2pServer(bc);
app.use(bodyParser.json());
app.get('/blocks', (req, res) => {
res.json(bc.chain);
})
app.post('/mine', (req, res) => {
const block = bc.addBlock(req.body.data);
console.log(`New block added: ${block.toString()}`);
res.redirect('/blocks');
});
app.listen(HTTP_PORT, () => console.log(`Listening on port ${HTTP_PORT}`));
p2pServer.listen();
p2p-server.js
const Websocket = require('ws');
const P2P_PORT = process.env.P2P_PORT || 5001;
const peers = process.env.PEERS ? process.env.PEERS.split(',') : [];
class P2pServer {
constructor(blockchain) {
this.blockchain = blockchain;
this.sockets = [];
}
listen() {
const server = new Websocket.Server({ port: P2P_PORT});
server.on('connection', socket => this.connectSocket(socket));
this.connectToPeers();
console.log(`Listening for peer-to-peer connections on: ${P2P_PORT}`);
}
connectToPeers() {
peers.forEach(peer => {
const socket = new Websocket(peer);
socket.on('open', () => this.connectSocket(socket));
});
}
connectSocket(socket) {
this.sockets.push(socket);
console.log(`Socket connected`);
}
}
module.export = P2pServer;
Any help resolving this error would be greatly appreciated -- I'm kind of stuck with the course until I can resolve this. Thanks!
The problem is at the export of the P2pServer class
should be like this (exports and not export):
module.exports = P2pServer;

app is undefined in loopback custom js file

i am using nodejs loopback framework.i want to run a cron job.i created a custom js file for this cron job in server/boot folder.but when manually i run this file(xyz). app is undefined.my code is below
var app = require('../server.js');
console.log(">>>>>>>>>>>>>>in test")
var subscription = app.models.UserNotification;
console.log(">>>>>>>>>>>..in manage")
var datasource=subscription.dataSource;
var query="SELECT DISTINCT userId FROM users_subscription";
datasource.connector.query(sql,function (err, data) {
console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>data is>>>>>",data);
})
here is my server.js file
var bodyParser = require('body-parser');
var loopback = require('loopback');
var boot = require('loopback-boot');
var app = module.exports = loopback();
var passport = require('passport');
var bodyParser = require('body-parser').urlencoded({
extended: true
})
app.use(bodyParser)
app.use(loopback.context());
app.use(loopback.token());
var path = require("path");
var url = require('url');
var http = require('http');
var fs = require('fs');
var request = require('request');
app.start = function() {
// start the web server
return app.listen(function() {
app.emit('started');
var baseUrl = app.get('url').replace(/\/$/, '');
console.log('Web server listening at: %s', baseUrl);
if (app.get('loopback-component-explorer')) {
var explorerPath = app.get('loopback-component-explorer').mountPath;
console.log('Browse your REST API at %s%s', baseUrl, explorerPath);
}
});
};
app.use(loopback.static(path.resolve(__dirname, '../client')));
app.use(loopback.static(path.resolve(__dirname, '../admin')));
app.use(loopback.static(path.resolve(__dirname, '../other-dir')));
boot(app, __dirname, function(err) {
if (err) throw err;
if (require.main === module) app.start();
});
Thanks,
It's really impossible to say for sure since you don't include the code that is included with:
var app = require('../server');
(which would be the most important code to include if the require returns undefined) but if app is undefined then it means that the module is loaded but its module.exports is undefined.
Do you export anything from that module?
Are you sure that it is really app that is undefined and not, say, app.models?
Without knowing the code in question those are the most reasonable things to investigate.
Update
If you don't export anything from your server.js (which was my suspection in my answer above, but now you confirmed it with you code and comment) then after this line:
var app = require('../server.js');
you will not be able to use app.models.UserNotification
If you want to use app.models in the code that requires server.js, then you'll have to add:
module.exports.models = SOMETHING;
in your server.js code. You don't seem to have anything called models in server.js, you don't export anything as module.exports.models, so you can't expect app.models to be defined in your code that does:
var app = require('../server.js');

How to save directly to a folder a CSV file using NodeJs?

How to save a CSV file directly to a folder destination?
Currently my code prompts the save window in the browser, I DO NOT want that.
I want NodeJS to save the CSV directly to a folder destination
How can I do that?
var fs = require('fs');
var express = require('express');
csv = require('express-csv');
var request = require('request');
var cheerio = require('cheerio');
var async = require('async');
var app = express();
app.get('/scraper', function(req, res){
var offset = req.query.offset || 0;
var limit = req.query.limit || 50;
if(gCounter === 0){
getStreamerInfo(offset, limit, function(response){
console.log("FILE READY!");
res.csv(response); // this export to browser but I want to save directly to a folder
});
}
});
Jus in case someone is looking for the same answer, this is what I did:
var fs = require('fs');
var jsonexport = require('jsonexport');
jsonexport(response,function(err, csv){
fs.writeFile("C:/outcome/c.csv", csv, function(err) {
if(err) {}
});
});
//res.csv(response);

How to define const in nodejs in global scope?

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

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