script - require in existing expressjs app. What am I doing wrong?



  • I have a project folder called adminserver. When I run the following in a report script

    const process = require('process');
    console.log('hello', process.cwd());
    

    it points to that folder, as I would expect. I want to include a file of my own which lives nested in the adminserver folder here: adminserver/src/controllers/inpatientReports.js but when I try this:

    const process = require('process');
    const inpatRept = require('src/controllers/inpatientReports');
    console.log('hello', process.cwd());
    console.log('facs', inpatRept.getFacilities());
    

    I get an error which says: Error: Error while executing user script. Unable to require module src/controllers/inpatientReports

    I have tried variations including /src and ./src at the beginning. What am I doing wrong. I'm sure this works in regular js files. Do I not import starting from cwd?



  • My bad. I wasn't doing it wrong. It was a problem with my file - or rather, jsreport didn't like my file.

    I'm still confused about a couple of things:

    1. Integration with an existing application doesn't seem to be completely integrated. If I require a file in a script that already exists in my project, it doesn't seem to be able to pull in the imports already on that file. As an example, my server application is a NodeJS application using Express. I think my confusion is in the adaptation code from here: https://jsreport.net/learn/adapting-jsreport
    const express = require('express');
    const app = express();
    
    app.get('/', (req, res) => {
      res.send('Hello from the main application');
    });
    
    const reportingApp = express();
    app.use('/reporting', reportingApp);
    
    const server = app.listen(3000);
    
    const jsreport = require('jsreport')({
      extensions: {
          express: { app: reportingApp, server: server },
      },
      appPath: "/reporting"
    });
    
    jsreport.init().then(() => {
      console.log('jsreport server started')
    }).catch((e) => {
      console.error(e);
    });
    

    I'm wondering if using two different instances of express keeps JSReport separated from my app. Why is jsreport given its own copy of express? Is it actually a separate application that just gets a ride on my app? Or does it actually have access to everything in my app? Can I just use one copy of express? What are the differences if I do?



    1. I wrote a script in jsreport that looks like this:
    const process = require('process');
    const test = require('src/controllers/test');
    console.log('hello', process.cwd());
    console.log('facs', test.crap() );
    test.crap();
    console.log('what', __appDirectory);
    

    where test contains:

    exports.crap = function () {
      console.log('this is a test');
    };
    

    why doesn't test.crap() output the line to the log when I use the Debug button? Instead, I get this:
    +0 Starting rendering request 1 (user: null)
    +5 Rendering template { name: Facilities2, recipe: html, engine: handlebars, preview: true }
    +9 Inline data specified.
    +11 Resources not defined for this template.
    +24 Executing script TestScript
    +2642 hello C:\Users\constar1\Documents\SutterNow\Express Projects\AdminServer
    +2646 facs undefined
    +2646 what C:\Users\constar1\Documents\SutterNow\Express Projects\AdminServer
    +2660 Base url not specified, skipping its injection.
    +2663 Rendering engine handlebars
    +3698 Compiled template not found in the cache, compiling
    +3724 Executing recipe html
    +3726 Skipping storing report.

    What am I missing?



  • BTW, if I can't get this stuff figured out quickly, I'll have to choose another solution. There just doesn't seem to be enough documentation on integrating with existing Express applications to make it easy to do.


  • administrators

    1.-
    I'm wondering if using two different instances of express keeps JSReport separated from my app. Why is jsreport given its own copy of express?

    simple, because it needs to configure its own set of middleware and in order to don't alter your main express application, it should be a normal express app that will live inside your app (in other words, when integrating with express, jsreport is an express app that lives as an a sub-app in your main express app)

    Is it actually a separate application that just gets a ride on my app?
    Or does it actually have access to everything in my app?

    it is a separate application, but it does not get ride of your app, it lives inside your app under a route that you specify. it is an standalone application so it does not care about your main app or has access to it, it already has its own set of middleware defined so you don't need to put something else for the route in which the jsreport app lives. that is why the example to integrate is so simple:

    const express = require('express');
    const app = express();
    
    app.get('/', (req, res) => {
      res.send('Hello from the main application');
    });
    
    const reportingApp = express();
    app.use('/reporting', reportingApp);
    
    const server = app.listen(3000);
    
    const jsreport = require('jsreport')({
      extensions: {
          express: { app: reportingApp, server: server },
      },
      appPath: "/reporting"
    });
    
    jsreport.init().then(() => {
      console.log('jsreport server started')
    }).catch((e) => {
      console.error(e);
    });
    

    as you can see there is no additional middleware defined for the jsreport app, i think you are having lot of problems because you are configuring cors, and other middlewares before the jsreport app, you can configure those for the routes of your app, but for the route that jsreport uses it is better to not do it because you will get a lot of conflicts.

    it is normal to define express apps in this way and it exists because it allows to distribute apps easily, but you have to careful about the middleware that runs.

    Can I just use one copy of express? What are the differences if I do?

    No, because as i have explained, the jsreport express app works standalone so it needs its own instance of express, which does not affect in anything to your code, having just one or multiple instance of express is common.

    1. I wrote a script in jsreport that looks like this:
      why doesn't test.crap() output the line to the log when I use the Debug button? Instead, I get this:

    i think your script should be more like this:

    const path = require('path')
    const process = require('process');
    const test = require(path.join(process.cwd(), 'src/controllers/test'));
    console.log('hello', process.cwd());
    console.log('facs', test.crap() );
    test.crap();
    console.log('what', __appDirectory);
    

    if it does not work, i would need more information. however the best will be that you share a simple project on github (it can be your project but without the parts that are not relevant, like business logic, etc) with that code that you are trying



  • Ah, I see. I think this: "it is an standalone application so it does not care about your main app or has access to it" is the main point I was hoping against. My application already has database connections and queries defined and also data models and other things I was hoping to leverage using jsreport. It appears I can't do that since it can't see my app. I definitely don't want to write report scripts where I have to copy all of that work again.

    Is there some other way I can reuse my existing work? If I run jsreport as a stand-alone server application, can I make calls to my server app's JSON API and get data that way? If so, can I use Axios to do so? My existing client app uses Axios and if I could use the same thing, that would be more consistent.


  • administrators

    Ah, I see. I think this: "it is an standalone application so it does not care about your main app or has access to it" is the main point I was hoping against.

    i say that just because the express code does not alter your code or express app, but you can still access any of your project files using the normal node.js require, so you can still share modules/business logic/database connectors between your jsreport script and the code in your app.

    I definitely don't want to write report scripts where I have to copy all of that work again.

    yes, you should be able to do this, that is the whole point of jsreport being javascript, that it can require your javascript files to create some reports.

    Is there some other way I can reuse my existing work? If I run jsreport as a stand-alone server application, can I make calls to my server app's JSON API and get data that way? If so, can I use Axios to do so?

    yes, you can do that too. inside your jsreport scripts you can require js files or modules, so you can easily require axios and communicate with any http endpoint you want, retrieve data and use it in any way you want. you should be able to do this also requiring your js files, but i don't understand how your project is setup, it probably has other problems, so if you want some help to understand this better as i say you can prepare a github project and i can take a look and show you how it can require js files in your project.



  • I finally figured this out. Thanks for the help. I ended up doing this:

    const fs = require('fs');
    const request = require('request');
    
    function beforeRender(req, res, done) {
        console.log('hello');
        request({
            url: "https://pharmacyinformatics.local:3000/v1/inpatient/facilitiesNA",
            method: "GET",
            json: true,
            strictSSL: false,
            headers: {
                'User-Agent': 'Super Agent/0.0.1',
                'content-type': 'application/json'
            },
        }, function(err, response, body) {
            //console.log('server encoded the data as: ' + (response.headers['content-encoding'] || 'identity'));
            console.log('the error is: ', err);
            //console.log('the response is: ', response);
            //console.log('the decoded data is: ', body);
            req.data = {
                "facilities": body
            };
            console.log('here', req.data);
            done();
        }).on('data', function(data) {
            // decompressed data as it is received
            console.log('decoded chunk: ' + data);
        }).on('response', function(response) {
            // unmodified http.IncomingMessage object
            response.on('data', function(data) {
                // compressed data as it is received
                console.log('received ' + data.length + ' bytes of compressed data');
            })
        })
    }
    

    Looks like I can move forward with a more robust test. If successful, my people will be in touch for acquiring a license.


Log in to reply
 

Looks like your connection to jsreport forum was lost, please wait while we try to reconnect.