Files
speckle-server/packages/server/modules/emails/services/emailRendering.ts
T
Kristaps Fabians Geikins ede566eed9 feat(server): serverInvites refactor + workspace invites CRUD & GQL API (#2530)
* prep for new resources algo

* typescriptifying stuff

* minor types fix

* migrate to resources col

* repo & creation updated, WIP processing/retrieval

* WIP invite processing

* finished finalization refactor

* project invite management

* transformed all invites services

* fixed up projects & core serverinvites resolvers

* test fixes

* WIP workspace create GQL & test

* basic invite creation test works

* a buncha working tests

* more tests

* cancelation tests

* minor invite use refactor

* invite retrieval tasks

* invite use() works as expected

* filtering out broken invites

* enabled invite retrieval by token irregardless of who is it for

* minor adjustments

* tests fix

* test config improvements

* test env adjustment

* extra test case

* making resource access limits harder to ignore

* linter fixes

* eventBus type cleanup

* better generic names

* refactored serverinvites resource migration

* fix(server): better error message in project invite edge case
2024-07-29 14:37:54 +03:00

126 lines
2.8 KiB
TypeScript

import { UserRecord } from '@/modules/core/helpers/types'
import { packageRoot } from '@/bootstrap'
import path from 'path'
import mjml2html from 'mjml'
import * as ejs from 'ejs'
import sanitizeHtml from 'sanitize-html'
export type EmailTemplateServerInfo = {
name: string
canonicalUrl: string
company: string
adminContact: string
}
export type EmailCta = {
title: string
url: string
}
export type EmailBody = {
text: string
mjml: string
}
export type EmailTemplateParams = {
mjml: { bodyStart: string; bodyEnd?: string }
text: { bodyStart: string; bodyEnd?: string }
cta?: {
url: string
title: string
altTitle?: string
}
}
export type EmailInput = {
from?: string
to: string
subject: string
text: string
html: string
}
export type EmailContent = {
text: string
html: string
}
export const renderEmail = async (
templateParams: EmailTemplateParams,
serverInfo: EmailTemplateServerInfo,
user: UserRecord | null = null
): Promise<EmailContent> => {
const [html, text] = await Promise.all([
renderEmailHtml(templateParams, serverInfo, user),
renderEmailText(templateParams, serverInfo)
])
return {
text,
html
}
}
const renderEmailHtml = async (
templateParams: EmailTemplateParams,
serverInfo: EmailTemplateServerInfo,
user: UserRecord | null = null
): Promise<string> => {
const mjmlPath = path.resolve(
packageRoot,
'assets/emails/templates/speckleBasicEmailTemplate.mjml.ejs'
)
const params = {
cta: templateParams.cta,
// i know, the parameter names need reshuffling
body: { mjml: templateParams.mjml.bodyStart },
bodyEnd: { mjml: templateParams.mjml.bodyEnd },
user,
serverInfo
}
const fullMjml = await ejs.renderFile(
mjmlPath,
{ params },
{ cache: false, outputFunctionName: 'print' }
)
const fullHtml = mjml2html(fullMjml, {
filePath: mjmlPath,
mjmlConfigPath: path.resolve(packageRoot, './assets/emails/config/.mjmlconfig')
})
const renderedHtml = ejs.render(fullHtml.html, { params })
return renderedHtml
}
const renderEmailText = async (
templateParams: EmailTemplateParams,
serverInfo: EmailTemplateServerInfo
): Promise<string> => {
const ejsPath = path.resolve(
packageRoot,
'assets/emails/templates/speckleBasicEmailTemplate.txt.ejs'
)
const params = {
cta: templateParams.cta,
text: {
bodyStart: templateParams.text.bodyStart,
bodyEnd: templateParams.text.bodyEnd
},
server: serverInfo
}
const fullText = await ejs.renderFile(
ejsPath,
{ params },
{ cache: false, outputFunctionName: 'print' }
)
return fullText
}
/**
* Sanitize message that potentially has HTML in it
*/
export function sanitizeMessage(message: string, stripAll: boolean = false): string {
return sanitizeHtml(message, {
allowedTags: stripAll ? [] : ['b', 'i', 'em', 'strong']
})
}