UNPKG

nreports

Version:

Provides basic reporting framework for NodeJS.

177 lines (145 loc) 4.15 kB
var async = require('async'); var Pipeline = require('./pipelines/pipeline') /** * The reporting engine, responsible for tying everthing together and rendering the report. Generally * render will run throug the folling phases. * I. Execute datasource * II. Compile template(s) * III. Bind datasource output and render report using template(s) * @class ReportEngine * @uses Report defines the report name, parameters, datasource and template. * @uses ReportDatasource the report datasource to use for execution. */ function ReportEngine(){ this.runtime = null; this.pipelines = []; } /** * [setRuntime Set the runtime for report generation.] * @param {[Runtime]} runtime the runtime template engine for report generation (Jade, Handlebars, etc). */ ReportEngine.prototype.setRuntime = function(runtime){ this.runtime = runtime; return this; } /** * [addPipeline Add a processing pipline to the engine.] * @param {[type]} pipeline [description] */ ReportEngine.prototype.addPipeline = function(pipeline) { this.pipelines.push(pipeline); return this; } /** * Render the report inline and return the response thru a callback. * @async * @method render * @param {Report} report * @param {ReportDatasource} datasource * @param {Function} callback(err, html) */ ReportEngine.prototype.render = function(report, datasource, callback){ var self = this; // juggle parameters if (typeof datasource == 'function') { callback = datasource; datasource = report.getDatasource(); } async.parallel({ data: function(cb) { console.log('Downloading datasource...'); // execute data source datasource.execute(function(e, data){ if (e) { console.error(e); cb(e); } cb(null, data); }); }, engine: function(cb){ console.log('Compiling templates...'); // compile template var runtime = self.compile(report); if (typeof runtime == 'Error') cb(runtime); else cb(null, runtime); } }, function(err, results){ // execute the report if (err) { console.error(err); callback(err); } console.log('Executing report...'); console.log(results); var locals = results.data; locals.parameters = report.parameters; console.log('with locals ->'); console.log(locals); var html = results.engine(locals); console.log('*** ENGINE OUTPUT ***'); console.log(html.length + ' BYTES'); if (self.pipelines.length > 0) { console.log('*** POST TEMPLATE PIPELINE PROCESSING ***'); Pipeline.execute(self.pipelines.slice(0), html, function(err, result){ if (err) { console.error(err); callback(err); } else { console.log('*** PIPELINE PROCESSING OUTPUT ***'); console.log(result); callback(null, result); } }) } else { callback(null, html); } }); }; /** * Render the report to the file system. * @async * @method renderToFS * @param {Report} report * @param {ReportDatasource} datasource * @param {String} destination the full location and filename to use when writing the report * @param {Function} callback(err, html) */ ReportEngine.prototype.renderToFS = function(report, datasource, destination, callback) { var self = this; var fs = require('fs'); self.render(report, datasource, function(err, html){ if (err) { console.error(err); callback(err); } fs.writeFile(destination, html, function(e){ if (e) { console.error(e); callback(e); } callback(null); }); }); }; /** * Compile the reporting templates * @method compile * @param {Report} report * @return {Function} the Handlebars execution pipeline */ ReportEngine.prototype.compile = function(report) { if (!this.runtime){ throw new Error('Please set the runtime before calling compile.'); } else { // for now it is a simple impl, when we add header, footer and detail templates it will be more complex return this.runtime.compile(report.template); } }; module.exports = ReportEngine;