const Vue = require('vue'); const VueI18n = require('vue-i18n'); const renderer = require('vue-server-renderer').createRenderer(); const fs = require('fs-extra'); const juice = require('juice'); const smtp = require('./smtp'); const i18n = new VueI18n({ locale: 'es', }); Vue.use(VueI18n); if (!process.env.OPENSSL_CONF) process.env.OPENSSL_CONF = '/etc/ssl/'; module.exports = { path: `${appPath}/reports`, /** * Renders a report component * * @param {String} name - Report name * @param {Object} ctx - Request context */ async render(name, ctx) { const component = require(`${this.path}/${name}`); const prefetchedData = await this.preFetch(component, ctx); const app = new Vue({ i18n, render: h => h(component), }); return renderer.renderToString(app).then(renderedHtml => { return { html: renderedHtml, data: prefetchedData, }; }); }, /** * Prefetch all component data from asyncData method * * @param {Object} component - Component object * @param {Object} ctx - Request context */ async preFetch(component, ctx) { const preFetchData = {attachments: []}; let params = {}; let data = {}; if (Object.keys(ctx.body).length > 0) params = ctx.body; if (Object.keys(ctx.query).length > 0) params = ctx.query; await this.attachAssets(component); if (component.hasOwnProperty('data')) data = component.data(); if (component.hasOwnProperty('asyncData')) { const asyncData = await component.asyncData(ctx, params); if (asyncData.locale) { const locale = component.i18n.messages[asyncData.locale]; preFetchData.subject = locale.subject; } if (asyncData.recipient) preFetchData.recipient = asyncData.recipient; const mergedData = {...data, ...asyncData}; component.data = function data() { return mergedData; }; } if (data && data.hasOwnProperty('attachments')) { const fileNames = data.attachments; fileNames.forEach(attachment => { const componentPath = `${this.path}/${component.name}`; let fileSrc = componentPath + attachment; if (attachment.slice(0, 4) === 'http' || attachment.slice(0, 4) === 'https') fileSrc = attachment; const fileName = attachment.split('/').pop(); preFetchData.attachments.push({ filename: fileName, path: fileSrc, cid: attachment, }); }); } if (component.components) { const components = component.components; const promises = []; Object.keys(components).forEach(component => { promises.push(this.preFetch(components[component], ctx)); }); return Promise.all(promises).then(results => { results.forEach(result => { result.attachments.forEach(atth => { preFetchData.attachments.push(atth); }); }); return preFetchData; }); } return preFetchData; }, async attachAssets(component) { const localePath = `${this.path}/${component.name}/locale.js`; const templatePath = `${this.path}/${component.name}/index.html`; const stylePath = `${this.path}/${component.name}/assets/css/style.css`; const template = await fs.readFile(templatePath, 'utf8'); const css = await fs.readFile(stylePath, 'utf8'); component.i18n = require(localePath); component.template = juice.inlineContent(template, css); }, async toEmail(name, ctx) { const rendered = await this.render(name, ctx); const data = rendered.data; const options = { to: data.recipient, subject: data.subject, html: rendered.html, attachments: data.attachments, }; return smtp.send(options); }, };