smp-serverless-utils
Version:
Utilities for working with GCP Storage, file handling, and PDF/SVG conversions
126 lines (125 loc) • 5.33 kB
JavaScript
;
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;