Skip to content

Commit 9988089

Browse files
committed
initial commit
1 parent e45ef28 commit 9988089

35 files changed

+8512
-1
lines changed

.eslintrc.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
module.exports = {
2+
parser: '@typescript-eslint/parser',
3+
parserOptions: {
4+
project: 'tsconfig.json',
5+
tsconfigRootDir: __dirname,
6+
sourceType: 'module',
7+
},
8+
plugins: ['@typescript-eslint/eslint-plugin'],
9+
extends: [
10+
'plugin:@typescript-eslint/recommended',
11+
'plugin:prettier/recommended',
12+
],
13+
root: true,
14+
env: {
15+
node: true,
16+
jest: true,
17+
},
18+
ignorePatterns: ['.eslintrc.js', '**/blah/**'],
19+
rules: {
20+
'@typescript-eslint/no-var-requires':"off",
21+
'@typescript-eslint/interface-name-prefix': 'off',
22+
'@typescript-eslint/explicit-function-return-type': 'off',
23+
'@typescript-eslint/explicit-module-boundary-types': 'off',
24+
'@typescript-eslint/no-explicit-any': 'off',
25+
},
26+
};

.gitignore

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# compiled output
2+
/dist
3+
/node_modules
4+
5+
# Logs
6+
logs
7+
*.log
8+
npm-debug.log*
9+
pnpm-debug.log*
10+
yarn-debug.log*
11+
yarn-error.log*
12+
lerna-debug.log*
13+
14+
# OS
15+
.DS_Store
16+
17+
# Tests
18+
/coverage
19+
/.nyc_output
20+
21+
# IDEs and editors
22+
/.idea
23+
.project
24+
.classpath
25+
.c9/
26+
*.launch
27+
.settings/
28+
*.sublime-workspace
29+
30+
# IDE - VSCode
31+
.vscode/*
32+
!.vscode/settings.json
33+
!.vscode/tasks.json
34+
!.vscode/launch.json
35+
!.vscode/extensions.json

.prettierrc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"singleQuote": true,
3+
"trailingComma": "all"
4+
}

README.md

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,79 @@
11
# nestjs-jsreport-examples
2-
Example app demonstrating NestJS and JSReport integration
2+
3+
```console
4+
git clone https://github.com/moofoo/nestjs-jsreport-examples && cd nestjs-jsreport-examples && yarn && yarn start:dev
5+
```
6+
7+
This repo demonstrates (very basic) NestJS + JSReport integration. The app has six endpoints which generate different reports, taken from the [JSReport Playground](https://playground.jsreport.net/).
8+
9+
The following 'Recipes' are used:
10+
11+
- [DocX](https://jsreport.net/learn/docx)
12+
- [Chrome PDF](https://jsreport.net/learn/chrome-pdf) (html-to-pdf using headless chromium)
13+
- [Xlsx](https://jsreport.net/learn/xlsx)
14+
- [Html-to-Xlsx](https://jsreport.net/learn/html-to-xlsx)
15+
16+
## Report Endpoints
17+
18+
### [http://localhost/reports/students](http://localhost/reports/students)
19+
20+
- DocX
21+
- [Playground Link](https://playground.jsreport.net/w/admin/d7o0nIWc)
22+
23+
### [http://localhost/reports/invoice](http://localhost/reports/invoice)
24+
25+
- DocX
26+
- [Playground Link](https://playground.jsreport.net/w/admin/yo9J3hvu)
27+
28+
### [http://localhost/reports/invoice-xlsx](http://localhost/reports/invoice-xlsx)
29+
30+
- Xlsx
31+
- [Playground Link](https://playground.jsreport.net/w/admin/Lh8Kjc~f)
32+
33+
### [http://localhost/reports/population](http://localhost/reports/population)
34+
35+
- Xlsx
36+
- [Playground Link](https://playground.jsreport.net/w/admin/V71OgRWt)
37+
38+
### [http://localhost/reports/html-to-xlsx](http://localhost/reports/html-to-xlsx)
39+
40+
- Html-to-Xlsx
41+
- [Playground Link](https://playground.jsreport.net/w/admin/h45L49Dp)
42+
43+
### [http://localhost/reports/flight-ticket](http://localhost/reportsflight-ticket)
44+
45+
- Chrome PDF
46+
- [Playground Link](https://playground.jsreport.net/w/admin/ms2EkdfI)
47+
48+
#
49+
50+
All endpoints except for `flight-ticket` endpoint will generate a PDF (instead of .docx or .xlsx) with the query `pdf=1` (i.e, http://localhost/reports/invoice?pdf=1)
51+
52+
## Why do this?
53+
54+
Well, in terms of pure document generation chops (not talking about templating backends, GUIs or workflows), JSReport is more-or-less on par with what is possible using SaaS services like [Bold Reports](https://www.boldreports.com/), [DocxTemplater](https://docxtemplater.com/), [CarboneIO](https://carbone.io), [DocuPilot](https://docupilot.app/), [Formstack](https://www.formstack.com/), etc...
55+
56+
However, unlike those services, JSReports does not gatekeep **ANY** functionality behind payment tiers. Rather, their business model is oriented around usage of their 'Studio' template builder GUI, which has SaaS and self-hosted versions, while the JSReport server code itself is completely open source and accessible.
57+
58+
So, by making use of the [jsreport core package](https://github.com/jsreport/jsreport/tree/master/packages/jsreport-core), and with shockingly little effort, you can have self-hosted document generation that's on-par with any SaaS out there. **For $0.00.**
59+
60+
The [JSReport Studio GUI](https://playground.jsreport.net/w/admin/S3xqZ0Zc) is actually quite good, if that's something you're looking for. Very 'developer oriented' and flexible, unlike other templating backends I've tried (which are usually intended for document creators, not devs).
61+
62+
## Notes
63+
64+
- Passing a string of javascript to create custom template handlers seems...kinda weird? Am I missing something? I suppose it makes more sense in the context of the Studio GUI.
65+
66+
- Note how the jsreport instance config affects the asset placeholder paths in [template.html](src/jsreport/examples/flight-ticket/template.html). Specifically the `rootDirectory` option:
67+
68+
```typescript
69+
this.jsreport = require('@jsreport/jsreport-core')({
70+
sandbox: { allowedModules: '*' },
71+
rootDirectory: __dirname,
72+
extensions: {
73+
assets: {
74+
allowedFiles: '**/*.*',
75+
searchOnDiskIfNotFoundInStore: true,
76+
},
77+
},
78+
});
79+
```

nest-cli.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"$schema": "https://json.schemastore.org/nest-cli",
3+
"collection": "@nestjs/schematics",
4+
"sourceRoot": "src",
5+
"compilerOptions": {"assets": ["**/template.*", "**/*.png", "**/*.css"]}
6+
}

package.json

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
{
2+
"name": "new_nest_app",
3+
"version": "0.0.1",
4+
"description": "",
5+
"author": "",
6+
"private": true,
7+
"license": "UNLICENSED",
8+
"scripts": {
9+
"build": "nest build",
10+
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
11+
"start": "nest start",
12+
"start:dev": "nest start --watch",
13+
"start:debug": "nest start --debug --watch",
14+
"start:prod": "node dist/main",
15+
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
16+
"test": "jest",
17+
"test:watch": "jest --watch",
18+
"test:cov": "jest --coverage",
19+
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
20+
"test:e2e": "jest --config ./test/jest-e2e.json"
21+
},
22+
"dependencies": {
23+
"@jsreport/jsreport-assets": "^3.6.0",
24+
"@jsreport/jsreport-chrome-pdf": "^3.3.0",
25+
"@jsreport/jsreport-core": "^3.11.4",
26+
"@jsreport/jsreport-docx": "^3.7.1",
27+
"@jsreport/jsreport-handlebars": "^3.2.1",
28+
"@jsreport/jsreport-html-to-xlsx": "^3.3.1",
29+
"@jsreport/jsreport-unoconv": "^3.0.1",
30+
"@jsreport/jsreport-xlsx": "^3.4.0",
31+
"@nestjs/common": "^9.4.2",
32+
"@nestjs/core": "^9.4.2",
33+
"@nestjs/platform-express": "^9.4.2",
34+
"bwip-js": "^3.4.0",
35+
"handlebars": "^4.7.7",
36+
"lodash": "^4.17.21",
37+
"moment": "^2.29.4",
38+
"puppeteer": "^20.4.0",
39+
"reflect-metadata": "^0.1.13",
40+
"rxjs": "^7.8.1",
41+
"xlsx": "^0.18.5"
42+
},
43+
"devDependencies": {
44+
"@nestjs/cli": "^9.5.0",
45+
"@nestjs/schematics": "^9.2.0",
46+
"@nestjs/testing": "^9.4.2",
47+
"@types/express": "^4.17.17",
48+
"@types/jest": "29.5.1",
49+
"@types/jsreport": "^2.9.1",
50+
"@types/jsreport-chrome-pdf": "^1.6.3",
51+
"@types/jsreport-core": "^2.0.5",
52+
"@types/jsreport-docx": "^2.8.2",
53+
"@types/jsreport-html-to-xlsx": "^2.0.3",
54+
"@types/jsreport-xlsx": "^1.4.2",
55+
"@types/node": "20.2.3",
56+
"@types/supertest": "^2.0.12",
57+
"@typescript-eslint/eslint-plugin": "^5.59.7",
58+
"@typescript-eslint/parser": "^5.59.7",
59+
"eslint": "^8.41.0",
60+
"eslint-config-prettier": "^8.8.0",
61+
"eslint-plugin-prettier": "^4.2.1",
62+
"jest": "29.5.0",
63+
"prettier": "^2.8.8",
64+
"source-map-support": "^0.5.21",
65+
"supertest": "^6.3.3",
66+
"ts-jest": "29.1.0",
67+
"ts-loader": "^9.4.3",
68+
"ts-node": "^10.9.1",
69+
"tsconfig-paths": "4.2.0",
70+
"typescript": "^5.0.4"
71+
},
72+
"jest": {
73+
"moduleFileExtensions": [
74+
"js",
75+
"json",
76+
"ts"
77+
],
78+
"rootDir": "src",
79+
"testRegex": ".*\\.spec\\.ts$",
80+
"transform": {
81+
"^.+\\.(t|j)s$": "ts-jest"
82+
},
83+
"collectCoverageFrom": [
84+
"**/*.(t|j)s"
85+
],
86+
"coverageDirectory": "../coverage",
87+
"testEnvironment": "node"
88+
}
89+
}

src/app.controller.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Controller, Get } from '@nestjs/common';
2+
3+
@Controller()
4+
export class AppController {
5+
constructor() {
6+
//
7+
}
8+
9+
@Get()
10+
getHello(): string {
11+
return 'Hello World!';
12+
}
13+
}

src/app.module.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { Module } from '@nestjs/common';
2+
import { AppController } from './app.controller';
3+
import { JsReportModule } from './jsreport/jsreport.module';
4+
5+
@Module({
6+
imports: [JsReportModule],
7+
controllers: [AppController],
8+
})
9+
export class AppModule {
10+
//
11+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"ticket": {
3+
"code": "581347789237158",
4+
"classType": "Y",
5+
"passengerName": "Doe/John, Mr.",
6+
"flightCode": "PR013",
7+
"originCode": "MJV",
8+
"originCity": "Madrid",
9+
"destinationCode": "CDG",
10+
"destinationCity": "Paris",
11+
"boardingHour": "05:00",
12+
"gate": 11,
13+
"dateTimestamp": 1563426000000,
14+
"flightHour": "05:30",
15+
"bagCode": "1PCS21KG",
16+
"seat": "28A"
17+
}
18+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/* eslint-disable @typescript-eslint/no-unused-vars */
2+
const bwipjs = require('bwip-js');
3+
4+
async function barcode(text) {
5+
const png = await bwipjs.toBuffer({
6+
bcid: 'pdf417',
7+
text,
8+
columns: 2,
9+
rotate: 'L',
10+
scale: 2,
11+
});
12+
return 'data:image/png;base64,' + png.toString('base64');
13+
}
14+
15+
function getClassTypeInText(type) {
16+
if (type === 'Y') {
17+
return 'Economy';
18+
} else if (type === 'P') {
19+
return 'Premium';
20+
} else if (type === 'B') {
21+
return 'Business';
22+
} else if (type === 'F') {
23+
return 'First';
24+
}
25+
26+
return '';
27+
}
28+
29+
function getDateText(timestamp) {
30+
const monthNames = [
31+
'Jan',
32+
'Feb',
33+
'Mar',
34+
'Apr',
35+
'May',
36+
'Jun',
37+
'Jul',
38+
'Aug',
39+
'Sept',
40+
'Oct',
41+
'Nov',
42+
'Dec',
43+
];
44+
const d = new Date(timestamp);
45+
46+
return `${d.getDate()}${monthNames[d.getMonth()]}`;
47+
}

0 commit comments

Comments
 (0)