Skip to content

Commit

Permalink
Merge pull request #108 from stephenplusplus/docs
Browse files Browse the repository at this point in the history
docs.
  • Loading branch information
Burcu Dogan committed Aug 19, 2014
2 parents 12ad6d4 + f19348a commit 7b3b24a
Show file tree
Hide file tree
Showing 10 changed files with 1,214 additions and 268 deletions.
154 changes: 120 additions & 34 deletions lib/common/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,56 @@
* limitations under the License.
*/

/**
* @module common/connection
*/

'use strict';

var fs = require('fs');
var GAPIToken = require('gapitoken');
var req = require('request');
var pkg = require('../../package.json');

/** @type {module:common/util} */
var util = require('./util');

/** @const {string} Base URL for outgoing requests. */
var METADATA_TOKEN_URL =
'http://metadata/computeMetadata/v1/instance/service-accounts/default/' +
'token';
var USER_AGENT = 'gcloud-node/' + pkg.version;

/** @const {object} gcloud-node's package.json file. */
var PKG = require('../../package.json');

/** @const {string} User agent. */
var USER_AGENT = 'gcloud-node/' + PKG.version;

/**
* Token represents an access token
* @param {string} accessToken Access token.
* @param {string} expiry Expiration datetime.
* Token represents an access token.
*
* @constructor
* @param {string} accessToken - Access token.
* @param {date} expiry - Expiration datetime.
*
* @example
* ```js
* var token = new Token(ACCESS_TOKEN, EXPIRY);
* ```
*/
function Token(accessToken, expiry) {
this.accessToken = accessToken;
this.expiry = expiry;
}

