├── .gitignore ├── LICENSE ├── README.md ├── createLambdaLayer.js ├── createLambdaPackage.js ├── data ├── fs.journal ├── fs.version ├── samples │ ├── Invoice │ │ ├── config.json │ │ ├── invoice-data │ │ │ ├── config.json │ │ │ └── dataJson.json │ │ ├── invoice-logo.png │ │ │ ├── config.json │ │ │ └── content.png │ │ ├── invoice-main │ │ │ ├── config.json │ │ │ ├── content.handlebars │ │ │ ├── footerTemplate.handlebars │ │ │ ├── headerTemplate.handlebars │ │ │ └── helpers.js │ │ └── invoice-styles.css │ │ │ ├── config.json │ │ │ └── content.css │ ├── Orders │ │ ├── config.json │ │ ├── orders-header │ │ │ ├── config.json │ │ │ ├── content.handlebars │ │ │ ├── footerTemplate.handlebars │ │ │ ├── headerTemplate.handlebars │ │ │ └── helpers.js │ │ ├── orders-main │ │ │ ├── config.json │ │ │ ├── content.handlebars │ │ │ ├── footerTemplate.handlebars │ │ │ ├── headerTemplate.handlebars │ │ │ └── helpers.js │ │ ├── orders-script │ │ │ ├── config.json │ │ │ └── content.js │ │ └── orders-styles.css │ │ │ ├── config.json │ │ │ └── content.css │ ├── Sales │ │ ├── config.json │ │ ├── sales-data │ │ │ ├── config.json │ │ │ └── dataJson.json │ │ ├── sales-main │ │ │ ├── config.json │ │ │ ├── content.handlebars │ │ │ └── helpers.js │ │ └── sales-styles.css │ │ │ ├── config.json │ │ │ └── content.css │ ├── config.json │ └── shared │ │ ├── config.json │ │ └── global helpers.js │ │ ├── config.json │ │ └── content.js └── settings ├── index.js ├── jsreport.config.json ├── package-lock.json ├── package.json ├── prod.config.json ├── server.js └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | report.pdf 64 | lambda.zip 65 | layer.zip -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 jsreport 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # jsreport-aws-lambda-starter-kit 4 | 5 | This repository helps you to get started with running jsreport serverless in AWS Lambda. The full documentation can be found here 6 | 7 | **[https://jsreport.net/learn/aws-lambda-serverless](https://jsreport.net/learn/aws-lambda-serverless)** 8 | -------------------------------------------------------------------------------- /createLambdaLayer.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const archiver = require('archiver') 3 | const FS = require('fs-extra') 4 | const path = require('path') 5 | const { rimraf } = require('rimraf') 6 | 7 | const fileUtils = require('@jsreport/jsreport-core/lib/main/extensions/fileUtils') 8 | 9 | async function pckg() { 10 | if (fs.existsSync('layer.zip')) { 11 | fs.unlinkSync('layer.zip') 12 | } 13 | 14 | const foldersToExcludeFromLambda = [ 15 | 'node_modules/@jsreport/jsreport-studio', 16 | 'node_modules/@jsreport/jsreport-authentication', 17 | 'node_modules/@jsreport/jsreport-authorization', 18 | 'node_modules/@jsreport/jsreport-cli', 19 | 'node_modules/@jsreport/jsreport-express', 20 | 'node_modules/@jsreport/jsreport-freeze', 21 | 'node_modules/@jsreport/jsreport-import-export', 22 | 'node_modules/@jsreport/jsreport-public-templates', 23 | 'node_modules/@jsreport/jsreport-sample-template', 24 | 'node_modules/@jsreport/jsreport-tags', 25 | 'node_modules/@jsreport/jsreport-studio-theme-dark', 26 | 'node_modules/@jsreport/jsreport-version-control' 27 | ] 28 | 29 | // we exclude big dep aws-sdk only when not explicitely referenced in deps 30 | if (!JSON.parse(fs.readFileSync('package.json')).dependencies['aws-sdk']) { 31 | foldersToExcludeFromLambda.push('node_modules/aws-sdk') 32 | } 33 | 34 | for (const folder of foldersToExcludeFromLambda) { 35 | await FS.remove(path.basename(folder)) 36 | await FS.move(folder, path.basename(folder)) 37 | } 38 | 39 | await cleanup() 40 | 41 | const output = fs.createWriteStream('layer.zip') 42 | const archive = archiver('zip') 43 | archive.pipe(output) 44 | 45 | // collect extensions paths, so we don't have to crawl in runtime 46 | // this helps just some 500ms for cold start 47 | const extensionPaths = fileUtils.walkSync('node_modules', 'jsreport.config.js') 48 | const relativeExtensionPaths = extensionPaths.map(p => path.relative(__dirname, p)) 49 | // archiver.append is buggy and doesnt work, need to add through directory 50 | await FS.writeFile('node_modules/locations.json', JSON.stringify({ 51 | locations: relativeExtensionPaths 52 | })) 53 | 54 | archive.directory('node_modules/', 'nodejs/node_modules'); 55 | 56 | await archive.finalize() 57 | 58 | for (const folder of foldersToExcludeFromLambda) { 59 | await FS.move(path.basename(folder), folder) 60 | } 61 | 62 | console.log('layer.zip is ready') 63 | } 64 | 65 | async function cleanup() { 66 | const patterns = [ 67 | `node_modules/ses`, 68 | `node_modules/jsreport-exceljs/dist`, 69 | `node_modules/winser-with-api`, 70 | `node_modules/@jsreport/**/main.js.map`, 71 | `node_modules/pdfjs-dist/build`, 72 | `node_modules/@jsreport/pdfjs/test`, 73 | `node_modules/@jsreport/pdfjs/playground`, 74 | // wont be needed after we use just single pdfjs-dist 75 | 'node_modules/@jsreport/pdfjs/node_modules/pdfjs-dist/legacy', 76 | `node_modules/**/Jenkinsfile`, 77 | `node_modules/**/Makefile`, 78 | `node_modules/**/Gulpfile.js`, 79 | `node_modules/**/Gruntfile.js`, 80 | `node_modules/**/gulpfile.js`, 81 | `node_modules/**/.DS_Store`, 82 | `node_modules/**/.tern-project`, 83 | `node_modules/**/.gitattributes`, 84 | `node_modules/**/.editorconfig`, 85 | `node_modules/**/.eslintrc`, 86 | `node_modules/**/.eslintrc.js`, 87 | `node_modules/**/.eslintrc.json`, 88 | `node_modules/**/.eslintrc.yml`, 89 | `node_modules/**/.eslintignore`, 90 | `node_modules/**/.stylelintrc`, 91 | `node_modules/**/stylelint.config.js`, 92 | `node_modules/**/.stylelintrc.json`, 93 | `node_modules/**/.stylelintrc.yaml`, 94 | `node_modules/**/.stylelintrc.yml`, 95 | `node_modules/**/.stylelintrc.js`, 96 | `node_modules/**/.htmllintrc`, 97 | `node_modules/**/.lint`, 98 | `node_modules/**/.npmrc`, 99 | `node_modules/**/.npmignore`, 100 | `node_modules/**/.jshintrc`, 101 | `node_modules/**/.flowconfig`, 102 | `node_modules/**/.documentup.json`, 103 | `node_modules/**/.yarn-metadata.json`, 104 | `node_modules/**/.travis.yml`, 105 | `node_modules/**/appveyor.yml`, 106 | `node_modules/**/.gitlab-ci.yml`, 107 | `node_modules/**/circle.yml`, 108 | `node_modules/**/.coveralls.yml`, 109 | `node_modules/**/CHANGES`, 110 | `node_modules/**/changelog`, 111 | `node_modules/**/LICENSE.txt`, 112 | `node_modules/**/LICENSE`, 113 | `node_modules/**/LICENSE-MIT`, 114 | `node_modules/**/LICENSE-MIT.txt`, 115 | `node_modules/**/LICENSE.BSD`, 116 | `node_modules/**/license`, 117 | `node_modules/**/LICENCE.txt`, 118 | `node_modules/**/LICENCE`, 119 | `node_modules/**/LICENCE-MIT`, 120 | `node_modules/**/LICENCE-MIT.txt`, 121 | `node_modules/**/LICENCE.BSD`, 122 | `node_modules/**/licence`, 123 | `node_modules/**/AUTHORS`, 124 | `node_modules/**/VERSION`, 125 | `node_modules/**/CONTRIBUTORS`, 126 | `node_modules/**/.yarn-integrity`, 127 | `node_modules/**/.yarnclean`, 128 | `node_modules/**/_config.yml`, 129 | `node_modules/**/.babelrc`, 130 | `node_modules/**/.yo-rc.json`, 131 | `node_modules/**/jest.config.js`, 132 | `node_modules/**/karma.conf.js`, 133 | `node_modules/**/wallaby.js`, 134 | `node_modules/**/wallaby.conf.js`, 135 | `node_modules/**/.prettierrc`, 136 | `node_modules/**/.prettierrc.yml`, 137 | `node_modules/**/.prettierrc.toml`, 138 | `node_modules/**/.prettierrc.js`, 139 | `node_modules/**/.prettierrc.json`, 140 | `node_modules/**/prettier.config.js`, 141 | `node_modules/**/.appveyor.yml`, 142 | `node_modules/**/tsconfig.json`, 143 | `node_modules/**/tslint.json`] 144 | 145 | const { default: limit } = await import('p-limit') 146 | const pLimit = limit(5) 147 | return Promise.all(patterns.map((p) => pLimit(() => rimraf(p, { glob: true })))) 148 | } 149 | 150 | pckg().catch(console.error) -------------------------------------------------------------------------------- /createLambdaPackage.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const archiver = require('archiver') 3 | 4 | 5 | 6 | async function pckg() { 7 | if (fs.existsSync('lambda.zip')) { 8 | fs.unlinkSync('lambda.zip') 9 | } 10 | 11 | const output = fs.createWriteStream('lambda.zip') 12 | const archive = archiver('zip') 13 | archive.pipe(output) 14 | 15 | archive.directory('data', 'data'); 16 | archive.file('prod.config.json'); 17 | archive.file('index.js'); 18 | await archive.finalize() 19 | console.log('lambda.zip is ready') 20 | } 21 | 22 | pckg().catch(console.error) -------------------------------------------------------------------------------- /data/fs.journal: -------------------------------------------------------------------------------- 1 | {"operation":"reload","timestamp":{"$$date":1652806413438},"version":1,"doc":{}} 2 | {"operation":"insert","timestamp":{"$$date":1652806413458},"version":2,"doc":{"key":"core-migrated-xlsxTemplates","value":"true","creationDate":{"$$date":1652806413453},"modificationDate":{"$$date":1652806413453},"shortid":"cR5im0O","_id":"w1P9dYlvUlkQeMtn","$entitySet":"settings","$$etag":1652806413458}} 3 | {"operation":"reload","timestamp":{"$$date":1652806413483},"version":3,"doc":{}} 4 | {"operation":"insert","timestamp":{"$$date":1652806413496},"version":4,"doc":{"key":"core-migrated-resources","value":"true","creationDate":{"$$date":1652806413493},"modificationDate":{"$$date":1652806413493},"shortid":"QzcimMy","_id":"ZHQaqtKcYUqndCZL","$entitySet":"settings","$$etag":1652806413496}} 5 | {"operation":"reload","timestamp":{"$$date":1652806413715},"version":5,"doc":{}} 6 | {"operation":"insert","timestamp":{"$$date":1652806413725},"version":6,"doc":{"key":"core-migrated-versionControl-props","value":"true","creationDate":{"$$date":1652806413723},"modificationDate":{"$$date":1652806413723},"shortid":"EI2nYTm","_id":"6opsXStNPm6iUywV","$entitySet":"settings","$$etag":1652806413724}} 7 | {"operation":"insert","timestamp":{"$$date":1652806413739},"version":7,"doc":{"key":"chrome-network-idle-migrated","value":"true","creationDate":{"$$date":1652806413736},"modificationDate":{"$$date":1652806413736},"shortid":"WR-aUH4","_id":"3Ii61lMJuW2pp3BS","$entitySet":"settings","$$etag":1652806413739}} 8 | {"operation":"insert","timestamp":{"$$date":1652806413752},"version":8,"doc":{"key":"sample-created","value":"true","creationDate":{"$$date":1652806413750},"modificationDate":{"$$date":1652806413750},"shortid":"0IevL6F","_id":"D1nnX0OZpmm5OHkO","$entitySet":"settings","$$etag":1652806413752}} 9 | {"operation":"insert","timestamp":{"$$date":1652806413801},"version":9,"doc":{"name":"samples","creationDate":{"$$date":1652806413785},"modificationDate":{"$$date":1652806413785},"shortid":"AKZn3N9","_id":"e8V2KOhXBStO2iZx","$entitySet":"folders","$$etag":1652806413801}} 10 | {"operation":"insert","timestamp":{"$$date":1652806413824},"version":10,"doc":{"shortid":"G3i2B3","name":"Invoice","folder":{"shortid":"AKZn3N9"},"creationDate":{"$$date":1652806413811},"modificationDate":{"$$date":1652806413811},"_id":"wdzlrxL1Cp9maO1t","$entitySet":"folders","$$etag":1652806413824}} 11 | {"operation":"insert","timestamp":{"$$date":1652806413845},"version":11,"doc":{"shortid":"erkLzi","name":"Orders","inheritedReadPermissions":[],"inheritedEditPermissions":[],"folder":{"shortid":"AKZn3N9"},"creationDate":{"$$date":1652806413832},"modificationDate":{"$$date":1652806413832},"_id":"er5ZzDTsdM5cFJQj","$entitySet":"folders","$$etag":1652806413845}} 12 | {"operation":"insert","timestamp":{"$$date":1652806413862},"version":12,"doc":{"shortid":"dOoi1a","name":"shared","folder":{"shortid":"AKZn3N9"},"creationDate":{"$$date":1652806413850},"modificationDate":{"$$date":1652806413850},"_id":"Q965D4kOFi8DW7U3","$entitySet":"folders","$$etag":1652806413862}} 13 | {"operation":"insert","timestamp":{"$$date":1652806413881},"version":13,"doc":{"name":"Sales","shortid":"FnHe~Wz","folder":{"shortid":"AKZn3N9"},"creationDate":{"$$date":1652806413867},"modificationDate":{"$$date":1652806413867},"_id":"2RwOcmuwT2gpC7uL","$entitySet":"folders","$$etag":1652806413880}} 14 | {"operation":"insert","timestamp":{"$$date":1652806413913},"version":14,"doc":{"shortid":"Sy5S19ncg","name":"invoice-data","dataJson":"{\n \"number\": \"123\",\n \"seller\": {\n \"name\": \"Next Step Webs, Inc.\",\n \"road\": \"12345 Sunny Road\",\n \"country\": \"Sunnyville, TX 12345\"\n },\n \"buyer\": {\n \"name\": \"Acme Corp.\",\n \"road\": \"16 Johnson Road\",\n \"country\": \"Paris, France 8060\"\n },\n \"items\": [{\n \"name\": \"Website design\",\n \"price\": 300\n }]\n}","folder":{"shortid":"G3i2B3"},"creationDate":{"$$date":1652806413890},"modificationDate":{"$$date":1652806413890},"_id":"0lLeuL7ZrBFYRWF2","$entitySet":"data","$$etag":1652806413913}} 15 | {"operation":"insert","timestamp":{"$$date":1652806413930},"version":15,"doc":{"folder":{"shortid":"FnHe~Wz"},"shortid":"B1lSTrt6NB","name":"sales-data","dataJson":"{\n \"customer\": \"Walker Group\",\n \"month\": \"April\",\n \"taxPercentage\": 0.20,\n \"detail\": [{\n \"date\": \"2019-04-03\",\n \"product\": \"Vitamin C\",\n \"category\": \"Health\",\n \"unitPrice\": 25,\n \"quantity\": 1,\n \"discountPercentage\": 0 \n }, {\n \"date\": \"2019-04-03\",\n \"product\": \"Probiotics\",\n \"category\": \"Health\",\n \"unitPrice\": 83,\n \"quantity\": 1,\n \"discountPercentage\": 0.25\n }, {\n \"date\": \"2019-04-04\",\n \"product\": \"Mild Bubble Cleanser\",\n \"category\": \"Cleansing\",\n \"unitPrice\": 13,\n \"quantity\": 2,\n \"discountPercentage\": 0\n }, {\n \"date\": \"2019-04-04\",\n \"product\": \"Deep Cleanser\",\n \"category\": \"Cleansing\",\n \"unitPrice\": 12,\n \"quantity\": 3,\n \"discountPercentage\": 0\n }, {\n \"date\": \"2019-04-04\",\n \"product\": \"Atomy Men Set\",\n \"category\": \"Men Skin Care\",\n \"unitPrice\": 54,\n \"quantity\": 1,\n \"discountPercentage\": 0.35\n }, {\n \"date\": \"2019-04-09\",\n \"product\": \"BB Cream\",\n \"category\": \"Make-Up\",\n \"unitPrice\": 12,\n \"quantity\": 3,\n \"discountPercentage\": 0\n }, {\n \"date\": \"2019-04-15\",\n \"product\": \"Lipstick Poppy\",\n \"category\": \"Make-Up\",\n \"unitPrice\": 22,\n \"quantity\": 1,\n \"discountPercentage\": 0\n }, {\n \"date\": \"2019-04-15\",\n \"product\": \"Healthy Glow Base\",\n \"category\": \"Make-Up\",\n \"unitPrice\": 18,\n \"quantity\": 2,\n \"discountPercentage\": 0.12\n }, {\n \"date\": \"2019-04-26\",\n \"product\": \"Lotion\",\n \"category\": \"Skin Care\",\n \"unitPrice\": 23,\n \"quantity\": 1,\n \"discountPercentage\": 0\n }]\n}","creationDate":{"$$date":1652806413917},"modificationDate":{"$$date":1652806413917},"_id":"az7sT3N7gapUGxww","$entitySet":"data","$$etag":1652806413930}} 16 | {"operation":"insert","timestamp":{"$$date":1652806413964},"version":16,"doc":{"folder":{"shortid":"FnHe~Wz"},"shortid":"B1Q2SFTNr","name":"sales-main","recipe":"html-to-xlsx","engine":"handlebars","chrome":{"printBackground":true},"htmlToXlsx":{"htmlEngine":"chrome"},"data":{"shortid":"B1lSTrt6NB"},"content":"\n\n \n \n \n \n \n \n \n \n \n \n \n \n {{generateEmptyCell 7}}\n \n \n {{generateEmptyCell 1}}\n \n \n {{generateEmptyCell 1 \"content border-top\"}}\n \n \n {{generateEmptyCell 1}}\n \n \n {{generateEmptyCell 1}}\n \n \n {{generateEmptyCell 1 \"content border-bottom\"}}\n \n \n \n {{generateEmptyCell 1}}\n \n \n {{generateEmptyCell 7}}\n \n \n \n \n \n \n \n \n \n \n \n \n {{#each detail}}\n \n \n \n \n \n \n \n \n \n {{/each}}\n \n {{generateEmptyCell 5}}\n \n \n \n \n {{generateEmptyCell 5}}\n \n \n \n \n {{generateEmptyCell 5}}\n \n \n \n \n
SALES DETAIL
Customer{{customer}}Report Date{{nowStr}}
Month{{month}}Tax{{taxPercentage}}
DateProductCategoryUnit PriceQuantityDiscountAmount
{{date}}{{product}}{{category}}{{unitPrice}}{{quantity}}{{discountPercentage}}=(D{{getDetailRowIndex @index}}*E{{getDetailRowIndex @index}}) - (D{{getDetailRowIndex @index}}*E{{getDetailRowIndex @index}}*F{{getDetailRowIndex @index}})
Total Net Amount $=SUM(G{{getDetailRowIndex 0}}:G{{getDetailRowIndex (sum detail.length -1)}})
=CONCATENATE(\"VAT (\", F4*100, \"%)\", \" $\")=G{{getDetailRowIndex detail.length}}*F4
Total $=SUM(G{{getDetailRowIndex detail.length}}:GG{{getDetailRowIndex (sum detail.length 1)}})
\n \n\n","helpers":"const moment = require('moment')\nconst rowOffset = 6\n\nfunction nowStr () {\n return moment().format('YYYY-MM-DD')\n}\n\nfunction generateEmptyCell (repeat, className) {\n const cells = []\n\n for (let i = 0; i < repeat; i++) {\n cells.push(``)\n }\n\n return new Handlebars.SafeString(cells.join(''))\n}\n\nfunction oddClassName (index) {\n return (index + 1) % 2 !== 0 ? 'odd' : ''\n}\n\nfunction sum (a, b) {\n return a + b\n}\n\nfunction getDetailRowIndex (index) {\n return (index + 1) + rowOffset\n}","creationDate":{"$$date":1652806413951},"modificationDate":{"$$date":1652806413951},"_id":"2KaorlenrmxKinSu","$entitySet":"templates","$$etag":1652806413964}} 17 | {"operation":"insert","timestamp":{"$$date":1652806413990},"version":17,"doc":{"shortid":"rkJTnK2ce","recipe":"chrome-pdf","engine":"handlebars","data":{"shortid":"Sy5S19ncg"},"name":"invoice-main","folder":{"shortid":"G3i2B3"},"chrome":{"printBackground":true,"marginTop":"1cm","marginRight":"1cm","marginBottom":"1cm","marginLeft":"1cm","headerTemplate":"","footerTemplate":""},"content":"\n\n\n \n \n \n \n \n
\n \n \n \n \n \n \n \n \n \n \n \n {{#each items}}\n \n \n \n \n {{/each}}\n \n \n \n \n
\n \n \n \n \n \n
\n \n \n Invoice #: {{number}}\n
Created: {{nowLocalStr}}\n
Due: {{nowPlus20Days}}\n
\n
\n \n \n \n \n \n
\n {{seller.name}}
\n {{seller.road}}
\n {{seller.country}}\n
\n {{buyer.name}}
\n {{buyer.road}}
\n {{buyer.country}}\n
\n
\n Item\n \n Price\n
\n {{name}}\n \n $ {{price}}\n
\n Total: ${{total items}}\n
\n
\n \n\n","helpers":"function nowPlus20Days() {\n var date = new Date()\n date.setDate(date.getDate() + 20);\n return date.toLocaleDateString();\n}\n\nfunction total(items) {\n var sum = 0\n items.forEach(function (i) {\n console.log('Calculating item ' + i.name + '; you should see this message in debug run')\n sum += i.price\n })\n return sum\n}\n","creationDate":{"$$date":1652806413969},"modificationDate":{"$$date":1652806413970},"_id":"zcYnFseTTjFShkZl","$entitySet":"templates","$$etag":1652806413990}} 18 | {"operation":"insert","timestamp":{"$$date":1652806414013},"version":18,"doc":{"phantom":{"waitForJS":true},"recipe":"chrome-pdf","engine":"handlebars","scripts":[{"shortid":"BJX1Jw82ce"}],"shortid":"HJH11D83ce","name":"orders-main","folder":{"shortid":"erkLzi"},"chrome":{"printBackground":true,"marginTop":"4cm","marginRight":"1.5cm","marginBottom":"1.5cm","marginLeft":"1.5cm","waitForJS":false,"headerTemplate":"","footerTemplate":""},"pdfOperations":[{"type":"merge","templateShortid":"SJVbqZr9f","renderForEveryPage":false,"mergeWholeDocument":true}],"inheritedReadPermissions":[],"inheritedEditPermissions":[],"content":"\n\n \n \n \n \n \n \n {{#each orders}}\n \n {{{pdfCreatePagesGroup country}}}\n \n \n \n \n \n \n \n \n \n \n \n {{#each rows}}\n \n \n \n \n \n \n {{/each}}\n \n
OrderIDShipAddressShipCityShipCountry
{{OrderID}}{{ShipAddress}}{{ShipCity}}{{ShipCountry}}
\n\n \n
\n
\n {{/each}}\n \n\n","helpers":"","creationDate":{"$$date":1652806413998},"modificationDate":{"$$date":1652806413998},"_id":"prbX4MvuDLbDZwS8","$entitySet":"templates","$$etag":1652806414013}} 19 | {"operation":"insert","timestamp":{"$$date":1652806414039},"version":19,"doc":{"shortid":"SJVbqZr9f","name":"orders-header","recipe":"chrome-pdf","engine":"handlebars","folder":{"shortid":"erkLzi"},"chrome":{"printBackground":true,"marginTop":"1.5cm","marginRight":"1.5cm","marginLeft":"1.cm","headerTemplate":"","footerTemplate":""},"inheritedReadPermissions":[],"inheritedEditPermissions":[],"content":"\n \n \n \n \n \n {{#each $pdf.pages}}\n {{#if @index}}\n
\n {{/if}}\n
\n
\n {{#with (lookup ../$pdf.pages @index)}}\n

{{group}}

\n {{/with}}\n
\n \n
\n {{/each}}\n \n\n","helpers":"function getPageNumber (pageIndex) {\n if (pageIndex == null) {\n return ''\n }\n\n const pageNumber = pageIndex + 1\n\n return pageNumber\n}\n\nfunction getTotalPages (pages) {\n if (!pages) {\n return ''\n }\n\n return pages.length\n}\n","creationDate":{"$$date":1652806414018},"modificationDate":{"$$date":1652806414018},"_id":"e92KS8QvOx4ccb9T","$entitySet":"templates","$$etag":1652806414039}} 20 | {"operation":"insert","timestamp":{"$$date":1652806414070},"version":20,"doc":{"shortid":"ByKOCF3cg","name":"invoice-styles.css","content":{"$$buffer":"Lmludm9pY2UtYm94IHsKICAgIG1heC13aWR0aDogODAwcHg7CiAgICBtYXJnaW46IGF1dG87CiAgICBwYWRkaW5nOiAzMHB4OwogICAgYm9yZGVyOiAxcHggc29saWQgI2VlZTsKICAgIGJveC1zaGFkb3c6IDAgMCAxMHB4IHJnYmEoMCwgMCwgMCwgLjE1KTsKICAgIGZvbnQtc2l6ZTogMTZweDsKICAgIGxpbmUtaGVpZ2h0OiAyNHB4OwogICAgZm9udC1mYW1pbHk6ICdIZWx2ZXRpY2EgTmV1ZScsICdIZWx2ZXRpY2EnLCBIZWx2ZXRpY2EsIEFyaWFsLCBzYW5zLXNlcmlmOwogICAgY29sb3I6ICM1NTU7Cn0KLmludm9pY2UtYm94IHRhYmxlIHsKICAgIHdpZHRoOiAxMDAlOwogICAgbGluZS1oZWlnaHQ6IGluaGVyaXQ7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9Ci5pbnZvaWNlLWJveCB0YWJsZSB0ZCB7CiAgICBwYWRkaW5nOiA1cHg7CiAgICB2ZXJ0aWNhbC1hbGlnbjogdG9wOwp9Ci5pbnZvaWNlLWJveCB0YWJsZSB0ciB0ZDpudGgtY2hpbGQoMikgewogICAgdGV4dC1hbGlnbjogcmlnaHQ7Cn0KLmludm9pY2UtYm94IHRhYmxlIHRyLnRvcCB0YWJsZSB0ZCB7CiAgICBwYWRkaW5nLWJvdHRvbTogMjBweDsKfQouaW52b2ljZS1ib3ggdGFibGUgdHIudG9wIHRhYmxlIHRkLnRpdGxlIHsKICAgIGZvbnQtc2l6ZTogNDVweDsKICAgIGxpbmUtaGVpZ2h0OiA0NXB4OwogICAgY29sb3I6ICMzMzM7Cn0KLmludm9pY2UtYm94IHRhYmxlIHRyLmluZm9ybWF0aW9uIHRhYmxlIHRkIHsKICAgIHBhZGRpbmctYm90dG9tOiA0MHB4Owp9Ci5pbnZvaWNlLWJveCB0YWJsZSB0ci5oZWFkaW5nIHRkIHsKICAgIGJhY2tncm91bmQ6ICNlZWU7CiAgICBib3JkZXItYm90dG9tOiAxcHggc29saWQgI2RkZDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwp9Ci5pbnZvaWNlLWJveCB0YWJsZSB0ci5kZXRhaWxzIHRkIHsKICAgIHBhZGRpbmctYm90dG9tOiAyMHB4Owp9Ci5pbnZvaWNlLWJveCB0YWJsZSB0ci5pdGVtIHRkIHsKICAgIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCAjZWVlOwp9Ci5pbnZvaWNlLWJveCB0YWJsZSB0ci5pdGVtLmxhc3QgdGQgewogICAgYm9yZGVyLWJvdHRvbTogbm9uZTsKfQouaW52b2ljZS1ib3ggdGFibGUgdHIudG90YWwgdGQ6bnRoLWNoaWxkKDIpIHsKICAgIGJvcmRlci10b3A6IDJweCBzb2xpZCAjZWVlOwogICAgZm9udC13ZWlnaHQ6IGJvbGQ7Cn0KQG1lZGlhIG9ubHkgc2NyZWVuIGFuZCAobWF4LXdpZHRoOiA2MDBweCkgewogICAgLmludm9pY2UtYm94IHRhYmxlIHRyLnRvcCB0YWJsZSB0ZCB7CiAgICAgICAgd2lkdGg6IDEwMCU7CiAgICAgICAgZGlzcGxheTogYmxvY2s7CiAgICAgICAgdGV4dC1hbGlnbjogY2VudGVyOwogICAgfQogICAgLmludm9pY2UtYm94IHRhYmxlIHRyLmluZm9ybWF0aW9uIHRhYmxlIHRkIHsKICAgICAgICB3aWR0aDogMTAwJTsKICAgICAgICBkaXNwbGF5OiBibG9jazsKICAgICAgICB0ZXh0LWFsaWduOiBjZW50ZXI7CiAgICB9Cn0="},"folder":{"shortid":"G3i2B3"},"creationDate":{"$$date":1652806414056},"modificationDate":{"$$date":1652806414056},"_id":"TmVxJOjyUuQ8h34E","$entitySet":"assets","$$etag":1652806414070}} 21 | {"operation":"insert","timestamp":{"$$date":1652806414088},"version":21,"doc":{"folder":{"shortid":"erkLzi"},"name":"orders-styles.css","shortid":"IEWXRnJ","inheritedReadPermissions":[],"inheritedEditPermissions":[],"content":{"$$buffer":"KiB7CiAgICBib3gtc2l6aW5nOiBib3JkZXItYm94Owp9CgpodG1sLCBib2R5IHsKICAgIG1hcmdpbjogMHB4OwogICAgcGFkZGluZzogMHB4Owp9CgoubWFpbiB7CiAgICBkaXNwbGF5OiBmbGV4OwogICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsKICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjsKICAgIHdpZHRoOiAxMDAlOwogICAgaGVpZ2h0OiAxMDAlOwp9CgouaGVhZGVyIHsKICAgIHdpZHRoOiAxMDAlOwogICAgcGFkZGluZy10b3A6IDEwcHg7Cn0KCi5mb290ZXIgewogICAgd2lkdGg6IDEwMCU7CiAgICBwYWRkaW5nLWJvdHRvbTogMjBweDsKICAgIGJvcmRlci10b3A6IDFweCBzb2xpZCBibGFjazsKfQ=="},"creationDate":{"$$date":1652806414074},"modificationDate":{"$$date":1652806414074},"_id":"cjZMMZlqwAkRZlag","$entitySet":"assets","$$etag":1652806414088}} 22 | {"operation":"insert","timestamp":{"$$date":1652806414112},"version":22,"doc":{"shortid":"SkMw3X69l","isSharedHelper":true,"name":"global helpers.js","content":{"$$buffer":"ZnVuY3Rpb24gbm93TG9jYWxTdHIgKCkgewogIHJldHVybiBuZXcgRGF0ZSgpLnRvTG9jYWxlRGF0ZVN0cmluZygpCn0K"},"folder":{"shortid":"dOoi1a"},"creationDate":{"$$date":1652806414097},"modificationDate":{"$$date":1652806414097},"_id":"tAUpN5MEdFz7hbok","$entitySet":"assets","$$etag":1652806414112}} 23 | {"operation":"insert","timestamp":{"$$date":1652806414136},"version":23,"doc":{"folder":{"shortid":"FnHe~Wz"},"name":"sales-styles.css","shortid":"B1m9OJE","content":{"$$buffer":"dGFibGUgewogICAgYm9yZGVyLWNvbGxhcHNlOiBjb2xsYXBzZTsKfQoKLmVtcHR5LWNlbGwgewogICAgcGFkZGluZy10b3A6IDEwcHg7CiAgICBwYWRkaW5nLWJvdHRvbTogMTBweDsKfQoKdGQ6bm90KC5lbXB0eS1jZWxsKSB7CiAgICBtaW4td2lkdGg6IDEwMHB4Owp9CgoudC1sZWZ0IHsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCi50LWNlbnRlciB7CiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCi50LXJpZ2h0IHsKICAgIHRleHQtYWxpZ246IHJpZ2h0Owp9CgouaGVhZCAudGl0bGUgewogICAgYmFja2dyb3VuZC1jb2xvcjogIzcwQUQ0NzsKICAgIGNvbG9yOiAjZmZmOwogICAgZm9udC1zaXplOiAyMXB4OwogICAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCi5sYWJlbCB7CiAgICBmb250LXdlaWdodDogYm9sZDsKfQoKLmhlYWQgLmNvbnRlbnQgewogICAgYmFja2dyb3VuZC1jb2xvcjogI2ZmZjsKICAgIHBhZGRpbmc6IDJweDsKfQoKLmhlYWQgLmJvcmRlci10b3AgewogICAgYm9yZGVyLXRvcDogMXB4IHNvbGlkICMwMDA7Cn0KCi5oZWFkIC5ib3JkZXItbGVmdCB7CiAgICBib3JkZXItbGVmdDogMXB4IHNvbGlkICMwMDA7Cn0KCi5oZWFkIC5ib3JkZXItcmlnaHQgewogICAgYm9yZGVyLXJpZ2h0OiAxcHggc29saWQgIzAwMDsKfQoKLmhlYWQgLmJvcmRlci1ib3R0b20gewogICAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkICMwMDA7Cn0KCi5kZXRhaWwgewogICAgYm9yZGVyOiAxcHggc29saWQgI0JFREJBQTsKfQoKLmRldGFpbCB0aCB7CiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjNzBBRDQ3OwogICAgYm9yZGVyOiAxcHggc29saWQgI0JFREJBQTsKICAgIGNvbG9yOiAjZmZmOwogICAgZm9udC13ZWlnaHQ6IGJvbGQ7Cn0KCi5kZXRhaWwgLm9kZCB0ZCB7CiAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjRTJFRkRBOwogICAgYm9yZGVyLXRvcDogMXB4IHNvbGlkICNCRURCQUE7CiAgICBib3JkZXItYm90dG9tOiAxcHggc29saWQgI0JFREJBQTsKfQoKLmRldGFpbCB0ZCB7CiAgICBwYWRkaW5nOiA0cHg7IAp9"},"creationDate":{"$$date":1652806414118},"modificationDate":{"$$date":1652806414118},"_id":"cTpjMA2CHjl3A6jM","$entitySet":"assets","$$etag":1652806414135}} 24 | {"operation":"insert","timestamp":{"$$date":1652806414152},"version":24,"doc":{"shortid":"SkKBCK39l","name":"invoice-logo.png","content":{"$$buffer":"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/GMzLdsAADzDaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/Pgo8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzExMSA3OS4xNTgzMjUsIDIwMTUvMDkvMTAtMDE6MTA6MjAgICAgICAgICI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIKICAgICAgICAgICAgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iCiAgICAgICAgICAgIHhtbG5zOnN0RXZ0PSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VFdmVudCMiCiAgICAgICAgICAgIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3RpZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE1IChXaW5kb3dzKTwveG1wOkNyZWF0b3JUb29sPgogICAgICAgICA8eG1wOkNyZWF0ZURhdGU+MjAxNi0wNi0wMVQxNjozNDozNS0wNTowMDwveG1wOkNyZWF0ZURhdGU+CiAgICAgICAgIDx4bXA6TWV0YWRhdGFEYXRlPjIwMTYtMDYtMDZUMTI6MDY6MTQtMDU6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgICAgICAgIDx4bXA6TW9kaWZ5RGF0ZT4yMDE2LTA2LTA2VDEyOjA2OjE0LTA1OjAwPC94bXA6TW9kaWZ5RGF0ZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDo3Y2MyOWM4Yi02YzgxLTcxNGUtOGM2ZS0xZjdhZmE4ZjMwNTI8L3htcE1NOkluc3RhbmNlSUQ+CiAgICAgICAgIDx4bXBNTTpEb2N1bWVudElEPmFkb2JlOmRvY2lkOnBob3Rvc2hvcDpmOWI4ZTUwNi0yYzA4LTExZTYtOWY5OC1kZGExOGVlMDJiZGU8L3htcE1NOkRvY3VtZW50SUQ+CiAgICAgICAgIDx4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ+eG1wLmRpZDpjZDZkODFjMS1mNTIyLTU5NDEtODNkNC0wNWU1YTk5ZDUzNDQ8L3htcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkhpc3Rvcnk+CiAgICAgICAgICAgIDxyZGY6U2VxPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5jcmVhdGVkPC9zdEV2dDphY3Rpb24+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDppbnN0YW5jZUlEPnhtcC5paWQ6Y2Q2ZDgxYzEtZjUyMi01OTQxLTgzZDQtMDVlNWE5OWQ1MzQ0PC9zdEV2dDppbnN0YW5jZUlEPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6d2hlbj4yMDE2LTA2LTAxVDE2OjM0OjM1LTA1OjAwPC9zdEV2dDp3aGVuPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6c29mdHdhcmVBZ2VudD5BZG9iZSBQaG90b3Nob3AgQ0MgMjAxNSAoV2luZG93cyk8L3N0RXZ0OnNvZnR3YXJlQWdlbnQ+CiAgICAgICAgICAgICAgIDwvcmRmOmxpPgogICAgICAgICAgICAgICA8cmRmOmxpIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmFjdGlvbj5zYXZlZDwvc3RFdnQ6YWN0aW9uPgogICAgICAgICAgICAgICAgICA8c3RFdnQ6aW5zdGFuY2VJRD54bXAuaWlkOjBlNTYyZTEyLWRkZjgtZTQ0YS1iMDExLTk0MzE5MWRhMTgyNTwvc3RFdnQ6aW5zdGFuY2VJRD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OndoZW4+MjAxNi0wNi0wMVQxNjozNDozNS0wNTowMDwvc3RFdnQ6d2hlbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OnNvZnR3YXJlQWdlbnQ+QWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKFdpbmRvd3MpPC9zdEV2dDpzb2Z0d2FyZUFnZW50PgogICAgICAgICAgICAgICAgICA8c3RFdnQ6Y2hhbmdlZD4vPC9zdEV2dDpjaGFuZ2VkPgogICAgICAgICAgICAgICA8L3JkZjpsaT4KICAgICAgICAgICAgICAgPHJkZjpsaSByZGY6cGFyc2VUeXBlPSJSZXNvdXJjZSI+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDphY3Rpb24+c2F2ZWQ8L3N0RXZ0OmFjdGlvbj4KICAgICAgICAgICAgICAgICAgPHN0RXZ0Omluc3RhbmNlSUQ+eG1wLmlpZDo3Y2MyOWM4Yi02YzgxLTcxNGUtOGM2ZS0xZjdhZmE4ZjMwNTI8L3N0RXZ0Omluc3RhbmNlSUQ+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDp3aGVuPjIwMTYtMDYtMDZUMTI6MDY6MTQtMDU6MDA8L3N0RXZ0OndoZW4+CiAgICAgICAgICAgICAgICAgIDxzdEV2dDpzb2Z0d2FyZUFnZW50PkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE1IChXaW5kb3dzKTwvc3RFdnQ6c29mdHdhcmVBZ2VudD4KICAgICAgICAgICAgICAgICAgPHN0RXZ0OmNoYW5nZWQ+Lzwvc3RFdnQ6Y2hhbmdlZD4KICAgICAgICAgICAgICAgPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOlNlcT4KICAgICAgICAgPC94bXBNTTpIaXN0b3J5PgogICAgICAgICA8cGhvdG9zaG9wOkNvbG9yTW9kZT4zPC9waG90b3Nob3A6Q29sb3JNb2RlPgogICAgICAgICA8cGhvdG9zaG9wOklDQ1Byb2ZpbGU+c1JHQiBJRUM2MTk2Ni0yLjE8L3Bob3Rvc2hvcDpJQ0NQcm9maWxlPgogICAgICAgICA8cGhvdG9zaG9wOkRvY3VtZW50QW5jZXN0b3JzPgogICAgICAgICAgICA8cmRmOkJhZz4KICAgICAgICAgICAgICAgPHJkZjpsaT5hZG9iZTpkb2NpZDpwaG90b3Nob3A6ZmRkNjI3ZmYtMjgzOS0xMWU2LThkNDctODMyYTVlN2Y4N2JkPC9yZGY6bGk+CiAgICAgICAgICAgIDwvcmRmOkJhZz4KICAgICAgICAgPC9waG90b3Nob3A6RG9jdW1lbnRBbmNlc3RvcnM+CiAgICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2UvcG5nPC9kYzpmb3JtYXQ+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjcyMDAwMC8xMDAwMDwvdGlmZjpYUmVzb2x1dGlvbj4KICAgICAgICAgPHRpZmY6WVJlc29sdXRpb24+NzIwMDAwLzEwMDAwPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZmOlJlc29sdXRpb25Vbml0PgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjYzMDwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4xMDQ8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PmEoDIcAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAK69JREFUeNrsnXe4FNX5xz/3XrogTbCCiAQFxRpRIygW1GisUTTRaDDW2I0FiR1jrLFhSzBGY4tJjKIiRVRADYpdEQUBS8QCShOk3Xt/f7zv/ObscHd3Zndmd/be9/M8PM5ed3bamXO+5z1vqcIwDMP4f4aPPJwpY2YwZcwMuxmGEYGWrZpz5aghdiPysw1wPvBroC7uH29m99cwDMMwDKMkdAGeBHoAnwCXxX2AarvHhmEYhmEYidMc+JeKOoBLgMNN2BmGYRiGYVQeNwG7O5+rgPuAvibsDMMwDMMwKoeTgDMb+Pu6wFNAVxN2hmEYhmEY6WdP4I4c/78n8DjQwoSdYRiGYRhGeukJ/BPxr8vFbsBdJuwMwzAMwzDSSTskArZzyO+fAJxjws4wDMMwDCNdVAMPAVtH3O8GYG8TdoZhGIZhGOlhBHBQAfs1Ax4FNjdhZxiGYRiGUX6OBi4uYv/1kEjZ9ibsDMMwDMMwyseOwL1Ijrpi6AM8DNSYsDMMwzAMwyg96+NHwK4O/FuTY7+6Br6/GhiMLOlGwmrFGoZhGIZhFM/XSHqThugBzM3y/0YDh8V1EmaxMwzDMAzDaCSYsDMMwzAMw4hGi7SemAk7wzAMo6lRBWyK+DCdYrfDiEANcBqyfJpKzMfOMAzDaGpsAnyi2z8A99gtMUKwG3A7sD3wRlpP0ix2hmEYhmEY2ekFPAZMUVGXasxiZxiGYRiGsTbrApcCZ5FinzoTdoZhGIZhGNmpAo4BrgM2qrSTN2FnGIZh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"},"folder":{"shortid":"G3i2B3"},"creationDate":{"$$date":1652806414140},"modificationDate":{"$$date":1652806414140},"_id":"aMjAW7PK0rHC1xMu","$entitySet":"assets","$$etag":1652806414152}} 25 | {"operation":"insert","timestamp":{"$$date":1652806414175},"version":25,"doc":{"shortid":"BJX1Jw82ce","name":"orders-script","folder":{"shortid":"erkLzi"},"inheritedReadPermissions":[],"inheritedEditPermissions":[],"content":"// server side script fetching remote data and preparing report data source\nconst https = require('https');\n\n// call remote http rest api\nfunction fetchOrders() {\n return new Promise((resolve, reject) => {\n https.get('https://services.odata.org/V4/Northwind/Northwind.svc/Orders',\n (result) => {\n var str = '';\n result.on('data', (b) => str += b);\n result.on('error', reject);\n result.on('end', () => resolve(JSON.parse(str).value));\n });\n })\n}\n\n// group the data for report\nasync function prepareDataSource() {\n const orders = await fetchOrders()\n const ordersByShipCountry = orders.reduce((a, v) => {\n a[v.ShipCountry] = a[v.ShipCountry] || []\n a[v.ShipCountry].push(v)\n return a\n }, {})\n\n return Object.keys(ordersByShipCountry).map((country) => {\n const ordersInCountry = ordersByShipCountry[country]\n\n const accumulated = {}\n\n ordersInCountry.forEach((o) => {\n o.OrderDate = new Date(o.OrderDate);\n const key = o.OrderDate.getFullYear() + '/' + (o.OrderDate.getMonth() + 1);\n accumulated[key] = accumulated[key] || {\n value: 0,\n orderDate: o.OrderDate\n };\n accumulated[key].value++;\n });\n\n return {\n rows: ordersInCountry,\n country,\n accumulated\n }\n\n }).slice(0, 2)\n}\n\n// add jsreport hook which modifies the report input data\nasync function beforeRender(req, res) {\n req.data.orders = await prepareDataSource()\n}","creationDate":{"$$date":1652806414162},"modificationDate":{"$$date":1652806414162},"_id":"pFGei1vCcTedQWrW","$entitySet":"scripts","$$etag":1652806414174}} 26 | -------------------------------------------------------------------------------- /data/fs.version: -------------------------------------------------------------------------------- 1 | 25 -------------------------------------------------------------------------------- /data/samples/Invoice/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "shortid": "G3i2B3", 3 | "name": "Invoice", 4 | "creationDate": { 5 | "$$date": 1652806413811 6 | }, 7 | "modificationDate": { 8 | "$$date": 1652806413811 9 | }, 10 | "_id": "wdzlrxL1Cp9maO1t", 11 | "$entitySet": "folders" 12 | } -------------------------------------------------------------------------------- /data/samples/Invoice/invoice-data/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "shortid": "Sy5S19ncg", 3 | "name": "invoice-data", 4 | "creationDate": { 5 | "$$date": 1652806413890 6 | }, 7 | "modificationDate": { 8 | "$$date": 1652806413890 9 | }, 10 | "_id": "0lLeuL7ZrBFYRWF2", 11 | "$entitySet": "data" 12 | } -------------------------------------------------------------------------------- /data/samples/Invoice/invoice-data/dataJson.json: -------------------------------------------------------------------------------- 1 | { 2 | "number": "123", 3 | "seller": { 4 | "name": "Next Step Webs, Inc.", 5 | "road": "12345 Sunny Road", 6 | "country": "Sunnyville, TX 12345" 7 | }, 8 | "buyer": { 9 | "name": "Acme Corp.", 10 | "road": "16 Johnson Road", 11 | "country": "Paris, France 8060" 12 | }, 13 | "items": [{ 14 | "name": "Website design", 15 | "price": 300 16 | }] 17 | } -------------------------------------------------------------------------------- /data/samples/Invoice/invoice-logo.png/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "shortid": "SkKBCK39l", 3 | "name": "invoice-logo.png", 4 | "creationDate": { 5 | "$$date": 1652806414140 6 | }, 7 | "modificationDate": { 8 | "$$date": 1652806414140 9 | }, 10 | "_id": "aMjAW7PK0rHC1xMu", 11 | "$entitySet": "assets" 12 | } -------------------------------------------------------------------------------- /data/samples/Invoice/invoice-logo.png/content.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsreport/jsreport-aws-lambda-starter-kit/fc4ea3fa6ccd6fd7446e5ceb655477d5b1580682/data/samples/Invoice/invoice-logo.png/content.png -------------------------------------------------------------------------------- /data/samples/Invoice/invoice-main/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "shortid": "rkJTnK2ce", 3 | "recipe": "chrome-pdf", 4 | "engine": "handlebars", 5 | "data": { 6 | "shortid": "Sy5S19ncg" 7 | }, 8 | "name": "invoice-main", 9 | "chrome": { 10 | "printBackground": true, 11 | "marginTop": "1cm", 12 | "marginRight": "1cm", 13 | "marginBottom": "1cm", 14 | "marginLeft": "1cm" 15 | }, 16 | "creationDate": { 17 | "$$date": 1652806413969 18 | }, 19 | "modificationDate": { 20 | "$$date": 1652806413970 21 | }, 22 | "_id": "zcYnFseTTjFShkZl", 23 | "$entitySet": "templates" 24 | } -------------------------------------------------------------------------------- /data/samples/Invoice/invoice-main/content.handlebars: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 |
19 | 20 | 21 | 35 | 36 | 37 | 53 | 54 | 55 | 58 | 61 | 62 | {{#each items}} 63 | 64 | 67 | 70 | 71 | {{/each}} 72 | 73 | 74 | 77 | 78 |
22 | 23 | 24 | 27 | 32 | 33 |
25 | 26 | 28 | Invoice #: {{number}} 29 |
Created: {{nowLocalStr}} 30 |
Due: {{nowPlus20Days}} 31 |
34 |
38 | 39 | 40 | 45 | 50 | 51 |
41 | {{seller.name}}
42 | {{seller.road}}
43 | {{seller.country}} 44 |
46 | {{buyer.name}}
47 | {{buyer.road}}
48 | {{buyer.country}} 49 |
52 |
56 | Item 57 | 59 | Price 60 |
65 | {{name}} 66 | 68 | $ {{price}} 69 |
75 | Total: ${{total items}} 76 |
79 |
80 | 81 | 82 | -------------------------------------------------------------------------------- /data/samples/Invoice/invoice-main/footerTemplate.handlebars: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsreport/jsreport-aws-lambda-starter-kit/fc4ea3fa6ccd6fd7446e5ceb655477d5b1580682/data/samples/Invoice/invoice-main/footerTemplate.handlebars -------------------------------------------------------------------------------- /data/samples/Invoice/invoice-main/headerTemplate.handlebars: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsreport/jsreport-aws-lambda-starter-kit/fc4ea3fa6ccd6fd7446e5ceb655477d5b1580682/data/samples/Invoice/invoice-main/headerTemplate.handlebars -------------------------------------------------------------------------------- /data/samples/Invoice/invoice-main/helpers.js: -------------------------------------------------------------------------------- 1 | function nowPlus20Days() { 2 | var date = new Date() 3 | date.setDate(date.getDate() + 20); 4 | return date.toLocaleDateString(); 5 | } 6 | 7 | function total(items) { 8 | var sum = 0 9 | items.forEach(function (i) { 10 | console.log('Calculating item ' + i.name + '; you should see this message in debug run') 11 | sum += i.price 12 | }) 13 | return sum 14 | } 15 | -------------------------------------------------------------------------------- /data/samples/Invoice/invoice-styles.css/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "shortid": "ByKOCF3cg", 3 | "name": "invoice-styles.css", 4 | "creationDate": { 5 | "$$date": 1652806414056 6 | }, 7 | "modificationDate": { 8 | "$$date": 1652806414056 9 | }, 10 | "_id": "TmVxJOjyUuQ8h34E", 11 | "$entitySet": "assets" 12 | } -------------------------------------------------------------------------------- /data/samples/Invoice/invoice-styles.css/content.css: -------------------------------------------------------------------------------- 1 | .invoice-box { 2 | max-width: 800px; 3 | margin: auto; 4 | padding: 30px; 5 | border: 1px solid #eee; 6 | box-shadow: 0 0 10px rgba(0, 0, 0, .15); 7 | font-size: 16px; 8 | line-height: 24px; 9 | font-family: 'Helvetica Neue', 'Helvetica', Helvetica, Arial, sans-serif; 10 | color: #555; 11 | } 12 | .invoice-box table { 13 | width: 100%; 14 | line-height: inherit; 15 | text-align: left; 16 | } 17 | .invoice-box table td { 18 | padding: 5px; 19 | vertical-align: top; 20 | } 21 | .invoice-box table tr td:nth-child(2) { 22 | text-align: right; 23 | } 24 | .invoice-box table tr.top table td { 25 | padding-bottom: 20px; 26 | } 27 | .invoice-box table tr.top table td.title { 28 | font-size: 45px; 29 | line-height: 45px; 30 | color: #333; 31 | } 32 | .invoice-box table tr.information table td { 33 | padding-bottom: 40px; 34 | } 35 | .invoice-box table tr.heading td { 36 | background: #eee; 37 | border-bottom: 1px solid #ddd; 38 | font-weight: bold; 39 | } 40 | .invoice-box table tr.details td { 41 | padding-bottom: 20px; 42 | } 43 | .invoice-box table tr.item td { 44 | border-bottom: 1px solid #eee; 45 | } 46 | .invoice-box table tr.item.last td { 47 | border-bottom: none; 48 | } 49 | .invoice-box table tr.total td:nth-child(2) { 50 | border-top: 2px solid #eee; 51 | font-weight: bold; 52 | } 53 | @media only screen and (max-width: 600px) { 54 | .invoice-box table tr.top table td { 55 | width: 100%; 56 | display: block; 57 | text-align: center; 58 | } 59 | .invoice-box table tr.information table td { 60 | width: 100%; 61 | display: block; 62 | text-align: center; 63 | } 64 | } -------------------------------------------------------------------------------- /data/samples/Orders/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "shortid": "erkLzi", 3 | "name": "Orders", 4 | "inheritedReadPermissions": [], 5 | "inheritedEditPermissions": [], 6 | "creationDate": { 7 | "$$date": 1652806413832 8 | }, 9 | "modificationDate": { 10 | "$$date": 1652806413832 11 | }, 12 | "_id": "er5ZzDTsdM5cFJQj", 13 | "$entitySet": "folders" 14 | } -------------------------------------------------------------------------------- /data/samples/Orders/orders-header/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "shortid": "SJVbqZr9f", 3 | "name": "orders-header", 4 | "recipe": "chrome-pdf", 5 | "engine": "handlebars", 6 | "chrome": { 7 | "printBackground": true, 8 | "marginTop": "1.5cm", 9 | "marginRight": "1.5cm", 10 | "marginLeft": "1.cm" 11 | }, 12 | "inheritedReadPermissions": [], 13 | "inheritedEditPermissions": [], 14 | "creationDate": { 15 | "$$date": 1652806414018 16 | }, 17 | "modificationDate": { 18 | "$$date": 1652806414018 19 | }, 20 | "_id": "e92KS8QvOx4ccb9T", 21 | "$entitySet": "templates" 22 | } -------------------------------------------------------------------------------- /data/samples/Orders/orders-header/content.handlebars: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | {{#each $pdf.pages}} 10 | {{#if @index}} 11 |
12 | {{/if}} 13 |
14 |
15 | {{#with (lookup ../$pdf.pages @index)}} 16 |

{{group}}

17 | {{/with}} 18 |
19 | 22 |
23 | {{/each}} 24 | 25 | 26 | -------------------------------------------------------------------------------- /data/samples/Orders/orders-header/footerTemplate.handlebars: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsreport/jsreport-aws-lambda-starter-kit/fc4ea3fa6ccd6fd7446e5ceb655477d5b1580682/data/samples/Orders/orders-header/footerTemplate.handlebars -------------------------------------------------------------------------------- /data/samples/Orders/orders-header/headerTemplate.handlebars: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsreport/jsreport-aws-lambda-starter-kit/fc4ea3fa6ccd6fd7446e5ceb655477d5b1580682/data/samples/Orders/orders-header/headerTemplate.handlebars -------------------------------------------------------------------------------- /data/samples/Orders/orders-header/helpers.js: -------------------------------------------------------------------------------- 1 | function getPageNumber (pageIndex) { 2 | if (pageIndex == null) { 3 | return '' 4 | } 5 | 6 | const pageNumber = pageIndex + 1 7 | 8 | return pageNumber 9 | } 10 | 11 | function getTotalPages (pages) { 12 | if (!pages) { 13 | return '' 14 | } 15 | 16 | return pages.length 17 | } 18 | -------------------------------------------------------------------------------- /data/samples/Orders/orders-main/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "phantom": { 3 | "waitForJS": true 4 | }, 5 | "recipe": "chrome-pdf", 6 | "engine": "handlebars", 7 | "scripts": [ 8 | { 9 | "shortid": "BJX1Jw82ce" 10 | } 11 | ], 12 | "shortid": "HJH11D83ce", 13 | "name": "orders-main", 14 | "chrome": { 15 | "printBackground": true, 16 | "marginTop": "4cm", 17 | "marginRight": "1.5cm", 18 | "marginBottom": "1.5cm", 19 | "marginLeft": "1.5cm", 20 | "waitForJS": false 21 | }, 22 | "pdfOperations": [ 23 | { 24 | "type": "merge", 25 | "templateShortid": "SJVbqZr9f", 26 | "renderForEveryPage": false, 27 | "mergeWholeDocument": true 28 | } 29 | ], 30 | "inheritedReadPermissions": [], 31 | "inheritedEditPermissions": [], 32 | "creationDate": { 33 | "$$date": 1652806413998 34 | }, 35 | "modificationDate": { 36 | "$$date": 1652806413998 37 | }, 38 | "_id": "prbX4MvuDLbDZwS8", 39 | "$entitySet": "templates" 40 | } -------------------------------------------------------------------------------- /data/samples/Orders/orders-main/content.handlebars: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {{#each orders}} 21 | 23 | {{{pdfCreatePagesGroup country}}} 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | {{#each rows}} 36 | 37 | 38 | 39 | 40 | 41 | 42 | {{/each}} 43 | 44 |
OrderIDShipAddressShipCityShipCountry
{{OrderID}}{{ShipAddress}}{{ShipCity}}{{ShipCountry}}
45 | 46 | 78 |
79 |
80 | {{/each}} 81 | 82 | 83 | -------------------------------------------------------------------------------- /data/samples/Orders/orders-main/footerTemplate.handlebars: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsreport/jsreport-aws-lambda-starter-kit/fc4ea3fa6ccd6fd7446e5ceb655477d5b1580682/data/samples/Orders/orders-main/footerTemplate.handlebars -------------------------------------------------------------------------------- /data/samples/Orders/orders-main/headerTemplate.handlebars: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsreport/jsreport-aws-lambda-starter-kit/fc4ea3fa6ccd6fd7446e5ceb655477d5b1580682/data/samples/Orders/orders-main/headerTemplate.handlebars -------------------------------------------------------------------------------- /data/samples/Orders/orders-main/helpers.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jsreport/jsreport-aws-lambda-starter-kit/fc4ea3fa6ccd6fd7446e5ceb655477d5b1580682/data/samples/Orders/orders-main/helpers.js -------------------------------------------------------------------------------- /data/samples/Orders/orders-script/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "shortid": "BJX1Jw82ce", 3 | "name": "orders-script", 4 | "inheritedReadPermissions": [], 5 | "inheritedEditPermissions": [], 6 | "creationDate": { 7 | "$$date": 1652806414162 8 | }, 9 | "modificationDate": { 10 | "$$date": 1652806414162 11 | }, 12 | "_id": "pFGei1vCcTedQWrW", 13 | "$entitySet": "scripts" 14 | } -------------------------------------------------------------------------------- /data/samples/Orders/orders-script/content.js: -------------------------------------------------------------------------------- 1 | // server side script fetching remote data and preparing report data source 2 | const https = require('https'); 3 | 4 | // call remote http rest api 5 | function fetchOrders() { 6 | return new Promise((resolve, reject) => { 7 | https.get('https://services.odata.org/V4/Northwind/Northwind.svc/Orders', 8 | (result) => { 9 | var str = ''; 10 | result.on('data', (b) => str += b); 11 | result.on('error', reject); 12 | result.on('end', () => resolve(JSON.parse(str).value)); 13 | }); 14 | }) 15 | } 16 | 17 | // group the data for report 18 | async function prepareDataSource() { 19 | const orders = await fetchOrders() 20 | const ordersByShipCountry = orders.reduce((a, v) => { 21 | a[v.ShipCountry] = a[v.ShipCountry] || [] 22 | a[v.ShipCountry].push(v) 23 | return a 24 | }, {}) 25 | 26 | return Object.keys(ordersByShipCountry).map((country) => { 27 | const ordersInCountry = ordersByShipCountry[country] 28 | 29 | const accumulated = {} 30 | 31 | ordersInCountry.forEach((o) => { 32 | o.OrderDate = new Date(o.OrderDate); 33 | const key = o.OrderDate.getFullYear() + '/' + (o.OrderDate.getMonth() + 1); 34 | accumulated[key] = accumulated[key] || { 35 | value: 0, 36 | orderDate: o.OrderDate 37 | }; 38 | accumulated[key].value++; 39 | }); 40 | 41 | return { 42 | rows: ordersInCountry, 43 | country, 44 | accumulated 45 | } 46 | 47 | }).slice(0, 2) 48 | } 49 | 50 | // add jsreport hook which modifies the report input data 51 | async function beforeRender(req, res) { 52 | req.data.orders = await prepareDataSource() 53 | } -------------------------------------------------------------------------------- /data/samples/Orders/orders-styles.css/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "orders-styles.css", 3 | "shortid": "IEWXRnJ", 4 | "inheritedReadPermissions": [], 5 | "inheritedEditPermissions": [], 6 | "creationDate": { 7 | "$$date": 1652806414074 8 | }, 9 | "modificationDate": { 10 | "$$date": 1652806414074 11 | }, 12 | "_id": "cjZMMZlqwAkRZlag", 13 | "$entitySet": "assets" 14 | } -------------------------------------------------------------------------------- /data/samples/Orders/orders-styles.css/content.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | html, body { 6 | margin: 0px; 7 | padding: 0px; 8 | } 9 | 10 | .main { 11 | display: flex; 12 | flex-direction: column; 13 | justify-content: space-between; 14 | width: 100%; 15 | height: 100%; 16 | } 17 | 18 | .header { 19 | width: 100%; 20 | padding-top: 10px; 21 | } 22 | 23 | .footer { 24 | width: 100%; 25 | padding-bottom: 20px; 26 | border-top: 1px solid black; 27 | } -------------------------------------------------------------------------------- /data/samples/Sales/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Sales", 3 | "shortid": "FnHe~Wz", 4 | "creationDate": { 5 | "$$date": 1652806413867 6 | }, 7 | "modificationDate": { 8 | "$$date": 1652806413867 9 | }, 10 | "_id": "2RwOcmuwT2gpC7uL", 11 | "$entitySet": "folders" 12 | } -------------------------------------------------------------------------------- /data/samples/Sales/sales-data/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "shortid": "B1lSTrt6NB", 3 | "name": "sales-data", 4 | "creationDate": { 5 | "$$date": 1652806413917 6 | }, 7 | "modificationDate": { 8 | "$$date": 1652806413917 9 | }, 10 | "_id": "az7sT3N7gapUGxww", 11 | "$entitySet": "data" 12 | } -------------------------------------------------------------------------------- /data/samples/Sales/sales-data/dataJson.json: -------------------------------------------------------------------------------- 1 | { 2 | "customer": "Walker Group", 3 | "month": "April", 4 | "taxPercentage": 0.20, 5 | "detail": [{ 6 | "date": "2019-04-03", 7 | "product": "Vitamin C", 8 | "category": "Health", 9 | "unitPrice": 25, 10 | "quantity": 1, 11 | "discountPercentage": 0 12 | }, { 13 | "date": "2019-04-03", 14 | "product": "Probiotics", 15 | "category": "Health", 16 | "unitPrice": 83, 17 | "quantity": 1, 18 | "discountPercentage": 0.25 19 | }, { 20 | "date": "2019-04-04", 21 | "product": "Mild Bubble Cleanser", 22 | "category": "Cleansing", 23 | "unitPrice": 13, 24 | "quantity": 2, 25 | "discountPercentage": 0 26 | }, { 27 | "date": "2019-04-04", 28 | "product": "Deep Cleanser", 29 | "category": "Cleansing", 30 | "unitPrice": 12, 31 | "quantity": 3, 32 | "discountPercentage": 0 33 | }, { 34 | "date": "2019-04-04", 35 | "product": "Atomy Men Set", 36 | "category": "Men Skin Care", 37 | "unitPrice": 54, 38 | "quantity": 1, 39 | "discountPercentage": 0.35 40 | }, { 41 | "date": "2019-04-09", 42 | "product": "BB Cream", 43 | "category": "Make-Up", 44 | "unitPrice": 12, 45 | "quantity": 3, 46 | "discountPercentage": 0 47 | }, { 48 | "date": "2019-04-15", 49 | "product": "Lipstick Poppy", 50 | "category": "Make-Up", 51 | "unitPrice": 22, 52 | "quantity": 1, 53 | "discountPercentage": 0 54 | }, { 55 | "date": "2019-04-15", 56 | "product": "Healthy Glow Base", 57 | "category": "Make-Up", 58 | "unitPrice": 18, 59 | "quantity": 2, 60 | "discountPercentage": 0.12 61 | }, { 62 | "date": "2019-04-26", 63 | "product": "Lotion", 64 | "category": "Skin Care", 65 | "unitPrice": 23, 66 | "quantity": 1, 67 | "discountPercentage": 0 68 | }] 69 | } -------------------------------------------------------------------------------- /data/samples/Sales/sales-main/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "shortid": "B1Q2SFTNr", 3 | "name": "sales-main", 4 | "recipe": "html-to-xlsx", 5 | "engine": "handlebars", 6 | "chrome": { 7 | "printBackground": true 8 | }, 9 | "htmlToXlsx": { 10 | "htmlEngine": "chrome" 11 | }, 12 | "data": { 13 | "shortid": "B1lSTrt6NB" 14 | }, 15 | "creationDate": { 16 | "$$date": 1652806413951 17 | }, 18 | "modificationDate": { 19 | "$$date": 1652806413951 20 | }, 21 | "_id": "2KaorlenrmxKinSu", 22 | "$entitySet": "templates" 23 | } -------------------------------------------------------------------------------- /data/samples/Sales/sales-main/content.handlebars: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | {{generateEmptyCell 7}} 23 | 24 | 25 | {{generateEmptyCell 1}} 26 | 27 | 28 | {{generateEmptyCell 1 "content border-top"}} 29 | 30 | 31 | {{generateEmptyCell 1}} 32 | 33 | 34 | {{generateEmptyCell 1}} 35 | 36 | 37 | {{generateEmptyCell 1 "content border-bottom"}} 38 | 39 | 40 | 41 | {{generateEmptyCell 1}} 42 | 43 | 44 | {{generateEmptyCell 7}} 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | {{#each detail}} 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | {{/each}} 68 | 69 | {{generateEmptyCell 5}} 70 | 71 | 72 | 73 | 74 | {{generateEmptyCell 5}} 75 | 76 | 77 | 78 | 79 | {{generateEmptyCell 5}} 80 | 81 | 82 | 83 | 84 |
SALES DETAIL
Customer{{customer}}Report Date{{nowStr}}
Month{{month}}Tax{{taxPercentage}}
DateProductCategoryUnit PriceQuantityDiscountAmount
{{date}}{{product}}{{category}}{{unitPrice}}{{quantity}}{{discountPercentage}}=(D{{getDetailRowIndex @index}}*E{{getDetailRowIndex @index}}) - (D{{getDetailRowIndex @index}}*E{{getDetailRowIndex @index}}*F{{getDetailRowIndex @index}})
Total Net Amount $=SUM(G{{getDetailRowIndex 0}}:G{{getDetailRowIndex (sum detail.length -1)}})
=CONCATENATE("VAT (", F4*100, "%)", " $")=G{{getDetailRowIndex detail.length}}*F4
Total $=SUM(G{{getDetailRowIndex detail.length}}:GG{{getDetailRowIndex (sum detail.length 1)}})
85 | 86 | 87 | -------------------------------------------------------------------------------- /data/samples/Sales/sales-main/helpers.js: -------------------------------------------------------------------------------- 1 | const moment = require('moment') 2 | const rowOffset = 6 3 | 4 | function nowStr () { 5 | return moment().format('YYYY-MM-DD') 6 | } 7 | 8 | function generateEmptyCell (repeat, className) { 9 | const cells = [] 10 | 11 | for (let i = 0; i < repeat; i++) { 12 | cells.push(``) 13 | } 14 | 15 | return new Handlebars.SafeString(cells.join('')) 16 | } 17 | 18 | function oddClassName (index) { 19 | return (index + 1) % 2 !== 0 ? 'odd' : '' 20 | } 21 | 22 | function sum (a, b) { 23 | return a + b 24 | } 25 | 26 | function getDetailRowIndex (index) { 27 | return (index + 1) + rowOffset 28 | } -------------------------------------------------------------------------------- /data/samples/Sales/sales-styles.css/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sales-styles.css", 3 | "shortid": "B1m9OJE", 4 | "creationDate": { 5 | "$$date": 1652806414118 6 | }, 7 | "modificationDate": { 8 | "$$date": 1652806414118 9 | }, 10 | "_id": "cTpjMA2CHjl3A6jM", 11 | "$entitySet": "assets" 12 | } -------------------------------------------------------------------------------- /data/samples/Sales/sales-styles.css/content.css: -------------------------------------------------------------------------------- 1 | table { 2 | border-collapse: collapse; 3 | } 4 | 5 | .empty-cell { 6 | padding-top: 10px; 7 | padding-bottom: 10px; 8 | } 9 | 10 | td:not(.empty-cell) { 11 | min-width: 100px; 12 | } 13 | 14 | .t-left { 15 | text-align: left; 16 | } 17 | 18 | .t-center { 19 | text-align: center; 20 | } 21 | 22 | .t-right { 23 | text-align: right; 24 | } 25 | 26 | .head .title { 27 | background-color: #70AD47; 28 | color: #fff; 29 | font-size: 21px; 30 | font-weight: bold; 31 | text-align: center; 32 | } 33 | 34 | .label { 35 | font-weight: bold; 36 | } 37 | 38 | .head .content { 39 | background-color: #fff; 40 | padding: 2px; 41 | } 42 | 43 | .head .border-top { 44 | border-top: 1px solid #000; 45 | } 46 | 47 | .head .border-left { 48 | border-left: 1px solid #000; 49 | } 50 | 51 | .head .border-right { 52 | border-right: 1px solid #000; 53 | } 54 | 55 | .head .border-bottom { 56 | border-bottom: 1px solid #000; 57 | } 58 | 59 | .detail { 60 | border: 1px solid #BEDBAA; 61 | } 62 | 63 | .detail th { 64 | background-color: #70AD47; 65 | border: 1px solid #BEDBAA; 66 | color: #fff; 67 | font-weight: bold; 68 | } 69 | 70 | .detail .odd td { 71 | background-color: #E2EFDA; 72 | border-top: 1px solid #BEDBAA; 73 | border-bottom: 1px solid #BEDBAA; 74 | } 75 | 76 | .detail td { 77 | padding: 4px; 78 | } -------------------------------------------------------------------------------- /data/samples/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "samples", 3 | "creationDate": { 4 | "$$date": 1652806413785 5 | }, 6 | "modificationDate": { 7 | "$$date": 1652806413785 8 | }, 9 | "shortid": "AKZn3N9", 10 | "_id": "e8V2KOhXBStO2iZx", 11 | "$entitySet": "folders" 12 | } -------------------------------------------------------------------------------- /data/samples/shared/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "shortid": "dOoi1a", 3 | "name": "shared", 4 | "creationDate": { 5 | "$$date": 1652806413850 6 | }, 7 | "modificationDate": { 8 | "$$date": 1652806413850 9 | }, 10 | "_id": "Q965D4kOFi8DW7U3", 11 | "$entitySet": "folders" 12 | } -------------------------------------------------------------------------------- /data/samples/shared/global helpers.js/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "shortid": "SkMw3X69l", 3 | "isSharedHelper": true, 4 | "name": "global helpers.js", 5 | "creationDate": { 6 | "$$date": 1652806414097 7 | }, 8 | "modificationDate": { 9 | "$$date": 1652806414097 10 | }, 11 | "_id": "tAUpN5MEdFz7hbok", 12 | "$entitySet": "assets" 13 | } -------------------------------------------------------------------------------- /data/samples/shared/global helpers.js/content.js: -------------------------------------------------------------------------------- 1 | function nowLocalStr () { 2 | return new Date().toLocaleDateString() 3 | } 4 | -------------------------------------------------------------------------------- /data/settings: -------------------------------------------------------------------------------- 1 | {"key":"core-migrated-xlsxTemplates","value":"true","creationDate":{"$$date":1652806413453},"modificationDate":{"$$date":1652806413453},"shortid":"cR5im0O","_id":"w1P9dYlvUlkQeMtn","$entitySet":"settings"} 2 | {"key":"core-migrated-resources","value":"true","creationDate":{"$$date":1652806413493},"modificationDate":{"$$date":1652806413493},"shortid":"QzcimMy","_id":"ZHQaqtKcYUqndCZL","$entitySet":"settings"} 3 | {"key":"core-migrated-versionControl-props","value":"true","creationDate":{"$$date":1652806413723},"modificationDate":{"$$date":1652806413723},"shortid":"EI2nYTm","_id":"6opsXStNPm6iUywV","$entitySet":"settings"} 4 | {"key":"chrome-network-idle-migrated","value":"true","creationDate":{"$$date":1652806413736},"modificationDate":{"$$date":1652806413736},"shortid":"WR-aUH4","_id":"3Ii61lMJuW2pp3BS","$entitySet":"settings"} 5 | {"key":"sample-created","value":"true","creationDate":{"$$date":1652806413750},"modificationDate":{"$$date":1652806413750},"shortid":"0IevL6F","_id":"D1nnX0OZpmm5OHkO","$entitySet":"settings"} 6 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const JsReport = require('jsreport') 2 | const FS = require('fs-extra') 3 | const path = require('path') 4 | const os = require('os') 5 | 6 | const chromium = require("@sparticuz/chromium") 7 | chromium.setHeadlessMode = true 8 | 9 | // Optional: Load any fonts you need. Open Sans is included by default in AWS Lambda instances 10 | /*await chromium.font( 11 | "https://raw.githack.com/googlei18n/noto-emoji/master/fonts/NotoColorEmoji.ttf" 12 | )*/ 13 | 14 | let jsreport 15 | 16 | console.log('starting') 17 | 18 | const init = (async () => { 19 | // this speeds up cold start by some ~500ms 20 | precreateExtensionsLocationsCache() 21 | 22 | jsreport = JsReport({ 23 | configFile: path.join(__dirname, 'prod.config.json'), 24 | chrome: { 25 | launchOptions: { 26 | args: chromium.args, 27 | defaultViewport: chromium.defaultViewport, 28 | executablePath: await chromium.executablePath(), 29 | headless: chromium.headless, 30 | ignoreHTTPSErrors: true, 31 | } 32 | } 33 | }) 34 | await FS.copy(path.join(__dirname, 'data'), '/tmp/data') 35 | return jsreport.init() 36 | })() 37 | 38 | exports.handler = async (event) => { 39 | console.log('handling event') 40 | await init 41 | 42 | const res = await jsreport.render(event.renderRequest) 43 | 44 | const response = { 45 | statusCode: 200, 46 | body: res.content.toString('base64'), 47 | } 48 | 49 | return response 50 | } 51 | 52 | async function precreateExtensionsLocationsCache() { 53 | const rootDir = path.join(path.dirname(require.resolve('jsreport')), '../../') 54 | const locationsPath = path.join(rootDir, 'node_modules/locations.json') 55 | 56 | if (FS.existsSync(locationsPath)) { 57 | console.log('locations.json found, extensions crawling will be skipped') 58 | const locations = JSON.parse(FS.readFileSync(locationsPath)).locations 59 | const tmpLocationsPath = path.join(os.tmpdir(), 'jsreport', 'core', 'locations.json') 60 | FS.ensureFileSync(tmpLocationsPath) 61 | FS.writeFileSync(tmpLocationsPath, JSON.stringify({ 62 | [path.join(rootDir, 'node_modules') + '/']: { 63 | rootDirectory: rootDir, 64 | locations: locations.map(l => path.join(rootDir, l).replace(/\\/g, '/')), 65 | lastSync: Date.now() 66 | } 67 | })) 68 | 69 | } else { 70 | console.log('locations.json not found, the startup will be a bit slower') 71 | } 72 | } -------------------------------------------------------------------------------- /jsreport.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "httpPort": 5488, 3 | "trustUserCode": true, 4 | "store": { 5 | "provider": "fs" 6 | }, 7 | "blobStorage": { 8 | "provider": "fs" 9 | }, 10 | "timeout": 60000, 11 | "extensions": { 12 | "studio": { 13 | "enabled": true 14 | }, 15 | "fs-store": { 16 | "dataDirectory": "data" 17 | }, 18 | "authentication": { 19 | "cookieSession": { 20 | "secret": "" 21 | }, 22 | "admin": { 23 | "username": "admin", 24 | "password": "password" 25 | }, 26 | "enabled": false 27 | }, 28 | "sample-template": { 29 | "createSamples": true 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jsreport-server", 3 | "main": "server.js", 4 | "scripts": { 5 | "start": "node server", 6 | "jsreport": "jsreport" 7 | }, 8 | "jsreport": { 9 | "entryPoint": "server.js" 10 | }, 11 | "dependencies": { 12 | "@sparticuz/chromium": "133.0.0", 13 | "jsreport": "4.9.0", 14 | "fs-extra": "11.1.1" 15 | }, 16 | "devDependencies": { 17 | "aws-sdk": "2.1395.0", 18 | "p-limit": "4.0.0", 19 | "rimraf": "5.0.1", 20 | "archiver": "5.3.1" 21 | } 22 | } -------------------------------------------------------------------------------- /prod.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "httpPort": 5488, 3 | "trustUserCode": true, 4 | "store": { 5 | "provider": "fs" 6 | }, 7 | "blobStorage": { 8 | "provider": "fs", 9 | "dataDirectory": "/tmp/storage" 10 | }, 11 | "timeout": 60000, 12 | "logger": { 13 | "file": { 14 | "silent": true 15 | }, 16 | "error": { 17 | "silent": true 18 | } 19 | }, 20 | "extensions": { 21 | "licensing": { 22 | "useSavedLicenseInfo": false 23 | }, 24 | "authentication": { 25 | "enabled": false 26 | }, 27 | "authorization": { 28 | "enabled": false 29 | }, 30 | "cli": { 31 | "enabled": false 32 | }, 33 | "express": { 34 | "enabled": false 35 | }, 36 | "freeze": { 37 | "enabled": false 38 | }, 39 | "fs-store": { 40 | "dataDirectory": "/tmp/data" 41 | }, 42 | "import-export": { 43 | "enabled": false 44 | }, 45 | "public-templates": { 46 | "enabled": false 47 | }, 48 | "sample-template": { 49 | "enabled": false 50 | }, 51 | "studio": { 52 | "enabled": false 53 | }, 54 | "studio-theme-dark": { 55 | "enabled": false 56 | }, 57 | "tags": { 58 | "enabled": false 59 | }, 60 | "version-control": { 61 | "enabled": false 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const jsreport = require('jsreport')() 2 | 3 | 4 | if (process.env.JSREPORT_CLI) { 5 | // export jsreport instance to make it possible to use jsreport-cli 6 | module.exports = jsreport 7 | } else { 8 | jsreport.init().then(() => { 9 | // running 10 | }).catch((e) => { 11 | // error during startup 12 | console.error(e.stack) 13 | process.exit(1) 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | const AWS = require('aws-sdk') 2 | const fs = require('fs') 3 | 4 | //TODO set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY env variables 5 | const lambda = new AWS.Lambda({ 6 | //TODO 7 | region: 'eu-west-1' 8 | }) 9 | 10 | lambda.invoke({ 11 | //TODO 12 | FunctionName: 'jsfunction', 13 | Payload: JSON.stringify({ 14 | renderRequest: { 15 | template: { 16 | name: 'invoice-main' 17 | } 18 | } 19 | }) 20 | }, (err, res) => { 21 | if (err) { 22 | return console.error(err) 23 | } 24 | 25 | const response = JSON.parse(res.Payload) 26 | if (response.errorMessage) { 27 | console.log(response.errorMessage) 28 | console.log(response.stackTrace) 29 | } else { 30 | fs.writeFileSync('report.pdf', Buffer.from(response.body, 'base64')) 31 | } 32 | }) --------------------------------------------------------------------------------