372 lines
8.2 KiB
JavaScript
372 lines
8.2 KiB
JavaScript
'use strict';
|
|
|
|
/**
|
|
* Dependencies
|
|
*/
|
|
const EmailAddress = require('./email-address');
|
|
const toCamelCase = require('../helpers/to-camel-case');
|
|
const toSnakeCase = require('../helpers/to-snake-case');
|
|
const deepClone = require('../helpers/deep-clone');
|
|
const deepMerge = require('deepmerge');
|
|
const wrapSubstitutions = require('../helpers/wrap-substitutions');
|
|
|
|
/**
|
|
* Personalization class
|
|
*/
|
|
class Personalization {
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
constructor(data) {
|
|
|
|
//Init array and object placeholders
|
|
this.to = [];
|
|
this.cc = [];
|
|
this.bcc = [];
|
|
this.headers = {};
|
|
this.customArgs = {};
|
|
this.substitutions = {};
|
|
this.substitutionWrappers = ['{{', '}}'];
|
|
this.dynamicTemplateData = {};
|
|
|
|
//Build from data if given
|
|
if (data) {
|
|
this.fromData(data);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* From data
|
|
*/
|
|
fromData(data) {
|
|
|
|
//Expecting object
|
|
if (typeof data !== 'object') {
|
|
throw new Error('Expecting object for Mail data');
|
|
}
|
|
|
|
//Convert to camel case to make it workable, making a copy to prevent
|
|
//changes to the original objects
|
|
data = deepClone(data);
|
|
data = toCamelCase(data, ['substitutions', 'dynamicTemplateData', 'customArgs', 'headers']);
|
|
|
|
//Extract properties from data
|
|
const {
|
|
to, from, cc, bcc, subject, headers, customArgs, sendAt,
|
|
substitutions, substitutionWrappers, dynamicTemplateData,
|
|
} = data;
|
|
|
|
//Set data
|
|
this.setTo(to);
|
|
this.setFrom(from);
|
|
this.setCc(cc);
|
|
this.setBcc(bcc);
|
|
this.setSubject(subject);
|
|
this.setHeaders(headers);
|
|
this.setSubstitutions(substitutions);
|
|
this.setSubstitutionWrappers(substitutionWrappers);
|
|
this.setCustomArgs(customArgs);
|
|
this.setDynamicTemplateData(dynamicTemplateData);
|
|
this.setSendAt(sendAt);
|
|
}
|
|
|
|
/**
|
|
* Set subject
|
|
*/
|
|
setSubject(subject) {
|
|
if (typeof subject === 'undefined') {
|
|
return;
|
|
}
|
|
if (typeof subject !== 'string') {
|
|
throw new Error('String expected for `subject`');
|
|
}
|
|
this.subject = subject;
|
|
}
|
|
|
|
/**
|
|
* Set send at
|
|
*/
|
|
setSendAt(sendAt) {
|
|
if (typeof sendAt === 'undefined') {
|
|
return;
|
|
}
|
|
if (!Number.isInteger(sendAt)) {
|
|
throw new Error('Integer expected for `sendAt`');
|
|
}
|
|
this.sendAt = sendAt;
|
|
}
|
|
|
|
/**
|
|
* Set to
|
|
*/
|
|
setTo(to) {
|
|
if (typeof to === 'undefined') {
|
|
return;
|
|
}
|
|
if (!Array.isArray(to)) {
|
|
to = [to];
|
|
}
|
|
this.to = EmailAddress.create(to);
|
|
}
|
|
|
|
/**
|
|
* Set from
|
|
* */
|
|
setFrom(from) {
|
|
if (typeof from === 'undefined') {
|
|
return;
|
|
}
|
|
this.from = EmailAddress.create(from);
|
|
}
|
|
|
|
/**
|
|
* Add a single to
|
|
*/
|
|
addTo(to) {
|
|
if (typeof to === 'undefined') {
|
|
return;
|
|
}
|
|
this.to.push(EmailAddress.create(to));
|
|
}
|
|
|
|
/**
|
|
* Set cc
|
|
*/
|
|
setCc(cc) {
|
|
if (typeof cc === 'undefined') {
|
|
return;
|
|
}
|
|
if (!Array.isArray(cc)) {
|
|
cc = [cc];
|
|
}
|
|
this.cc = EmailAddress.create(cc);
|
|
}
|
|
|
|
/**
|
|
* Add a single cc
|
|
*/
|
|
addCc(cc) {
|
|
if (typeof cc === 'undefined') {
|
|
return;
|
|
}
|
|
this.cc.push(EmailAddress.create(cc));
|
|
}
|
|
|
|
/**
|
|
* Set bcc
|
|
*/
|
|
setBcc(bcc) {
|
|
if (typeof bcc === 'undefined') {
|
|
return;
|
|
}
|
|
if (!Array.isArray(bcc)) {
|
|
bcc = [bcc];
|
|
}
|
|
this.bcc = EmailAddress.create(bcc);
|
|
}
|
|
|
|
/**
|
|
* Add a single bcc
|
|
*/
|
|
addBcc(bcc) {
|
|
if (typeof bcc === 'undefined') {
|
|
return;
|
|
}
|
|
this.bcc.push(EmailAddress.create(bcc));
|
|
}
|
|
|
|
/**
|
|
* Set headers
|
|
*/
|
|
setHeaders(headers) {
|
|
if (typeof headers === 'undefined') {
|
|
return;
|
|
}
|
|
if (typeof headers !== 'object' || headers === null) {
|
|
throw new Error('Object expected for `headers`');
|
|
}
|
|
this.headers = headers;
|
|
}
|
|
|
|
/**
|
|
* Add a header
|
|
*/
|
|
addHeader(key, value) {
|
|
if (typeof key !== 'string') {
|
|
throw new Error('String expected for header key');
|
|
}
|
|
if (typeof value !== 'string') {
|
|
throw new Error('String expected for header value');
|
|
}
|
|
this.headers[key] = value;
|
|
}
|
|
|
|
/**
|
|
* Set custom args
|
|
*/
|
|
setCustomArgs(customArgs) {
|
|
if (typeof customArgs === 'undefined') {
|
|
return;
|
|
}
|
|
if (typeof customArgs !== 'object' || customArgs === null) {
|
|
throw new Error('Object expected for `customArgs`');
|
|
}
|
|
this.customArgs = customArgs;
|
|
}
|
|
|
|
/**
|
|
* Add a custom arg
|
|
*/
|
|
addCustomArg(key, value) {
|
|
if (typeof key !== 'string') {
|
|
throw new Error('String expected for custom arg key');
|
|
}
|
|
if (typeof value !== 'string') {
|
|
throw new Error('String expected for custom arg value');
|
|
}
|
|
this.customArgs[key] = value;
|
|
}
|
|
|
|
/**
|
|
* Set substitutions
|
|
*/
|
|
setSubstitutions(substitutions) {
|
|
if (typeof substitutions === 'undefined') {
|
|
return;
|
|
}
|
|
if (typeof substitutions !== 'object') {
|
|
throw new Error('Object expected for `substitutions`');
|
|
}
|
|
this.substitutions = substitutions;
|
|
}
|
|
|
|
/**
|
|
* Add a substitution
|
|
*/
|
|
addSubstitution(key, value) {
|
|
if (typeof key !== 'string') {
|
|
throw new Error('String expected for substitution key');
|
|
}
|
|
if (typeof value !== 'string' && typeof value !== 'number') {
|
|
throw new Error('String or Number expected for substitution value');
|
|
}
|
|
this.substitutions[key] = value;
|
|
}
|
|
|
|
/**
|
|
* Reverse merge substitutions, preserving existing ones
|
|
*/
|
|
reverseMergeSubstitutions(substitutions) {
|
|
if (typeof substitutions === 'undefined' || substitutions === null) {
|
|
return;
|
|
}
|
|
if (typeof substitutions !== 'object') {
|
|
throw new Error(
|
|
'Object expected for `substitutions` in reverseMergeSubstitutions'
|
|
);
|
|
}
|
|
this.substitutions = Object.assign({}, substitutions, this.substitutions);
|
|
}
|
|
|
|
/**
|
|
* Set substitution wrappers
|
|
*/
|
|
setSubstitutionWrappers(wrappers) {
|
|
if (typeof wrappers === 'undefined' || wrappers === null) {
|
|
return;
|
|
}
|
|
|
|
if (!Array.isArray(wrappers) || wrappers.length !== 2) {
|
|
throw new Error(
|
|
'Array expected with two elements for `substitutionWrappers`'
|
|
);
|
|
}
|
|
this.substitutionWrappers = wrappers;
|
|
}
|
|
|
|
/**
|
|
* Reverse merge dynamic template data, preserving existing ones
|
|
*/
|
|
deepMergeDynamicTemplateData(dynamicTemplateData) {
|
|
if (typeof dynamicTemplateData === 'undefined' || dynamicTemplateData === null) {
|
|
return;
|
|
}
|
|
if (typeof dynamicTemplateData !== 'object') {
|
|
throw new Error(
|
|
'Object expected for `dynamicTemplateData` in deepMergeDynamicTemplateData'
|
|
);
|
|
}
|
|
this.dynamicTemplateData = deepMerge(dynamicTemplateData, this.dynamicTemplateData);
|
|
}
|
|
|
|
/**
|
|
* Set dynamic template data
|
|
*/
|
|
setDynamicTemplateData(dynamicTemplateData) {
|
|
if (typeof dynamicTemplateData === 'undefined') {
|
|
return;
|
|
}
|
|
if (typeof dynamicTemplateData !== 'object') {
|
|
throw new Error('Object expected for `dynamicTemplateData`');
|
|
}
|
|
this.dynamicTemplateData = dynamicTemplateData;
|
|
}
|
|
|
|
/**
|
|
* To JSON
|
|
*/
|
|
toJSON() {
|
|
|
|
//Get data from self
|
|
const {
|
|
to, from, cc, bcc, subject, headers, customArgs, sendAt,
|
|
substitutions, substitutionWrappers, dynamicTemplateData,
|
|
} = this;
|
|
|
|
//Initialize with mandatory values
|
|
const json = {to};
|
|
|
|
//Arrays
|
|
if (Array.isArray(cc) && cc.length > 0) {
|
|
json.cc = cc;
|
|
}
|
|
if (Array.isArray(bcc) && bcc.length > 0) {
|
|
json.bcc = bcc;
|
|
}
|
|
|
|
//Objects
|
|
if (Object.keys(headers).length > 0) {
|
|
json.headers = headers;
|
|
}
|
|
if (substitutions && Object.keys(substitutions).length > 0) {
|
|
const [left, right] = substitutionWrappers;
|
|
json.substitutions = wrapSubstitutions(substitutions, left, right);
|
|
}
|
|
if (Object.keys(customArgs).length > 0) {
|
|
json.customArgs = customArgs;
|
|
}
|
|
|
|
if (dynamicTemplateData && Object.keys(dynamicTemplateData).length > 0) {
|
|
json.dynamicTemplateData = dynamicTemplateData;
|
|
}
|
|
|
|
//Simple properties
|
|
if (typeof subject !== 'undefined') {
|
|
json.subject = subject;
|
|
}
|
|
if (typeof sendAt !== 'undefined') {
|
|
json.sendAt = sendAt;
|
|
}
|
|
if (typeof from !== 'undefined') {
|
|
json.from = from;
|
|
}
|
|
|
|
//Return as snake cased object
|
|
return toSnakeCase(json, ['substitutions', 'dynamicTemplateData', 'customArgs', 'headers']);
|
|
}
|
|
}
|
|
|
|
//Export class
|
|
module.exports = Personalization;
|