nodejitsu-api
Advanced tools
Comparing version 0.3.8 to 0.4.0
@@ -0,20 +1,33 @@ | ||
'use strict'; | ||
var parts = ['Apps', 'Users', 'Keys', 'Tokens', 'Snapshots', 'Databases', 'Logs', 'Client']; | ||
parts.forEach(function (k) { | ||
parts.forEach(function forEach(k) { | ||
exports[k] = require('./client/' + k.toLowerCase())[k]; | ||
}) | ||
}); | ||
exports.createClient = function (options) { | ||
// | ||
// ### function createClient(options) | ||
// #### @options {Object} options for the clients | ||
// Generates a new API client. | ||
// | ||
exports.createClient = function createClient(options) { | ||
var client = {}; | ||
parts.forEach(function (k) { | ||
client[k.toLowerCase()] = new exports[k](options); | ||
client[k.toLowerCase()].on('debug::request', debug); | ||
client[k.toLowerCase()].on('debug::response', debug); | ||
}); | ||
function debug (arguments) { | ||
parts.forEach(function generate(k) { | ||
var endpoint = k.toLowerCase(); | ||
client[endpoint] = new exports[k](options); | ||
if (options.debug) { | ||
console.log(arguments); | ||
client[endpoint].on('debug::request', debug); | ||
client[endpoint].on('debug::response', debug); | ||
} | ||
}); | ||
function debug(args) { | ||
console.log(args); | ||
} | ||
return client; | ||
} | ||
}; |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
/* | ||
@@ -36,4 +38,19 @@ * app.js: Client for the Nodejitsu apps API. | ||
this.request('GET', ['apps', username], callback, function (res, result) { | ||
callback(null, result.apps || res.statusCode); | ||
var self = this; | ||
this.request({ uri: ['apps', username] }, function (err, result, res) { | ||
if (err) return callback(err); | ||
callback(err, result.apps); | ||
// | ||
// Cache the lookups so we know which datacenters belong to the apps. | ||
// | ||
if (username === self.options.get('username')) { | ||
result.apps.forEach(function reduce(memo, app) { | ||
if (app.config && app.config.cloud) { | ||
self.clouds[app._id] = app.cloud; | ||
} | ||
}); | ||
} | ||
}); | ||
@@ -51,5 +68,3 @@ }; | ||
this.request('POST', ['apps', appName], app, callback, function (res, result) { | ||
callback(null, result || res.statusCode); | ||
}); | ||
this.request({ method: 'POST', uri: ['apps', appName], body: app }, callback); | ||
}; | ||
@@ -65,6 +80,17 @@ | ||
appName = defaultUser.call(this, appName); | ||
var argv = ['apps'].concat(appName.split('/')); | ||
var argv = ['apps'].concat(appName.split('/')), | ||
self = this; | ||
this.request('GET', argv, callback, function (res, result) { | ||
callback(null, result.app || res.statusCode); | ||
this.request({ uri: argv }, function (err, result) { | ||
if (err) return callback(err); | ||
var app = result.app; | ||
callback(err, app); | ||
// | ||
// Update the cloud cache. | ||
// | ||
if (app.config && app.config.cloud) { | ||
self.clouds[appName] = app.config.cloud; | ||
} | ||
}); | ||
@@ -84,5 +110,3 @@ }; | ||
this.request('PUT', argv, attrs, callback, function (res, result) { | ||
callback(null, result || res.statusCode); | ||
}); | ||
this.request({ method: 'PUT', uri: argv, body: attrs }, callback); | ||
}; | ||
@@ -100,5 +124,3 @@ | ||
this.request('DELETE', argv, callback, function (res, result) { | ||
callback(null, result || res.statusCode); | ||
}); | ||
this.request({ method: 'DELETE', uri: argv, appName: appName }, callback); | ||
}; | ||
@@ -109,12 +131,22 @@ | ||
// #### @appName {string} Name of the application to start | ||
// #### @cloud {Object|Array} **Optional** Cloud to start this application in. | ||
// #### @callback {function} Continuation to pass control to when complete | ||
// Starts the application with `name` for the authenticated user. | ||
// | ||
Apps.prototype.start = function (appName, callback) { | ||
Apps.prototype.start = function (appName, cloud, callback) { | ||
if (!callback && typeof cloud === 'function') { | ||
callback = cloud; | ||
cloud = null; | ||
} | ||
appName = defaultUser.call(this, appName); | ||
var argv = ['apps'].concat(appName.split('/')).concat('start'); | ||
this.request('POST', argv, callback, function (res, result) { | ||
callback(null, result || res.statusCode); | ||
}); | ||
if (cloud) { | ||
self.clouds[appName] = !Array.isArray(cloud) | ||
? [cloud] | ||
: cloud; | ||
} | ||
this.cloud({ method: 'POST', uri: argv, appName: appName }, this.request, callback); | ||
}; | ||
@@ -132,5 +164,3 @@ | ||
this.request('POST', argv, callback, function (res, result) { | ||
callback(null, result || res.statusCode); | ||
}); | ||
this.cloud({ method: 'POST', uri: argv, appName: appName }, this.request, callback); | ||
}; | ||
@@ -148,5 +178,3 @@ | ||
this.request('POST', argv, callback, function (res, result) { | ||
callback(null, result || res.statusCode); | ||
}); | ||
this.cloud({ method: 'POST', uri: argv, appName: appName }, this.request, callback); | ||
}; | ||
@@ -165,5 +193,3 @@ | ||
this.request('POST', argv, app, callback, function (res, result) { | ||
callback(null, result || res.statusCode); | ||
}); | ||
this.request({ method: 'POST', uri: argv, body: app }, callback); | ||
}; | ||
@@ -180,7 +206,39 @@ | ||
appName = defaultUser.call(this, appName); | ||
var argv = ['apps'].concat(appName.split('/')).concat('drones'); | ||
var argv = ['apps'].concat(appName.split('/')).concat('cloud'), | ||
cloud = [{ drones: drones }]; | ||
this.request('POST', argv, { drones: drones }, callback, function (res, result) { | ||
callback(null, result || res.statusCode); | ||
this.cloud({ method: 'POST', uri: argv, body: cloud, appName: appName }, this.request, callback); | ||
}; | ||
// | ||
// ### function datacenter(appName, cloud, callback) | ||
// #### @appName {String} Name of the application | ||
// #### @cloud {Object} Cloud specification | ||
// #### @callback {Function} Continuation to pass control to when complete | ||
// Deploy the given application in a new datacenter. | ||
// | ||
Apps.prototype.datacenter = function (appName, cloud, callback) { | ||
appName = defaultUser.call(this, appName); | ||
var argv = ['apps'].concat(appName.split('/')).concat('cloud'), | ||
self = this; | ||
if (!Array.isArray(cloud)) cloud = [cloud]; | ||
// | ||
// As this API request needs to go to the correct datacenter, add the current | ||
// cloud call to our internal datacenter cache so it will target the correct | ||
// API | ||
// | ||
this.clouds[appName] = cloud; | ||
this.cloud({ method: 'POST', uri: argv, body: cloud, appName: appName }, this.request, function (err, result) { | ||
// | ||
// Assume that this call invalidates our cached datacenter endpoint, so | ||
// remove it, and it will be fetched again on the next call | ||
// | ||
delete self.clouds[appName]; | ||
if (err) return callback(err); | ||
callback(err, result); | ||
}); | ||
}; | ||
}; |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
/* | ||
@@ -9,6 +11,6 @@ * client.js: Client base for the Nodejitsu API clients. | ||
var fs = require('fs'), | ||
util = require('util'), | ||
request = require('request'), | ||
util = require('util'), | ||
EventEmitter = require('events').EventEmitter, | ||
Client = require('./client').Client; | ||
async = require('./helpers').async, | ||
EventEmitter = require('events').EventEmitter; | ||
@@ -22,2 +24,4 @@ // | ||
var Client = exports.Client = function (options) { | ||
this.clouds = {}; | ||
this.datacenters = {}; | ||
this.options = options; | ||
@@ -31,3 +35,2 @@ this._request = request; | ||
} | ||
}; | ||
@@ -38,79 +41,178 @@ | ||
// | ||
// ### @private function request (method, uri, [body], success, callback) | ||
// #### @method {string} HTTP method to use | ||
// #### @uri {Array} Locator for the Remote Resource | ||
// #### @body {Object} **optional** JSON Request Body | ||
// ### function endpoints(callback) | ||
// #### @callback {function} Continuation to respond to when complete. | ||
// Retrieves a list of currenlty active datacenters and providers | ||
// | ||
Client.prototype.endpoints = function (callback) { | ||
var self = this; | ||
this.request({ uri: ['endpoints'] }, function (err, result) { | ||
if (err) return callback(err); | ||
self.datacenters = result.endpoints; | ||
callback(err, result.endpoints); | ||
}); | ||
}; | ||
// | ||
// ### @private function cloud (options, api, callback) | ||
// #### @options {Object} Configuration | ||
// #### @api {Function} Private API that needs to be called, request / upload | ||
// #### @callback {Function} Continuation | ||
// Transforms the given API in to a cloud aware method assigning it to the | ||
// correct datacenter. | ||
// | ||
Client.prototype.cloud = function (options, api, callback) { | ||
var self = this, | ||
flow = []; | ||
// We don't need to have any datacenter information for these types of calls | ||
if (options.remoteUri || !options.appName || !options.method || options.method === 'GET') { | ||
return api.call(this, options, callback); | ||
} | ||
// | ||
// Fetches the datacenter locations for the app | ||
// | ||
function locations(done) { | ||
var argv = ['apps', options.appName, 'cloud']; | ||
self.request({ uri: argv }, function apps(err, result) { | ||
if (err) return done(err); | ||
self.clouds[options.appName] = result; | ||
done(); | ||
}); | ||
} | ||
// | ||
// We don't have any datacenter data by default as it's only needed for | ||
// starting or stopping the application. | ||
// | ||
if (!Object.keys(this.datacenters).length) flow.push(this.endpoints.bind(this)); | ||
// | ||
// Make sure that we have this app in our cloud cache so we know in which | ||
// datacenter it is. | ||
// | ||
if (!(options.appName in this.clouds)) flow.push(locations); | ||
// | ||
// Iterate over the possible steps. | ||
// | ||
async.iterate(flow, function completed(err) { | ||
if (err) return callback(err); | ||
// The returned clouds is an array of datacenters, iterate over them. | ||
async.map(self.clouds[options.appName], function iterate(cloud, done) { | ||
// | ||
// Clone the options to prevent race conditions. | ||
// | ||
var opts = Object.keys(options).reduce(function clone(memo, field) { | ||
memo[field] = options[field]; | ||
return memo; | ||
}, {}); | ||
if (!self.datacenters || !self.datacenters[cloud.provider] | ||
|| !self.datacenters[cloud.provider][cloud.datacenter]) { | ||
return done(new Error('Unknown cloud: ' + cloud.provider + ' ' + cloud.datacenter)); | ||
} | ||
opts.remoteUri = self.datacenters[cloud.provider][cloud.datacenter]; | ||
if (!~opts.remoteUri.indexOf('http')) opts.remoteUri = 'https://'+ opts.remoteUri; | ||
api.call(self, opts, done); | ||
}, function ready(err, results) { | ||
if (err) { | ||
delete self.clouds[options.appName]; | ||
return callback(err); | ||
} | ||
return results.length === 1 | ||
? callback(null, results[0]) | ||
: callback(null, results) | ||
// | ||
// We probably want to figure out which calls went okay, and which one | ||
// failed when we get an error so we only have to retry that one. | ||
// | ||
}); | ||
}); | ||
}; | ||
// | ||
// ### @private function request (options, callback) | ||
// #### @options {Object} Configuration | ||
// #### @callback {function} Continuation to call if errors occur. | ||
// #### @success {function} Continuation to call upon successful transactions | ||
// Makes a request to `this.remoteUri + uri` using `method` and any | ||
// `body` (JSON-only) if supplied. Short circuits to `callback` if the response | ||
// code from Nodejitsu matches `failCodes`. | ||
// Makes a request to the remoteUri + uri using the HTTP and any body if | ||
// supplied. | ||
// | ||
Client.prototype.request = function (method, uri /* variable arguments */) { | ||
var options, args = Array.prototype.slice.call(arguments), | ||
success = args.pop(), | ||
callback = args.pop(), | ||
body = typeof args[args.length - 1] === 'object' && !Array.isArray(args[args.length - 1]) && args.pop(), | ||
token = this.options.get('password') || this.options.get('api-token'), | ||
encoded = new Buffer(this.options.get('username') + ':' + token).toString('base64'), | ||
proxy = this.options.get('proxy'); | ||
// Options: | ||
// - method {String}: HTTP method to use | ||
// - uri {Array}: Locator for the remote resource | ||
// - remoteUri {String}: Location of the remote API | ||
// - timeout {Number}: Request timeout | ||
// - body {Array|Object}: JSON request body | ||
// - headers {Object}: Headers you want to set | ||
// | ||
Client.prototype.request = function (options, callback) { | ||
options = options || {}; | ||
options = { | ||
method: method || 'GET', | ||
uri: this.options.get('remoteUri') + '/' + uri.join('/'), | ||
var password = this.options.get('password') || this.options.get('api-token'), | ||
auth = new Buffer(this.options.get('username') + ':' + password).toString('base64'), | ||
proxy = this.options.get('proxy'), | ||
self = this, | ||
opts = {}; | ||
opts = { | ||
method: options.method || 'GET', | ||
uri: (options.remoteUri || this.options.get('remoteUri')) + '/' + options.uri.join('/'), | ||
headers: { | ||
'Authorization': 'Basic ' + encoded, | ||
'Authorization': 'Basic ' + auth, | ||
'Content-Type': 'application/json' | ||
}, | ||
timeout: this.options.get('timeout') || 8 * 60 * 1000 | ||
timeout: options.timeout || this.options.get('timeout') || 8 * 60 * 1000, | ||
}; | ||
if (body) { | ||
options.body = JSON.stringify(body); | ||
if (options.body) { | ||
try { opts.body = JSON.stringify(options.body); } | ||
catch (e) { return callback(e); } | ||
} else if (opts.method !== 'GET' && options.body !== false) { | ||
opts.body = '{}'; | ||
} | ||
else if (method !== 'GET') { | ||
options.body = '{}'; | ||
} | ||
if (proxy) { | ||
options.proxy = proxy; | ||
} | ||
if (options.headers) Object.keys(options.headers).forEach(function each(field) { | ||
opts.headers[field] = options.headers[field]; | ||
}); | ||
var self = this; | ||
if (proxy) opts.proxy = proxy; | ||
self.emit('debug::request', options); | ||
this.emit('debug::request', opts); | ||
return this._request(options, function (err, response, body) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
return this._request(opts, function requesting(err, res, body) { | ||
if (err) return callback(err); | ||
var statusCode, result, error; | ||
var poweredBy = res.headers['x-powered-by'], | ||
result, statusCode, error; | ||
try { | ||
statusCode = response.statusCode; | ||
statusCode = res.statusCode; | ||
result = JSON.parse(body); | ||
} | ||
catch (ex) { | ||
// Ignore Errors | ||
} | ||
} catch (e) {} | ||
self.emit('debug::response', { statusCode: statusCode, result: result }); | ||
var poweredBy = response.headers['x-powered-by']; | ||
if (!self.options.get('ignorePoweredBy') && !poweredBy || poweredBy.indexOf('Nodejitsu') === -1) { | ||
if (!self.options.get('ignorePoweredBy') && !poweredBy || !~poweredBy.indexOf('Nodejitsu')) { | ||
error = new Error('The Nodejitsu-API requires you to connect the Nodejitsu\'s stack (api.nodejitsu.com)'); | ||
error.statusCode = 403; | ||
error.result = ""; | ||
return callback(error); | ||
} | ||
if (failCodes[statusCode]) { | ||
error.result = ''; | ||
} else if (failCodes[statusCode]) { | ||
error = new Error('Nodejitsu Error (' + statusCode + '): ' + failCodes[statusCode]); | ||
error.statusCode = statusCode; | ||
error.result = result; | ||
return callback(error); | ||
} | ||
success(response, result); | ||
// Only add the response argument when people ask for it | ||
if (callback.length === 3) return callback(error, result, res); | ||
callback(error, result); | ||
}); | ||
@@ -120,86 +222,66 @@ }; | ||
// | ||
// ### function upload (uri, contentType, file, callback, success) | ||
// #### @uri {Array} Locator for the Remote Resource | ||
// #### @contentType {string} Content-Type header to use for the upload. | ||
// #### @file {string} Path of the local file to upload. | ||
// #### @success {function} Continuation to call upon successful transactions | ||
// ### @private function upload (options, callback) | ||
// #### @options {Object} | ||
// #### @callback {function} Continuation to call if errors occur. | ||
// Makes a `POST` request to `this.remoteUri + uri` with the data in `file` | ||
// as the request body. Short circuits to `callback` if the response | ||
// code from Nodejitsu matches `failCodes`. | ||
// Makes a POST request to the remoteUri + uri using the HTTP and any body if | ||
// supplied. It defers the call the private request method. | ||
// | ||
Client.prototype.upload = function (uri, contentType, file, callback, success) { | ||
var self = this, | ||
options, | ||
out, | ||
encoded, | ||
emitter = new EventEmitter(), | ||
proxy = self.options.get('proxy'), | ||
token = this.options.get('password') || this.options.get('api-token'), | ||
encoded = new Buffer(this.options.get('username') + ':' + token).toString('base64'); | ||
// Options: | ||
// - uri {Array}: Locator for the remote resource | ||
// - remoteUri {String}: Location of the remote API | ||
// - timeout {Number}: Request timeout | ||
// - file: {String} path to the file you want to upload | ||
// | ||
Client.prototype.upload = function (options, callback) { | ||
options = options || {}; | ||
fs.stat(file, function (err, stat) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
var progress = new EventEmitter(), | ||
self = this; | ||
emitter.emit('start', stat); | ||
fs.stat(options.file, function fstat(err, stat) { | ||
if (err) return callback(err); | ||
options = { | ||
method: 'POST', | ||
uri: self.options.get('remoteUri') + '/' + uri.join('/'), | ||
headers: { | ||
'Authorization': 'Basic ' + encoded, | ||
'Content-Type': contentType, | ||
'Content-Length': stat.size | ||
}, | ||
timeout: self.options.get('timeout') || 8 * 60 * 1000 | ||
}; | ||
var size = stat.size; | ||
if(proxy) { | ||
options.proxy = proxy; | ||
} | ||
// Set the correct headers | ||
if (!options.headers) options.headers = {}; | ||
options.headers['Content-Length'] = size; | ||
options.headers['Content-Type'] = options.contentType || 'application/octet-stream'; | ||
out = self._request(options, function (err, response, body) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
// And other default options to do a successful post | ||
if (!options.method) options.method = 'POST'; | ||
options.body = false; | ||
var statusCode, result, error; | ||
// Defer all the error handling to the request method | ||
var req = self.request(options, callback); | ||
if (!req) return; | ||
try { | ||
statusCode = response.statusCode; | ||
result = JSON.parse(body); | ||
} | ||
catch (ex) { | ||
// Ignore Errors | ||
} | ||
if (failCodes[statusCode]) { | ||
error = new Error('Nodejitsu Error (' + statusCode + '): ' + failCodes[statusCode]); | ||
error.result = result; | ||
return callback(error); | ||
} | ||
// Notify that we have started the upload procedure and give it a reference | ||
// to the stat. | ||
progress.emit('start', stat); | ||
success(response, result); | ||
}); | ||
req.once('request', function requested(request) { | ||
request.once('socket', function data(socket) { | ||
var buffer = 0; | ||
out.on('request', function(request) { | ||
var buffer = 0; | ||
request.on('socket', function(socket) { | ||
var id = setInterval(function() { | ||
var interval = setInterval(function polling() { | ||
var data = socket._bytesDispatched || (socket.socket && socket.socket._bytesDispatched); | ||
emitter.emit('data', data - buffer); | ||
buffer = data; | ||
if(buffer >= stat.size) { | ||
clearInterval(id); | ||
emitter.emit('end'); | ||
if (data) { | ||
progress.emit('data', data - buffer); | ||
buffer = data; | ||
} | ||
},100); | ||
if (buffer >= size) { | ||
clearInterval(interval); | ||
progress.emit('end'); | ||
} | ||
}, 100); | ||
}); | ||
}); | ||
fs.createReadStream(file).pipe(out); | ||
fs.createReadStream(options.file).pipe(req); | ||
}); | ||
return emitter; | ||
return progress; | ||
}; | ||
@@ -217,2 +299,1 @@ | ||
}; | ||
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
/* | ||
@@ -18,3 +20,3 @@ * databases.js: Client for the Nodejitsu users API. | ||
var Databases = exports.Databases = function (options) { | ||
Client = require('./client').Client;Client.call(this, options); | ||
Client.call(this, options); | ||
}; | ||
@@ -33,11 +35,9 @@ | ||
Databases.prototype.create = function (databaseType, databaseName, callback) { | ||
this.request( | ||
'POST', | ||
['databases', this.options.get('username'), databaseName], | ||
{ type: databaseType }, | ||
callback, | ||
function (res, result) { | ||
callback(null, result.database, res); | ||
} | ||
); | ||
var argv = ['databases', this.options.get('username'), databaseName]; | ||
this.request({ method: 'POST', uri: argv, body: { type: databaseType }}, function (err, result, res) { | ||
if (err) return callback(err); | ||
callback(err, result.database, res); | ||
}); | ||
}; | ||
@@ -52,10 +52,9 @@ | ||
Databases.prototype.get = function (databaseName, callback) { | ||
this.request( | ||
'GET', | ||
['databases', this.options.get('username'), databaseName], | ||
callback, | ||
function (res, result) { | ||
callback(null, result.database); | ||
} | ||
); | ||
var argv = ['databases', this.options.get('username'), databaseName]; | ||
this.request({ uri: argv }, function (err, result) { | ||
if (err) return callback(err); | ||
callback(null, result.database); | ||
}); | ||
}; | ||
@@ -65,2 +64,3 @@ | ||
// ### function list (username, callback) | ||
// #### @username {String} **optional** Username | ||
// #### @callback {function} Continuation to pass control to when complete | ||
@@ -70,3 +70,2 @@ // Gets the list of databases assigned to the user | ||
Databases.prototype.list = function (username, callback) { | ||
if (arguments.length === 1) { | ||
@@ -76,11 +75,8 @@ callback = username; | ||
} | ||
this.request( | ||
'GET', | ||
['databases', username], | ||
callback, | ||
function (res, result) { | ||
callback(null, result.databases); | ||
} | ||
); | ||
this.request({ uri: ['databases', username] }, function (err, result) { | ||
if (err) return callback(err); | ||
callback(null, result.databases); | ||
}); | ||
}; | ||
@@ -95,10 +91,5 @@ | ||
Databases.prototype.destroy = function (databaseName, callback) { | ||
this.request( | ||
'DELETE', | ||
['databases', this.options.get('username'), databaseName], | ||
callback, | ||
function (res, result) { | ||
callback(null, result); | ||
} | ||
); | ||
} | ||
var argv = ['databases', this.options.get('username'), databaseName]; | ||
this.request({ method: 'DELETE', uri: argv }, callback); | ||
}; |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
// | ||
@@ -14,2 +16,67 @@ // ### function defaultUser (appName) | ||
return appName; | ||
} | ||
}; | ||
// | ||
// Async flow control helper function, to clean up some messy code. | ||
// | ||
exports.async = { | ||
// | ||
// ### function iterate (arr, callback) | ||
// #### @arr {Array} Array of functions to call | ||
// #### @callback {Function} Completion function | ||
// Iterates of over the array of functions and triggers the callback once it | ||
// has been completed or when an error occures. | ||
// | ||
iterate: function iterate(arr, callback) { | ||
callback = callback || noop; | ||
var completed = 0, | ||
expected = arr.length; | ||
if (!expected) return callback(); | ||
(function iterator() { | ||
arr[completed](function next(err) { | ||
if (err) return callback(err); | ||
if (++completed !== expected) return iterator(); | ||
callback(); | ||
}); | ||
}()); | ||
}, | ||
// | ||
// ### function map (arr, iterator, callback) | ||
// #### @arr {Array} Array of functions to call | ||
// #### @callback {Function} Completion function | ||
// Async mapping | ||
// | ||
map: function map(arr, iterator, callback) { | ||
callback = callback || noop; | ||
var results = [], | ||
completed = 0, | ||
expected = arr.length; | ||
if (!expected) return callback(); | ||
arr.forEach(function loop(something, index) { | ||
iterator(something, function completion(err, value) { | ||
if (err) { | ||
callback(err, results); | ||
return callback = noop; | ||
} | ||
results[index] = value; | ||
if (++completed === expected) { | ||
callback(undefined, results); | ||
} | ||
}); | ||
}); | ||
} | ||
}; | ||
// | ||
// Simple dummy function that is used when no callback is provided | ||
// | ||
function noop() {} |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
/* | ||
@@ -7,7 +9,7 @@ * keys.js: Client for the Nodejitsu Keys API. | ||
*/ | ||
var util = require('util'), | ||
Client = require('./client').Client, | ||
defaultUser = require('./helpers').defaultUser; | ||
// | ||
@@ -32,13 +34,12 @@ // ### function Keys (options) | ||
Keys.prototype.list = function (username, callback) { | ||
if (arguments.length == 1) { | ||
if (arguments.length === 1) { | ||
callback = username; | ||
username = this.options.get('username'); | ||
} | ||
this.request('GET', ['users', username, 'keys'], callback, function (res, result) { | ||
callback(null, result); | ||
}) | ||
this.request({ uri: ['users', username, 'keys'] }, callback); | ||
}; | ||
// | ||
// ### function create (key, callback) | ||
// ### function create (key, callback) | ||
// #### @key {Object} Properties for the new key. | ||
@@ -49,14 +50,12 @@ // #### @callback {function} Continuation to pass control to when complete | ||
Keys.prototype.create = function (id, key, callback) { | ||
if(arguments.length === 2) { | ||
if (arguments.length === 2) { | ||
callback = key; | ||
key = {}; | ||
} | ||
this.request('POST', ['users', id], key, callback, function (res, result) { | ||
callback(null, result); | ||
}); | ||
this.request({ method: 'POST', uri: ['users', id], body: key }, callback); | ||
}; | ||
// | ||
// ### function destroy (key, callback) | ||
// ### function destroy (key, callback) | ||
// #### @key {Object} Properties for the new key. | ||
@@ -67,5 +66,3 @@ // #### @callback {function} Continuation to pass control to when complete | ||
Keys.prototype.destroy = function (key, callback) { | ||
this.request('DELETE', ['users', key], key, callback, function (res, result) { | ||
callback(null, result); | ||
}); | ||
this.request({ method: 'DELETE', uri: ['users', key], body: key }, callback); | ||
}; | ||
@@ -79,5 +76,3 @@ | ||
Keys.prototype.view = function (key, callback) { | ||
this.request('GET', ['users', key], callback, function (res, result) { | ||
callback(null, result); | ||
}); | ||
this.request({ uri: ['users', key] }, callback); | ||
}; |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
/* | ||
@@ -33,4 +35,4 @@ * logs.js: Client for the Nodejitsu logs API. | ||
Logs.prototype.byApp = function (appName, amount, callback) { | ||
var appName = defaultUser.call(this, appName), | ||
argv = ['logs'].concat(appName.split('/')), | ||
appName = defaultUser.call(this, appName); | ||
var argv = ['logs'].concat(appName.split('/')), | ||
options = { | ||
@@ -42,5 +44,3 @@ from: 'NOW-1DAY', | ||
this.request('POST', argv, options, callback, function (res, result) { | ||
callback(null, result); | ||
}); | ||
this.request({ method: 'POST', uri: argv, body: options }, callback); | ||
}; | ||
@@ -58,8 +58,6 @@ | ||
if (arguments.length == 2) { | ||
if (arguments.length === 2) { | ||
callback = amount; | ||
amount = username; | ||
username = this.options.get('username'); | ||
} | ||
@@ -77,5 +75,3 @@ | ||
this.request('POST', ['logs', username], options, callback, function (res, result) { | ||
callback(null, result); | ||
}); | ||
this.request({method: 'POST', uri: ['logs', username], body: options }, callback); | ||
}; |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
/* | ||
@@ -32,7 +34,9 @@ * snapshots.js: Client for the Nodejitsu snapshots API. | ||
Snapshots.prototype.list = function (appName, callback) { | ||
var username = defaultUser.call(this, appName), | ||
argv = ['apps'].concat(username.split('/')).concat('snapshots'); | ||
appName = defaultUser.call(this, appName); | ||
var argv = ['apps'].concat(appName.split('/')).concat('snapshots'); | ||
this.request('GET', argv, callback, function (res, result) { | ||
callback(null, result.snapshots); | ||
this.request({ uri: argv }, function (err, result) { | ||
if (err) return callback(err); | ||
callback(err, result.snapshots); | ||
}); | ||
@@ -51,10 +55,6 @@ }; | ||
Snapshots.prototype.create = function (appName, snapshotName, filename, callback) { | ||
var appName = defaultUser.call(this, appName), | ||
argv = ['apps'] | ||
.concat(appName.split('/')) | ||
.concat(['snapshots', snapshotName]); | ||
appName = defaultUser.call(this, appName); | ||
var argv = ['apps'].concat(appName.split('/')).concat(['snapshots', snapshotName]); | ||
return this.upload(argv, 'application/octet-stream', filename, callback, function (res, body) { | ||
callback(null, body || res.statusCode); | ||
}); | ||
return this.upload({ uri: argv, file: filename }, callback); | ||
}; | ||
@@ -71,11 +71,7 @@ | ||
Snapshots.prototype.fetch = function (appName, snapshotName, callback) { | ||
var appName = defaultUser.call(this, appName), | ||
argv = ['apps'] | ||
.concat(appName.split('/')) | ||
.concat(['snapshots', snapshotName + '.tgz']); | ||
appName = defaultUser.call(this, appName); | ||
var argv = ['apps'].concat(appName.split('/')).concat(['snapshots', snapshotName + '.tgz']); | ||
callback = callback || function () {}; | ||
return this.request('GET', argv, callback, function (res, body) { | ||
callback(null, body || res.statusCode); | ||
}); | ||
return this.request({ uri: argv }, callback); | ||
}; | ||
@@ -88,14 +84,10 @@ | ||
// #### @callback {function} Continuation to pass control to when complete | ||
// Destroys a snapshot for the application with `app.name = name` and | ||
// Destroys a snapshot for the application with `app.name = name` and | ||
// `snapshot.id === snapshotName`. | ||
// | ||
Snapshots.prototype.destroy = function (appName, snapshotName, callback) { | ||
var appName = defaultUser.call(this, appName), | ||
argv = ['apps'] | ||
.concat(appName.split('/')) | ||
.concat(['snapshots', snapshotName]); | ||
this.request('DELETE', argv, callback, function (res, body) { | ||
callback(null, body || res.statusCode); | ||
}); | ||
appName = defaultUser.call(this, appName); | ||
var argv = ['apps'].concat(appName.split('/')).concat(['snapshots', snapshotName]); | ||
this.request({ method: 'DELETE', uri: argv }, callback); | ||
}; | ||
@@ -108,14 +100,10 @@ | ||
// #### @callback {function} Continuation to pass control to when complete | ||
// Activates a snapshot for the application with `app.name = name` and | ||
// Activates a snapshot for the application with `app.name = name` and | ||
// `snapshot.id === snapshotName`. | ||
// | ||
Snapshots.prototype.activate = function (appName, snapshotName, callback) { | ||
var appName = defaultUser.call(this, appName), | ||
argv = ['apps'] | ||
.concat(appName.split('/')) | ||
.concat(['snapshots', snapshotName, 'activate']); | ||
this.request('POST', argv, callback, function (res, body) { | ||
callback(null, body || res.statusCode); | ||
}); | ||
appName = defaultUser.call(this, appName); | ||
var argv = ['apps'].concat(appName.split('/')).concat(['snapshots', snapshotName, 'activate']); | ||
this.request({ method: 'POST', uri: argv }, callback); | ||
}; |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
/* | ||
@@ -7,7 +9,7 @@ * tokens.js: Client for the Nodejitsu Tokens API. | ||
*/ | ||
var util = require('util'), | ||
Client = require('./client').Client, | ||
defaultUser = require('./helpers').defaultUser; | ||
// | ||
@@ -36,5 +38,4 @@ // ### function Tokens (options) | ||
} | ||
this.request('GET', ['users', username, 'tokens'], callback, function (res, result) { | ||
callback(null, result); | ||
}); | ||
this.request({ uri: ['users', username, 'tokens'] }, callback); | ||
}; | ||
@@ -54,2 +55,3 @@ | ||
} | ||
if(arguments.length === 2) { | ||
@@ -62,9 +64,5 @@ callback = tokenID; | ||
if(tokenID !== null){ | ||
this.request('PUT', ['users', username, 'tokens', tokenID], callback, function (res, result) { | ||
callback(null, result); | ||
}); | ||
this.request({ method: 'PUT', uri: ['users', username, 'tokens', tokenID] }, callback); | ||
} else { | ||
this.request('POST', ['users', username, 'tokens'], callback, function (res, result) { | ||
callback(null, result); | ||
}); | ||
this.request({ method: 'POST', uri: ['users', username, 'tokens'] }, callback); | ||
} | ||
@@ -86,7 +84,4 @@ }; | ||
} | ||
this.request('DELETE', ['users', username, 'tokens', tokenID], callback, function (res, result) { | ||
callback(null, result); | ||
}); | ||
this.request({ method: 'DELETE', uri: ['users', username, 'tokens', tokenID] }, callback); | ||
}; | ||
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
/* | ||
@@ -7,7 +9,7 @@ * users.js: Client for the Nodejitsu users API. | ||
*/ | ||
var util = require('util'), | ||
Client = require('./client').Client, | ||
defaultUser = require('./helpers').defaultUser; | ||
// | ||
@@ -32,4 +34,5 @@ // ### function Users (options) | ||
Users.prototype.auth = function (callback) { | ||
this.request('GET', ['auth'], callback, function (res, body) { | ||
callback(null, true); | ||
this.request({ uri: ['auth'] }, function (err, result) { | ||
if (err) return callback(err) | ||
callback(err, true); | ||
}); | ||
@@ -39,3 +42,3 @@ }; | ||
// | ||
// ### function create (user, callback) | ||
// ### function create (user, callback) | ||
// #### @user {Object} Properties for the new user. | ||
@@ -46,9 +49,7 @@ // #### @callback {function} Continuation to pass control to when complete | ||
Users.prototype.create = function (user, callback) { | ||
this.request('POST', ['users', user.username], user, callback, function (res, result) { | ||
callback(); | ||
}); | ||
this.request({ method: 'POST', uri: ['users', user.username], body: user }, callback); | ||
}; | ||
// | ||
// ### function available (username, callback) | ||
// ### function available (username, callback) | ||
// #### @username {string} Username to check availability for. | ||
@@ -59,5 +60,3 @@ // #### @callback {function} Continuation to pass control to when complete | ||
Users.prototype.available = function (username, callback) { | ||
this.request('GET', ['users', username, 'available'], callback, function (res, result) { | ||
callback(null, result); | ||
}); | ||
this.request({ uri: ['users', username, 'available'] }, callback); | ||
}; | ||
@@ -71,6 +70,3 @@ | ||
Users.prototype.view = function (username, callback) { | ||
this.request('GET', ['users', username], callback, function (res, result) { | ||
callback(null, result); | ||
}); | ||
this.request({ uri: ['users', username] }, callback); | ||
}; | ||
@@ -85,9 +81,7 @@ | ||
Users.prototype.confirm = function (user, callback) { | ||
this.request('POST', ['users', user.username, 'confirm'], user, callback, function (res, result) { | ||
callback(null, result); | ||
}); | ||
this.request({ method: 'POST', uri: ['users', user.username, 'confirm'], body: user }, callback); | ||
}; | ||
// | ||
// ### function forgot (username, callback) | ||
// ### function forgot (username, callback) | ||
// #### @username {Object} username requesting password reset. | ||
@@ -99,3 +93,3 @@ // #### @params {Object} Object containing shake and new password, if applicable. | ||
Users.prototype.forgot = function (username, params, callback) { | ||
if (!callback && typeof params == 'function') { | ||
if (!callback && typeof params === 'function') { | ||
callback = params; | ||
@@ -105,5 +99,3 @@ params = {}; | ||
this.request('POST', ['users', username, 'forgot'], params, callback, function (res, result) { | ||
return callback(null, result); | ||
}); | ||
this.request({ method: 'POST', uri: ['users', username, 'forgot'], body: params }, callback); | ||
}; | ||
@@ -119,5 +111,3 @@ | ||
Users.prototype.update = function (username, object, callback) { | ||
this.request('PUT', ['users', username], object, callback, function (res, result) { | ||
callback(null, result); | ||
}); | ||
this.request({ method: 'PUT', uri: ['users', username], body: object }, callback); | ||
}; | ||
@@ -134,5 +124,3 @@ | ||
Users.prototype.destroy = function (username, callback) { | ||
this.request('DELETE', ['users', username], callback, function (res, result) { | ||
callback(null, result); | ||
}); | ||
this.request({ method: 'DELETE', uri: ['users', username] }, callback); | ||
}; |
{ | ||
"name": "nodejitsu-api", | ||
"version": "0.3.8", | ||
"version": "0.4.0", | ||
"description": "nodejitsu API client wrapper", | ||
"keywords": ["nodejitsu", "nodejitsu-api"], | ||
"homepage": "http://github.com/nodejitsu/nodejitsu-api", | ||
@@ -15,7 +16,7 @@ "repository": { | ||
"dependencies": { | ||
"request": "2.9.203" | ||
"request": "2.12.0" | ||
}, | ||
"devDependencies": { | ||
"vows": "0.7.x", | ||
"nock": "0.10.x" | ||
"nock": "0.14.x" | ||
}, | ||
@@ -22,0 +23,0 @@ "author": "Nodejitsu Inc. <info@nodejitsu.com>", |
@@ -6,2 +6,11 @@ var vows = require('vows'), | ||
var cloud = [{ drones: 0, provider: 'jitsu', datacenter: 'foobar' }], | ||
endpoints = { | ||
"endpoints": { | ||
"jitsu": { | ||
"foobar": "api.mockjitsu.com" | ||
} | ||
} | ||
}; | ||
vows.describe('apps').addBatch(makeApiCall( | ||
@@ -74,2 +83,6 @@ 'apps list', | ||
.reply(200, {}, { 'x-powered-by': 'Nodejitsu' }) | ||
.get('/endpoints') | ||
.reply(200, endpoints, { 'x-powered-by': 'Nodejitsu' }) | ||
.get('/apps/tester/myApp/cloud') | ||
.reply(200, cloud, { 'x-powered-by': 'Nodejitsu' }) | ||
} | ||
@@ -76,0 +89,0 @@ )).addBatch(makeApiCall( |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
69733
1585
696
1
+ Addedrequest@2.12.0(transitive)
- Removedrequest@2.9.203(transitive)
Updatedrequest@2.12.0