Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@sendgrid/helpers

Package Overview
Dependencies
Maintainers
16
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sendgrid/helpers - npm Package Compare versions

Comparing version 6.2.1 to 6.3.0

classes/personalization_specs/reverse-merge-dynamic_teplate_data.spec.js

66

classes/mail.js

@@ -24,2 +24,3 @@ 'use strict';

//Initialize array and object properties
this.isDynamic = false;
this.personalizations = [];

@@ -39,2 +40,3 @@ this.attachments = [];

this.substitutionWrappers = null;
this.dynamicTemplateData = null;

@@ -60,3 +62,3 @@ //Process data if given

data = deepClone(data);
data = toCamelCase(data, ['substitutions', 'customArgs', 'headers']);
data = toCamelCase(data, ['substitutions', 'dynamicTemplateData', 'customArgs', 'headers', 'sections']);

@@ -68,3 +70,3 @@ //Extract properties from data

sections, headers, categories, category, customArgs, asm, mailSettings,
trackingSettings, substitutions, substitutionWrappers, isMultiple,
trackingSettings, substitutions, substitutionWrappers, dynamicTemplateData, isMultiple,
} = data;

@@ -90,5 +92,10 @@

this.setTrackingSettings(trackingSettings);
this.setSubstitutions(substitutions);
this.setSubstitutionWrappers(substitutionWrappers);
if (this.isDynamic) {
this.setDynamicTemplateData(dynamicTemplateData)
} else {
this.setSubstitutions(substitutions);
this.setSubstitutionWrappers(substitutionWrappers);
}
//Add contents from text/html properties

@@ -161,3 +168,3 @@ this.addTextContent(text);

/**
* Set template ID
* Set template ID, also checks if the template is dynamic or legacy
*/

@@ -171,2 +178,7 @@ setTemplateId(templateId) {

}
if (templateId.indexOf('d-') === 0) {
this.isDynamic = true;
}
this.templateId = templateId;

@@ -236,2 +248,10 @@ }

//We should either send substitutions or dynamicTemplateData
//depending on the templateId
if (this.isDynamic && personalization.substitutions) {
delete personalization.substitutions;
} else if (personalization.dynamicTemplateData) {
delete personalization.dynamicTemplateData;
}
//Convert to class if needed

@@ -242,4 +262,10 @@ if (!(personalization instanceof Personalization)) {

//Apply substitutions and push to array
this.applySubstitutions(personalization);
//If this is dynamic, set dynamicTemplateData, or set substitutions
if (this.isDynamic) {
this.applyDynamicTemplateData(personalization);
} else {
this.applySubstitutions(personalization);
}
//Push personalization to array
this.personalizations.push(personalization);

@@ -301,2 +327,24 @@ }

/**
* Helper which applies globally set dynamic_template_data to personalizations
*/
applyDynamicTemplateData(personalization) {
if (personalization instanceof Personalization) {
personalization.deepMergeDynamicTemplateData(this.dynamicTemplateData);
}
}
/**
* Set dynamicTemplateData
*/
setDynamicTemplateData(dynamicTemplateData) {
if (typeof dynamicTemplateData === 'undefined') {
return;
}
if (typeof dynamicTemplateData !== 'object') {
throw new Error('Object expected for `dynamicTemplateData`');
}
this.dynamicTemplateData = dynamicTemplateData;
}
/**
* Set content

@@ -390,3 +438,3 @@ */

if (!Array.isArray(categories) ||
!categories.every(cat => typeof cat === 'string')) {
!categories.every(cat => typeof cat === 'string')) {
throw new Error('Array of strings expected for `categories`');

@@ -553,3 +601,3 @@ }

//Return as snake cased object
return toSnakeCase(json, ['substitutions', 'customArgs', 'headers']);
return toSnakeCase(json, ['substitutions', 'dynamicTemplateData', 'customArgs', 'headers', 'sections']);
}

@@ -556,0 +604,0 @@

