bitly-node-api
Version:
bitly api wrapper
173 lines (147 loc) • 5.41 kB
JavaScript
// 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);
}
};
;