UNPKG

victorops-api-client

Version:

A library for interacting with the VictorOps REST API

271 lines (241 loc) 8.73 kB
const axios = require('axios'); const mapValues = require('lodash.mapvalues'); const has = require('lodash.has'); const isPlainObject = require('lodash.isplainobject'); const isEmpty = require('lodash.isempty'); const { version } = require('../package.json'); // Import all of the endpoints. const oncall = require('./endpoints/oncall'); const incidents = require('./endpoints/incidents'); const alerts = require('./endpoints/alerts'); const reporting = require('./endpoints/reporting'); const users = require('./endpoints/users'); const contactMethods = require('./endpoints/contact_methods'); const userPagingPolicies = require('./endpoints/user_paging_policies'); const pagingPolicyValues = require('./endpoints/paging_policy_values'); const pagingPolicies = require('./endpoints/personal_paging_policies'); const teams = require('./endpoints/teams'); const escalationPolicies = require('./endpoints/escalation_policies'); const routingKeys = require('./endpoints/routing_keys'); const overrides = require('./endpoints/scheduled_overrides'); const rotations = require('./endpoints/rotations'); const webhooks = require('./endpoints/webhooks'); const chat = require('./endpoints/chat'); const notes = require('./endpoints/notes'); const maintenanceMode = require('./endpoints/maintenance_mode'); // Import the error utils. const { RequestError, StatusCodeError, isAxiosRequestError, isAxiosResponseError } = require('./utils/errors'); const status = require('./utils/status'); // Base URL for VictorOps REST API. const BASE_URL = 'https://api.victorops.com'; // API Prefixes. const API_PUBLIC = '/api-public'; const API_REPORTING = '/api-reporting'; // Client user agent string. const USER_AGENT = `VictorOps-API-Client-JS/${version}`; // Default API version. const API_VERSION = 1; /** * A library for interacting with the VictorOps REST API. * * @class VictorOpsApiClient */ class VictorOpsApiClient { /** * Creates an instance of VictorOpsApiClient. * * @param {Object} [options={}] The client options. * @memberof VictorOpsApiClient */ constructor(options) { this._options = options || {}; this._apiId = undefined; this._apiKey = undefined; // Check the options. this._checkOptions(this._options); // Get the headers for the requests. this._headers = this._getRequestHeaders(); this.timeout = this._options.timeout || 5000; this.baseUrl = this._options.baseUrl || BASE_URL; this.fullResponse = this._options.fullResponse || false; this.maxContentLength = this._options.maxContentLength || 10000; this.maxBodyLength = this._options.maxBodyLength || 2000; // Create the Axios instance. this._axiosInstance = this._getAxiosInstance(); // Add the endpoints. this.oncall = mapValues(oncall, (ep) => ep.bind(this)); this.incidents = mapValues(incidents, (ep) => ep.bind(this)); this.alerts = mapValues(alerts, (ep) => ep.bind(this)); this.reporting = mapValues(reporting, (ep) => ep.bind(this)); this.users = mapValues(users, (ep) => ep.bind(this)); this.contactMethods = mapValues(contactMethods, (ep) => ep.bind(this)); this.userPagingPolicies = mapValues(userPagingPolicies, (ep) => ep.bind(this)); this.pagingPolicyValues = mapValues(pagingPolicyValues, (ep) => ep.bind(this)); this.personalPagingPolicies = mapValues(pagingPolicies, (ep) => ep.bind(this)); this.teams = mapValues(teams, (ep) => ep.bind(this)); this.escalationPolicies = mapValues(escalationPolicies, (ep) => ep.bind(this)); this.routingKeys = mapValues(routingKeys, (ep) => ep.bind(this)); this.scheduledOverrides = mapValues(overrides, (ep) => ep.bind(this)); this.rotations = mapValues(rotations, (ep) => ep.bind(this)); this.webhooks = mapValues(webhooks, (ep) => ep.bind(this)); this.chat = mapValues(chat, (ep) => ep.bind(this)); this.notes = mapValues(notes, (ep) => ep.bind(this)); this.maintenanceMode = mapValues(maintenanceMode, (ep) => ep.bind(this)); } /** * Checks the provided options. * * @param {Object} options Provided options. * @memberof VictorOpsApiClient */ _checkOptions(options) { // Check the 'apiId'. if ((!has(options, 'apiId') && !has(process, 'env.VO_API_ID')) && isEmpty(options.apiId) ) { throw new Error('A VictorOps Api ID is a required option.'); } // Check the 'apiKey'. if ((!has(options, 'apiKey') && !has(process, 'env.VO_API_KEY')) && isEmpty(options.apiKey) ) { throw new Error('A VictorOps Api Key is a required option.'); } // Set the API ID and API key values. this._apiId = (process.env.VO_API_ID || options.apiId).trim(); this._apiKey = (process.env.VO_API_KEY || options.apiKey).trim(); // Make sure the API ID is not empty. if (!this._apiId.length) { this._apiId = undefined; throw new Error('A VictorOps Api ID is a required option.'); } // Make sure the API key is not empty. if (!this._apiKey.length) { this._apiKey = undefined; throw new Error('A VictorOps Api Key is a required option.'); } } /** * Gets the headers for a VictorOps API request. * * @returns {Object} Request headers. * @memberof VictorOpsApiClient */ _getRequestHeaders() { if (!this._apiId || !this._apiKey) { throw new Error('Missing the Api ID (apiId) or Api Key (apiKey).'); } return { 'Accept': 'application/json; charset=utf-8', 'Content-Type': 'application/json; charset=utf-8', 'X-VO-Api-Id': this._apiId, 'X-VO-Api-Key': this._apiKey, 'User-Agent': USER_AGENT, }; } /** * Creates an Axios instance. * * @returns {Axios} Axios instance. * @memberof VictorOpsApiClient */ _getAxiosInstance() { return axios.create({ baseURL: this.baseUrl, headers: this._headers, timeout: this.timeout, responseType: 'json', responseEncoding: 'utf8', maxContentLength: this.maxContentLength, maxBodyLength: this.maxBodyLength, }); } /** * Gets the request options for a VictorOps API request. * * @param {String} method HTTP method. * @param {String} path HTTP request path. * @param {Object} [qs=null] Query parameters. * @param {Object} [body=null] Request body. * @returns {Object} Request options. * @memberof VictorOpsApiClient */ _getRequestOptions(method, path, qs = null, body = null) { // Set the request options. const options = { method, url: path, params: (qs && isPlainObject(qs)) ? qs : undefined, }; // Add body value (if needed). if (/put|post|patch|delete/i.test(method) && (body && isPlainObject(body)) ) { options.data = body; } return options; } /** * Performs a VictorOps API request. * * @param {Object} options Request options. * @returns {Promise<Object|Array>} The response from the API request. * @memberof VictorOpsApiClient */ async _performRequest(options) { // Check the options. if (!options || !isPlainObject(options) || isEmpty(options)) { throw new Error('A request options object must be provided'); } // Get the response. const response = await this._axiosInstance.request(options); // Should the full response be returned. if (this.fullResponse) { // Get the status message. const statusMessage = response.statusText || status[response.status]; return { statusCode: response.status, statusMessage, headers: response.headers, data: response.data, }; } return response.data; } /** * Creates a custom error from an Axios error. * * @param {Error} err The 'axios' Error. * @returns {Error} The custom error. * @memberof VictorOpsApiClient */ _handleError(err) { // Check for Axios errors. if (isAxiosRequestError(err)) { return new RequestError(err); } else if (isAxiosResponseError(err)) { return new StatusCodeError(err); } return err; } /** * Gets the API prefix for a request. * * @param {String} [path=null] Endpoint path. * @param {Number} [version=API_VERSION] API version. * @param {Boolean} [reporting=false] Reporting endpoint or not. * @returns {String} The API prefix. * @memberof VictorOpsApiClient */ getApiPrefix(path = null, version = API_VERSION, reporting = false) { // Get the base API prefix. const baseApi = (reporting) ? API_REPORTING : API_PUBLIC; if (path) { return `${baseApi}/v${version}/${path}`; } else { return `${baseApi}/v${version}`; } } } module.exports = VictorOpsApiClient;