fix some bug and update document

This commit is contained in:
Sorawit Bholsithi 2023-10-08 18:29:28 +07:00
parent bb6dbd8055
commit 8c3790bead
9 changed files with 74 additions and 33 deletions

View file

@ -1,35 +1,38 @@
# report-server-ts # report-server-ts
เป็น Web API ออกแบบมาเพื่อสร้างเอกสาร สามารถใช้ frontend โดยตรง เพื่อจะได้ไม่ต้องเขียนโปรแกรมทำเอกสารเฉพาะแต่ละตัวออกมา ปรับปรุงของเดิมจาก เป็น Web API ออกแบบมาเพื่อสร้างเอกสารจาก templste สามารถใช้ frontend โดยตรง เพื่อจะได้ไม่ต้องทำ backend เพื่อสร้างเอกสารเฉพาะตัวออกมา
## Feature & Change ## Feature & Change
- แก้ไขจากเดิมตัวเดิมเป็น JavaScript เป็น TypeScript ตัด pandoc ออก - แก้ไขจากเดิมตัวเดิมเป็น JavaScript เป็น TypeScript ตัด pandoc ออก
- ใช้ docx xlsx เป็น template เพื่อสร้างเอกสารคล้าย Mail Merge ลูกค้าออกแบบเองได้ - ใช้ docx xlsx เป็น template เพื่อสร้างเอกสารคล้าย Mail Merge ลูกค้าออกแบบเองได้
- รายงานเป็นไฟล์แบบเดียวกับ template หรือแปลงเป็น pdf หรือฟอร์แม็ตอื่นๆได้ - รายงานที่ได้เป็นไฟล์แบบเดียวกับ template หรือแปลงเป็น pdf หรือฟอร์แม็ตของ LibreOffice ได้
- แปลงไฟล์จาก MS Office เป็น PDF - แปลงไฟล์จาก MS Office เป็น PDF รองรับการตัดคำไทย
- โค้ดมีการ obfuscator - โค้ดมีการ obfuscator เพื่อลดขนาดและกันลูกค้าเอาโค้ดไปใช้
- API document ด้วย swagger - มี Swagger ไว้ทดสอบ API มี libs/swagger-specs.json เพื่อนำเข้า Postman หรือเครื่องมื่อื่นๆได้
- มีโปรแกรมช่วยทดสอบ template แบบง่ายๆให้ - มีโปรแกรมช่วยทดสอบ template แบบง่ายๆ ให้ทดสอบก่อนเอาเข้าเซิร์ฟเวอร์
- Docker Image จะใช้แบบ Standalone หรือเป็น Microservice ร่วมกับโปรเจ็กอื่นๆได้ ใช้งานทันที - Docker Image จะใช้แบบ Standalone หรือเป็น Microservice ร่วมกับโปรเจ็กอื่นๆได้ ใช้งานทันที
- Docker image เหลือ 1.76GB จากเดิม 3.5GB
## ติดตั้ง ## ติดตั้ง
clone project แล้วไปหัวข้อใช้งานได้เลย หัวนี้ไว้เพื่ออ้างอิงเท่านั้น รันโปรเจ็กบน Linux ,clone project ติดตั้ง Fonts และ LibreOffice ตามวิธีใน Dockerfile แล้วไปหัวข้อการใช้งานได้เลย หัวนี้ไว้เพื่ออ้างอิงเท่านั้น ใช้ node 20.7.0 บน Linux AMD x86-64
ตั้งค่าของ TypeScript [ตามเวปนี้](https://www.geeksforgeeks.org/how-to-use-express-in-typescript/) ให้ใช้ ES module ได้ด้วย ตั้งค่าของ TypeScript [ตามเวปนี้](https://www.geeksforgeeks.org/how-to-use-express-in-typescript/) ให้ใช้ ES module ได้ด้วย
```bash ```bash
npm i express npm i express
npm i -D typescript @types/express @types/node ts-node npm i -D typescript @types/express @types/node ts-node
npm i docx-templates xlsx-template-next swagger-ui-express swagger-jsdoc yaqrcode libreoffice-file-converter npm i docx-templates xlsx-template-next swagger-ui-express swagger-jsdoc yaqrcode cors libreoffice-file-converter
npm i -D @types/swagger-ui-express @types/swagger-jsdoc npm i -D @types/swagger-ui-express @types/swagger-jsdoc @types/cors
# obfuscate code tools # obfuscate code tools
npm i -D javascript-obfuscator npm i -D javascript-obfuscator
# add type support for yaqrcode # add type support for yaqrcode
cd node_modules/yaqrcode cd node_modules/yaqrcode
wget https://raw.githubusercontent.com/zenozeng/node-yaqrcode/master/index.d.ts wget https://raw.githubusercontent.com/zenozeng/node-yaqrcode/master/index.d.ts
``` ```
## การใช้งาน ## การใช้งาน
ดู scripts ใน package.json และ compose.yaml ดู scripts ใน package.json และ compose.yaml ให้ดูให้เข้าใจ การสร้าง docker อิมเมจ จะต้อง swaggergen,obfuscator ก่อน หลังจากนั้นขึ้น Docker registry
บน production ให้ดู compose.yaml จะต้องนำ template ไปเก็บไว้ที่โฟลเดอร์ templates ด้วย
```bash ```bash
npm run dev npm run dev
npm run build npm run build
@ -38,10 +41,12 @@ npm run obfuscator
npm run preview npm run preview
npm run build:docker npm run build:docker
docker compose up -d docker compose up -d
npm run push:docker
``` ```
## ทดสอบ template ## ทดสอบ template
ไปที่โฟลเดอร์ test-run มีโปรแกรมเพื่อทดสอบ template ที่ออกมามาก่อน ไปว่างในเซิร์ฟเวอร์ ใช้ค่า default ได้เลย แปลงไปไฟล์แบบต่างๆที่ Libreoffice รองรับได้ ควรทดสอบรูปแบบข้อมูล(json) ให้เข้ากับ template(docx,xlsx) ถ้าเกิดปัญหา ถ้าค่าไม่ครบ template แบบ docx จะ error log ที่เซิร์ฟเวอร์ ส่วน xlsx ไม่แจ้งปัญหา แค่ไม่แสดงค่านั้นๆ คู่มือการใช้งานที่สมบูรณ์ให้ไปที่เวปของ library ที่ใช้
ไปที่โฟลเดอร์ test-run มีโปรแกรมเพื่อทดสอบ template ให้ทดสอบที่นี้ก่อนเอา template ไปวางในเซิร์ฟเวอร์ มีค่า default สำหรับการทดสอบที่ใช้ได้เลย สามารถแปลงไปไฟล์แบบต่างๆที่ Libreoffice รองรับ(จำเป็นต้องติดตั้ง ) ควรทดสอบรูปแบบข้อมูล(json) ให้เข้ากับ template(docx,xlsx) ถ้าเกิดปัญหา ถ้าค่าไม่ครบ template แบบ docx จะ error log ที่เซิร์ฟเวอร์ ส่วน xlsx ไม่แจ้งปัญหา แค่ไม่แสดงค่านั้นๆ คู่มือการใช้งานที่สมบูรณ์ให้ไปที่เวปของ library ที่ใช้
[docx-templates](https://www.npmjs.com/package/docx-templates) และ [docx-templates](https://www.npmjs.com/package/docx-templates) และ
[xlsx-template-next](https://www.npmjs.com/package/xlsx-template-next) [xlsx-template-next](https://www.npmjs.com/package/xlsx-template-next)
@ -66,9 +71,9 @@ docker run --name rserver -p 80:3000 docker.frappet.com/demo/report-server
# Bun Note # Bun Note
เริ่มแรกในการพอร์ตจาก JavaScript ลองใช้ Bun(TypeScript) แทน Node.js ตัว Bun ค่อนข้างน่าประทับใจใช้ TypeScript โดยตรงไม่ต้องตั้งค่า หรือติดตั้งเพิ่ม แต่มีปัญหากับ libreoffice-file-converter ต้องแก้ค่าใน package.json เริ่มแรกในการพอร์ตจาก JavaScript ลองใช้ Bun(TypeScript) แทน Node.js ตัว Bun ค่อนข้างน่าประทับใจใช้ TypeScript โดยตรงไม่ต้องตั้งค่า หรือติดตั้งเพิ่ม แต่มีปัญหากับ libreoffice-file-converter ต้องแก้ค่าใน package.json
docker-template ฟังก์ชั่นพื้นฐานใช้งานพอได้ ส่วน EXEC กับ custom function ทำงานไม่ได้ คาดว่าเป็นปัญหาจาก eval เลยกลับมาใช้ node เหมือนเดิม
docker-template คาดว่าเป็นปัญหาจาก eval ทำให้ ส่วน EXEC กับ custom function ทำงานไม่ได้ เลยกลับมาใช้ node
## Todo ## Todo
- รองรับ Authentication Header เพื่อให้ยูสเซอร์ในระบบใช้งานได้เท่านั้น - รองรับ Authentication Header เพื่อให้ยูสเซอร์ในระบบใช้งานได้เท่านั้น
- หาทางสร้างเอกสารจาก text เช่น Markdown เป็นเอกสาร MS Office - หาทางสร้างเอกสารจาก text เช่น Markdown เป็นเอกสาร MS Office
- น่าจะทำ license key เผื่อขายให้ลูกค้าติดตั้งใช้งานต่อ (โค้ดที่ผ่าน obfuscator แล้วย้อนกลับมาได้ง่ายหรือเปล่า ?)

2
app.ts
View file

@ -4,6 +4,7 @@
* Node.js reverse proxy pandoc swan * Node.js reverse proxy pandoc swan
* demo frontent public * demo frontent public
*/ */
import cors from "cors"
import swaggerspecs from "./libs/swagger-specs.json" import swaggerspecs from "./libs/swagger-specs.json"
import swaggerUi from "swagger-ui-express" import swaggerUi from "swagger-ui-express"
import express, { Express, Request, Response } from 'express' import express, { Express, Request, Response } from 'express'
@ -12,6 +13,7 @@ import { xlsxTemplateRoute } from './libs/xlsx-template-lib'
import { convertTemplateRoute } from './libs/convert-libs' import { convertTemplateRoute } from './libs/convert-libs'
const app: Express = express() const app: Express = express()
const port: number = Number(process.env.PORT) || 80; const port: number = Number(process.env.PORT) || 80;
app.use(cors());
app.use(express.json()); //application/json app.use(express.json()); //application/json
app.use(express.raw()); //application/octet-stream app.use(express.raw()); //application/octet-stream
app.use(express.urlencoded({ extended: true })); app.use(express.urlencoded({ extended: true }));

View file

@ -2,6 +2,8 @@ version: "3.2"
services: services:
report-server: report-server:
image: docker.frappet.com/demo/report-server:latest image: docker.frappet.com/demo/report-server:latest
restart: unless-stopped
mem_limit: 500m
ports: ports:
- 3000:80 - 3000:80
volumes: volumes:

View file

@ -6,24 +6,19 @@ const swaggerOptions = {
openapi: "3.1.0", openapi: "3.1.0",
info: { info: {
title: "Report Server", title: "Report Server",
version: "0.1.0", version: "0.8.0",
description: description:
"Advance Create and convert document API for microservice.", "Advance create and convert document API for microservice era.",
license: { license: {
name: "by Frappet", name: "by Frappet",
url: "https://frappet.com", url: "https://frappet.com",
}, },
}, },
servers: [ servers: [
{ {url: "https://report-server.frappet.synology.me"},
url: "https://report-server.frappet.synology.me", {url:"https://bma-ehr.frappet.synology.me/"},
}, {url: "http://localhost:3000"},
{ {url: "http://192.168.2.100:3000"},
url: "http://localhost:3000",
},
{
url: "http://192.168.2.100:3000",
},
], ],
}, },
apis: ["./libs/*.ts"], apis: ["./libs/*.ts"],

View file

@ -2,8 +2,8 @@
"openapi": "3.1.0", "openapi": "3.1.0",
"info": { "info": {
"title": "Report Server", "title": "Report Server",
"version": "0.1.0", "version": "0.8.0",
"description": "Advance Create and convert document API for microservice.", "description": "Advance create and convert document API for microservice era.",
"license": { "license": {
"name": "by Frappet", "name": "by Frappet",
"url": "https://frappet.com" "url": "https://frappet.com"
@ -13,6 +13,9 @@
{ {
"url": "https://report-server.frappet.synology.me" "url": "https://report-server.frappet.synology.me"
}, },
{
"url": "https://bma-ehr.frappet.synology.me/"
},
{ {
"url": "http://localhost:3000" "url": "http://localhost:3000"
}, },
@ -281,7 +284,7 @@
"201": { "201": {
"description": "เอกสารถูกสร้างขึ้น created.", "description": "เอกสารถูกสร้างขึ้น created.",
"content": { "content": {
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": { "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {
"schema": { "schema": {
"type": "string", "type": "string",
"format": "binary" "format": "binary"
@ -293,7 +296,7 @@
"format": "binary" "format": "binary"
} }
}, },
"application/vnd.oasis.opendocument.text": { "application/vnd.oasis.opendocument.spreadsheet": {
"schema": { "schema": {
"type": "string", "type": "string",
"format": "binary" "format": "binary"

View file

@ -8,7 +8,7 @@ import { LibreOfficeFileConverter } from 'libreoffice-file-converter';
const TEMPLATE_FOLDER_NAME = "templates/xlsx" const TEMPLATE_FOLDER_NAME = "templates/xlsx"
/** /**
* docxTemplate Uses docx-template to convert input data and template to output buffer. * xlsxTemplate Uses xlsx-template-next to convert input data and template to output buffer.
* You have to handle exception throw by function * You have to handle exception throw by function
* template keep in folder templates * template keep in folder templates
* @param {String} base base path of caller relate to template-docx foler (no trail slash) * @param {String} base base path of caller relate to template-docx foler (no trail slash)
@ -92,7 +92,7 @@ xlsxTemplateRoute.get("/", async function (req, res) {
* 201: * 201:
* description: เอกสารถูกสร้างขึ้น created. * description: เอกสารถูกสร้างขึ้น created.
* content: * content:
* application/vnd.openxmlformats-officedocument.wordprocessingml.document: * application/vnd.openxmlformats-officedocument.spreadsheetml.sheet:
* schema: * schema:
* type: string * type: string
* format: binary * format: binary
@ -100,7 +100,7 @@ xlsxTemplateRoute.get("/", async function (req, res) {
* schema: * schema:
* type: string * type: string
* format: binary * format: binary
* application/vnd.oasis.opendocument.text: * application/vnd.oasis.opendocument.spreadsheet:
* schema: * schema:
* type: string * type: string
* format: binary * format: binary

31
package-lock.json generated
View file

@ -9,6 +9,7 @@
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"cors": "^2.8.5",
"docx-templates": "^4.11.3", "docx-templates": "^4.11.3",
"express": "^4.18.2", "express": "^4.18.2",
"libreoffice-file-converter": "^1.2.1", "libreoffice-file-converter": "^1.2.1",
@ -18,6 +19,7 @@
"yaqrcode": "^0.2.1" "yaqrcode": "^0.2.1"
}, },
"devDependencies": { "devDependencies": {
"@types/cors": "^2.8.14",
"@types/express": "^4.17.18", "@types/express": "^4.17.18",
"@types/node": "^20.8.2", "@types/node": "^20.8.2",
"@types/swagger-jsdoc": "^6.0.1", "@types/swagger-jsdoc": "^6.0.1",
@ -180,6 +182,15 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/cors": {
"version": "2.8.14",
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.14.tgz",
"integrity": "sha512-RXHUvNWYICtbP6s18PnOCaqToK8y14DnLd75c6HfyKf228dxy7pHNOQkxPtvXKp/hINFMDjbYzsj63nnpPMSRQ==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/express": { "node_modules/@types/express": {
"version": "4.17.18", "version": "4.17.18",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.18.tgz", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.18.tgz",
@ -678,6 +689,18 @@
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
}, },
"node_modules/cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"dependencies": {
"object-assign": "^4",
"vary": "^1"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/create-require": { "node_modules/create-require": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
@ -1711,6 +1734,14 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-inspect": { "node_modules/object-inspect": {
"version": "1.12.3", "version": "1.12.3",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",

View file

@ -9,12 +9,14 @@
"serve": "PORT=3000 node dist/app.js", "serve": "PORT=3000 node dist/app.js",
"obfuscator": "tsc && javascript-obfuscator ./dist --output ./dist2 && cp libs/swagger-specs.json dist/libs", "obfuscator": "tsc && javascript-obfuscator ./dist --output ./dist2 && cp libs/swagger-specs.json dist/libs",
"preview": "PORT=3000 node dist2/app.js", "preview": "PORT=3000 node dist2/app.js",
"build:docker": "ts-node libs/create-swagger-spec.ts && tsc && javascript-obfuscator ./dist --output ./dist2&& cp libs/swagger-specs.json dist2/libs && docker build -t docker.frappet.com/demo/report-server ." "build:docker": "ts-node libs/create-swagger-spec.ts && tsc && javascript-obfuscator ./dist --output ./dist2&& cp libs/swagger-specs.json dist2/libs && docker build -t docker.frappet.com/demo/report-server .",
"push:docker": "docker push docker.frappet.com/demo/report-server"
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"cors": "^2.8.5",
"docx-templates": "^4.11.3", "docx-templates": "^4.11.3",
"express": "^4.18.2", "express": "^4.18.2",
"libreoffice-file-converter": "^1.2.1", "libreoffice-file-converter": "^1.2.1",
@ -24,6 +26,7 @@
"yaqrcode": "^0.2.1" "yaqrcode": "^0.2.1"
}, },
"devDependencies": { "devDependencies": {
"@types/cors": "^2.8.14",
"@types/express": "^4.17.18", "@types/express": "^4.17.18",
"@types/node": "^20.8.2", "@types/node": "^20.8.2",
"@types/swagger-jsdoc": "^6.0.1", "@types/swagger-jsdoc": "^6.0.1",

Binary file not shown.