Security News
New Python Packaging Proposal Aims to Solve Phantom Dependency Problem with SBOMs
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.
@jsreport/jsreport-core
Advanced tools
The minimalist jsreport rendering core. The full distribution can be found in the jsreport package.
jsreport is a platform providing dynamic documents assembling and printing. It supports various document types or printing techniques.
@jsreport/jsreport-core
contains the jsreport rendering core that is useless alone. It is up to you which jsreport extensions you combine
To generate a document using jsreport, you always need a javascript templating engine. The engine is used to dynamically assemble the document based on the input values. For start lets pick @jsreport/jsreport-handlebars engine and install it using npm.
Next to the engine, you need something we call recipe. A recipe represents the technique used to print the document. It can be an HTML to pdf conversion, DOCX rendering, and others. In this example lets pick @jsreport/jsreport-chrome-pdf. This recipe implements HTML to pdf conversion using chrome. So in this example, we use handlebars to assemble HTML based on the input data and then print the output into the final pdf.
npm install @jsreport/jsreport-core
npm install @jsreport/jsreport-handlebars
npm install puppeteer @jsreport/jsreport-chrome-pdf
const fs = require('fs').promises
const jsreport = require('@jsreport/jsreport-core')()
jsreport.use(require('@jsreport/jsreport-chrome-pdf')())
jsreport.use(require('@jsreport/jsreport-handlebars')())
await jsreport.init()
const result = await jsreport.render({
template: {
content: '<h1>Hello {{foo}}</h1>',
engine: 'handlebars',
recipe: 'chrome-pdf'
},
data: {
foo: "world"
}
})
await fs.writeFile('out.pdf', result.content)
render
is the main method that invokes report generation. A single parameter is an object representing describing what to render. It has the following structure:
{
//[required definition of the document]
template: {
//[required] templating engine used to assemble document
engine: "handlebars",
//[required] recipe used for printing previously assembled document
recipe: "chrome-pdf",
//[required] template for the engine
content: "<h1>{{foo}}</h1>",
//javascript helper functions used by templating engines
helpers: "function foo() { ...} " +
"function foo2() { ... }"
//any other settings used by recipes
...
},
//dynamic data inputs used by templating engines
data: { foo: "hello world"}
...
}
In case you have the template stored in the jsreport templates store, you can reference the template using a name or path.
{
template: {
name: '/myfolder/mytemplate'
},
data: { foo: "hello world"}
...
}
The render returns a promise with the single response value
{
//node.js buffer with the document
content: ...
//stream with the document
stream: ...
//object containing metadata about the report generation (reportName, logs, etc)..
meta: { ... }
}
The convention is that jsreport repository extension starts with jsreport-xxx
, but the extension real name and also the recipes or engines it registers excludes the jsreport-
prefix. This means if you install extension @jsreport/jsreport-handlebars
the engine's name you specify in the render should be handlebars
.
jsreport by default runs helpers in the sandbox where is the require
function blocked. To unblock particular modules or local scripts you need to configure sandbox.allowedModules
option.
const jsreport = require('@jsreport/jsreport-core')({
sandbox: { allowedModules: ['moment'] }
})
// or unblock everything
const jsreport = require('@jsreport/jsreport-core')({
sandbox: { allowedModules: '*' }
})
Additionally, jsreport provides global variables which can be used to build the local script path and read it.
const jsreport = require('@jsreport/jsreport-core')({
sandbox: { allowedModules: '*' }
})
await jsreport.init()
await jsreport.render({
template: {
content: '<script>{{jquery}}</script>',
helpers: `
function jquery() {
const fs = require('fs')
const path = require('path')
return fs.readFileSync(path.join(__rootDirectory, 'jquery.js'))
}
`,
engine: 'handlebars',
recipe: 'chrome-pdf'
}
})
The following variables are available in the global scope:
__rootDirectory
- two directories up from jsreport-core__appDirectory
- directory of the script which is used when starting node__parentModuleDirectory
- directory of script which was initializing jsreport-coreYou need to install additional packages (extensions) even for the simplest pdf printing. This is the philosophy of jsreport, and you will need to install additional extensions very often. There are many extensions adding support for persisting templates, dynamic script evaluation, adding browser based reports studio or exposing API. To get the idea of the whole platform you can install the full jsreport distribution and pick what you like. Then you can go back to jsreport-core
and install extensions you need.
You are also welcome to write your own extension or even publish it to the community. See the following articles how to get started.
The best place to find availible extensions is in the jsreport documentation or you can search in this monorepo's packages - every package with jsreport-
prefix is an extension.
jsreport by default auto-discovers extensions in the application's directory tree. This means, there is no need to explicitely require
and call jsreport.use
for all extensions you want to use. However it is prefered for the clarity.
jsreport accepts options as the first parameter. The core options are the following:
require('@jsreport/jsreport-core')({
// optionally specifies where's the application root and where jsreport searches for extensions
rootDirectory: path.join(__dirname, '../../'),
// optionally specifies where the application stores temporary files used by the conversion pipeline
tempDirectory: path.join(dataDirectory, 'temp'),
// options for logging
logger: {
silent: false // when true, it will silence all transports defined in logger
},
// options for templating engines and other scripts execution
// see the https://github.com/pofider/node-script-manager for more information
sandbox: {
cache: {
max: 100, //LRU cache with max 100 entries, see npm lru-cache for other options
enabled: true //disable cache
}
},
loadConfig: false,
// the temporary files used to render reports are cleaned up by default
autoTempCleanup: true,
// set to false when you want to always force crawling node_modules when searching for extensions and starting jsreport
useExtensionsLocationCache: true
})
jsreport-core
is also able to load configuration from other sources including configuration file, environment variables and command line parameters. This can be opted in through option loadConfig:true
. If this option is set to true the configuration is merged from the following sources in the particular order:
configFile
environment variablerequire('@jsreport/jsreport-core')({})
Each extension (recipe, store...) usually provides some options you can apply and adapt its behavior. These options can be typically set through standard configuration under the top-level extensions
property, options in there with the name corresponding to the extension's name are forwarded to the particular extension. This is the common way how to globally configure all extensions at one place.
require('@jsreport/jsreport-core')({
...
"extensions": {
"scripts": {
"allowedModules": ["url"]
}
}
})
You can find configuration notes for the full jsreport distribution here.
jsreport leverages winston logging abstraction together with debug utility. To output logs in the console just simply set the DEBUG
environment variable
DEBUG=jsreport node app.js
on windows do
set DEBUG=jsreport & node app.js
To declarative configure logging levels and outputs you can see this page which contains all the details for that.
jsreport also exposes logger
property which can be used to adapt the logging as you like. You can for example just add winston console transport and filter in only important log messages into console.
const winston = require('winston')
const jsreport = require('@jsreport/jsreport-core')()
jsreport.logger.add(winston.transports.Console, { level: 'info' })
jsreport types are in the DefinitelyTyped repository. You can install @types/jsreport-core and invidual types for extensions, or get all types at once from @types/jsreport.
You can also find jsreport typescript examples here.
jsreport extensions are mainly using the system of event listeners to adapt the rendering process. Extensions, can for example listen to event, which is called before the rendering process starts and adapt the input values.
//jsreport must be initialized at this time
jsreport.beforeRenderListeners.add('name-of-listener', (req, res) => {
req.template.content = 'Changing the template in listener!'
})
To start the listening, you must first add the listener function to the right listener. In the example is used beforeRenderListeners
which is called before the rendering starts. jsreport then in the right time sequentially fires all the listener functions and let them do the required work. If the function returns a promise, jsreport awaits until it is fulfilled.
Note this technique can be used in extensions, but also outside in nodejs application using jsreport.
jsreport currently support these main listeners
initializeListeners()
- called when all extensions are initializedbeforeRenderListeners(req, res)
- very first in the rendering pipeline, used to load templates and parse input datavalidateRenderListeners(req, res)
- possible to reject rendering before it starts, jsut return failed promise or exceptionafterTemplatingEnginesExecutedListeners(req, res)
- engine like handlebars or jsrender extracted the content, the res.content
contains Buffer with extracted contentafterRenderListeners(req, res)
- recipes are executed, res.content
contains final buffer which will be returned as a stream back, the last change to modify the output or send it elsewhererenderErrorListeners(req, res, err)
- fired when there is error somewhere in the rendering pipelinecloseListeners()
called when jsreport is about to be closed, you will usually put here some code that clean up some resourcejsreport includes also visual html studio and rest API. This is provided through two extensions, @jsreport/jsreport-express extension to have a web server available and @jsreport/jsreport-studio for the web UI, both extensions should be installed in order to have the studio ready. See the documentation of each extension for the details.
jsreport-core
includes API for persisting and accessing report templates. This API is then used by extensions mainly in combination with jsreport studio. jsreport-core
implements just in-memory persistence, but you can add other persistence methods through extensions, see the template stores docummentation
The persistence API is almost compatible to the mongodb API:
jsreport.documentStore.collection('templates')
.find({name: 'test'})
.then((res) => {})
jsreport.documentStore.collection('templates')
.update({name: 'test'}, { $set: { attr: 'value' })
.then((res) => {})
jsreport.documentStore.collection('templates')
.insert({name: 'test'})
.then((res) => {})
jsreport.documentStore.collection('templates')
.remove({name: 'test'})
.then((res) => {})
18.15.0
migrateXlsxTemplatesToAssets
, migrateResourcesToAssets
sandbox.isolateModules: false
options.onReqReady
to be able to receive the parsed req valuesreq.options
on reporter main code when enableRequestReportTimeout
is enabledmainReporter.executeWorkerAction
now supports cancellation with AbortController.signal
collection.findAdmin
, collection.findOneAdmin
, reporter.adminRequest
to easily allow execure store queries without taking into account permissionstrustUserCode
is trueprofiler.maxDiffSize
applies to both req and resjsreport-proxy
for better working with async helpersvm2
to fix security vulnerability in sandboxxlsxTemplatesToAssets
, resourcesToAssets
to inherit permissions and change name for resource script to ${template.name}_resources
LGPL
FAQs
javascript based business reporting
The npm package @jsreport/jsreport-core receives a total of 1,468 weekly downloads. As such, @jsreport/jsreport-core popularity was classified as popular.
We found that @jsreport/jsreport-core demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PEP 770 proposes adding SBOM support to Python packages to improve transparency and catch hidden non-Python dependencies that security tools often miss.
Security News
Socket CEO Feross Aboukhadijeh discusses open source security challenges, including zero-day attacks and supply chain risks, on the Cyber Security Council podcast.
Security News
Research
Socket researchers uncover how threat actors weaponize Out-of-Band Application Security Testing (OAST) techniques across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data.