@@ -43,2 +43,116 @@ 'use strict';

});
describe('#689', function() {
it('should detect dynamic template id', function() {
const mail = new Mail({
personalizations: [{
to: 'test@example.com',
headers: {
'test-header': 'test',
},
}],
from: {
email: 'test@example.com',
},
templateId: 'd-df80613cccc6441ea5cd7c95377bc1ef',
subject: 'test',
content: [{
type: 'text/plain',
value: 'test',
}],
});
expect(mail.isDynamic).to.equal(true);
});
it('should detect legacy template id', function() {
const mail = new Mail({
personalizations: [{
to: 'test@example.com',
headers: {
'test-header': 'test',
},
}],
from: {
email: 'test@example.com',
},
templateId: 'df80613cccc6441ea5cd7c95377bc1ef',
subject: 'test',
content: [{
type: 'text/plain',
value: 'test',
}],
});
expect(mail.isDynamic).to.equal(false);
});
it('should ignore substitutions if templateId is dynamic', function() {
const mail = new Mail({
personalizations: [{
to: 'test@example.com',
headers: {
'test-header': 'test',
},
substitutions: {
test2: 'Test2',
},
dynamicTemplateData: {
test2: 'Testy 2',
test3: 'Testy 3',
},
}],
dynamicTemplateData: {
test1: 'Test 1',
test2: 'Test 2',
},
substitutions: {
test1: 'Test1',
},
from: {
email: 'test@example.com',
},
templateId: 'd-df80613cccc6441ea5cd7c95377bc1ef',
subject: 'test',
content: [{
type: 'text/plain',
value: 'test',
}],
});
expect(mail.substitutions).to.equal(null);
expect(mail.personalizations[0].substitutions).to.deep.equal({});
expect(mail.dynamicTemplateData).to.deep.equal({ test1: 'Test 1', test2: 'Test 2' });
expect(mail.personalizations[0].dynamicTemplateData).to.deep.equal({ test1: 'Test 1', test2: 'Testy 2', test3: 'Testy 3' });
expect(mail.toJSON()).to.deep.equal({
'content': [
{
'type': 'text/plain',
'value': 'test',
},
],
'from': {
'email': 'test@example.com',
},
'personalizations': [
{
'dynamic_template_data': {
'test1': 'Test 1',
'test2': 'Testy 2',
'test3': 'Testy 3',
},
'headers': {
'test-header': 'test',
},
'to': [
{
'email': 'test@example.com',
'name': '',
},
],
},
],
'subject': 'test',
'template_id': 'd-df80613cccc6441ea5cd7c95377bc1ef',
});
});
});
});

@@ -19,4 +19,5 @@ #### Personalization helper specs

- setSubstitutionWrappers() - set-substitutions-wrappers.spec.js
- deepMergeDynamicTemplateData() - reverse-merge-dynamic_template_data.spec.js
- toJSON() - to-json.spec.js
- fromData() - from-data.spec.js
- #527 - 527-camel-case-headers.spec.js

58

classes/personalization_specs/to-json.spec.js

@@ -12,7 +12,7 @@ 'use strict';

