UNPKG

smp-serverless-utils

Version:

Utilities for working with GCP Storage, file handling, and PDF/SVG conversions

126 lines (125 loc) 5.33 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const puppeteer_core_1 = __importDefault(require("puppeteer-core")); const chromium_1 = __importDefault(require("@sparticuz/chromium")); const path_1 = require("path"); const fs_1 = require("fs"); const os_1 = require("os"); const utils_1 = require("./utils"); const chromeArgs_1 = require("./chromeArgs"); const constants_1 = require("./constants"); const tempDir = (0, os_1.tmpdir)(); const exportStory = async ({ title, format = "png", quality = 1, multiplier = 1, organization, storyId, pageUrl, }) => { let browser = null; const fileName = (0, utils_1.getFileName)({ title, format }); const localFilePath = (fileFormat) => (0, path_1.join)(tempDir, `${fileName.split(".")[0]}.${fileFormat}`); browser = await puppeteer_core_1.default.launch({ args: [...chromium_1.default.args, ...chromeArgs_1.minimalArgs], defaultViewport: chromium_1.default.defaultViewport, executablePath: await chromium_1.default.executablePath(), headless: chromium_1.default.headless, // ignoreHTTPSErrors: true, }); const page = await browser.newPage(); console.log("Page URL: ", pageUrl); await page.goto(pageUrl, { waitUntil: "networkidle0" }); await page.waitForSelector(`${constants_1.CANVAS_PREVIEW}`, { timeout: constants_1.TIMEOUT }); const { canvasDataUrl, svgData, pageHeight, pageWidth } = await page.evaluate(async (format, quality, multiplier, FILE_FORMAT, CANVAS_PREVIEW) => { const canvasHTMLElement = document.querySelector(`${CANVAS_PREVIEW}`); if (!canvasHTMLElement) { throw new Error("Canvas element not found."); } const staticCanvas = canvasHTMLElement?.staticCanvas; if (!staticCanvas) { throw new Error("Static canvas not found."); } async function waitForCanvasRender(staticCanvas) { return new Promise((resolve) => { setTimeout(() => { resolve(staticCanvas); }, 500); // Wait for any rendering to complete }); } await waitForCanvasRender(staticCanvas); const convertToSVG = (staticCanvas) => { let svgString = staticCanvas.toSVG({ suppressPreamble: true, viewBox: true, }); const fontStyles = document.querySelectorAll('style[data-type="fontFaceStyle"]'); let style = ""; fontStyles.forEach((fontFaceStyle) => { style = `${style}${fontFaceStyle.outerHTML}\n`; }); if (Boolean(style)) { svgString = svgString.replace("<defs>", `$&${style}`); } return svgString; }; if (format === FILE_FORMAT.SVG || format === FILE_FORMAT.PDF) { const svgString = convertToSVG(staticCanvas); const pageHeight = staticCanvas.actualHeight || 842; // Default A4 size in pixels const pageWidth = staticCanvas.actualWidth || 595; // Default A4 size in pixels return { svgData: svgString, canvasDataUrl: null, pageHeight, pageWidth, }; } const dataURL = staticCanvas.toDataURL({ format: format, quality: quality, multiplier: multiplier, }); return { canvasDataUrl: dataURL, svgData: null, pageHeight: null, pageWidth: null, }; }, format, quality, multiplier, constants_1.FILE_FORMAT, constants_1.CANVAS_PREVIEW); page.close(); let localPath; if (format === constants_1.FILE_FORMAT.SVG) { if (!svgData) throw new Error("svgData is not string. can not convert to a SVG file"); localPath = (0, utils_1.saveSvgToFile)(svgData, tempDir, fileName); } else if (format === constants_1.FILE_FORMAT.PDF) { if (!svgData) throw new Error("svgData is not string. can not convert to a PDF file"); localPath = await (0, utils_1.svgToPDF)(svgData, tempDir, fileName, pageHeight, pageWidth, browser); } else { const base64Data = canvasDataUrl.split(",")[1]; const buffer = Buffer.from(base64Data, "base64"); localPath = localFilePath(format); (0, fs_1.writeFileSync)(localPath, buffer); } const publicUrl = await (0, utils_1.uploadToGCPBucket)(process.env.BUCKET_NAME, localPath, { orgId: String(organization), functionName: "storyExporter", storyId, fileName, }); (0, fs_1.unlinkSync)(localPath); await browser.close(); return { headers: { "Access-Control-Allow-Headers": "Content-Type, Content-Disposition", "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "OPTIONS,POST,GET", }, message: `File uploaded successfully in ${format} format.`, download: { url: publicUrl, key: publicUrl, fileName: fileName, } }; }; exports.default = exportStory;