/**
* Returns true if token is expired.
* @return {Boolean}
* Is this token expired?
*
* @return {boolean}
*
* @example
* ```js
* token.isExpired();
* ```
*/
Token.prototype.isExpired = function() {
if (!this.accessToken || !this.expiry) {
Expand All @@ -48,8 +72,22 @@ Token.prototype.isExpired = function() {
return new Date().getTime() - this.expiry.getTime() > 0;
};

module.exports.Token = Token;

/**
* @param {Object} opts Options.
* Create a connection object.
*
* @param {object} opts - Configuration options.
* @param {array} opts.scopes - Scopes required for access.
*
* @example
* ```js
* var SCOPES = [
* 'https://www.googleapis.com/auth/datastore',
* 'https://www.googleapis.com/auth/userinfo.email'
* ];
* var conn = new Connection({ scopes: SCOPES });
* ```
*/
function Connection(opts) {
this.opts = opts || {};
Expand All @@ -63,13 +101,19 @@ function Connection(opts) {
}

/**
* Retrieves a token to authorize the requests.
* @param {Function} callback Callback.
* Retrieve a token to authorize requests.
*
* @todo Connect should be context aware, it should not require an email and
* key, if it's running on Google Compute Engine.
*
* @param {function} callback - The callback function.
*
* @example
* ```js
* conn.connect(function(err) {});
* ```
*/
Connection.prototype.connect = function(callback) {
// TODO(jbd): Connect should be context aware,
// should not require an email and key, if it's
// running on Google Compute Engine.
var that = this;
this.isConnecting = true;
// retrieves an access token
Expand All @@ -83,8 +127,14 @@ Connection.prototype.connect = function(callback) {
};

/**
* Fetches a new access token.
* @param {Function} callback Callback function.
* Fetch a new access token.
*
* @param {function} callback - The callback function.
*
* @example
* ```js
* conn.fetchToken(function(err) {});
* ```
*/
Connection.prototype.fetchToken = function(callback) {
var that = this;
Expand Down Expand Up @@ -121,6 +171,18 @@ Connection.prototype.fetchToken = function(callback) {
this.fetchServiceAccountToken_(callback);
};

/**
* Fetch a service account token.
*
* @private
*
* @param {function} callback - The callback function.
*
* @example
* ```js
* conn.fetchServiceAccountToken_(function(err) {});
* ```
*/
Connection.prototype.fetchServiceAccountToken_ = function(callback) {
var gapi = new GAPIToken({
iss: this.credentials.client_email,
Expand All @@ -141,15 +203,21 @@ Connection.prototype.fetchServiceAccountToken_ = function(callback) {
};

/**
* Makes an authorized request if the current connection token is
* still valid. Tries to reconnect and makes a request otherwise.
* @param {Object} Request options.
* @param {Function=} callback
* Make an authorized request if the current connection token is still valid. If
* it's not, try to reconnect.
*
* @param {object} requestOptions - Request options.
* @param {function=} callback - The callback function.
*
* @example
* ```js
* conn.req({}, function(err) {});
* ```
*/
Connection.prototype.req = function(reqOpts, callback) {
Connection.prototype.req = function(requestOptions, callback) {
var that = this;
callback = callback || util.noop;
this.createAuthorizedReq(reqOpts, function(err, authorizedReq) {
this.createAuthorizedReq(requestOptions, function(err, authorizedReq) {
if (err) {
callback(err);
return;
Expand All @@ -158,6 +226,17 @@ Connection.prototype.req = function(reqOpts, callback) {
});
};

/**
* Create an authorized request.
*
* @param {object} requestOptions - Request options.
* @param {function} callback - The callback function.
*
* @example
* ```js
* conn.createAuthorizedReq({}, function(err) {});
* ```
*/
Connection.prototype.createAuthorizedReq = function(reqOpts, callback) {
var that = this;
// Add user agent.
Expand Down Expand Up @@ -201,26 +280,33 @@ Connection.prototype.createAuthorizedReq = function(reqOpts, callback) {
Connection.prototype.requester = req;

/**
* Returns true if connection is inited with a valid token
* that is not expired.
* @return {Boolean} The status of the connection.
* Get the status of the connection.
*
* `true`: connection is inited with a valid token that is not expired.
*
* @return {boolean}
*
* @example
* ```js
* conn.isConnected();
* ```
*/
Connection.prototype.isConnected = function() {
return this.token && !this.token.isExpired();
};

/**
* Adds authorization header to the specified request.
* @param {Object} reqOpts Request options.
* @return {Object} Authorized request options.
* Add authorization header to the specified request.
*
* @todo Clone the request object.
*
* @param {object} requestOptions - Request options.
* @return {object} Authorized request options.
*/
Connection.prototype.authorizeReq = function(reqOpts) {
// TODO(jbd): Clone the request object.
reqOpts.headers = reqOpts.headers || {};
reqOpts.headers.Authorization = 'Bearer ' + this.token.accessToken;
return reqOpts;
Connection.prototype.authorizeReq = function(requestOptions) {
requestOptions.headers = requestOptions.headers || {};
requestOptions.headers.Authorization = 'Bearer ' + this.token.accessToken;
return requestOptions;
};

module.exports.Token = Token;

module.exports.Connection = Connection;
97 changes: 86 additions & 11 deletions lib/common/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,20 @@

/*jshint strict:false, noarg:false */

/**
* @module common/util
*/

var util = require('util');

/**
* Extend a base object with properties from another.
*
* @param {object} from - The base object.
* @param {object} to - The object to extend with.
* @return {object}
* ```
*/
function extend(from, to) {
if (from === null || typeof from !== 'object') {
return from;
Expand All @@ -39,25 +51,78 @@ function extend(from, to) {

module.exports.extend = extend;

module.exports.arrayize = function(input) {
/**
* Wrap an array around a non-Array object. If given an Array, it is returned.
*
* @param {*} input - Non-array object to wrap.
* @return {array}
*
* @example
* ```js
* arrayize(2);
* // [ 2 ]
*
* arrayize(['Hi']);
* // [ 'Hi' ]
* ```
*/
function arrayize(input) {
if (!Array.isArray(input)) {
return [input];
}
return input;
};
}

module.exports.format = function(templ, args) {
Object.keys(args).forEach(function(k) {
templ = templ.replace('{' + k + '}', args[k]);
module.exports.arrayize = arrayize;

/**
* Format a string with values from the provided object.
*
* @param {string} template - String with {} denoted keys. (See example)
* @param {object} args - Key/value pairs matching the holes in the template.
* @return {string}
*
* @example
* ```js
* format('This is a {language} ({abbr}) codebase.', {
* language: 'JavaScript',
* abbr: 'JS'
* });
* // 'This is a JavaScript (JS) codebase.'
* ```
*/
function format(template, args) {
return template.replace(/{([^}]*)}/g, function(match, key) {
return args[key] || match;
});
return templ;
};
}

var noop = function() {};
module.exports.format = format;

/**
* No op.
*
* @example
* ```js
* function doSomething(callback) {
* callback = callback || noop;
* }
* ```
*/
function noop() {}

module.exports.noop = noop;

function ApiError (errorBody) {
/**
* Extend the native Error object.
*
* @constructor
*
* @private
*
* @param {object} errorBody - Error object.
*/
function ApiError(errorBody) {
Error.call(this);
Error.captureStackTrace(this, arguments.callee);
this.errors = errorBody.errors;
Expand All @@ -67,7 +132,15 @@ function ApiError (errorBody) {

util.inherits(ApiError, Error);

module.exports.handleResp = function(err, resp, body, callback) {
/**
* Uniformly process an API response.
*
* @param {*} err - Error value.
* @param {*} resp - Response value.
* @param {*} body - Body value.
* @param {function} callback - The callback function.
*/
function handleResp(err, resp, body, callback) {
callback = callback || noop;
if (err) {
callback(err);
Expand All @@ -87,4 +160,6 @@ module.exports.handleResp = function(err, resp, body, callback) {
return;
}
callback(null, body, resp);
};
}

module.exports.handleResp = handleResp;
Loading

0 comments on commit 7b3b24a

Please sign in to comment.