*/
describe('Personalization', function() {
describe('Personalization', function () {
//Create new personalization before each test
let p;
beforeEach(function() {
beforeEach(function () {
p = new Personalization();

@@ -22,8 +22,8 @@ });

//JSON conversion
describe('toJSON()', function() {
beforeEach(function() {
describe('toJSON()', function () {
beforeEach(function () {
p.setTo('test@example.org');
});
it('should always have the to field', function() {
it('should always have the to field', function () {
const json = p.toJSON();

@@ -36,3 +36,3 @@ expect(json).to.have.property('to');

});
it('should set the cc field', function() {
it('should set the cc field', function () {
p.setCc('testcc@example.org');

@@ -46,3 +46,3 @@ const json = p.toJSON();

});
it('should set the bcc field', function() {
it('should set the bcc field', function () {
p.setBcc('testbcc@example.org');

@@ -56,4 +56,4 @@ const json = p.toJSON();

});
it('should set the headers field', function() {
p.setHeaders({test: 'Test'});
it('should set the headers field', function () {
p.setHeaders({ test: 'Test' });
const json = p.toJSON();

@@ -64,4 +64,4 @@ expect(json).to.have.property('headers');

});
it('should set the custom_args field', function() {
p.setCustomArgs({test: 'Test'});
it('should set the custom_args field', function () {
p.setCustomArgs({ test: 'Test' });
const json = p.toJSON();

@@ -72,4 +72,4 @@ expect(json).to.have.property('custom_args');

});
it('should set the substitutions field', function() {
p.setSubstitutions({test: 'Test'});
it('should set the substitutions field', function () {
p.setSubstitutions({ test: 'Test' });
const json = p.toJSON();

@@ -79,4 +79,4 @@ expect(json).to.have.property('substitutions');

});
it('should apply wrappers to the substitutions', function() {
p.setSubstitutions({test: 'Test', otherTest2: 'Test2'});
it('should apply wrappers to the substitutions', function () {
p.setSubstitutions({ test: 'Test', otherTest2: 'Test2' });
p.setSubstitutionWrappers(['{{', '}}']);

@@ -91,3 +91,9 @@ const json = p.toJSON();

});
it('should set the subject field', function() {
it('should set the dynamicTemplateData field', function () {
p.setDynamicTemplateData({ test: 'Test' });
const json = p.toJSON();
expect(json).to.have.property('dynamic_template_data');
expect(json.dynamic_template_data).to.be.an.instanceof(Object);
});
it('should set the subject field', function () {
p.setSubject('Test');

@@ -98,3 +104,3 @@ const json = p.toJSON();

});
it('should set the send_at field', function() {
it('should set the send_at field', function () {
p.setSendAt(555);

@@ -108,4 +114,4 @@ const json = p.toJSON();

to: 'to@example.org',
customArgs: {snake_case: 'Test', T_EST: 'Test', camelCase: 'Test'},
substitutions: {snake_case: 'Test', T_EST: 'Test', camelCase: 'Test'},
customArgs: { snake_case: 'Test', T_EST: 'Test', camelCase: 'Test' },
substitutions: { snake_case: 'Test', T_EST: 'Test', camelCase: 'Test' },
};

@@ -127,3 +133,17 @@ p.fromData(data);

});
it('should not modify the keys of dynamic template data', () => {
const data = {
to: 'to@example.org',
dynamicTemplateData: { snake_case: 'Test', T_EST: 'Test', camelCase: 'Test' },
};
p.fromData(data);
const json = p.toJSON();
expect(json.dynamic_template_data).to.have.property('T_EST');
expect(json.dynamic_template_data).to.have.property('camelCase');
expect(json.dynamic_template_data).to.have.property('snake_case');
expect(json.dynamic_template_data.T_EST).to.equal('Test');
expect(json.dynamic_template_data.camelCase).to.equal('Test');
expect(json.dynamic_template_data.snake_case).to.equal('Test');
});
});
});

@@ -1,10 +0,11 @@

import {EmailData, EmailJSON} from "./email-address";
import { EmailData, EmailJSON } from "./email-address";
export interface PersonalizationData {
to: EmailData|EmailData[],
cc?: EmailData|EmailData[],
bcc?: EmailData|EmailData[],
to: EmailData | EmailData[],
cc?: EmailData | EmailData[],
bcc?: EmailData | EmailData[],
subject?: string;
headers?: { [key: string]: string };
substitutions?: { [key: string]: string };
dynamicTemplateData?: { [key: string]: string; };
customArgs?: { [key: string]: string };

@@ -15,3 +16,3 @@ sendAt?: number;

export interface PersonalizationJSON {
to: EmailJSON|EmailJSON[];
to: EmailJSON | EmailJSON[];
cc?: EmailJSON[];

@@ -21,2 +22,3 @@ bcc?: EmailJSON[];

substitutions?: { [key: string]: string; };
dynamic_template_data?: { [key: string]: string; };
custom_args?: { [key: string]: string; };

@@ -31,3 +33,3 @@ subject?: string;

fromData(data: PersonalizationData): void;
/**

@@ -46,3 +48,3 @@ * Set subject

*/
setTo(to: EmailData|EmailData[]): void;
setTo(to: EmailData | EmailData[]): void;

@@ -57,3 +59,3 @@ /**

*/
setCc(cc: EmailData|EmailData[]): void;
setCc(cc: EmailData | EmailData[]): void;

@@ -68,3 +70,3 @@ /**

*/
setBcc(bcc: EmailData|EmailData[]): void;
setBcc(bcc: EmailData | EmailData[]): void;

@@ -117,2 +119,7 @@ /**

/**
* Set dynamic template data
*/
setDynamicTemplateData(dynamicTemplateData: { [key: string]: string }): void;
/**
* To JSON

@@ -119,0 +126,0 @@ */

@@ -10,2 +10,3 @@ 'use strict';

const deepClone = require('../helpers/deep-clone');
const merge = require('deepmerge');
const wrapSubstitutions = require('../helpers/wrap-substitutions');

@@ -31,2 +32,3 @@

this.substitutionWrappers = ['{{', '}}'];
this.dynamicTemplateData = {};

@@ -52,3 +54,3 @@ //Build from data if given

data = deepClone(data);
data = toCamelCase(data, ['substitutions', 'customArgs', 'headers']);
data = toCamelCase(data, ['substitutions', 'dynamicTemplateData', 'customArgs', 'headers']);

@@ -58,3 +60,3 @@ //Extract properties from data

to, cc, bcc, subject, headers, customArgs, sendAt,
substitutions, substitutionWrappers,
substitutions, substitutionWrappers, dynamicTemplateData,
} = data;

@@ -71,2 +73,3 @@

this.setCustomArgs(customArgs);
this.setDynamicTemplateData(dynamicTemplateData);
this.setSendAt(sendAt);

@@ -280,2 +283,30 @@ }

/**
* 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 = merge(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

@@ -288,3 +319,3 @@ */

to, cc, bcc, subject, headers, customArgs, sendAt,
substitutions, substitutionWrappers,
substitutions, substitutionWrappers, dynamicTemplateData,
} = this;

@@ -307,3 +338,3 @@

}
if (Object.keys(substitutions).length > 0) {
if (substitutions && Object.keys(substitutions).length > 0) {
const [left, right] = substitutionWrappers;

@@ -316,2 +347,6 @@ json.substitutions = wrapSubstitutions(substitutions, left, right);

if (dynamicTemplateData && Object.keys(dynamicTemplateData).length > 0) {
json.dynamicTemplateData = dynamicTemplateData;
}
//Simple properties

@@ -326,3 +361,3 @@ if (typeof subject !== 'undefined') {

//Return as snake cased object
return toSnakeCase(json, ['substitutions', 'customArgs', 'headers']);
return toSnakeCase(json, ['substitutions', 'dynamicTemplateData', 'customArgs', 'headers']);
}

@@ -329,0 +364,0 @@ }

@@ -1,3 +0,3 @@

import * as helpers from "@sendgrid/helpers/helpers/index"
import * as classes from "@sendgrid/helpers/classes/index"
import * as helpers from '@sendgrid/helpers/helpers/index';
import * as classes from '@sendgrid/helpers/classes/index';

@@ -7,2 +7,2 @@ export {

classes,
};
};
{
"name": "@sendgrid/helpers",
"description": "SendGrid NodeJS internal helpers",
"version": "6.2.1",
"version": "6.3.0",
"author": "SendGrid <dx@sendgrid.com> (sendgrid.com)",

@@ -33,4 +33,5 @@ "contributors": [

"dependencies": {
"chalk": "^2.0.1"
"chalk": "^2.0.1",
"deepmerge": "^2.1.1"
}
}

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc