UNPKG

@sendgrid/client

Version:

Twilio SendGrid NodeJS API client

190 lines (160 loc) 4.93 kB
'use strict'; const axios = require('axios'); const pkg = require('../../package.json'); const { helpers: { mergeData, }, classes: { Response, ResponseError, }, } = require('@sendgrid/helpers'); const API_KEY_PREFIX = 'SG.'; const SENDGRID_BASE_URL = 'https://api.sendgrid.com/'; const TWILIO_BASE_URL = 'https://email.twilio.com/'; const SENDGRID_REGION = 'global'; // Initialize the allowed regions and their corresponding hosts const REGION_HOST_MAP = { eu: 'https://api.eu.sendgrid.com/', global: 'https://api.sendgrid.com/', }; class Client { constructor() { this.auth = ''; this.impersonateSubuser = ''; this.sendgrid_region = SENDGRID_REGION; this.defaultHeaders = { Accept: 'application/json', 'Content-Type': 'application/json', 'User-Agent': 'sendgrid/' + pkg.version + ';nodejs', }; this.defaultRequest = { baseUrl: SENDGRID_BASE_URL, url: '', method: 'GET', headers: {}, maxContentLength: Infinity, // Don't limit the content length. maxBodyLength: Infinity, }; } setApiKey(apiKey) { this.auth = 'Bearer ' + apiKey; this.setDefaultRequest('baseUrl', REGION_HOST_MAP[this.sendgrid_region]); if (!this.isValidApiKey(apiKey)) { console.warn(`API key does not start with "${API_KEY_PREFIX}".`); } } setTwilioEmailAuth(username, password) { const b64Auth = Buffer.from(username + ':' + password).toString('base64'); this.auth = 'Basic ' + b64Auth; this.setDefaultRequest('baseUrl', TWILIO_BASE_URL); if (!this.isValidTwilioAuth(username, password)) { console.warn('Twilio Email credentials must be non-empty strings.'); } } isValidApiKey(apiKey) { return this.isString(apiKey) && apiKey.trim().startsWith(API_KEY_PREFIX); } isValidTwilioAuth(username, password) { return this.isString(username) && username && this.isString(password) && password; } isString(value) { return typeof value === 'string' || value instanceof String; } setImpersonateSubuser(subuser) { this.impersonateSubuser = subuser; } setDefaultHeader(key, value) { if (key !== null && typeof key === 'object') { // key is an object Object.assign(this.defaultHeaders, key); return this; } this.defaultHeaders[key] = value; return this; } setDefaultRequest(key, value) { if (key !== null && typeof key === 'object') { // key is an object Object.assign(this.defaultRequest, key); return this; } this.defaultRequest[key] = value; return this; } /** * Global is the default residency (or region) * Global region means the message will be sent through https://api.sendgrid.com * EU region means the message will be sent through https://api.eu.sendgrid.com **/ setDataResidency(region) { if (!REGION_HOST_MAP.hasOwnProperty(region)) { console.warn('Region can only be "global" or "eu".'); } else { this.sendgrid_region = region; this.setDefaultRequest('baseUrl', REGION_HOST_MAP[region]); } return this; } createHeaders(data) { // Merge data with default headers. const headers = mergeData(this.defaultHeaders, data); // Add auth, but don't overwrite if header already set. if (typeof headers.Authorization === 'undefined' && this.auth) { headers.Authorization = this.auth; } if (this.impersonateSubuser) { headers['On-Behalf-Of'] = this.impersonateSubuser; } return headers; } createRequest(data) { let options = { url: data.uri || data.url, baseUrl: data.baseUrl, method: data.method, data: data.body, params: data.qs, headers: data.headers, }; // Merge data with default request. options = mergeData(this.defaultRequest, options); options.headers = this.createHeaders(options.headers); options.baseURL = options.baseUrl; delete options.baseUrl; return options; } request(data, cb) { data = this.createRequest(data); const promise = new Promise((resolve, reject) => { axios(data) .then(response => { return resolve([ new Response(response.status, response.data, response.headers), response.data, ]); }) .catch(error => { if (error.response) { if (error.response.status >= 400) { return reject(new ResponseError(error.response)); } } return reject(error); }); }); // Throw an error in case a callback function was not passed. if (cb && typeof cb !== 'function') { throw new Error('Callback passed is not a function.'); } if (cb) { return promise .then(result => cb(null, result)) .catch(error => cb(error, null)); } return promise; } } module.exports = Client;