@sendgrid/helpers
Advanced tools
Comparing version 6.0.0-beta.3 to 6.0.0-beta.4
@@ -62,7 +62,7 @@ 'use strict'; | ||
/** | ||
* Set email | ||
* Set email (mandatory) | ||
*/ | ||
setEmail(email) { | ||
if (typeof email === 'undefined') { | ||
return; | ||
throw new Error('Must provide `email`'); | ||
} | ||
@@ -87,3 +87,3 @@ if (typeof email !== 'string') { | ||
//Add name if present | ||
if (typeof name !== 'undefined') { | ||
if (name !== '') { | ||
json.name = name; | ||
@@ -90,0 +90,0 @@ } |
@@ -35,2 +35,6 @@ 'use strict'; | ||
//Helper properties | ||
this.substitutions = null; | ||
this.substitutionWrappers = null; | ||
//Process data if given | ||
@@ -61,3 +65,3 @@ if (data) { | ||
templateId, personalizations, attachments, ipPoolName, batchId, | ||
sections, headers, categories, customArgs, asm, mailSettings, | ||
sections, headers, categories, category, customArgs, asm, mailSettings, | ||
trackingSettings, substitutions, substitutionWrappers, isMultiple, | ||
@@ -78,2 +82,3 @@ } = data; | ||
this.setHeaders(headers); | ||
this.setCategories(category); | ||
this.setCategories(categories); | ||
@@ -84,3 +89,4 @@ this.setCustomArgs(customArgs); | ||
this.setTrackingSettings(trackingSettings); | ||
this.setPersonalizations(personalizations); | ||
this.setSubstitutions(substitutions); | ||
this.setSubstitutionWrappers(substitutionWrappers); | ||
@@ -91,29 +97,15 @@ //Add contents from text/html properties | ||
//Use to property for personalizations | ||
if (to) { | ||
//Using "to" property for personalizations | ||
if (personalizations) { | ||
this.setPersonalizations(personalizations); | ||
} | ||
//Create base data for personalizations | ||
const baseData = { | ||
cc, | ||
bcc, | ||
substitutions, | ||
substitutionWrappers, | ||
}; | ||
//Multiple individual emails | ||
else if (isMultiple && Array.isArray(to)) { | ||
to.forEach(to => this.addTo(to, cc, bcc)); | ||
} | ||
//Multiple individual emails | ||
if (isMultiple && Array.isArray(to)) { | ||
to.forEach(to => { | ||
const toData = Object.assign({}, baseData, {to}); | ||
if (to.substitutions) { | ||
toData.substitutions = to.substitutions; | ||
} | ||
this.addTo(toData); | ||
}); | ||
} | ||
//Single email (possibly with multiple recipients in the to field) | ||
else { | ||
const toData = Object.assign({}, baseData, {to}); | ||
this.addTo(toData); | ||
} | ||
//Single email (possibly with multiple recipients in the to field) | ||
else { | ||
this.addTo(to, cc, bcc); | ||
} | ||
@@ -230,3 +222,7 @@ } | ||
} | ||
this.personalizations = personalizations; | ||
//Clear and use add helper to add one by one | ||
this.personalizations = []; | ||
personalizations | ||
.forEach(personalization => this.addPersonalization(personalization)); | ||
} | ||
@@ -238,2 +234,3 @@ | ||
addPersonalization(personalization) { | ||
this.applySubstitutions(personalization); | ||
this.personalizations.push(personalization); | ||
@@ -243,9 +240,52 @@ } | ||
/** | ||
* Add recipient (convenience method for quickly creating personalizations) | ||
* Convenience method for quickly creating personalizations | ||
*/ | ||
addTo(data) { | ||
this.addPersonalization(new Personalization(data)); | ||
addTo(to, cc, bcc) { | ||
if ( | ||
typeof to === 'undefined' && | ||
typeof cc === 'undefined' && | ||
typeof bcc === 'undefined' | ||
) { | ||
throw new Error('Provide at least one of to, cc or bcc'); | ||
} | ||
this.addPersonalization(new Personalization({to, cc, bcc})); | ||
} | ||
/** | ||
* Set substitutions | ||
*/ | ||
setSubstitutions(substitutions) { | ||
if (typeof substitutions === 'undefined') { | ||
return; | ||
} | ||
if (typeof substitutions !== 'object') { | ||
throw new Error('Object expected for `substitutions`'); | ||
} | ||
this.substitutions = substitutions; | ||
} | ||
/** | ||
* Set substitution wrappers | ||
*/ | ||
setSubstitutionWrappers(wrappers) { | ||
if (typeof wrappers === 'undefined') { | ||
return; | ||
} | ||
if (!Array.isArray(wrappers) || wrappers.length !== 2) { | ||
throw new Error( | ||
'Array expected with two elements for `substitutionWrappers`' | ||
); | ||
} | ||
this.substitutionWrappers = wrappers; | ||
} | ||
/** | ||
* Helper which applies globally set substitutions to personalizations | ||
*/ | ||
applySubstitutions(personalization) { | ||
personalization.reverseMergeSubstitutions(this.substitutions); | ||
personalization.setSubstitutionWrappers(this.substitutionWrappers); | ||
} | ||
/** | ||
* Set content | ||
@@ -335,2 +375,5 @@ */ | ||
} | ||
if (typeof categories === 'string') { | ||
categories = [categories]; | ||
} | ||
if (!Array.isArray(categories) || | ||
@@ -337,0 +380,0 @@ !categories.every(cat => typeof cat === 'string')) { |
@@ -23,3 +23,5 @@ 'use strict'; | ||
//Init array and object placeholders | ||
this.to = []; | ||
this.cc = []; | ||
this.bcc = []; | ||
this.headers = {}; | ||
@@ -111,4 +113,7 @@ this.customArgs = {}; | ||
*/ | ||
addTo(email) { | ||
this.to.push(EmailAddress.create(email)); | ||
addTo(to) { | ||
if (typeof to === 'undefined') { | ||
return; | ||
} | ||
this.to.push(EmailAddress.create(to)); | ||
} | ||
@@ -132,4 +137,7 @@ | ||
*/ | ||
addCc(email) { | ||
this.cc.push(EmailAddress.create(email)); | ||
addCc(cc) { | ||
if (typeof cc === 'undefined') { | ||
return; | ||
} | ||
this.cc.push(EmailAddress.create(cc)); | ||
} | ||
@@ -153,4 +161,7 @@ | ||
*/ | ||
addBcc(email) { | ||
this.bcc.push(EmailAddress.create(email)); | ||
addBcc(bcc) { | ||
if (typeof bcc === 'undefined') { | ||
return; | ||
} | ||
this.bcc.push(EmailAddress.create(bcc)); | ||
} | ||
@@ -165,3 +176,3 @@ | ||
} | ||
if (typeof headers !== 'object') { | ||
if (typeof headers !== 'object' || headers === null) { | ||
throw new Error('Object expected for `headers`'); | ||
@@ -186,17 +197,28 @@ } | ||
/** | ||
* Set substitution wrappers | ||
* Set custom args | ||
*/ | ||
setSubstitutionWrappers(wrappers) { | ||
if (typeof wrappers === 'undefined') { | ||
setCustomArgs(customArgs) { | ||
if (typeof customArgs === 'undefined') { | ||
return; | ||
} | ||
if (!Array.isArray(wrappers) || wrappers.length !== 2) { | ||
throw new Error( | ||
'Array expected with two elements for `substitutionWrappers`' | ||
); | ||
if (typeof customArgs !== 'object' || customArgs === null) { | ||
throw new Error('Object expected for `customArgs`'); | ||
} | ||
this.substitutionWrappers = wrappers; | ||
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 | ||
@@ -208,3 +230,3 @@ */ | ||
} | ||
if (typeof substitutions !== 'object') { | ||
if (typeof substitutions !== 'object' || substitutions === null) { | ||
throw new Error('Object expected for `substitutions`'); | ||
@@ -222,2 +244,5 @@ } | ||
} | ||
if (typeof value !== 'string' && typeof value !== 'number') { | ||
throw new Error('String or Number expected for substitution value'); | ||
} | ||
this.substitutions[key] = value; | ||
@@ -227,15 +252,30 @@ } | ||
/** | ||
* Set custom args | ||
* Reverse merge substitutions, preserving existing ones | ||
*/ | ||
setCustomArgs(customArgs) { | ||
if (typeof customArgs === 'undefined') { | ||
reverseMergeSubstitutions(substitutions) { | ||
if (typeof substitutions === 'undefined') { | ||
return; | ||
} | ||
if (typeof customArgs !== 'object') { | ||
throw new Error('Object expected for `customArgs`'); | ||
if (typeof substitutions !== 'object' || substitutions === null) { | ||
throw new Error('Object expected for `substitutions`'); | ||
} | ||
this.customArgs = customArgs; | ||
this.substitutions = Object.assign({}, substitutions, this.substitutions); | ||
} | ||
/** | ||
* Set substitution wrappers | ||
*/ | ||
setSubstitutionWrappers(wrappers) { | ||
if (typeof wrappers === 'undefined') { | ||
return; | ||
} | ||
if (!Array.isArray(wrappers) || wrappers.length !== 2) { | ||
throw new Error( | ||
'Array expected with two elements for `substitutionWrappers`' | ||
); | ||
} | ||
this.substitutionWrappers = wrappers; | ||
} | ||
/** | ||
* To JSON | ||
@@ -283,3 +323,3 @@ */ | ||
//Return as snake cased object | ||
return toSnakeCase(json); | ||
return toSnakeCase(json, ['substitutions']); | ||
} | ||
@@ -286,0 +326,0 @@ } |
'use strict'; | ||
/** | ||
* Dependencies | ||
*/ | ||
const chalk = require('chalk'); | ||
/** | ||
* Response error class | ||
@@ -16,12 +21,9 @@ */ | ||
//Set response | ||
this.response = response; | ||
//Extract data from response | ||
const {headers, statusCode, statusMessage, body} = response; | ||
//Set message | ||
if (response.statusCode >= 500) { | ||
this.message = 'Server error'; | ||
} | ||
else if (response.statusCode >= 400) { | ||
this.message = 'Client error'; | ||
} | ||
//Set data | ||
this.code = statusCode; | ||
this.message = statusMessage; | ||
this.response = {headers, body}; | ||
@@ -42,3 +44,13 @@ //Capture stack trace | ||
toString() { | ||
return `${this.name}: ${this.message}`; | ||
const {body} = this.response; | ||
let err = chalk.red(`${this.message} (${this.code})`); | ||
if (Array.isArray(body.errors)) { | ||
body.errors.forEach(error => { | ||
const message = chalk.yellow(error.message); | ||
const field = chalk.grey(error.field); | ||
const help = chalk.grey(error.help); | ||
err += `\n ${message}\n ${field}\n ${help}`; | ||
}); | ||
} | ||
return err; | ||
} | ||
@@ -50,4 +62,4 @@ | ||
toJSON() { | ||
const {message, response} = this; | ||
return {message, response}; | ||
const {message, code, response} = this; | ||
return {message, code, response}; | ||
} | ||
@@ -54,0 +66,0 @@ } |
@@ -6,3 +6,3 @@ 'use strict'; | ||
*/ | ||
module.exports = function convertKeys(obj, converter) { | ||
module.exports = function convertKeys(obj, converter, ignored) { | ||
@@ -14,2 +14,7 @@ //Validate | ||
//Ignore arrays | ||
if (Array.isArray(obj)) { | ||
return obj; | ||
} | ||
//Process all properties | ||
@@ -20,5 +25,7 @@ for (const key in obj) { | ||
//Recursive for child objects | ||
//Recursive for child objects, unless ignored | ||
if (typeof obj[key] === 'object' && obj[key] !== null) { | ||
obj[key] = convertKeys(obj[key], converter); | ||
if (!Array.isArray(ignored) || !ignored.includes(key)) { | ||
obj[key] = convertKeys(obj[key], converter, ignored); | ||
} | ||
} | ||
@@ -35,4 +42,4 @@ | ||
//Return object copy | ||
//Return object | ||
return obj; | ||
}; |
@@ -7,2 +7,3 @@ 'use strict'; | ||
const convertKeys = require('./convert-keys'); | ||
const deepClone = require('./deep-clone'); | ||
const strToCamelCase = require('./str-to-camel-case'); | ||
@@ -30,27 +31,47 @@ | ||
}, | ||
arr: ['a', 'b'], | ||
}; | ||
//Create clone | ||
const clone = convertKeys(obj, strToCamelCase); | ||
//Create copy of the object | ||
const objCopy = deepClone(obj); | ||
//Convert keys | ||
convertKeys(obj, strToCamelCase); | ||
//Tests | ||
it('should convert top level keys properly', function() { | ||
expect(clone).to.have.property('a'); | ||
expect(clone).to.have.property('snakeCase'); | ||
expect(clone).to.have.property('camelCase'); | ||
expect(clone).to.have.property('nestedSnakeCase'); | ||
expect(clone).to.have.property('nestedCamelCase'); | ||
expect(clone).not.to.have.property('snake_case'); | ||
expect(clone).not.to.have.property('nested_snake_case'); | ||
expect(obj).to.have.property('a'); | ||
expect(obj).to.have.property('snakeCase'); | ||
expect(obj).to.have.property('camelCase'); | ||
expect(obj).to.have.property('nestedSnakeCase'); | ||
expect(obj).to.have.property('nestedCamelCase'); | ||
expect(obj).not.to.have.property('snake_case'); | ||
expect(obj).not.to.have.property('nested_snake_case'); | ||
}); | ||
it('should convert nested keys properly', function() { | ||
expect(clone.nestedSnakeCase).to.have.property('a'); | ||
expect(clone.nestedSnakeCase).to.have.property('snakeCase'); | ||
expect(clone.nestedSnakeCase).to.have.property('camelCase'); | ||
expect(clone.nestedSnakeCase).not.to.have.property('snake_case'); | ||
expect(clone.nestedCamelCase).to.have.property('a'); | ||
expect(clone.nestedCamelCase).to.have.property('snakeCase'); | ||
expect(clone.nestedCamelCase).to.have.property('camelCase'); | ||
expect(clone.nestedCamelCase).not.to.have.property('snake_case'); | ||
expect(obj.nestedSnakeCase).to.have.property('a'); | ||
expect(obj.nestedSnakeCase).to.have.property('snakeCase'); | ||
expect(obj.nestedSnakeCase).to.have.property('camelCase'); | ||
expect(obj.nestedSnakeCase).not.to.have.property('snake_case'); | ||
expect(obj.nestedCamelCase).to.have.property('a'); | ||
expect(obj.nestedCamelCase).to.have.property('snakeCase'); | ||
expect(obj.nestedCamelCase).to.have.property('camelCase'); | ||
expect(obj.nestedCamelCase).not.to.have.property('snake_case'); | ||
}); | ||
it('should handle arrays properly', function() { | ||
expect(obj.arr).to.be.an.instanceof(Array); | ||
expect(obj.arr).to.have.lengthOf(2); | ||
expect(obj.arr).to.have.members(['a', 'b']); | ||
}); | ||
it('should not converted nested objects if ignored', function() { | ||
convertKeys(objCopy, strToCamelCase, ['nestedCamelCase']); | ||
expect(objCopy.nestedSnakeCase).to.have.property('a'); | ||
expect(objCopy.nestedSnakeCase).to.have.property('snakeCase'); | ||
expect(objCopy.nestedSnakeCase).to.have.property('camelCase'); | ||
expect(objCopy.nestedSnakeCase).not.to.have.property('snake_case'); | ||
expect(objCopy.nestedCamelCase).to.have.property('a'); | ||
expect(objCopy.nestedCamelCase).to.have.property('camelCase'); | ||
expect(objCopy.nestedCamelCase).to.have.property('snake_case'); | ||
expect(objCopy.nestedCamelCase).not.to.have.property('snakeCase'); | ||
}); | ||
it('should throw an error for non object input', function() { | ||
@@ -57,0 +78,0 @@ expect(function() { |
@@ -17,2 +17,3 @@ 'use strict'; | ||
e: 5, | ||
arr: ['a', 'b'], | ||
}; | ||
@@ -38,2 +39,7 @@ | ||
}); | ||
it('should handle arrays properly', function() { | ||
expect(clone.arr).to.be.an.instanceof(Array); | ||
expect(clone.arr).to.have.lengthOf(2); | ||
expect(clone.arr).to.have.members(['a', 'b']); | ||
}); | ||
}); |
@@ -12,4 +12,4 @@ 'use strict'; | ||
*/ | ||
module.exports = function toCamelCase(obj) { | ||
return convertKeys(obj, strToCamelCase); | ||
module.exports = function toCamelCase(obj, ignored) { | ||
return convertKeys(obj, strToCamelCase, ignored); | ||
}; |
@@ -12,4 +12,4 @@ 'use strict'; | ||
*/ | ||
module.exports = function toSnakeCase(obj) { | ||
return convertKeys(obj, strToSnakeCase); | ||
module.exports = function toSnakeCase(obj, ignored) { | ||
return convertKeys(obj, strToSnakeCase, ignored); | ||
}; |
{ | ||
"name": "@sendgrid/helpers", | ||
"description": "SendGrid NodeJS internal helpers", | ||
"version": "6.0.0-beta.3", | ||
"version": "6.0.0-beta.4", | ||
"author": "SendGrid <dx@sendgrid.com> (sendgrid.com)", | ||
@@ -31,3 +31,6 @@ "contributors": [ | ||
"helpers" | ||
] | ||
], | ||
"dependencies": { | ||
"chalk": "^2.0.1" | ||
} | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
73265
30
2448
1
+ Addedchalk@^2.0.1
+ Addedansi-styles@3.2.1(transitive)
+ Addedchalk@2.4.2(transitive)
+ Addedcolor-convert@1.9.3(transitive)
+ Addedcolor-name@1.1.3(transitive)
+ Addedescape-string-regexp@1.0.5(transitive)
+ Addedhas-flag@3.0.0(transitive)
+ Addedsupports-color@5.5.0(transitive)