Search…
Renderer
Renderer Service.
1
const { Job } = require('renderer'),
2
job = new Job(apiKey)
Copied!
Renderer runs as a service, and will allow to convert HTML/CSS templates into PDF/CSV/HTML files, and put them into different kind of targets (FileObject, SFTP, or return as base64 result).
To enable Renderer for your environment, please contact support.

module Renderer

constructor(apiKey)

Creates an instance of renderer.
Arguments
  • apiKey { String } Api key of an existing app.
Returns
  • { renderer.Job } A new render Job instance.

addObject(name, data)

Adds a single object array or plain javascript object. An object can be referenced by a template directly.
Arguments
  • name { String } Top-level template data object key.
  • data { Object|Array } Data to be referenced in the template.
Returns
{ renderer.Job } this.
1
const { Job } = require('renderer'),
2
job = new Job(apiKey)
3
4
return job
5
.addObject('values', [{val: 'one'}, {val: 'two'}])
6
.addTemplate('tpl', `
7
{{#each values}}
8
<h1>{{val}}</h1>
9
{{/each}}
10
`)
11
.pipe()
Copied!

addCursor(name, cursor)

Adds a QueryCursor or AggregationCursor. JWT tokens will be created from the current principal and cursor options.
Arguments
  • name { String } The input name for use in referencing the data in templates.
  • cursor { QueryCursor|AggregationCursor } The cursor (e.g. org.objects.c_studies.find().paths('c_name))
Returns
{ renderer.Job } this.

addApiRequest(name, path, environment, credentials, options, [requestOptions={}])

Adds a request object that will be used from render, it could be a custom route or any other api request. the result can be used into the templates.
Arguments
  • name { String } Is used to reference this data into the templates.
  • path { String } Path to request. e.g. /c_patients/234523423423
  • environment { Object } Environment object.
    • endpoint: { String } Environment url to use e.g. https://api.dev.medable.com.
    • env: { String } Environment name. This is the org code. e.g. dev
  • credentials { Object } Credentials object.
    • type { String } Token/Signature types are allowed.
    • token { String } Token data. If type is set to token
    • signature { String } Signature data. If type is set to signature
    • apiKey { String } If not set, default job apiKey will be used.
  • options { Object } Request options, like method, body, query, etc can be described here.
  • requestOptions { Object } Extra options like json, strictSSL can be described here.
Returns
{ renderer.Job } this.

addTemplate(name, [content, partial=false])

Adds a HTML/CSS template already saved or can define a inline template. If you set the content argument, it will behave as inline template.
Arguments
  • name { String } Defines name, this can be used into the templates.
  • content { String } Inline content, here you can reference objects/requests etc.
  • partial { Boolean } Defines if the template behave as partial template, partials can be included/extended from other templates.
Returns
{ renderer.Job } this.

addOutput(name, type, templates)

Defines the output format of the entire process, you can use pdf/csv or html.
Arguments
  • name { String } Defines name, this can be used into the templates.
  • type { String } Defines the output format type (pdf,csv,html).
  • templates { String[] } Defines the templates to be used in the output, them will be processed sequentially.
Returns
{ renderer.Job } this.

addSftpTarget(outputs, credentials)

Specify a SFTP target where to put the resultant file.
Arguments
  • outputs { Object } Defines a key/value object where key is the name of an output and the value is the filename representing that output into the sftp remote location.
  • credentials { Object } Defines the credentials to connect the remote sftp server.
    • username { String } SFTP username.
    • password { String } SFTP password.
    • host { String } SFTP host. e.g. 100.1.23.41 or domain name sftp.my_host.com.
  • options { Object } Defines options for the target.
    • compress: { Object } Defines the compression options for target.
      • filename: { String } filename specifying remote location e.g. /documents/my_document.zip
      • outputs: { String[] } Defines the outputs to include in bundle.
Returns
{ renderer.Job } this.

addFileTarget(path, options)

Specify a File Object target where to put the resultant file.
Arguments
  • path { String } Path to access the FileProperty used to put the resultant file. e.g. path/to/234523423423/file.
  • data { Object } Specify the facets where to put the file, where key is the facet name and value is the output format type defined. e.g. { facets: { content: 'my_pdf' } }.
  • options { Object } Defines options for the target.
    • compress: { Object } Defines the compression options for target.
      • facet: { String } name of the facet that will contain the compressed bundle.
      • outputs: { String[] } Defines the outputs to include in bundle.
Returns
{ renderer.Job } this.

addCallback(name, path, environment, credentials, options, [requestOptions={}])

This is similar to addApiRequest but will be used when the process ends successfully or with error.
Returns
{ renderer.Job } this.

start()

This initiate the rendering process.
Returns
  • { Object } A result object.
    • object { String } Type of result.
    • data { Object } Data result object.
      • jobId { String } UUID representing the current job.
      • status { String } Job status text.
1
{
2
"object": "result",
3
"data": {
4
"jobId": "d8c1f89b-b0e2-4453-8235-dbf9a4dd889c",
5
"status": "Process Initiated"
6
}
7
}
Copied!
If you do not define a target, the response will contain the output process into base64 encoding
If you don't define a target, and the process take too long, you can get a timeout issue.
1
{
2
"object": "result",
3
"data": {
4
"my_output": "CiAgICAgICAgICAgIDxoMT5UYW5uZXIgSGVhdGhjb3RlPC9oMT4KICAgICAgICAgICAgPHNwYW4+PT09PT09PT09PT09PT09PT09PC9zcGFuPgogICAgICAgICAgICA8dWw+CiAgICAgICAgICAgICAgICA8bGk+RW1haWw6IE1hcmllLldpbGtpbnNvbkBnbWFpbC5jb208L2xpPgogICAgICAgICAgICAgICAgPGxpPlBob25lOiAxLTUzMS02NjctMTI4NTwvbGk+CiAgICAgICAgICAgICAgICA8bGk+Q29tcGFueTogUmV5bm9sZHMsIENoYW1wbGluIGFuZCBLZXJ0em1hbm48L2xpPgogICAgICAgICAgICA8L3VsPgogICAgICAgICAgICAKICAgICAgICAgICAgPGgxPkNvbGJ5IE8mI3gyNztDb25uZWxsPC9oMT4KICAgICAgICAgICAgPHNwYW4+PT09PT09PT09PT09PT09PT09PC9zcGFuPgogICAgICAgICAgICA8dWw+CiAgICAgICAgICAgICAgICA8bGk+RW1haWw6IFJheW11bmRvODlAZ21haWwuY29tPC9saT4KICAgICAgICAgICAgICAgIDxsaT5QaG9uZTogMS0wMTUtNzQyLTk5Nzk8L2xpPgogICAgICAgICAgICAgICAgPGxpPkNvbXBhbnk6IFpib25jYWssIFNtaXRoIGFuZCBXaXNva3k8L2xpPgogICAgICAgICAgICA8L3VsPgogICAgICAgICAgICAKICAgICAgICAgICAgPGgxPkphbnkgQm95bGUgRERTPC9oMT4KICAgICAgICAgICAgPHNwYW4+PT09PT09PT09PT09PT09PT09PC9zcGFuPgogICAgICAgICAgICA8dWw+CiAgICAgICAgICAgICAgICA8bGk+RW1haWw6IEthcmluYV9PQ29ubmVsbEBob3RtYWlsLmNvbTwvbGk+CiAgICAgICAgICAgICAgICA8bGk+UGhvbmU6ICg4MjIpIDc3My00NzUwIHg2NDY2OTwvbGk+CiAgICAgICAgICAgICAgICA8bGk+Q29tcGFueTogU2NodWxpc3QgLSBMdWVpbHdpdHo8L2xpPgogICAgICAgICAgICA8L3VsPgogICAgICAgICAgICAKICAgICAgICAgICAgPGgxPk1pc3MgRmVybmFuZG8gQ3VtbWVyYXRhPC9oMT4KICAgICAgICAgICAgPHNwYW4+PT09PT09PT09PT09PT09PT09PC9zcGFuPgogICAgICAgICAgICA8dWw+CiAgICAgICAgICAgICAgICA8bGk+RW1haWw6IEpvc3VlX1N3YW5pYXdza2lAeWFob28uY29tPC9saT4KICAgICAgICAgICAgICAgIDxsaT5QaG9uZTogKDM1NykgMjE1LTU3ODkgeDgzMzQwPC9saT4KICAgICAgICAgICAgICAgIDxsaT5Db21wYW55OiBLZW1tZXIgLSBXYXRlcnM8L2xpPgogICAgICAgICAgICA8L3VsPgogICAgICAgICAgICAKICAgICAgICAgICAgPGgxPklsYSBTY2hvZW48L2gxPgogICAgICAgICAgICA8c3Bhbj49PT09PT09PT09PT09PT09PT08L3NwYW4+CiAgICAgICAgICAgIDx1bD4KICAgICAgICAgICAgICAgIDxsaT5FbWFpbDogQmVsbDMwQGdtYWlsLmNvbTwvbGk+CiAgICAgICAgICAgICAgICA8bGk+UGhvbmU6ICgzOTUpIDA0OC0wNzk3PC9saT4KICAgICAgICAgICAgICAgIDxsaT5Db21wYW55OiBKYWNvYnMgSW5jPC9saT4KICAgICAgICAgICAgPC91bD4KICAgICAgICAgICAgCiAgICAgICAg"
5
}
6
}
Copied!

status(jobId)

This will return the status of an already inititated process
Returns
  • { Object } A result object.
    • object { String } Type of result.
    • data { Object } Data result object.
      • [cluster_name].jobId { String } UUID representing the current job.
      • [cluster_name].status { String } Job status text.
1
{
2
"object": "result",
3
"data": {
4
"cortex-renderer-management-service.default.svc.cluster.local": {
5
"id": "d8c1f89b-b0e2-4453-8235-dbf9a4dd889c",
6
"status": "Processing"
7
}
8
}
9
}
Copied!

cancel(jobId)

This will cancel an already initiated process
Returns
  • { Object } A result object.
    • object { String } Yype of result.
    • data { Object } Data result object.
      • [cluster_name].result { String } Text containing uuid of job cancelled
1
{
2
"object": "result",
3
"data": {
4
"cortex-renderer-management-service.default.svc.cluster.local": {
5
"result": "Job d8c1f89b-b0e2-4453-8235-dbf9a4dd889c cancelled",
6
}
7
}
8
}
Copied!

Examples

Example using a sftp target.
1
import { Job } from 'renderer'
2
const pdfJob = new Job('EeZ3VQVIahV7JGIG3tOQEx')
3
4
return pdfJob
5
.addCursor(org.objects.myObject.find())
6
.addTemplate('my_aweosme_pdf_template')// this will look for that template into the already saved templates.
7
.addOutput('my_pdf', 'pdf', ['my_awesome_pdf_template']) // only non partials templates can go here.
8
.addSftpTarget({
9
my_pdf: '/my_pdf.pdf' //the key is the output name, and the value is the remote filename location.
10
}, {
11
username: 'user',
12
password: 'password',
13
host: 'the.host.com'
14
}).start()
Copied!
Example using a file target.
1
import { Job } from 'renderer'
2
const pdfJob = new Job('EeZ3VQVIahV7JGIG3tOQEx')
3
4
return pdfJob
5
.addCursor('patients', org.objects.myObject.find())
6
.addTemplate('my_aweosme_pdf_template') // this will look for that template into the already saved templates.
7
.addOutput('my_pdf', 'pdf', ['my_awesome_pdf_template']) // only non partials templates can go here.
8
.addFileTarget('/path/to/234523423423/file', {
9
facets: {
10
content: "my_pdf" //content is the name of the facet in where the output will be stored with the content-type defined on that facet.
11
}
12
}).start()
Copied!
Example with multiple outputs.
1
import { Job } from 'renderer'
2
const pdfJob = new Job('EeZ3VQVIahV7JGIG3tOQEx')
3
4
return pdfJob
5
.addCursor('patients', org.objects.myObject.find())
6
.addTemplate('my_aweosme_pdf_template') // this will look for that template into the already saved templates.
7
.addOutput('my_pdf', 'pdf', ['my_awesome_pdf_template']) // only non partials templates can go here.
8
.addOutput('my_html', 'html', ['my_awesome_pdf_template']) // only non partials templates can go here.
9
.addFileTarget('/path/to/234523423423/file', {
10
facets: {
11
content: "my_pdf" //content is the name of the facet in where the output will be stored with the content-type defined on that facet.
12
html: "my_html"
13
}
14
}).start()
Copied!
Example with multiple templates into single output.
1
import { Job } from 'renderer'
2
const pdfJob = new Job('EeZ3VQVIahV7JGIG3tOQEx')
3
4
return pdfJob
5
.addCursor('patients', org.objects.myObject.find())
6
.addTemplate('my_aweosme_pdf_template') // this will look for that template into the already saved templates.
7
.addTemplate('my_other_template', `
8
<div class="my_patients">
9
{{#each (cursor patients)}}
10
<div>
11
<h1>{{c_name}}</h1>
12
<p>{{c_additional_information}}</p>
13
</div>
14
{{/each}}
15
</div>`) // this will use the content of the template even if this exists
16
.addOutput('my_pdf', 'pdf', ['my_awesome_pdf_template', 'my_other_template']) // this process will append second template at the end of first one
17
.addFileTarget('/path/to/234523423423/file', {
18
facets: {
19
content: "my_pdf" //content is the name of the facet in where the output will be stored with the content-type defined on that facet.
20
}
21
}).start()
Copied!
Example with multiple templates into multiple outputs/targets.
1
import { Job } from 'renderer'
2
const pdfJob = new Job('EeZ3VQVIahV7JGIG3tOQEx')
3
4
return pdfJob
5
.addCursor('patients', org.objects.myObject.find())
6
.addTemplate('my_aweosme_pdf_template') // this will look for that template into the already saved templates.
7
.addTemplate('my_other_template', `
8
<div class="my_patients">
9
{{#each (cursor patients)}}
10
<div>
11
<h1>{{c_name}}</h1>
12
<p>{{c_additional_information}}</p>
13
</div>
14
{{/each}}
15
</div>`) // this will use the content of the template even if this exists
16
.addOutput('my_pdf', 'pdf', ['my_awesome_pdf_template'])
17
.addOutput('my_html', 'html', ['my_other_template'])
18
.addFileTarget('/path/to/234523423423/file', {
19
facets: {
20
content: "my_pdf" //content is the name of the facet in where the output will be stored with the content-type defined on that facet.
21
}
22
})
23
.addSftpTarget({
24
my_html: '/my_patients.html' // my_html is the name of the output, it should match the outputs added.
25
}, {
26
username: 'user',
27
password: 'password',
28
host: 'the.host.com'
29
}).start()
Copied!

Template Helpers.

List of helpers you can use into the template
  • extend: Allows to extend a partial template.
  • block: Defines a content block that can be used with append, replace and prepend.
  • replace: Replaces the content of a block.
  • append: Append content into a block.
  • prepend: Prepend content into a block.
  • each
  • if
  • with
  • unless
  • cursor: Allows to resolve a stream/cursor/request returned from cortex api.
  • log
  • lookup

Examples

How to use helpers in templates.
Iterate through results of a cursor data, cursor helper can receive a CursorOperation, Array or Stream.
If you are using cursor inside another helper, you must call it using parenthesis e.g. (cursor parameter) in order to resolve this first before iterate.
1
<div class="my_patients">
2
{{#each (cursor patients)}}
3
<div>
4
<h1>{{c_name}}</h1>
5
<p>{{c_additional_information}}</p>
6
</div>
7
{{/each}}
8
</div>
Copied!
Compiled template.
1
<div class="my_patients">
2
<div>
3
<h1>Patient 1</h1>
4
<p>Age: 36, Height: 180</p>
5
</div>
6
<div>
7
<h1>Patient 2</h1>
8
<p>Age: 36, Height: 175</p>
9
</div>
10
<div>
11
<h1>Patient 3</h1>
12
<p>Age: 28, Height: 178</p>
13
</div>
14
</div>
Copied!
Extending templates.
Let's define a template as master template (layout as name).
1
<div id="master">
2
<div class="header>
3
{{#block "header"}}
4
<h1>This is the header</div>
5
{{/block}}
6
</div>
7
<div class="content>
8
{{#block "content"}}{{/block}}
9
</div>
10
<div class="footer>
11
{{#block "footer"}}
12
<p>This should be last</p>
13
{{/block}}
14
</div>
15
</div>
Copied!
Now let\'s create a template that will extend the master template.
1
{{#extend "layout"}}
2
{{#append "header"}}
3
<p>This content will be appended to the header</p>
4
{{/append}}
5
{{#replace "content"}} //All the conent in the block "content" will be replaced
6
{{#each (cursor patients)}}
7
<div>
8
<h1>{{c_name}}</h1>
9
<p>{{c_additional_information}}</p>
10
</div>
11
{{/each}}
12
{{/replace}}
13
{{#prepend "footer"}}
14
<p>This line goes before the sentence</p>
15
{{/prepend}}
16
{{/extend}}
Copied!
Compiled template.
1
<div id="master">
2
<div class="header">
3
<h1>This is the header</div>
4
<p>This content will be appended to the header</p>
5
</div>
6
<div class="content">
7
<div>
8
<h1>James</h1>
9
<p>Age: 36, Height: 180</p>
10
</div>
11
<div>
12
<h1>Gaston</h1>
13
<p>Age: 36, Height: 175</p>
14
</div>
15
<div>
16
<h1>Joaquin</h1>
17
<p>Age: 28, Height: 178</p>
18
</div>
19
</div>
20
<div class="footer">
21
<p>This line goes before the sentence</p>
22
<p>This should be last</p>
23
</div>
24
</div>
Copied!
Last modified 2mo ago