@sendgrid/client
Version:
Twilio SendGrid NodeJS API client
190 lines (160 loc) • 4.93 kB
JavaScript
'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;