UNPKG

bitly-node-api

Version:
173 lines (147 loc) 5.41 kB
'use strict'; // var debug = require('debug')('bitly:BitlyHttpClient'); var Promise = require('bluebird'); var utils = require('./utils'); var OPTIONAL_REGEX = /^optional!/; var _ = require('lodash'); /** * Create an API method from the declared spec. * * @param [spec.method='GET'] Request Method (POST, GET, DELETE, PUT) * @param [spec.path=''] Path to be appended to the API BASE_PATH, joined with * the instance's path (e.g. 'charges' or 'customers') * @param [spec.required=[]] Array of required arguments in the order that they * must be passed by the consumer of the API. Subsequent optional arguments are * optionally passed through a hash (Object) as the penultimate argument * (preceding the also-optional callback argument * @param [spec.encode] Function for mutating input parameters to a method. * Usefully for applying transforms to data on a per-method basis. */ module.exports = { bitlyMethod: function (spec) { var commandPath = typeof spec.path === 'function' ? spec.path : utils.makeURLInterpolator(spec.path || ''); var requestMethod = (spec.method || 'GET').toUpperCase(); var urlParams = spec.urlParams || []; var encode = spec.encode || function (data) { return data; }; return function () { var self = this; var args = [].slice.call(arguments); var callback = typeof args[args.length - 1] === 'function' && args.pop(); var urlData = this.createUrlData(); return this.wrapTimeout(new Promise((function (resolve, reject) { for (var i = 0, l = urlParams.length; i < l; ++i) { // Note that we shift the args array after every iteration so this just // grabs the "next" argument for use as a URL parameter. var arg = args[0]; var param = urlParams[i]; var isOptional = OPTIONAL_REGEX.test(param); param = param.replace(OPTIONAL_REGEX, ''); if (!arg) { if (isOptional) { urlData[param] = ''; continue; } return reject(new Error( 'bitly: Argument "' + urlParams[i] + '" required, but got: ' + arg + ' (on API request to ' + requestMethod + ' ' + commandPath + ')' )); } urlData[param] = args.shift(); } var data = encode(utils.getDataFromArgs(args)); var opts = utils.getOptionsFromArgs(args); if (args.length) { var err = new Error('bitly: Unknown arguments (' + args + ').'); return reject(err); } var requestPath = this.createFullPath(commandPath, urlData); function requestCallback(err, response) { if (err) { reject(err); } else { resolve( spec.transformResponseData ? spec.transformResponseData(response) : response ); } } var options = { headers: Object.assign(opts.headers, spec.headers) }; options.useBody = spec.useBody || false; options.authorization = spec.authorization || ''; options.contentType = spec.contentType || ''; self._request(requestMethod, requestPath, data, opts.auth, options, requestCallback); }).bind(this)), callback); }; }, setMetadata: function (id, key, value, auth, cb) { var self = this; var data = key; var isObject = _.isPlainObject(key); // We assume null for an empty object var isNull = data === null || (isObject && !Object.keys(data).length); // Allow optional passing of auth & cb: if ((isNull || isObject) && typeof value === 'string') { auth = value; } else if (typeof auth !== 'string') { if (!cb && typeof auth === 'function') { cb = auth; } auth = null; } var urlData = this.createUrlData(); var path = this.createFullPath('/' + id, urlData); return this.wrapTimeout(new Promise((function (resolve, reject) { if (isNull) { // Reset metadata: sendMetadata(null, auth); } else if (!isObject) { // Set individual metadata property: var metadata = {}; metadata[key] = value; sendMetadata(metadata, auth); } else { // Set entire metadata object after resetting it: this._request('POST', path, { metadata: null }, auth, {}, function (err) { if (err) { return reject(err); } sendMetadata(data, auth); }); } function sendMetadata(metadata, auth) { self._request('POST', path, { metadata: metadata }, auth, {}, function (err, response) { if (err) { reject(err); } else { resolve(response.metadata); } }); } }).bind(this)), cb); }, getMetadata: function (id, auth, cb) { if (!cb && typeof auth === 'function') { cb = auth; auth = null; } var urlData = this.createUrlData(); var path = this.createFullPath('/' + id, urlData); return this.wrapTimeout(new Promise((function (resolve, reject) { this._request('GET', path, {}, auth, {}, function (err, response) { if (err) { reject(err); } else { resolve(response.metadata); } }); }).bind(this)), cb); } };