From 221790ae2c70d167222dcd4c4b25aec51aa3dafc Mon Sep 17 00:00:00 2001 From: Tony Ho Date: Fri, 5 Oct 2018 00:18:50 +1000 Subject: [PATCH 1/6] Update ESLint rules Disable `global-require`. Set `complexity` to `warn`. Set `max-statements` to `warn`. --- .eslintrc.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 0712935c5..4e95dc763 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -173,7 +173,7 @@ rules: block-scoped-var: off class-methods-use-this: off complexity: - - error + - warn - 6 consistent-return: off default-case: off @@ -253,7 +253,7 @@ rules: # Node.js and CommonJS callback-return: error - global-require: error + global-require: off handle-callback-err: error no-mixed-requires: off no-new-require: off @@ -282,7 +282,7 @@ rules: max-params: off max-statements-per-line: off max-statements: - - error + - warn - 30 multiline-ternary: off new-parens: off From aff34de5cb5bdad4c4e0815151e0d0d12afe50d1 Mon Sep 17 00:00:00 2001 From: Tony Ho Date: Fri, 5 Oct 2018 00:19:32 +1000 Subject: [PATCH 2/6] Fix ESLint errors --- .../inbound-mail-parser/src/parser.spec.js | 2 +- packages/mail/src/classes/mail-service.js | 1 + .../controllers/contact_list_controller.js | 444 +++++++++--------- 3 files changed, 228 insertions(+), 219 deletions(-) diff --git a/packages/inbound-mail-parser/src/parser.spec.js b/packages/inbound-mail-parser/src/parser.spec.js index 293d41080..83d04445a 100644 --- a/packages/inbound-mail-parser/src/parser.spec.js +++ b/packages/inbound-mail-parser/src/parser.spec.js @@ -31,7 +31,7 @@ describe('test_parse', () => { const parse = new Parse({}, {}); function callback(email) { - expect(email).to.be.null; + expect(email).to.be.null(); done(); } diff --git a/packages/mail/src/classes/mail-service.js b/packages/mail/src/classes/mail-service.js index 5184ec8f8..8fae119fe 100644 --- a/packages/mail/src/classes/mail-service.js +++ b/packages/mail/src/classes/mail-service.js @@ -112,6 +112,7 @@ class MailService { //Pass to callback if provided if (cb) { + // eslint-disable-next-line callback-return cb(error, null); } diff --git a/packages/subscription-widget/server/controllers/contact_list_controller.js b/packages/subscription-widget/server/controllers/contact_list_controller.js index dd6a187f8..a7e3cf81b 100644 --- a/packages/subscription-widget/server/controllers/contact_list_controller.js +++ b/packages/subscription-widget/server/controllers/contact_list_controller.js @@ -6,245 +6,253 @@ const Settings = require('../../settings'); const optIn = 'opt-in'; function prepareConfirmationEmail(reqBody) { - const subject = "Please Confirm Your Email Address"; - const url = formatUrl(Settings.url) + '/success'; - const link = "this link" - const mailText = "Thanks for signing up! Click " + link + " to sign up! This link will be active for 24 hours."; - - var emailBody = { - personalizations: [ - { - to: [ - { - email: reqBody.email, - } - ], - subject: subject, - custom_args: { - type: optIn, - time_sent: String(Date.now()), - }, - substitutions: { - link_insert: link - } - }, - ], - from: { - email: Settings.senderEmail, - name: Settings.senderName, - }, - content: [ - { - type: "text/html", - value: mailText, - } - ] - } - - const templateId = Settings.templateId; - if (templateId) emailBody.template_id = templateId; - - for (key in reqBody) { - emailBody.personalizations[0].custom_args[key] = reqBody[key]; - } - - return emailBody; + const subject = 'Please Confirm Your Email Address'; + const url = formatUrl(Settings.url) + '/success'; + const link = 'this link'; + const mailText = 'Thanks for signing up! Click ' + link + ' to sign up! This link will be active for 24 hours.'; + + var emailBody = { + personalizations: [ + { + to: [ + { + email: reqBody.email, + }, + ], + subject: subject, + custom_args: { + type: optIn, + time_sent: String(Date.now()), + }, + substitutions: { + link_insert: link, + }, + }, + ], + from: { + email: Settings.senderEmail, + name: Settings.senderName, + }, + content: [ + { + type: 'text/html', + value: mailText, + }, + ], + }; + + const templateId = Settings.templateId; + if (templateId) { + emailBody.template_id = templateId; + } + + for (key in reqBody) { + if ({}.hasOwnProperty.call(reqBody, key)) { + emailBody.personalizations[0].custom_args[key] = reqBody[key]; + } + } + + return emailBody; } function prepareNotificationEmail(reqBody) { - const subject = "New email signup"; - const mailText = "A new person just confirmed they would look to receive your emails via your email subscription widget.
Name: " + reqBody.first_name + " " + reqBody.last_name + "
Email: " + reqBody.email; - - var emailBody = { - personalizations: [ - { - to: [ - { - email: Settings.notificationEmail, - } - ], - subject: subject - }, - ], - from: { - email: Settings.senderEmail, - name: Settings.senderName, - }, - content: [ - { - type: "text/html", - value: mailText, - } - ], - } - - return emailBody; + const subject = 'New email signup'; + const mailText = 'A new person just confirmed they would look to receive your emails via your email subscription widget.
Name: ' + reqBody.first_name + ' ' + reqBody.last_name + '
Email: ' + reqBody.email; + + var emailBody = { + personalizations: [ + { + to: [ + { + email: Settings.notificationEmail, + }, + ], + subject: subject, + }, + ], + from: { + email: Settings.senderEmail, + name: Settings.senderName, + }, + content: [ + { + type: 'text/html', + value: mailText, + }, + ], + }; + + return emailBody; } // Send confirmation email to contact with link to confirm email exports.sendConfirmation = (req, res, next) => { - var request = sg.emptyRequest({ - method: 'POST', - path: '/v3/mail/send', - body: prepareConfirmationEmail(req.body) - }); - - sg.API(request, function(error, response) { - if (error) { - console.log('Error response received'); - } - - if (response.statusCode >= 200 && response.statusCode < 300) { - res.sendFile(path.join(__dirname, '../static/check-inbox.html')); - } else { - res.sendFile(path.join(__dirname, '../static/error.html')); - } - }); -} + var request = sg.emptyRequest({ + method: 'POST', + path: '/v3/mail/send', + body: prepareConfirmationEmail(req.body), + }); + + sg.API(request, function(error, response) { + if (error) { + console.log('Error response received'); + } + + if (response.statusCode >= 200 && response.statusCode < 300) { + res.sendFile(path.join(__dirname, '../static/check-inbox.html')); + } + else { + res.sendFile(path.join(__dirname, '../static/error.html')); + } + }); +}; // Create new contact and add contact to given list exports.addUser = function(req, res, next) { - addUserToList(req.body[0], function() { - //send notification about the new signup - if (Settings.sendNotification) { - console.log("Sending notification"); - - var request = sg.emptyRequest({ - method: 'POST', - path: '/v3/mail/send', - body: prepareNotificationEmail(req.body[0]) - }); - - sg.API(request, function(error, response) { - if (error) { - console.log('Error sending notification'); - } - }); - } - - res.sendStatus(200); - }); -} + addUserToList(req.body[0], function() { + //send notification about the new signup + if (Settings.sendNotification) { + console.log('Sending notification'); + + var request = sg.emptyRequest({ + method: 'POST', + path: '/v3/mail/send', + body: prepareNotificationEmail(req.body[0]), + }); + + sg.API(request, function(error, response) { + if (error) { + console.log('Error sending notification'); + } + }); + } + + res.sendStatus(200); + }); +}; function addUserToList(emailBody, callback) { - console.log(emailBody); - - var ignoreFields = ['ip', 'sg_event_id', 'sg_message_id', 'useragent', 'event', - 'url_offset', 'time_sent', 'timestamp', 'url', 'type', 'smtp-id']; - - var customFields = [{}]; - var customFieldArr = []; - - for (key in emailBody) { - if (!stringInArray(key, ignoreFields)) { - customFields[0][key] = emailBody[key]; - if (key != 'email' && key != 'first_name' && key != 'last_name') { - customFieldArr.push(key); - } - } - } - - checkAndAddCustomFields(customFieldArr, function() { - const emailType = emailBody.type; - const timestamp = parseInt(emailBody.time_sent); - const listId = Settings.listId; - const secondsInDay = 86400; - const timeElapsed = (Date.now() - timestamp) / 1000; - - // Confirm email type is opt in and link has been clicked within 1 day - if (emailType == optIn && timeElapsed < secondsInDay) { - var request = sg.emptyRequest({ - method: 'POST', - path: '/v3/contactdb/recipients', - body: customFields - }); - - sg.API(request, function(error, response) { - if (listId) { - var contactID = JSON.parse(response.body.toString()).persisted_recipients[0]; - var request = sg.emptyRequest({ - method: 'POST', - path: '/v3/contactdb/lists/' + listId + '/recipients/' + contactID, - body: customFields - }); - sg.API(request, function(error, response) { - console.log(response.statusCode) - console.log(response.body) - console.log(response.headers) - - callback(); - }); - } else { - callback(); - } - }); - } else { - callback(); - } - }); + console.log(emailBody); + + var ignoreFields = ['ip', 'sg_event_id', 'sg_message_id', 'useragent', 'event', + 'url_offset', 'time_sent', 'timestamp', 'url', 'type', 'smtp-id']; + + var customFields = [{}]; + var customFieldArr = []; + + for (key in emailBody) { + if (!stringInArray(key, ignoreFields)) { + customFields[0][key] = emailBody[key]; + if (key !== 'email' && key !== 'first_name' && key !== 'last_name') { + customFieldArr.push(key); + } + } + } + + checkAndAddCustomFields(customFieldArr, function() { + const emailType = emailBody.type; + const timestamp = parseInt(emailBody.time_sent, 10); + const listId = Settings.listId; + const secondsInDay = 86400; + const timeElapsed = (Date.now() - timestamp) / 1000; + + // Confirm email type is opt in and link has been clicked within 1 day + if (emailType === optIn && timeElapsed < secondsInDay) { + var request = sg.emptyRequest({ + method: 'POST', + path: '/v3/contactdb/recipients', + body: customFields, + }); + + sg.API(request, function(error, response) { + if (listId) { + var contactID = JSON.parse(response.body.toString()).persisted_recipients[0]; + var request = sg.emptyRequest({ + method: 'POST', + path: '/v3/contactdb/lists/' + listId + '/recipients/' + contactID, + body: customFields, + }); + sg.API(request, function(error, response) { + console.log(response.statusCode); + console.log(response.body); + console.log(response.headers); + + callback(); + }); + } + else { + return callback(); + } + }); + } + else { + return callback(); + } + }); } function checkAndAddCustomFields(submittedFields, callback) { - var request = sg.emptyRequest({ - method: 'GET', - path: '/v3/contactdb/custom_fields', - }); - - sg.API(request, function(error, response) { - console.log(response.statusCode) - console.log(response.body) - console.log(response.headers) - - var existingCustomFields = JSON.parse(response.body); - var fieldsToCreate = []; - - submittedFields.map((submittedField) => { - var fieldExists = false; - existingCustomFields.custom_fields.map((field) => { - if (submittedField == field.name) { - fieldExists = true; - } - }); - if (!fieldExists) { - fieldsToCreate.push(submittedField) - } - }); - - if (fieldsToCreate.length == 0) { - callback(); - } else { - fieldsToCreate.map((fieldsToCreate) => { - var body = { name: fieldsToCreate, type: 'text' }; - - var request = sg.emptyRequest({ - method: 'POST', - path: '/v3/contactdb/custom_fields', - body: body - }); - - sg.API(request, function(error, response) { - callback(); - }); - }); - } - + var request = sg.emptyRequest({ + method: 'GET', + path: '/v3/contactdb/custom_fields', + }); + + sg.API(request, function(error, response) { + console.log(response.statusCode); + console.log(response.body); + console.log(response.headers); + + var existingCustomFields = JSON.parse(response.body); + var fieldsToCreate = []; + + submittedFields.map((submittedField) => { + var fieldExists = false; + existingCustomFields.custom_fields.map((field) => { + if (submittedField === field.name) { + fieldExists = true; + } + }); + if (!fieldExists) { + fieldsToCreate.push(submittedField); + } }); + + if (fieldsToCreate.length === 0) { + return callback(); + } + else { + fieldsToCreate.map((fieldsToCreate) => { + var body = { name: fieldsToCreate, type: 'text' }; + + var request = sg.emptyRequest({ + method: 'POST', + path: '/v3/contactdb/custom_fields', + body: body, + }); + + sg.API(request, function(error, response) { + callback(); + }); + }); + } + + }); } function formatUrl(url) { - if (url.substr(-1) == '/') { - return url.substring(0, url.length - 1); - } - return url; + if (url.substr(-1) === '/') { + return url.substring(0, url.length - 1); + } + return url; } function stringInArray(string, array) { - var isInArray = false; - array.map((item) => { - if (string == item) { - isInArray = true; - } - }); - return isInArray; + var isInArray = false; + array.map((item) => { + if (string === item) { + isInArray = true; + } + }); + return isInArray; } From 137ddbc5663223f1ea65704ebb7daecbd60af5d6 Mon Sep 17 00:00:00 2001 From: Tony Ho Date: Fri, 5 Oct 2018 00:22:16 +1000 Subject: [PATCH 3/6] Add npm run script for ESDoc --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 8e0e7053e..1cf0dbc46 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "typescript": "~2.4.2" }, "scripts": { + "doc": "esdoc", "lint": "eslint . --fix", "prism:install": "curl https://raw.githubusercontent.com/stoplightio/prism/master/install.sh | sh", "prism": "prism run --mock --list --spec https://raw.githubusercontent.com/sendgrid/sendgrid-oai/master/oai_stoplight.json", From aad68d69735bdd66f581db73f35d07f66c05d909 Mon Sep 17 00:00:00 2001 From: Tony Ho Date: Fri, 5 Oct 2018 00:27:52 +1000 Subject: [PATCH 4/6] Add TravisCI scripts for ESLint and ESDoc --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index fe2b42bc6..24c3795a8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,6 +20,8 @@ script: - yarn test:client - yarn test:helpers - yarn test:typescript +- yarn lint +- yarn doc notifications: hipchat: rooms: From 8a414005b2dcb8375fd94c707e916dda49b393e9 Mon Sep 17 00:00:00 2001 From: Tony Ho Date: Fri, 5 Oct 2018 12:11:11 +1000 Subject: [PATCH 5/6] Exclude coverage folder from ESLint --- .eslintignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintignore b/.eslintignore index 15d354055..67fb517ac 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ node_modules examples test +coverage From 43000d7cbdaed406e605f7ce992e6e591fffc1bb Mon Sep 17 00:00:00 2001 From: Tony Ho Date: Thu, 11 Oct 2018 19:24:11 +1100 Subject: [PATCH 6/6] Add instructions for running ESLint and ESDoc Fix link to ESDoc. --- CONTRIBUTING.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 53cbbaf56..0e19875c1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -160,7 +160,13 @@ Generally, we follow the style guidelines as suggested by the official language. Please run your code through: - [ESLint](http://eslint.org/) with the standard style guide. -- [esdoc](https://github.com/sendgrid/sendgrid-nodejs/blob/master/.github/USAGE.md) to check the documentation coverage of your added code. + ```bash + yarn lint + ``` +- [ESDoc](https://esdoc.org/) to check the documentation coverage of your added code. + ```bash + yarn doc + ``` ## Creating a Pull Request