RapiPdf
RapiPdf copied to clipboard
Use with node.js
Hello, Is there an example on how we could use this in node js? It would be a great functionality for microservice and serverless applications.
this being a web-component based solution, there isn't any good tooling AFAIK that can render web-components on server
That being said keep an eye on this space, We do have it planned out in our roadmap, but need to wait for lit-ssr to be in some usable form
anther approach would be to factor out the core-engine and create a CLI, it can be done using lit-html-server. I am open for a PR in this direction too
If you need this now, it's possible to do with jsdom. Load up the index.html in there, and mock window.URL.createObjectURL in the DOM and you'll get a blob back with the PDF content.
I'm afraid I don't have a code example but this is what I've been using for the past couple of days. It's just a pain to get the blob output to a file afterwards, but things like this should work so long as you're getting globals from the jsdom window.
For what it's worth, we were able to use RapiPdf in Node.js with something like this:
const fs = require('fs');
const jsdom = require('jsdom');
const virtualConsole = new jsdom.VirtualConsole();
const {JSDOM} = jsdom;
const script = fs.readFileSync('./node_modules/rapipdf/dist/rapipdf-min.js', 'utf-8');
const json = fs.readFileSync('api.json', 'utf-8');
const obj = JSON.parse(json);
const dom = new JSDOM(`
<!doctype html>
<script>${script}</script>
<rapi-pdf id="thedoc"></rapi-pdf>
`, {
virtualConsole,
runScripts: 'dangerously'
});
const {document} = dom.window;
dom.window.onopen = function () {};
dom.window.URL.createObjectURL = (blob) => {
const reader = new dom.window.FileReader();
reader.addEventListener('loadend', () => {
fs.writeFileSync('out.pdf', Buffer.from(reader.result));
});
reader.readAsArrayBuffer(blob);
};
document.addEventListener('DOMContentLoaded', async () => {
const rapiPdf = document.querySelector('rapi-pdf');
rapiPdf.generatePdf(obj);
});
Unfortunately, it stopped working with Node.js 18. Further inspection revealed that the custom element type rapi-pdf failed to register due to a JavaScript error when loaded by jsdom.
JS DOM error: Error: Uncaught [TypeError: Cannot redefine property: onmessage]
at reportException (...\docs\node_modules\jsdom\lib\jsdom\living\helpers\runtime-script-errors.js:66:24)
at processJavaScript (...\docs\node_modules\jsdom\lib\jsdom\living\nodes\HTMLScriptElement-impl.js:240:7)
at HTMLScriptElementImpl._innerEval (...\docs\node_modules\jsdom\lib\jsdom\living\nodes\HTMLScriptElement-impl.js:173:5)
at ...\docs\node_modules\jsdom\lib\jsdom\living\nodes\HTMLScriptElement-impl.js:114:12
at ResourceQueue.push (...\docs\node_modules\jsdom\lib\jsdom\browser\resources\resource-queue.js:53:16)
at HTMLScriptElementImpl._fetchInternalScript (...\docs\node_modules\jsdom\lib\jsdom\living\nodes\HTMLScriptElement-impl.js:113:21)
at HTMLScriptElementImpl._eval (...\docs\node_modules\jsdom\lib\jsdom\living\nodes\HTMLScriptElement-impl.js:167:12)
at HTMLScriptElementImpl._poppedOffStackOfOpenElements (...\docs\node_modules\jsdom\lib\jsdom\living\nodes\HTMLScriptElement-impl.js:130:10)
at JSDOMParse5Adapter.onItemPop (...\docs\node_modules\jsdom\lib\jsdom\browser\parser\html.js:175:43)
at Parser.onItemPop (...\docs\node_modules\parse5\dist\cjs\parser\index.js:158:90) {
detail: TypeError: Cannot redefine property: onmessage
at about:blank:55:149568
at about:blank:55:149574
at Object.<anonymous> (about:blank:55:150731)
at Object.<anonymous> (about:blank:55:150783)
at D (about:blank:6:7214)
at r (about:blank:6:568)
at Object.<anonymous> (about:blank:55:54348)
at Object.<anonymous> (about:blank:55:54589)
at D (about:blank:6:7214)
at r (about:blank:6:568),
type: 'unhandled exception'
}
...\docs\use_rapipdf.js:43
rapiPdf.generatePdf({});
^
TypeError: rapiPdf.generatePdf is not a function
at Document.<anonymous> (...\docs\use_rapipdf.js:43:13)
at Document.callTheUserObjectsOperation (...\docs\node_modules\jsdom\lib\jsdom\living\generated\EventListener.js:26:30)
at innerInvokeEventListeners (...\docs\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:350:25)
at invokeEventListeners (...\docs\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:286:3)
at DocumentImpl._dispatch (...\docs\node_modules\jsdom\lib\jsdom\living\events\EventTarget-impl.js:233:9)
at fireAnEvent (...\docs\node_modules\jsdom\lib\jsdom\living\helpers\events.js:18:36)
at dispatchEvent (...\docs\node_modules\jsdom\lib\jsdom\living\nodes\Document-impl.js:452:9)
at ...\docs\node_modules\jsdom\lib\jsdom\living\nodes\Document-impl.js:457:11
at new Promise (<anonymous>)
at onDOMContentLoad (...\docs\node_modules\jsdom\lib\jsdom\living\nodes\Document-impl.js:455:14)
Node.js v18.16.0
There might be a way to fix this particular problem, but I wouldn't know where to look at the moment.
Update: See jsdom/jsdom#3546