Emitter is not a constructor meteor 1.3 and npm

Dear Programmers,
I have a problem with npm modules in meteor 1.3
I work on old project remembering 1.0 times. Now it’s a hybrid running blaze and react on meteor 1.3.

When I try to run ‘dhl’ npm I get an error:
Exception from Tracker recompute function:
debug.js:41 TypeError: Emitter is not a constructor
at meteorInstall.node_modules.stream.index.js (index.js:27)
at fileEvaluate (install.js:153)
at require (install.js:82)
at meteorInstall.node_modules.meteor-node-stubs.node_modules.http-browserify.lib.request.js (request.js:1)
at fileEvaluate (install.js:153)
at require (install.js:82)
at meteorInstall.node_modules.meteor-node-stubs.node_modules.http-browserify.index.js (index.js:3)
at fileEvaluate (install.js:153)
at require (install.js:82)
at meteorInstall.node_modules.dhl.node_modules.request.main.js (main.js:15)

My npm modules:
“dependencies”: {
“d3”: “^3.5.16”,
“dhl”: “^1.2.0”,
“emitter”: “0.0.5”,
“jquery”: “^2.2.3”,
“meteor-node-stubs”: “^0.2.3”,
“moment”: “^2.13.0”,
“moment-range”: “^2.2.0”,
“react”: “^15.0.2”,
“react-bootstrap”: “^0.29.3”,
“react-bootstrap-select”: “^0.14.0”,
“react-date-picker”: “^4.0.10”,
“react-datepicker”: “^0.27.0”,
“react-dom”: “^15.0.2”,
“react-dropzone”: “^3.4.0”,
“react-input-calendar”: “^0.3.6”,
“react-komposer”: “^1.8.0”,
“react-select”: “^1.0.0-beta13”,
“stream”: “0.0.2”,
“switchery”: “0.0.2”,
“underscore”: “^1.8.3”

my packages:

meteor-base
mongo
blaze-html-templates
session
tracker
logging
reload
random
ejson
spacebars
check
ecmascript
underscore

mdg:validated-method

less

twbs:bootstrap
fortawesome:fontawesome
jquery
accounts-password
ian:accounts-ui-bootstrap-3
aldeed:simple-schema
aldeed:collection2
pcel:accounting
momentjs:moment
lbee:moment-helpers
alanning:roles
reywood:publish-composite
jagi:astronomy
jagi:astronomy-validators
jagi:astronomy-timestamp-behavior
jagi:reactive-map
manuel:viewmodel
alethes:lodash
raix:ui-dropped-event
dbarrett:dropzonejs
kadira:flow-router
kadira:blaze-layout
arillo:flow-router-helpers
zimme:active-route
percolate:momentum
cfs:standard-packages
cfs:gridfs
cfs:s3
cfs:filesystem
cfs:graphicsmagick
cfs:ui
tmeasday:publish-counts
miguelalarcos:flow-router-pagination
meteorhacks:npm
meteorhacks:async
http
gquemart:meteor-reactive-fullcalendar
meteortoys:allthings
tap:i18n
tap:i18n-ui
email
standard-minifier-css
standard-minifier-js
react-template-helper
themeteorchef:bert
nilsdannemann:pdfmake

I have to admin that I tried to run the nilsdannemann:pdfmake as npm module but got the same error like now I’m asking you. Using the module way solved the problem…but now I’m experiencing it once again…

I also receive the error index.js:27 Uncaught TypeError: Emitter is not a constructor in the client, after trying to add pdfmake from npm.

meteor run works though (without error), but the iron:router crashes in the browser and the console shows the above error.

Iron router browser error:

Router.route('/', function () {
  this.render('Home', {
    data: function () { return Items.findOne({_id: this.params._id}); }
  });
});

Steps to add the pdfmake

meteor npm install --save pdfmake
(and adding missing packages below, as suggested by meteor)
meteor npm install --save stream
meteor npm install --save events
meteor npm install --save emitter index.js meteor-node-stubs

installed packages:

meteor list
accounts-password       1.3.0  Password support for accounts
blaze-html-templates    1.0.4* Compile HTML templates into reactive UI with Meteor Blaze
ecmascript              0.5.8  Compiler plugin that supports ES2015+ in all .js files
es5-shim                4.6.14  Shims and polyfills to improve ECMAScript 5 support
http                    1.2.9  Make HTTP calls to remote servers
iron:router             1.0.13  Routing specifically designed for Meteor
jquery                  1.11.9  Manipulate the DOM using CSS selectors
meteor-base             1.0.4  Packages that every Meteor app needs
mobile-experience       1.0.4  Packages for a great mobile user experience
mongo                   1.1.12  Adaptor for using MongoDB and Minimongo over DDP
reactive-var            1.0.10  Reactive variable
shell-server            0.2.1  Server-side component of the `meteor shell` command.
standard-minifier-css   1.2.0  Standard css minifier used with Meteor apps by default.
standard-minifier-js    1.2.0  Standard javascript minifiers used with Meteor apps by default.
tracker                 1.1.0  Dependency tracker to allow reactive callbacks
twbs:bootstrap          3.3.6  The most popular front-end framework for developing responsive, mobile first projects on the web.
useraccounts:bootstrap  1.14.2  Accounts Templates styled for Twitter Bootstrap.

meteor --version
Meteor 1.4.1.1

updated as of 2016/09/20

You know, I finaly did the pdf work on the server side and pushed pdf to the client side.
If you want I can give you code showing how to do it.

It would be great if you could share it, along with the packages/how you installed them (after adding the package and requirements itself my app is crashing now. lol)

Just for reference, if it be usefull to anyone else:

I was able to create a server route to download the pdf:

SAMPLE/DEBUG CODE (not for production use)

Router.map(function() {
  this.route('pdfReport', {
    where: 'server',
    path: '/report/pdf/',
    action: function() {

      pdfgen2();  

      var filename = '/tmp/pdftemp.pdf';

      var fs = Npm.require('fs');
      var data = fs.readFileSync(filename);

      var headers = {
        'Content-Type': 'application/pdf',
        'Content-Disposition': "attachment; filename=file.pdf"
      };

      this.response.writeHead(200, headers);
      return this.response.end(data);
    }
  })
});

And create the pdf on the server:

pdfgen2 = function () {


    var fonts = {
      SourceSansPro: {
        normal: process.cwd().split('.meteor')[0] + 'public/fonts/SourceSansPro-Regular.ttf',
        bold: process.cwd().split('.meteor')[0] + 'public/fonts/SourceSansPro-Bold.ttf',
        italics: process.cwd().split('.meteor')[0] + 'public/fonts/SourceSansPro-It.ttf',
        bolditalics: process.cwd().split('.meteor')[0] + 'public/fonts/SourceSansPro-BoldIt.ttf'
      }
    };

    console.log( process.cwd().split('.meteor')[0] + 'public/fonts/SourceSansPro-Regular.ttf' );

     var docDefinition = {
       content: [
         // if you don't need styles, you can use a simple string to define a paragraph
         'This is a standard paragraph, using default style',

         // using a { text: '...' } object lets you set styling properties
         { text: 'This paragraph will have a bigger font', fontSize: 15 },

         // if you set pass an array instead of a string, you'll be able
         // to style any fragment individually
         {
           text: [
             'This paragraph is defined as an array of elements to make it possible to ',
             { text: 'restyle part of it and make it bigger ', fontSize: 15 },
             'than the rest.'
           ]
         }
       ]
     };


    var PdfPrinter = require('pdfmake/src/printer');
    var printer = new PdfPrinter(fonts);

    var pdfDoc = printer.createPdfKitDocument(docDefinition);
    // console.log("pdfDoc", typeof(pdfDoc), pdfDoc);
    pdfDoc.pipe(fs.createWriteStream('/tmp/pdftemp2.pdf')).on('finish',function(){
        //success
    });

    pdfDoc.end();

    return "PDF Generation completed."
}
  • PDF download works fine.

  • Maybe it could be improved so pdf creation function pass the binary stream directly to the pdf download function (without using the server filesystem).

  • But the PDF creation function seems to work (it does create a PDF file, with apparently legit content), but the file is empty (as if it is corrupt).

Anyone knows what am I doing wrong with pdfmake/printer ?

Pdfmake documentation seems focused on “pdfMake” object, for client side. I’m not sure how properly use it for server side generation.

Best regards,

Mario

if I want to save:

pdfMake.createPdf(this.getDefinition()).getBuffer(function(cb){

        var fsFile = new FS.File();
        let arrayBuffer = cb.toArrayBuffer();

        fsFile.attachData(arrayBuffer, {type: 'application/pdf'});

        fsFile.userId = Meteor.userId();
        fsFile.type('application/pdf');
        fsFile.name(proformaName);

        var result = ProductAttachmentStore.insert(fsFile, function (err, fileObj) {
            if (err) {
                console.log(err);
                Bert.alert("smth", 'danger');
            }

If I want to show on website:

pdfMake.createPdf(this.getDefinition()).getDataUrl(function (outDoc) {
                //document.getElementById('iframePdf').src = outDoc;
                import PDFObject from 'pdfobject';
                const options1 = {
                    height: '100%',
                    width: '100%',
                    minHeight:'900px'
                };
                var options = {
                    width: "20rem",
                    height: "20rem",
                    minHeight: "900px"
                };
                PDFObject.embed(outDoc, "#iframePdf");
            });

the getDefinition is call to method that is generating the structure. It uses items stored in props/state and voila I have client side pdf rendering. I just had to move the data to client.

Oh and imports how I was able to run this idiotic thing: (package)

nilsdannemann:pdfmake

and how I made iframe publication easy: (npm)

"pdfobject": "^2.0.201604172",