@panosoft/chronicle
v0.10.3
Published
Create Reports with Web Technologies and run them in Node.
Downloads
29
Readme
Chronicle
Create Reports with Web Technologies and run them in Node.
Finally, a reporting engine for JavaScript!
Writing Reports is as easy as writing CommonJS modules (i.e. Node modules) and they can pull data from any source (APIs, SQL Servers, Code data generation, etc.).
The following Web Technologies are supported for use in Reports:
- HTML + Handlebars
- CSS + LESS
- JavaScript + Browserify + npm
Contents
Architecture
Reports are CommonJS modules (i.e. Node modules) that export a Report Function.
Report Functions accept runtime parameters, retrieve data, and generate HTML.
Chronicle bundle
can be used to bundle Reports. Bundling reduces a Report Module, and all of it's dependencies, into a single, portable, version locked file. As such, bundling makes transporting Reports across networks a trivial task.
Chronicle runs Reports. It accepts a variety of inputs: urls to Bundles, paths to Modules, or references to Report Functions. Running a Report loads the Report Function, evaluates it, and returns it's HTML output.
Finally, HTML renderers like PrinceXML that support CSS Paged Media can be used to generate PDFs complete with page headers, footers, numbers, etc.!
Philosophy
Unlike Crystal Reports, Jasper Reports, BIRT, SQL Server Reporting Services (SSRS), Pentaho, etc., Chronicle doesn't subscribe to the WYSIWYG approach to report development. This is reminiscent of using FrontPage to produce web pages.
With the WYSIWYG approach, most powerful features are hidden and buried under menu items, property sheets and require a half a dozen clicks to expose the correct radio button or check box. And many times, the powerful features just aren't there.
Anyone who has had to suffer through these poorly designed systems has quickly realized that reports are harder than they need to be and that one must contort oneself in order to accomplish what would be trivial in a programming language.
Another big problem with these traditional reporting systems, is that since it has a GUI, people assume that anyone can build a report. While it's true that anyone can, not everyone should.
Good reports transform data into useful information in a form that's easy to understand. This is not a trivial task that you can give the receptionist or the intern. This requires layout design, data processing and logic. These are all things that good developers are skilled at, particularly web developers.
Chronicle embraces these truths and caters to developers by using standard Web Technologies, viz. HTML/Handlebars, CSS/Less, Javascript, NodeJS, Browserify and PrinceXML to produce high quality PDF reports from any data source.
Usage
Reports can be run from the command line:
chronicle run report.js
Or using the Node api:
var co = require('co');
var chronicle = require('@panosoft/chronicle');
var prince = require('prince-promise');
co(function * () {
var html = yield chronicle.run('report.js');
var pdf = yield prince(html);
});
Examples
- Static Data Source Report (PDF)
- API Data Source Report (PDF)
- SQL Data Source Report (PDF)
- SQL Data Source, CSV Output Report (CSV)
- Static Chart Report (PDF)
- Dynamic Chart Report (PDF)
- Report Bundle Server
- Simple Reporting App
Installation
npm install -g @panosoft/chronicle
Report Structure
Reports can take the form of a simple Function or a Module that exports a Function.
They are run by Chronicle which returns static HTML content that can be visually rendered by a browser or any other third party HTML renderers.
Module
A report Module is simply a CommonJS module (i.e. Node module) that exports a report Function.
Report Modules can optionally be bundled using Chronicle bundle
so that all of their dependencies are contained within a single file.
Chronicle can then run
a Report using a url that references a bundled Module, a path to a local Module, or by simply passing the Function itself.
Example
var report = function (parameters) {
// ...
};
module.exports = report;
Function
The Report Function retrieves data and renders it as HTML.
This can be an ordinary or a yieldable function that accepts runtime parameters and returns static HTML.
Examples
Simplistic:
const report = function (parameters) {
const context = { date: parameters.date };
const html = `Created: ${{context.date}}`;
return html;
};
Realistic:
const co = require('co');
const Handlebars = require('handlebars');
const inlineHtml = require('inline-html');
const getContext = co.wrap(function * (parameters) {
// Fetch and process data
// return the template context.
return context;
};
const render = co.wrap(function * (context) {
// Define helpers
const helpers = {
// ...
};
// Define partials
const partials = {
// ...
};
// Load template source
const source = yield inlineHtml.file('path/to/template.html');
// Compile source and evaluate template
const template = Handlebars.compile(source);
const html = template(context, { helpers, partials });
return html;
});
const report = co.wrap(function * (parameters) {
const context = yield getContext(parameters);
const html = yield render(context);
return html;
});
CLI
chronicle
bundle [entry] [--output] [--watch]
Bundles a report Module along with all of its dependencies into a single file called a bundle.
Bundles are completely self contained and thus very portable. For instance, bundles could be stored on a static file server and requested remotely by Chronicle when run.
Since bundle
uses Browserify internally, all Browserify compatible Modules can be bundled. Browserify transforms can also be used simply by including them in the Modules package.json in the standard way.
Arguments
entry
- The main entry filename of a report Module to bundle. If an entry is not specified, thepackage.json
's'main
property will be used. If thepackage.json
doesn't exist or if themain
property is not specified, thenindex.js
will be used as the entry.-o, --output
- The filename for the bundled module. Defaults tobundle.js
.-w, --watch
- Enable watch mode. As files are modified, the bundle will be updated automatically and incrementally.
Examples
chronicle bundle -w
chronicle bundle entry.js -o output.js -w
run [report] [--parameters] [--output]
Runs a report and returns the output. If the output is an Array
or Object
, it is returned as a JSON string.
Arguments
report
- The report to run. Supported values are:-o, --output
- The destination for the report HTML to be written. Supported values are:- A filename - Write to the filesystem.
- No value - Write to
stdout
-p, --parameters
- A JSON parseable string of parameters to run the report with.
Examples
chronicle run index.js
chronicle run bundle.js -o report.html -p '{"sample": "parameter"}'
API
chronicle
bundle ( entry , options )
Bundles a report Module along with all of its dependencies into a single file called a bundle.
Since bundle
uses Browserify internally, all Browserify compatible Modules can be bundled. Browserify transforms can also be used simply by including them in the Modules package.json in the standard way.
Upon completion, the bundle is written directly to the filesystem per output
option.
Arguments
entry
- The main entry filename of a report Module to bundle. If an entry is not specified, thepackage.json
's'main
property will be used. If thepackage.json
doesn't exist or if themain
property is not specified, thenindex.js
will be used as the entry.options
Example
var entry = 'index.js';
var options = {
output: 'bundle.js'
};
chronicle.bundle(entry, options);
run ( report , parameters )
Runs a Report and returns a Promise
that is fulfilled with the HTML produced.
The Report is loaded, evaluated, and the HTML output is returned.
Arguments
report
- The Report to run. Supported values are:parameters
- An object of parameters used to run the report. This object is passed to the report Function at runtime.
Examples
var report = 'bundle.js';
var parameters = {};
press.run(report, parameters)
.then(function (html) {
// ...
});