jspdf module crashing every time with ReferenceError: window is not defined - node.js

I am working on a small project that works with generating pdf's in node and express, and been trying to use the jspdf npm module but somehow whenever I install that package and require it its crashing my sever. Here in how I am requiring in my server.js file:
var jsPDF = require('jspdf')
And this is the response that it is giving me when l try to run my server:
(window.AcroForm=function(t){var n=window.AcroForm;n.scale=function(t) {return t*(r.internal.scaleFactor/1)},n.antiScale=function(t){return 1/r.internal.scaleFactor*t};var r={fields:[],xForms:[],acroFormDictionaryRoot:null,printedOut:!1,internal:null};e.API.acroformPlugin=r;var i=function(){for(var t in this.acroformPlugin.acroFormDictionaryRoot.Fields){var e=this.acroformPlugin.acroFormDictionaryRoot.Fields[t];e.hasAnnotation&&a.call(this,e)}},o=function(){if(this.acroformPlugin.acroFormDictionaryRoot)throw new Error("Exception while creating AcroformDictionary");this.acroformPlugin.acroFormDictionaryRoot=new n.AcroFormDictionary,this.acroformPlugin.internal=this.internal,this.acroformPlugin.acroFormDictionaryRoot._eventID=this.internal.events.subscribe("postPutResources",l),this.internal.events.subscribe("buildDocument",i),this.internal.events.subscribe("putCatalog",c),this.internal.events.subscribe("pos
ReferenceError: window is not defined

The jsPDF library is for the client side (web browser) which is why it's expecting a window variable to be present. Luckily someone has already answered how to make this work server side here. Taken from that answer:
global.window = {document: {createElementNS: () => {return {}} }};
global.navigator = {};
global.btoa = () => {};
var fs = require('fs');
var jsPDF = require('jspdf');
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;

Related

Angular 9 and SSR - window is not defined

I am using Angular 9 and SSR and I am getting the error on one of the packages.
const DragEvevent = window.DragEvent
ReferenceError: window is not defined
On the ngx-chips package
We already tried adding to the nodeJs the variables:
const domino = require('domino');
const fs = require('fs');
const template = fs.readFileSync(join(join(process.cwd(), 'dist/emaua-front/browser'), 'index.html')).toString();
console.log(template);
const win = domino.createWindow(template);
// mock
global['window'] = win;
global['document'] = win.document;
global['DOMTokenList'] = win.DOMTokenList;
global['Node'] = win.Node;
global['Text'] = win.Text;
global['HTMLElement'] = win.HTMLElement;
global['navigator'] = win.navigator;
But still the error persists.
Update
After updating all packages I got the error:
ERROR in multi ./src/assets/css/ripple.min.scss ./src/assets/css/lounge.scss ./src/assets/css/discovery.scss ./src/assets/css/main.scss ./src/styles.scss ./node_modules/roboto-fontface/css/roboto/roboto-fontface.css ./node_modules/material-design-icons/iconfont/material-icons.css ./node_modules/bootstrap/dist/css/bootstrap.min.css ./node_modules/bootstrap/dist/css/bootstrap-theme.min.css ./node_modules/ng-bootstrap-to-bootstrap-3/dist/ng-bootstrap-to-bootstrap-3.min.css ./node_modules/jquery-ui-dist/jquery-ui.min.css ./node_modules/jquery-ui-dist/jquery-ui.theme.min.css ./node_modules/ag-grid-community/dist/styles/ag-grid.css ./node_modules/ag-grid-community/dist/styles/ag-theme-balham.css ./node_modules/slick-carousel/slick/slick.scss ./node_modules/slick-carousel/slick/slick-theme.scss ./src/assets/css/animate.css ./node_modules/cookieconsent/build/cookieconsent.min.css
Module not found: Error: Can't resolve '/Users/vinh/learning/front-end/node_modules/bootstrap/dist/css/bootstrap-theme.min.css' in '/Users/vinh/learning/front-end'
this.debug is not a function
After that I applied the fix as said in here
And again I am getting the same error like:
const DragEvent = window.DragEvent;
^
ReferenceError: window is not defined
On the ngx-chips package
UPDATE
The problems we have in ngx-chips is something that was happening before.
https://github.com/Gbuomprisco/ngx-chips/issues/740
https://github.com/Gbuomprisco/ngx-chips/issues/786
Does anyone knows a way of overcoming this problem?
I upgraded to Angular 10 and I had the same problem with ngx-chips on the server.
I solved this problem as follows:
I, probably like many, do not really need this component when rendering on the server.
Too lazy to create a separate project to exclude this module.
So I just disabled this component.
In template:
<div *ngIf="isBrowser()">
<tag-input [(ngModel)]=...
</tag-input>
</div>
In typescript:
isBrowser() {
if (window) {
return true;
}
return false;
}

can't add images with jsPDF when using node.js

jsPDF works well within node, but adding an images does not work. There are no error messages, the images just don't show up in the pdf document.
Working with:
macOS: 10.13.4
nodejs: v10.15.0
jsPDF: 1.4.1
The code I use:
// setting up node to act as browser
// library jspdf is built for the browser
// global.window does not work on older versions of node
global.window = {document: {createElementNS: () => {return {}}}};
global.navigator = {};
global.btoa = () => {};
global.node = true;
var fs = require('fs');
atob = require('atob') // npm install atob
var jsPDF = require('/absolute/path/to/jspdf.js');
var pdf = new jsPDF
var imgData = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QCsRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgExAAIAAAAgAAAAWodpAAQAAAABAAAAegAAAAAAAABIAAAAAQAAAEgAAAABQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgV2luZG93cwAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAMKADAAQAAAABAAAAMAAAAAD/4QruaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA1LjQuMCI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjYyOERCQkYzMjQwODExRTc5QkZEOUI0RUIwREJBOUQ1IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjYyOERCQkY0MjQwODExRTc5QkZEOUI0RUIwREJBOUQ1IiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE0IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0iN0M1QzRFNEY2RTlDOTBBNjlBRjYxRUEwQzg4OTE4NzIiIHN0UmVmOmRvY3VtZW50SUQ9IjdDNUM0RTRGNkU5QzkwQTY5QUY2MUVBMEM4ODkxODcyIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDw/eHBhY2tldCBlbmQ9InciPz4A/+0AOFBob3Rvc2hvcCAzLjAAOEJJTQQEAAAAAAAAOEJJTQQlAAAAAAAQ1B2M2Y8AsgTpgAmY7PhCfv/AABEIADAAMAMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2wBDABALCwsMCxAMDBAXDw0PFxsUEBAUGx8XFxcXFx8eFxoaGhoXHh4jJSclIx4vLzMzLy9AQEBAQEBAQEBAQEBAQED/2wBDAREPDxETERUSEhUUERQRFBoUFhYUGiYaGhwaGiYwIx4eHh4jMCsuJycnLis1NTAwNTVAQD9AQEBAQEBAQEBAQED/3QAEAAP/2gAMAwEAAhEDEQA/AO/oJA6nFQXt5HZ27TSHpwo9Segrk3li1K4aS9nxHuwqs+0H/ZVc4x71nOqoyUd5Ppe2h1YfCyqqU23CEeqXM2+yWh2eRjNQWcssyPLJtEbuTAACD5YwFLEk5JwT9CK5mS125FpezwAjbt3l0IPs+f0rEk8QaxZM9r9obdEdquOOF6HBBBBHtQ6lt0/kXHAud+SpF26STT/U9Ipa5Xw34ta/mWxvwBO/+qmXgOeu1l7H0xwfaupq4yTV0c1WlOlJwmrNfc13R//Q0vGl48dzZ24Py4dyB3PCj9M1y13dAqVU54A/rXWeMLbdNBNjjaVz6HP/ANeuOljCucCuWrR5qnNfse5gayjh4xS1Sf5sE1W7jTYj/KOmeT+pqr57s7SMd0jclj1qUxrj0FNCKF6DmqUH32NW0tUtXuS2srNMkij97CVeMj1Rgw/lXriNuRW9QD+fNeZ6HZCe6RUXlmC59ief0r00AAADoOK2irI8rHSTml2TP//R7PVbEXto0YGXX5k+vp+NedarF5EhBGDnp0r1E5xx1rmNb8KXeqT+ctxFGT1yjcn1+VhUyV9tzrwmIVNtT+Hf5nCs+eneotx3Y/Supb4f6pxtuoGx6hx/U1JbeAL1ZVknuYSoOSoVzn8S1Qoz8vvO2WOoW05vuNTwhpflWy3sg5cfu/x6t/hXS1m2elz25XNyxC4+UdMDtzWlWtrHlVZuc3J9T//Z'
pdf.setFontSize(40)
pdf.text(35, 25, 'Some Sample Text')
pdf.addImage(imgData, 'JPEG', 15, 40, 180, 160)
fs.writeFileSync('my_image_pdf_test.pdf', pdf.output());
The pdf file is larger when the image is added (97806 bytes).
Without the image it is just 2448 bytes.
What can be wrong? Any node packages missing?
It seems that when you write pdf files with images in nodejs, you have to use pdf.output('arraybuffer')
So replace the following line:
fs.writeFileSync('my_image_pdf_test.pdf', pdf.output());
with:
fs.appendFileSync('another_image_pdf_test.pdf', new Buffer.from(pdf.output('arraybuffer')));

Send a function, module to main via object Function node.js

I work on a server in node.js, and i'm quite new to the concept.
I'm using socket.io to communicate with clients
I have many modules in my server and i try to send a function declared in a module to my main. I don't want to use exports.plugin=plugin because I try to work with the observer pattern.
I tried :
In main.js:
//Modules NPM
var express = require('express');
var observer = require('node-observer');
//Extensions JS
var mymodule = require('./mymodule');
var plugin = require('./plugin');
//Initialisation
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
...
socket.on('message', function (var1, var2) { //Come from client
socket.var1=var1;
socket.var2=var2;
observer.send(this, "Message", "varSpecification");
});
In plugin.js :
//Modules NPM
var express = require('express');
var observer = require('node-observer');
//Extensions JS
var mymodule = require('./mymodule');
var main = require("./main");
...
observer.subscribe(this, "Message", function(who, data) {
var functionToSend= new Function ("varA", "varB" ,"mymodule.function(varA, varB); socket.emit('messageOK');"); //I can't create a real function because i don't use socket.io in the module Plugin
observer.send(this, "Response", functionToSend); });
Back to the main:
observer.subscribe(this, "Response", function(who, functionReceived) {
functionReceived(socket.var1, socket.var2); //Doesn't work
});
The problem is that when I execute the function in main.js, it doesn't find mymodule and can't execute the function associated.
(ReferenceError : mymodule is not defined)
When i execute the function directly in the main.js, it works.
observer.subscribe(this, "Response", function(who, functionReceived) {
mymodule.function(socket.var1, socket.var2); //Works
});
So I guess it's a problem with the object that I send
I will be more than grateful if you can help me!
EDIT : After other tests I found the source of the problem :
var mymodule = require('./mymodule');
...
mymodule.function(a, b); //works
var functionTest= new Function('mymodule.function(a, b)');
functionTest(); //Doesn't work (mymodule is not defined)
I still want to use the second option for my project but don't know how
I used the function constructor, and i didn't know that the function is declared in the global scope.
So i had to write this to make it work :
var functionTest= new Function('mymodule', 'a', 'b','mymodule.function(a, b)');
functionTest(mymodule,a,b);
I had to pass mymodule, a and b in parameter

exporting console.log from a module in node.js

I'm using a customized version of node-clim, but I want to put away all the customization code in a module of its own and require() it in my main app. But I can't seem to do that..
This code works
var util = require('util');
var clim = require('clim')
clim.logWrite = function(level, prefixes, msg) {
...
customizing code
...
process.stderr.write(...);
};
var console = clim();
console.log('hey'); // works
But in trying to put the above in a separate file clim.js and exporting the console object...
module.export = console;
and require()ing it in my main app doesn't work..
var console = require('./clim');
console.log('hey');
// ^ TypeError: Object #<Object> has no method 'log'
What am I doing wrong?
Change
module.export = console;
to
module.exports = console;

Synchronously load a dependency in node.js

I'm loading a node library in script and immediately after loading some customization that depends on that library:
var somelib = require('somelib');
// some customizations made to
// somelib's methods
require('./somelib.custom');
somelib.SomeObject = ...
^
ReferenceError: somelib is not defined
I keep getting an exception since the loading is done asynchronously and the second require happens before the first is namespaced correctly. What's a good way to resolve this? thanks.
EDIT: My original code
I'm trying to create a PNG image from json data using fabric.js node package (building on the article in package site). This is done by loading the server-side fabric canvas with JSON data that was originally generated on the client, then writing to a file stream:
var path = require('path');
var fs = require('fs');
var fabric = require('fabric').fabric;
require('./fabric.custom');
var canvas = fabric.createCanvasForNode(400, 400);
var outfile = fs.createWriteStream("image.png");
var filepath = "/path/to/file.json";
fs.readFile(filepath, 'utf8', function(err, json) {
canvas.loadFromJSON(json, function() {
var stream = canvas.createPNGStream();
stream.on('data', function(chunk) {
outfile.write(chunk);
});
});
});
The "fabric.custom" file holds several custom fabric canvas objects that override some fabric prototype defaults. They work well on the client, and are needed to properly render the canvas. It looks something like this:
fabric.TextBox = fabric.util.createClass(fabric.Text, {
type: 'text-box',
// more object specific stuff ...
});
Thanks.
Rather than relying on side effects in a require to mutate your fabric object, how about having the fabric.custom.js file export the modified fabric, like so?
fabric.custom.js:
var fabric = require('fabric').fabric;
fabric.myCustomMethod = function(){ ... }
...
module.exports = fabric; // the modified fabric
And in your main file:
var path = require('path');
var fs = require('fs');
// var fabric = require('fabric').fabric; No need for this line anymore
var modifiedFabric = require('./fabric.custom');
...
modifiedFabric.myCustomMethod( ... ); // should now be available

Resources