import { Widget } from "@db_models" import compileWidgetCode from "@utils/compileWidgetCode" import path from "path" export default async ( widgetId, { useCache = true, origin = null, } ) => { if (!widgetId) { throw new Error("Widget ID not defined.") } if (!origin) { throw new Error("Origin not defined.") } // try to find Widget const widget = await Widget.findOne({ _id: widgetId, }).catch(() => { return null }) if (!widget) { throw new Error("Widget not found.") } if (!widget.manifest.main) { throw new Error("Widget entry file not defined") } const requestedVersion = widgetId.split("@")[1] ?? widget.manifest.version let widgetCode = null const finalOrigin = `${origin}/static/widgets/${widgetId}@${requestedVersion}/` const remotePath = `/widgets/${widgetId}@${requestedVersion}/` const remoteEntyFilePath = path.join(remotePath, widget.manifest.main) if (useCache) { widgetCode = await global.redis.get(`${origin}:widget:${widgetId}@${requestedVersion}}`) } if (!widgetCode) { try { widgetCode = await new Promise(async (resolve, reject) => { await global.storage.getObject(process.env.S3_BUCKET, remoteEntyFilePath, (error, dataStream) => { if (error) { return reject(error) } let data = "" dataStream.on("data", (chunk) => { data += chunk }) dataStream.on("end", () => { resolve(data) }) dataStream.on("error", (error) => { reject(error) }) }) }) } catch (error) { throw new Error(`Unable to fetch widget code. ${error.message}`) } try { console.log(`🔌 [widget:${widgetId}] Compiling widget code...`) widgetCode = await compileWidgetCode(widgetCode, widget.manifest, finalOrigin) await global.redis.set(`${origin}:widget:${widgetId}@${requestedVersion}}`, widgetCode) } catch (error) { throw new Error(`Unable to transform widget code. ${error.message}`) } } return widgetCode }