Compare commits
2 Commits
feature/IO
...
feature/IO
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83a1952880 | ||
|
|
a885bdec74 |
304
package-lock.json
generated
304
package-lock.json
generated
@@ -41,6 +41,7 @@
|
||||
"intuit-oauth": "^4.1.3",
|
||||
"ioredis": "^5.4.1",
|
||||
"json-2-csv": "^5.5.6",
|
||||
"juice": "^11.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"moment": "^2.30.1",
|
||||
"moment-timezone": "^0.5.46",
|
||||
@@ -3359,6 +3360,15 @@
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-colors": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
|
||||
"integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
@@ -3927,6 +3937,15 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "12.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
|
||||
"integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/component-emitter": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
|
||||
@@ -4604,6 +4623,31 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/encoding-sniffer": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz",
|
||||
"integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"iconv-lite": "^0.6.3",
|
||||
"whatwg-encoding": "^3.1.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/encoding-sniffer/node_modules/iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/end-of-stream": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
@@ -4690,6 +4734,18 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-goat": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-3.0.0.tgz",
|
||||
"integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
@@ -6046,6 +6102,69 @@
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/juice": {
|
||||
"version": "11.0.0",
|
||||
"resolved": "https://registry.npmjs.org/juice/-/juice-11.0.0.tgz",
|
||||
"integrity": "sha512-sGF8hPz9/Wg+YXbaNDqc1Iuoaw+J/P9lBHNQKXAGc9pPNjCd4fyPai0Zxj7MRtdjMr0lcgk5PjEIkP2b8R9F3w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cheerio": "^1.0.0",
|
||||
"commander": "^12.1.0",
|
||||
"mensch": "^0.3.4",
|
||||
"slick": "^1.12.2",
|
||||
"web-resource-inliner": "^7.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"juice": "bin/juice"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.17"
|
||||
}
|
||||
},
|
||||
"node_modules/juice/node_modules/cheerio": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz",
|
||||
"integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cheerio-select": "^2.1.0",
|
||||
"dom-serializer": "^2.0.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.1.0",
|
||||
"encoding-sniffer": "^0.2.0",
|
||||
"htmlparser2": "^9.1.0",
|
||||
"parse5": "^7.1.2",
|
||||
"parse5-htmlparser2-tree-adapter": "^7.0.0",
|
||||
"parse5-parser-stream": "^7.1.2",
|
||||
"undici": "^6.19.5",
|
||||
"whatwg-mimetype": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/cheeriojs/cheerio?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/juice/node_modules/htmlparser2": {
|
||||
"version": "9.1.0",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz",
|
||||
"integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==",
|
||||
"funding": [
|
||||
"https://github.com/fb55/htmlparser2?sponsor=1",
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.1.0",
|
||||
"entities": "^4.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jwa": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz",
|
||||
@@ -6298,6 +6417,12 @@
|
||||
"cssom": "^0.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/mensch": {
|
||||
"version": "0.3.4",
|
||||
"resolved": "https://registry.npmjs.org/mensch/-/mensch-0.3.4.tgz",
|
||||
"integrity": "sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/merge-descriptors": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
|
||||
@@ -6780,6 +6905,18 @@
|
||||
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/parse5-parser-stream": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
|
||||
"integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"parse5": "^7.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/inikulin/parse5?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/parseurl": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||
@@ -8294,6 +8431,15 @@
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.21.0.tgz",
|
||||
"integrity": "sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.19.8",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
|
||||
@@ -8355,6 +8501,15 @@
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/valid-data-url": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/valid-data-url/-/valid-data-url-3.0.1.tgz",
|
||||
"integrity": "sha512-jOWVmzVceKlVVdwjNSenT4PbGghU0SBIizAev8ofZVgivk/TVHXSbNL8LP6M3spZvkR9/QolkyJavGSX5Cs0UA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
@@ -8379,6 +8534,131 @@
|
||||
"node": ">=6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/web-resource-inliner": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/web-resource-inliner/-/web-resource-inliner-7.0.0.tgz",
|
||||
"integrity": "sha512-NlfnGF8MY9ZUwFjyq3vOUBx7KwF8bmE+ywR781SB0nWB6MoMxN4BA8gtgP1KGTZo/O/AyWJz7HZpR704eaj4mg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-colors": "^4.1.1",
|
||||
"escape-goat": "^3.0.0",
|
||||
"htmlparser2": "^5.0.0",
|
||||
"mime": "^2.4.6",
|
||||
"valid-data-url": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/web-resource-inliner/node_modules/dom-serializer": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
|
||||
"integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.2.0",
|
||||
"entities": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/web-resource-inliner/node_modules/dom-serializer/node_modules/domhandler": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
|
||||
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/web-resource-inliner/node_modules/domhandler": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
|
||||
"integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/web-resource-inliner/node_modules/domutils": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
|
||||
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"dom-serializer": "^1.0.1",
|
||||
"domelementtype": "^2.2.0",
|
||||
"domhandler": "^4.2.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/web-resource-inliner/node_modules/domutils/node_modules/domhandler": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
|
||||
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/web-resource-inliner/node_modules/entities": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
|
||||
"license": "BSD-2-Clause",
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/web-resource-inliner/node_modules/htmlparser2": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-5.0.1.tgz",
|
||||
"integrity": "sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^3.3.0",
|
||||
"domutils": "^2.4.2",
|
||||
"entities": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/htmlparser2?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/web-resource-inliner/node_modules/mime": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
|
||||
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"mime": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
@@ -8407,6 +8687,30 @@
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-encoding": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
|
||||
"integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"iconv-lite": "0.6.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-encoding/node_modules/iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/whatwg-mimetype": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
"intuit-oauth": "^4.1.3",
|
||||
"ioredis": "^5.4.1",
|
||||
"json-2-csv": "^5.5.6",
|
||||
"juice": "^11.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"moment": "^2.30.1",
|
||||
"moment-timezone": "^0.5.46",
|
||||
|
||||
20
server/middleware/validateCanvasRequestMiddleware.js
Normal file
20
server/middleware/validateCanvasRequestMiddleware.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const { isObject } = require("lodash");
|
||||
|
||||
const validateCanvasRequestMiddleware = (req, res, next) => {
|
||||
const { w, h, values, keys, override } = req.body;
|
||||
if (!values || !keys) {
|
||||
return res.status(400).send("Missing required data");
|
||||
}
|
||||
if (override && !isObject(override)) {
|
||||
return res.status(400).send("Override must be an object");
|
||||
}
|
||||
if (w && (!Number.isFinite(w) || w <= 0)) {
|
||||
return res.status(400).send("Width must be a positive number");
|
||||
}
|
||||
if (h && (!Number.isFinite(h) || h <= 0)) {
|
||||
return res.status(400).send("Height must be a positive number");
|
||||
}
|
||||
next();
|
||||
};
|
||||
|
||||
module.exports = validateCanvasRequestMiddleware;
|
||||
@@ -5,89 +5,120 @@ const logger = require("../utils/logger");
|
||||
const { backgroundColors, borderColors } = require("./canvas-colors");
|
||||
const { isObject, defaultsDeep, isNumber } = require("lodash");
|
||||
|
||||
let isProcessing = false;
|
||||
const requestQueue = [];
|
||||
|
||||
const processCanvasRequest = async (req, res) => {
|
||||
try {
|
||||
const { w, h, values, keys, override } = req.body;
|
||||
logger.log("inbound-canvas-creation", "debug", "jsr", null, { w, h, values, keys, override });
|
||||
|
||||
// Set dimensions with defaults
|
||||
const width = isNumber(w) ? w : 500;
|
||||
const height = isNumber(h) ? h : 275;
|
||||
|
||||
const configuration = {
|
||||
type: "doughnut",
|
||||
data: {
|
||||
labels: keys,
|
||||
datasets: [
|
||||
{
|
||||
data: values,
|
||||
backgroundColor: backgroundColors,
|
||||
borderColor: borderColors,
|
||||
borderWidth: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
animation: false,
|
||||
devicePixelRatio: 4,
|
||||
responsive: false,
|
||||
maintainAspectRatio: true,
|
||||
circumference: 180,
|
||||
rotation: -90,
|
||||
plugins: {
|
||||
legend: {
|
||||
labels: {
|
||||
boxWidth: 20,
|
||||
font: {
|
||||
family: "'Montserrat'",
|
||||
size: 10,
|
||||
style: "normal",
|
||||
weight: "normal"
|
||||
}
|
||||
},
|
||||
position: "left"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// If we have a valid override object, merge it with the default configuration object.
|
||||
// This allows for you to override the default configuration with a custom one.
|
||||
const defaults = () => {
|
||||
if (!override || !isObject(override)) {
|
||||
return configuration;
|
||||
}
|
||||
return defaultsDeep(override, configuration);
|
||||
};
|
||||
|
||||
// Generate chart
|
||||
let canvas = createCanvas(width, height);
|
||||
let ctx = canvas.getContext("2d");
|
||||
let chart = new Chart(ctx, defaults());
|
||||
const result = canvas.toDataURL();
|
||||
|
||||
chart.destroy();
|
||||
canvas.width = 0;
|
||||
canvas.height = 0;
|
||||
ctx = null;
|
||||
canvas = null;
|
||||
chart = null;
|
||||
|
||||
res.status(200).send(result);
|
||||
} catch (error) {
|
||||
if (chart) chart.destroy();
|
||||
if (canvas) {
|
||||
canvas.width = 0;
|
||||
canvas.height = 0;
|
||||
}
|
||||
ctx = null;
|
||||
canvas = null;
|
||||
chart = null;
|
||||
|
||||
logger.log("inbound-canvas-creation", "error", "jsr", null, { error: error.message, stack: error.stack });
|
||||
res.status(500).send("Error generating canvas");
|
||||
}
|
||||
};
|
||||
|
||||
const processNextInQueue = async () => {
|
||||
if (requestQueue.length === 0) {
|
||||
isProcessing = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const { req, res } = requestQueue.shift();
|
||||
await processCanvasRequest(req, res);
|
||||
processNextInQueue();
|
||||
};
|
||||
|
||||
exports.canvastest = function (req, res) {
|
||||
//console.log("Incoming test request.", req);
|
||||
res.status(200).send("OK");
|
||||
};
|
||||
|
||||
exports.canvas = function (req, res) {
|
||||
const { w, h, values, keys, override } = req.body;
|
||||
//console.log("Incoming Canvas Request:", w, h, values, keys, override);
|
||||
logger.log("inbound-canvas-creation", "debug", "jsr", null, { w, h, values, keys, override });
|
||||
// Gate required values
|
||||
if (!values || !keys) {
|
||||
res.status(400).send("Missing required data");
|
||||
exports.canvas = async function (req, res) {
|
||||
if (isProcessing) {
|
||||
if (requestQueue.length >= 100) {
|
||||
// Set a maximum queue size
|
||||
return res.status(503).send("Server is busy. Please try again later.");
|
||||
}
|
||||
requestQueue.push({ req, res });
|
||||
logger.log("inbound-canvas-creation-queue", "debug", "jsr", null, { queue: requestQueue.length });
|
||||
return;
|
||||
}
|
||||
|
||||
// Override must be an object if it exists
|
||||
if (override && !isObject(override)) {
|
||||
res.status(400).send("Override must be an object");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the default Width and Height
|
||||
let [width, height] = [500, 275];
|
||||
|
||||
// Allow for custom width and height
|
||||
if (isNumber(w)) {
|
||||
width = w;
|
||||
}
|
||||
if (isNumber(h)) {
|
||||
height = h;
|
||||
}
|
||||
|
||||
const configuration = {
|
||||
type: "doughnut",
|
||||
data: {
|
||||
labels: keys,
|
||||
datasets: [
|
||||
{
|
||||
data: values,
|
||||
backgroundColor: backgroundColors,
|
||||
borderColor: borderColors,
|
||||
borderWidth: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
devicePixelRatio: 4,
|
||||
responsive: false,
|
||||
maintainAspectRatio: true,
|
||||
circumference: 180,
|
||||
rotation: -90,
|
||||
plugins: {
|
||||
legend: {
|
||||
labels: {
|
||||
boxWidth: 20,
|
||||
font: {
|
||||
family: "'Montserrat'",
|
||||
size: 10,
|
||||
style: "normal",
|
||||
weight: "normal"
|
||||
}
|
||||
},
|
||||
position: "left"
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// If we have a valid override object, merge it with the default configuration object.
|
||||
// This allows for you to override the default configuration with a custom one.
|
||||
const defaults = () => {
|
||||
if (!override || !isObject(override)) {
|
||||
return configuration;
|
||||
}
|
||||
return defaultsDeep(override, configuration);
|
||||
};
|
||||
|
||||
res.status(200).send(
|
||||
(() => {
|
||||
const canvas = createCanvas(width, height);
|
||||
const ctx = canvas.getContext("2d");
|
||||
new Chart(ctx, defaults());
|
||||
return canvas.toDataURL();
|
||||
})()
|
||||
);
|
||||
isProcessing = true;
|
||||
await processCanvasRequest(req, res);
|
||||
processNextInQueue();
|
||||
};
|
||||
|
||||
@@ -3,24 +3,36 @@ require("dotenv").config({
|
||||
path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`)
|
||||
});
|
||||
const logger = require("../utils/logger");
|
||||
const inlineCssTool = require("inline-css");
|
||||
//const inlineCssTool = require("inline-css");
|
||||
const juice = require("juice");
|
||||
|
||||
exports.inlinecss = (req, res) => {
|
||||
exports.inlinecss = async (req, res) => {
|
||||
//Perform request validation
|
||||
|
||||
logger.log("email-inline-css", "DEBUG", req.user.email, null, null);
|
||||
|
||||
const { html, url } = req.body;
|
||||
|
||||
inlineCssTool(html, { url: url })
|
||||
.then((inlinedHtml) => {
|
||||
res.send(inlinedHtml);
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.log("email-inline-css-error", "ERROR", req.user.email, null, {
|
||||
error
|
||||
});
|
||||
|
||||
res.send(error);
|
||||
try {
|
||||
const inlinedHtml = juice(html, {
|
||||
applyAttributesTableElements: false,
|
||||
preserveMediaQueries: false,
|
||||
applyWidthAttributes: false
|
||||
});
|
||||
res.send(inlinedHtml);
|
||||
} catch (error) {
|
||||
logger.log("email-inline-css-error", "ERROR", req.user.email, null, {
|
||||
error
|
||||
});
|
||||
res.send(error.message);
|
||||
}
|
||||
|
||||
// inlineCssTool(html, { url: url })
|
||||
// .then((inlinedHtml) => {
|
||||
// res.send(inlinedHtml);
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// logger.log("email-inline-css-error", "ERROR", req.user.email, null, {
|
||||
// error
|
||||
// });
|
||||
|
||||
// });
|
||||
};
|
||||
|
||||
@@ -2,10 +2,11 @@ const express = require("express");
|
||||
const router = express.Router();
|
||||
const { inlinecss } = require("../render/inlinecss");
|
||||
const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware");
|
||||
const validateCanvasRequestMiddleware = require("../middleware/validateCanvasRequestMiddleware");
|
||||
const { canvas } = require("../render/canvas-handler");
|
||||
|
||||
// Define the route for inline CSS rendering
|
||||
router.post("/inlinecss", validateFirebaseIdTokenMiddleware, inlinecss);
|
||||
router.post("/canvas", validateFirebaseIdTokenMiddleware, canvas);
|
||||
router.post("/canvas", [validateFirebaseIdTokenMiddleware, validateCanvasRequestMiddleware], canvas);
|
||||
|
||||
module.exports = router;
|
||||
|
||||
Reference in New Issue
Block a user