From b1af0d07012a97039d8984a0ded3c9bc8749c49b Mon Sep 17 00:00:00 2001 From: Ryan Seys Date: Mon, 16 Mar 2015 21:03:45 -0400 Subject: [PATCH] Add apiResponse parameter to callbacks --- lib/bigquery/dataset.js | 28 ++++----- lib/bigquery/index.js | 43 ++++++++------ lib/bigquery/job.js | 10 ++-- lib/bigquery/table.js | 81 ++++++++++++++----------- lib/datastore/request.js | 52 +++++++++-------- lib/datastore/transaction.js | 18 +++--- lib/pubsub/index.js | 30 +++++----- lib/pubsub/subscription.js | 26 ++++----- lib/pubsub/topic.js | 35 +++++------ lib/storage/acl.js | 31 +++++----- lib/storage/bucket.js | 44 +++++++------- lib/storage/file.js | 83 +++++++++++++------------- lib/storage/index.js | 29 +++++---- test/bigquery/dataset.js | 51 ++++++++++++++++ test/bigquery/index.js | 61 +++++++++++++++++++ test/bigquery/job.js | 8 +++ test/bigquery/table.js | 98 +++++++++++++++++++++++++++++++ test/datastore/request.js | 83 ++++++++++++++++++++++++++ test/datastore/transaction.js | 39 +++++++++++++ test/pubsub/index.js | 33 +++++++++++ test/pubsub/subscription.js | 107 ++++++++++++++++++++++++++++++++++ test/pubsub/topic.js | 46 ++++++++++++++- test/storage/acl.js | 50 +++++++++++++++- test/storage/bucket.js | 59 +++++++++++++++++++ test/storage/file.js | 44 +++++++++++++- test/storage/index.js | 26 +++++++-- 26 files changed, 971 insertions(+), 244 deletions(-) diff --git a/lib/bigquery/dataset.js b/lib/bigquery/dataset.js index 9eef048dbbf..f6d2f936833 100644 --- a/lib/bigquery/dataset.js +++ b/lib/bigquery/dataset.js @@ -73,7 +73,7 @@ function Dataset(bigQuery, id) { * schema: 'UNITID,INSTNM,ADDR,CITY,STABBR,ZIP,FIPS,OBEREG,CHFNM,...' * }; * - * dataset.createTable(tableConfig, function(err, table) {}); + * dataset.createTable(tableConfig, function(err, table, apiResponse) {}); */ Dataset.prototype.createTable = function(options, callback) { var that = this; @@ -94,14 +94,14 @@ Dataset.prototype.createTable = function(options, callback) { this.makeReq_('POST', '/tables', null, options, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } var table = that.table(resp.tableReference.tableId); table.metadata = resp; - callback(null, table); + callback(null, table, resp); }); }; @@ -117,12 +117,12 @@ Dataset.prototype.createTable = function(options, callback) { * //- * // Delete the dataset, only if it does not have any tables. * //- - * dataset.delete(function(err) {}); + * dataset.delete(function(err, apiResponse) {}); * * //- * // Delete the dataset and any tables it contains. * //- - * dataset.delete({ force: true }, function(err) {}); + * dataset.delete({ force: true }, function(err, apiResponse) {}); */ Dataset.prototype.delete = function(options, callback) { if (!callback) { @@ -143,19 +143,19 @@ Dataset.prototype.delete = function(options, callback) { * @param {function} callback - The callback function. * * @example - * dataset.getMetadata(function(err, metadata) {}); + * dataset.getMetadata(function(err, metadata, apiResponse) {}); */ Dataset.prototype.getMetadata = function(callback) { var that = this; this.makeReq_('GET', '', null, null, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } that.metadata = resp; - callback(null, that.metadata); + callback(null, that.metadata, resp); }); }; @@ -169,7 +169,7 @@ Dataset.prototype.getMetadata = function(callback) { * @param {function} callback - The callback function. * * @example - * dataset.getTables(function(err, tables, nextQuery) { + * dataset.getTables(function(err, tables, nextQuery, apiResponse) { * // If `nextQuery` is non-null, there are more results to fetch. * }); */ @@ -185,7 +185,7 @@ Dataset.prototype.getTables = function(query, callback) { this.makeReq_('GET', '/tables', query, null, function(err, resp) { if (err) { - callback(err); + callback(err, null, null, resp); return; } @@ -203,7 +203,7 @@ Dataset.prototype.getTables = function(query, callback) { return table; }); - callback(null, tables, nextQuery); + callback(null, tables, nextQuery, resp); }); }; @@ -239,20 +239,20 @@ Dataset.prototype.query = function(options, callback) { * description: 'Information for every institution in the 2013 IPEDS universe' * }; * - * dataset.setMetadata(metadata, function(err) {}); + * dataset.setMetadata(metadata, function(err, apiResponse) {}); */ Dataset.prototype.setMetadata = function(metadata, callback) { var that = this; this.makeReq_('PATCH', '', null, metadata, function(err, resp) { if (err) { - callback(err); + callback(err, resp); return; } that.metadata = resp; - callback(null, that.metadata); + callback(null, that.metadata, resp); }); }; diff --git a/lib/bigquery/index.js b/lib/bigquery/index.js index 3ffa2c9cf9d..515a44afa56 100644 --- a/lib/bigquery/index.js +++ b/lib/bigquery/index.js @@ -72,6 +72,8 @@ var SCOPES = ['https://www.googleapis.com/auth/bigquery']; * @alias module:bigquery * @constructor * + * @param {object=} options - Configuration object. + * * @example * var gcloud = require('gcloud'); * @@ -125,7 +127,7 @@ function BigQuery(options) { * @param {function} callback - The callback function. * * @example - * bigquery.createDataset('higher_education', function(err, dataset) {}); + * bigquery.createDataset('my-dataset', function(err, dataset, apiResponse) {}); */ BigQuery.prototype.createDataset = function(id, callback) { var that = this; @@ -138,14 +140,14 @@ BigQuery.prototype.createDataset = function(id, callback) { this.makeReq_('POST', '/datasets', null, body, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } var dataset = that.dataset(id); dataset.metadata = resp; - callback(null, dataset); + callback(null, dataset, resp); }); }; @@ -173,7 +175,7 @@ BigQuery.prototype.dataset = function(id) { * @param {function} callback - The callback function. * * @example - * bigquery.getDatasets(function(err, datasets, nextQuery) { + * bigquery.getDatasets(function(err, datasets, nextQuery, apiResponse) { * // If `nextQuery` is non-null, there are more results to fetch. * }); */ @@ -189,7 +191,7 @@ BigQuery.prototype.getDatasets = function(query, callback) { this.makeReq_('GET', '/datasets', query, null, function(err, resp) { if (err) { - callback(err); + callback(err, null, null, resp); return; } @@ -207,7 +209,7 @@ BigQuery.prototype.getDatasets = function(query, callback) { return ds; }); - callback(null, datasets, nextQuery); + callback(null, datasets, nextQuery, resp); }); }; @@ -228,7 +230,7 @@ BigQuery.prototype.getDatasets = function(query, callback) { * @param {function} callback - The callback function. * * @example - * bigquery.getJobs(function(err, jobs, nextQuery) { + * bigquery.getJobs(function(err, jobs, nextQuery, apiResponse) { * // If `nextQuery` is non-null, there are more results to fetch. * }); */ @@ -244,7 +246,7 @@ BigQuery.prototype.getJobs = function(options, callback) { this.makeReq_('GET', '/jobs', options, null, function(err, resp) { if (err) { - callback(err); + callback(err, null, null, resp); return; } @@ -262,7 +264,7 @@ BigQuery.prototype.getJobs = function(options, callback) { return job; }); - callback(null, jobs, nextQuery); + callback(null, jobs, nextQuery, resp); }); }; @@ -336,9 +338,12 @@ BigQuery.prototype.job = function(id) { * //- * // You can run a query against your data in a serial manner. * //- - * bigquery.query(query, function(err, rows, nextQuery) { + * bigquery.query(query, function(err, rows, nextQuery, apiResponse) { + * // Handle results here. * if (nextQuery) { - * bigquery.query(nextQuery, function(err, rows, nextQuery) {}); + * bigquery.query(nextQuery, function(err, rows, nextQuery, apiResponse) { + * // Handle more results here. + * }); * } * }); * @@ -387,7 +392,7 @@ BigQuery.prototype.query = function(options, callback) { function responseHandler(err, resp) { if (err) { - onComplete(err); + onComplete(err, null, null, resp); return; } @@ -409,16 +414,16 @@ BigQuery.prototype.query = function(options, callback) { }); } - onComplete(null, rows, nextQuery); + onComplete(null, rows, nextQuery, resp); } - function onComplete(err, rows, nextQuery) { + function onComplete(err, rows, nextQuery, resp) { if (err) { if (stream) { stream.emit('error', err); stream.end(); } else { - callback(err); + callback(err, null, null, resp); } return; } @@ -434,7 +439,7 @@ BigQuery.prototype.query = function(options, callback) { stream.end(); } } else { - callback(null, rows, nextQuery); + callback(null, rows, nextQuery, resp); } } } @@ -484,7 +489,7 @@ BigQuery.prototype.query = function(options, callback) { * //- * bigquery.startQuery(query, function(err, job) { * if (!err) { - * job.getQueryResults(function(err, rows) {}); + * job.getQueryResults(function(err, rows, apiResponse) {}); * } * }); */ @@ -525,14 +530,14 @@ BigQuery.prototype.startQuery = function(options, callback) { this.makeReq_('POST', '/jobs', null, body, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } var job = that.job(resp.jobReference.jobId); job.metadata = resp; - callback(null, job); + callback(null, job, resp); }); }; diff --git a/lib/bigquery/job.js b/lib/bigquery/job.js index 117924830fb..6de6a218a8c 100644 --- a/lib/bigquery/job.js +++ b/lib/bigquery/job.js @@ -62,7 +62,7 @@ function Job(bigQuery, id) { * @param {function} callback - The callback function. * * @example - * job.getMetadata(function(err, metadata) {}); + * job.getMetadata(function(err, metadata, apiResponse) {}); */ Job.prototype.getMetadata = function(callback) { var that = this; @@ -71,13 +71,13 @@ Job.prototype.getMetadata = function(callback) { this.bigQuery.makeReq_('GET', path, null, null, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } that.metadata = resp; - callback(null, that.metadata); + callback(null, that.metadata, resp); }); }; @@ -102,7 +102,7 @@ Job.prototype.getMetadata = function(callback) { * //- * // Use the default options to get the results of a query. * //- - * job.getQueryResults(function(err, rows, nextQuery) {}); + * job.getQueryResults(function(err, rows, nextQuery, apiResponse) {}); * * //- * // Customize the results you want to fetch. @@ -111,7 +111,7 @@ Job.prototype.getMetadata = function(callback) { * maxResults: 100 * }; * - * job.getQueryResults(options, function(err, rows, nextQuery) {}); + * job.getQueryResults(options, function(err, rows, nextQuery, apiResponse) {}); * * //- * // Consume the results from the query as a readable stream. diff --git a/lib/bigquery/table.js b/lib/bigquery/table.js index e8a902244a8..21ea4ad1493 100644 --- a/lib/bigquery/table.js +++ b/lib/bigquery/table.js @@ -124,7 +124,7 @@ Table.mergeSchemaWithRows_ = function(schema, rows) { * @throws {Error} If a destination other than a Table object is provided. * * @example - * table.copy(dataset.table('institution_data'), function(err, job) {}); + * table.copy(dataset.table('my-table'), function(err, job, apiResponse) {}); * * //- * // See the [`configuration.copy`](http://goo.gl/dKWIyS) object for all @@ -135,7 +135,7 @@ Table.mergeSchemaWithRows_ = function(schema, rows) { * writeDisposition: 'WRITE_TRUNCATE' * }; * - * table.copy(options, metadata, function(err, job) {}); + * table.copy(options, metadata, function(err, job, apiResponse) {}); */ Table.prototype.copy = function(destination, metadata, callback) { var that = this; @@ -168,14 +168,14 @@ Table.prototype.copy = function(destination, metadata, callback) { this.bigQuery.makeReq_('POST', '/jobs', null, body, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } var job = that.bigQuery.job(resp.jobReference.jobId); job.metadata = resp; - callback(null, job); + callback(null, job, resp); }); }; @@ -335,7 +335,7 @@ Table.prototype.createWriteStream = function(metadata) { * @param {function} callback - The callback function. * * @example - * table.delete(function(err) {}); + * table.delete(function(err, apiResponse) {}); */ Table.prototype.delete = function(callback) { this.makeReq_('DELETE', '', null, null, callback); @@ -366,7 +366,7 @@ Table.prototype.delete = function(callback) { * // If you wish to override this, or provide an array of destination files, * // you must provide an `options` object. * //- - * table.export(exportedFile, function(err, job) {}); + * table.export(exportedFile, function(err, job, apiResponse) {}); * * //- * // If you need more customization, pass an `options` object. @@ -376,7 +376,7 @@ Table.prototype.delete = function(callback) { * gzip: true * }; * - * table.export(exportedFile, options, function(err, job) {}); + * table.export(exportedFile, options, function(err, job, apiResponse) {}); * * //- * // You can also specify multiple destination files. @@ -384,7 +384,7 @@ Table.prototype.delete = function(callback) { * table.export([ * storage.bucket('institutions').file('2014.json'), * storage.bucket('institutions-copy').file('2014.json') - * ], options, function(err, job) {}); + * ], options, function(err, job, apiResponse) {}); */ Table.prototype.export = function(destination, options, callback) { var that = this; @@ -447,14 +447,14 @@ Table.prototype.export = function(destination, options, callback) { this.bigQuery.makeReq_('POST', '/jobs', null, body, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } var job = that.bigQuery.job(resp.jobReference.jobId); job.metadata = resp; - callback(null, job); + callback(null, job, resp); }); }; @@ -464,20 +464,20 @@ Table.prototype.export = function(destination, options, callback) { * @param {function} callback - The callback function. * * @example - * table.getMetadata(function(err, metadata) {}); + * table.getMetadata(function(err, metadata, apiResponse) {}); */ Table.prototype.getMetadata = function(callback) { var that = this; this.makeReq_('GET', '', null, null, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } that.metadata = resp; - callback(null, that.metadata); + callback(null, that.metadata, resp); }); }; @@ -494,10 +494,10 @@ Table.prototype.getMetadata = function(callback) { * maxResults: 100 * }; * - * table.getRows(options, function(err, rows, nextQuery) { + * table.getRows(options, function(err, rows, nextQuery, apiResponse) { * // If `nextQuery` is non-null, there are more results to fetch. * if (nextQuery) { - * table.getRows(nextQuery, function(err, rows, nextQuery) {}); + * table.getRows(nextQuery, function(err, rows, nextQuery, apiResponse) {}); * } * });` */ @@ -513,7 +513,7 @@ Table.prototype.getRows = function(options, callback) { this.makeReq_('GET', '/data', options, null, function(err, resp) { if (err) { - onComplete(err); + onComplete(err, null, null, resp); return; } @@ -533,24 +533,24 @@ Table.prototype.getRows = function(options, callback) { return; } - onComplete(null, resp.rows, nextQuery); + onComplete(null, resp.rows, nextQuery, resp); }); return; } - onComplete(null, resp.rows, nextQuery); + onComplete(null, resp.rows, nextQuery, resp); }); - function onComplete(err, rows, nextQuery) { + function onComplete(err, rows, nextQuery, resp) { if (err) { - callback(err); + callback(err, null, null, resp); return; } rows = Table.mergeSchemaWithRows_(that.metadata.schema, rows || []); - callback(null, rows, nextQuery); + callback(null, rows, nextQuery, resp); } }; @@ -577,7 +577,7 @@ Table.prototype.getRows = function(options, callback) { * //- * // Load data from a local file. * //- - * table.import('./institutions.csv', function(err, job) {}); + * table.import('./institutions.csv', function(err, job, apiResponse) {}); * * //- * // You may also pass in metadata in the format of a Jobs resource. See @@ -588,13 +588,13 @@ Table.prototype.getRows = function(options, callback) { * sourceFormat: 'JSON' * }; * - * table.import('./institutions.csv', metadata, function(err, job) {}); + * table.import('./my-data.csv', metadata, function(err, job, apiResponse) {}); * * //- * // Load data from a file in your Storage bucket. * //- * var data = storage.bucket('institutions').file('data.csv'); - * table.import(data, function(err, job) {}); + * table.import(data, function(err, job, apiResponse) {}); * * //- * // Load data from multiple files in your Storage bucket(s). @@ -602,7 +602,7 @@ Table.prototype.getRows = function(options, callback) { * table.import([ * storage.bucket('institutions').file('2011.csv'), * storage.bucket('institutions').file('2012.csv') - * ], function(err, job) {}); + * ], function(err, job, apiResponse) {}); */ Table.prototype.import = function(source, metadata, callback) { var that = this; @@ -631,9 +631,12 @@ Table.prototype.import = function(source, metadata, callback) { // Read the file into a new write stream. return fs.createReadStream(source) .pipe(this.createWriteStream(metadata)) - .on('error', callback) - .on('complete', function(job) { - callback(null, job); + .on('error', function(err, resp) { + callback(err, null, resp); + }) + .on('complete', function(resp) { + // TODO(ryanseys): Does this have to create a job object? + callback(null, resp, resp); }); } @@ -669,14 +672,14 @@ Table.prototype.import = function(source, metadata, callback) { this.bigQuery.makeReq_('POST', '/jobs', null, body, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } var job = that.bigQuery.job(resp.jobReference.jobId); job.metadata = resp; - callback(null, job); + callback(null, job, resp); }); }; @@ -717,7 +720,7 @@ Table.prototype.import = function(source, metadata, callback) { * //- * // Handling the response. * //- - * function insertHandler(err, insertErrors) { + * function insertHandler(err, insertErrors, apiResponse) { * // err (object): * // An API error occurred. * @@ -748,7 +751,7 @@ Table.prototype.insert = function(rows, callback) { this.makeReq_('POST', '/insertAll', null, body, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } @@ -764,7 +767,7 @@ Table.prototype.insert = function(rows, callback) { }; }); - callback(null, failedToInsert); + callback(null, failedToInsert, resp); }); }; @@ -791,6 +794,14 @@ Table.prototype.query = function(query, callback) { * JSON array of fields, which allows for nested and repeated fields. See * a [Table resource](http://goo.gl/sl8Dmg) for more detailed information. * @param {function} callback - The callback function. + * + * @example + * var metadata = { + * name: 'My recipes', + * description: 'A table for storing my recipes.', + * schema: 'name:string, servings:integer, cookingTime:float, quick:boolean' + * }; + * table.setMetadata(metadata, function(err, metadata, apiResponse) {}); */ Table.prototype.setMetadata = function(metadata, callback) { var that = this; @@ -806,13 +817,13 @@ Table.prototype.setMetadata = function(metadata, callback) { this.makeReq_('PUT', '', null, metadata, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } that.metadata = resp; - callback(null, that.metadata); + callback(null, that.metadata, resp); }); }; diff --git a/lib/datastore/request.js b/lib/datastore/request.js index 44f86dbf70a..1dd01c28773 100644 --- a/lib/datastore/request.js +++ b/lib/datastore/request.js @@ -90,13 +90,14 @@ function DatastoreRequest() {} * //- * * // Get a single entity. - * transaction.get(dataset.key(['Company', 123]), function(err, entity) {}); + * var key = dataset.key(['Company', 123]); + * transaction.get(key, function(err, entity, apiResponse) {}); * * // Get multiple entities at once. * transaction.get([ * dataset.key(['Company', 123]), * dataset.key(['Product', 'Computer']) - * ], function(err, entities) {}); + * ], function(err, entities, apiResponse) {}); */ DatastoreRequest.prototype.get = function(keys, callback) { var that = this; @@ -112,7 +113,7 @@ DatastoreRequest.prototype.get = function(keys, callback) { this.makeReq_('lookup', req, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } @@ -123,7 +124,7 @@ DatastoreRequest.prototype.get = function(keys, callback) { that.get( resp.deferred.map(entity.keyFromKeyProto), function(err, entities) { if (err) { - callback(err); + callback(err, null, resp); return; } @@ -131,13 +132,13 @@ DatastoreRequest.prototype.get = function(keys, callback) { found = (found || []).concat(entities); } - callback(null, found); + callback(null, found, resp); }); return; } - callback(null, isMultipleRequest ? found : found[0]); + callback(null, isMultipleRequest ? found : found[0], resp); }); }; @@ -242,7 +243,7 @@ DatastoreRequest.prototype.insert = function(entities, callback) { * fullName: 'Andrew Chilton' * } * } - * ], function(err) {}); + * ], function(err, apiResponse) {}); */ DatastoreRequest.prototype.save = function(entities, callback) { entities = util.arrayize(entities); @@ -324,7 +325,7 @@ DatastoreRequest.prototype.save = function(entities, callback) { function onCommit(err, resp) { if (err || !resp) { - callback(err); + callback(err, resp); return; } @@ -334,7 +335,7 @@ DatastoreRequest.prototype.save = function(entities, callback) { entities[insertIndexes[index]].key.path = path; }); - callback(null); + callback(null, resp); } }; @@ -352,7 +353,7 @@ DatastoreRequest.prototype.save = function(entities, callback) { * dataset.delete([ * dataset.key(['Company', 123]), * dataset.key(['Product', 'Computer']) - * ], function(err) {}); + * ], function(err, apiResponse) {}); */ DatastoreRequest.prototype.delete = function(keys, callback) { callback = callback || util.noop; @@ -396,10 +397,11 @@ DatastoreRequest.prototype.delete = function(keys, callback) { * //- * * // Retrieve 5 companies. - * transaction.runQuery(queryObject, function(err, entities, endCursor) { + * transaction.runQuery(query, function(err, entities, endCursor, apiResponse) { * // Use `endCursor` as the starting cursor for your next query. - * var nextQuery = queryObject.start(endCursor); - * transaction.runQuery(nextQuery, function(err, entities, endCursor) {}); + * var nextQuery = query.start(endCursor); + * var callback = function(err, entities, endCursor, apiResponse) {}; + * transaction.runQuery(nextQuery, callback); * }); * * //- @@ -438,10 +440,10 @@ DatastoreRequest.prototype.runQuery = function(q, callback) { that.makeReq_('runQuery', req, function(err, resp) { if (err) { if (stream) { - stream.emit('error', err); + stream.emit('error', err, resp); stream.end(); } else { - callback(err); + callback(err, null, null, resp); } return; } @@ -454,7 +456,7 @@ DatastoreRequest.prototype.runQuery = function(q, callback) { } if (!stream) { - callback(null, entities, cursor); + callback(null, entities, cursor, resp); return; } @@ -505,7 +507,8 @@ DatastoreRequest.prototype.runQuery = function(q, callback) { * namespace: 'ns-test', * path: ['Company'] * }); - * transaction.allocateIds(incompleteKey, 100, function(err, keys) {}); + * var callback = function(err, keys, apiResponse) {}; + * transaction.allocateIds(incompleteKey, 100, callback); */ DatastoreRequest.prototype.allocateIds = function(incompleteKey, n, callback) { if (entity.isKeyComplete(incompleteKey)) { @@ -523,13 +526,13 @@ DatastoreRequest.prototype.allocateIds = function(incompleteKey, n, callback) { this.makeReq_('allocateIds', req, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } var keys = (resp.key || []).map(entity.keyFromKeyProto); - callback(null, keys); + callback(null, keys, resp); }); }; @@ -565,7 +568,8 @@ DatastoreRequest.prototype.upsert = function(entities, callback) { * delete: [] // datastore key objects. * } * }; - * transaction.makeReq('commit', deleteRequest, function(err) {}); + * var callback = function(err, result, apiResponse) {}; + * transaction.makeReq('commit', deleteRequest, callback); */ DatastoreRequest.prototype.makeReq_ = function(method, body, callback) { // TODO: Handle non-HTTP 200 cases. @@ -611,7 +615,7 @@ DatastoreRequest.prototype.makeReq_ = function(method, body, callback) { this.makeAuthorizedRequest_(reqOpts, { onAuthorized: function(err, authorizedReqOpts) { if (err) { - callback(err); + callback(err, null); // TODO(ryanseys): What goes as third parameter? return; } @@ -628,12 +632,12 @@ DatastoreRequest.prototype.makeReq_ = function(method, body, callback) { buffer = Buffer.concat([buffer, chunk]); }); resp.on('end', function() { - util.handleResp(null, resp, buffer.toString(), function(err) { + util.handleResp(null, resp, buffer.toString(), function(err, result) { if (err) { - callback(err); + callback(err, null, result); return; } - callback(null, pbResponse.decode(buffer)); + callback(null, pbResponse.decode(buffer), result); }); }); }); diff --git a/lib/datastore/transaction.js b/lib/datastore/transaction.js index 3f882994e95..888bad2772d 100644 --- a/lib/datastore/transaction.js +++ b/lib/datastore/transaction.js @@ -89,10 +89,10 @@ nodeutil.inherits(Transaction, DatastoreRequest); * // Perform Datastore operations as usual. * transaction.get(dataset.key(['Company', 123]), function(err, entity) { * // Commit the transaction. - * transaction.finalize(function(err) {}); + * transaction.finalize(function(err, apiResponse) {}); * * // Rollback the transaction. - * transaction.rollback(function(err) {}); + * transaction.rollback(function(err, apiResponse) {}); * }); * }); */ @@ -103,13 +103,13 @@ Transaction.prototype.begin = function(callback) { this.makeReq_('beginTransaction', function(err, resp) { if (err) { - callback(err); + callback(err, resp); return; } that.id = resp.transaction; - callback(null); + callback(null, resp); }); }; @@ -132,10 +132,10 @@ Transaction.prototype.rollback = function(callback) { callback = callback || util.noop; - this.makeReq_('rollback', function(err) { + this.makeReq_('rollback', function(err, resp) { that.skipCommit = true; - callback(err || null); + callback(err || null, resp); }); }; @@ -146,7 +146,7 @@ Transaction.prototype.rollback = function(callback) { * * @example * transaction.begin(function(err) { - * transaction.commit(function(err) { + * transaction.commit(function(err, apiResponse) { * if (err) { * // Transaction could not be committed. * } @@ -228,7 +228,7 @@ Transaction.prototype.commit = function(callback) { this.makeReq_('commit', req, function(err, resp) { if (err) { - callback(err); + callback(err, resp); return; } @@ -239,7 +239,7 @@ Transaction.prototype.commit = function(callback) { cb(null, resp); }); - callback(null); + callback(null, resp); }); }; diff --git a/lib/pubsub/index.js b/lib/pubsub/index.js index 06a4473aec9..e26cfa9e58c 100644 --- a/lib/pubsub/index.js +++ b/lib/pubsub/index.js @@ -123,7 +123,7 @@ function PubSub(options) { * * @example * // Get all topics. - * pubsub.getTopics(function(err, topics, nextQuery) { + * pubsub.getTopics(function(err, topics, nextQuery, apiResponse) { * // If `nextQuery` is non-null, there may be more results to fetch. To do * // so, run `pubsub.getTopics(nextQuery, callback);`. * }); @@ -131,7 +131,7 @@ function PubSub(options) { * // Customize the query. * pubsub.getTopics({ * pageSize: 3 - * }, function(err, topics, nextQuery) {}); + * }, function(err, topics, nextQuery, apiResponse) {}); */ PubSub.prototype.getTopics = function(query, callback) { var self = this; @@ -142,7 +142,7 @@ PubSub.prototype.getTopics = function(query, callback) { var path = this.projectName + '/topics'; this.makeReq_('GET', path, query, true, function(err, result) { if (err) { - callback(err); + callback(err, null, null, result); return; } var topics = (result.topics || []).map(function(item) { @@ -155,7 +155,7 @@ PubSub.prototype.getTopics = function(query, callback) { nextQuery = query; nextQuery.pageToken = result.nextPageToken; } - callback(null, topics, nextQuery); + callback(null, topics, nextQuery, result); }); }; @@ -166,7 +166,7 @@ PubSub.prototype.getTopics = function(query, callback) { * @param {function=} callback - The callback function. * * @example - * pubsub.createTopic('my-new-topic', function(err, topic) { + * pubsub.createTopic('my-new-topic', function(err, topic, apiResponse) { * topic.publish('New message!', function(err) {}); * }); */ @@ -174,12 +174,12 @@ PubSub.prototype.createTopic = function(name, callback) { callback = callback || util.noop; var topic = this.topic(name); var path = this.projectName + '/topics/' + name; - this.makeReq_('PUT', path, null, null, function(err) { + this.makeReq_('PUT', path, null, null, function(err, result) { if (err) { - callback(err); + callback(err, null, result); return; } - callback(null, topic); + callback(null, topic, result); }); }; @@ -222,16 +222,18 @@ PubSub.prototype.topic = function(name, options) { * @param {function} callback - The callback function. * * @example - * // Get all subscriptions. - * pubsub.getSubscriptions(function(err, subscriptions, nextQuery) { + * var callback = function(err, subscriptions, nextQuery, apiResponse) { * // If `nextQuery` is non-null, there may be more results to fetch. To do * // so, run `pubsub.getSubscriptions(nextQuery, callback);`. - * }); + * }; + * + * // Get all subscriptions. + * pubsub.getSubscriptions(callback); * * // Customize the query. * pubsub.getSubscriptions({ * pageSize: 10 - * }, function(err, subscriptions, nextQuery) {}); + * }, callback); */ PubSub.prototype.getSubscriptions = function(query, callback) { var self = this; @@ -243,7 +245,7 @@ PubSub.prototype.getSubscriptions = function(query, callback) { var path = this.projectName + '/subscriptions'; this.makeReq_('GET', path, query, true, function(err, result) { if (err) { - callback(err); + callback(err, null, null, result); return; } @@ -257,7 +259,7 @@ PubSub.prototype.getSubscriptions = function(query, callback) { nextQuery = query; nextQuery.pageToken = result.nextPageToken; } - callback(null, subscriptions, nextQuery); + callback(null, subscriptions, nextQuery, result); }); }; diff --git a/lib/pubsub/subscription.js b/lib/pubsub/subscription.js index c4a954766b5..fe110e4a51a 100644 --- a/lib/pubsub/subscription.js +++ b/lib/pubsub/subscription.js @@ -228,13 +228,13 @@ Subscription.prototype.startPulling_ = function() { } this.pull({ returnImmediately: false - }, function(err, messages) { + }, function(err, messages, apiResponse) { if (err) { - self.emit('error', err); + self.emit('error', err, apiResponse); } if (messages) { messages.forEach(function(message) { - self.emit('message', message); + self.emit('message', message, apiResponse); }); } setTimeout(self.startPulling_.bind(self), self.interval); @@ -251,7 +251,7 @@ Subscription.prototype.startPulling_ = function() { * @param {function=} callback - The callback function. * * @example - * subscription.ack('ePHEESyhuE8e...', function(err) {}); + * subscription.ack('ePHEESyhuE8e...', function(err, apiResponse) {}); */ Subscription.prototype.ack = function(ids, callback) { if (!ids || ids.length === 0) { @@ -273,19 +273,19 @@ Subscription.prototype.ack = function(ids, callback) { * @param {function=} callback - The callback function. * * @example - * subscription.delete(function(err) {}); + * subscription.delete(function(err, apiResponse) {}); */ Subscription.prototype.delete = function(callback) { var self = this; callback = callback || util.noop; - this.makeReq_('DELETE', this.name, null, true, function(err) { + this.makeReq_('DELETE', this.name, null, true, function(err, result) { if (err) { - callback(err); + callback(err, result); return; } self.closed = true; self.removeAllListeners(); - callback(null); + callback(null, result); }); }; @@ -330,7 +330,7 @@ Subscription.prototype.delete = function(callback) { * maxResults: 1 * }; * - * subscription.pull(opts, function(err, messages) {}); + * subscription.pull(opts, function(err, messages, apiResponse) {}); */ Subscription.prototype.pull = function(options, callback) { var self = this; @@ -353,7 +353,7 @@ Subscription.prototype.pull = function(options, callback) { var path = this.name + ':pull'; this.makeReq_('POST', path, null, body, function(err, response) { if (err) { - callback(err); + callback(err, null, response); return; } @@ -366,10 +366,10 @@ Subscription.prototype.pull = function(options, callback) { }); self.ack(ackIds, function(err) { - callback(err, messages); + callback(err, messages, response); }); } else { - callback(null, messages); + callback(null, messages, response); } }); }; @@ -391,7 +391,7 @@ Subscription.prototype.pull = function(options, callback) { * ackId: 123, * seconds: 10 // Expire in 10 seconds from call. * }; - * subscription.setAckDeadline(options, function(err) {}); + * subscription.setAckDeadline(options, function(err, apiResponse) {}); */ Subscription.prototype.setAckDeadline = function(options, callback) { var body = { diff --git a/lib/pubsub/topic.js b/lib/pubsub/topic.js index 2479cf791cb..30dceb56b72 100644 --- a/lib/pubsub/topic.js +++ b/lib/pubsub/topic.js @@ -143,7 +143,7 @@ Topic.prototype.autoCreateWrapper_ = function(method, path, q, body, callback) { * @param {function=} callback - The callback function. * * @example - * var registrationMessage = { + * var registerMessage = { * data: { * userId: 3, * name: 'Stephen', @@ -154,7 +154,7 @@ Topic.prototype.autoCreateWrapper_ = function(method, path, q, body, callback) { * hello: 'world' * } * }; - * topic.publish(registrationMessage, function(err, messageIds) {}); + * topic.publish(registerMessage, function(err, messageIds, apiResponse) {}); * * //- * // You can publish a batch of messages at once by supplying an array. @@ -170,7 +170,7 @@ Topic.prototype.autoCreateWrapper_ = function(method, path, q, body, callback) { * topic.publish([ * registrationMessage, * purchaseMessage - * ], function(err, messageIds) {}); + * ], function(err, messageIds, apiResponse) {}); */ Topic.prototype.publish = function(messages, callback) { messages = util.arrayize(messages); @@ -192,10 +192,10 @@ Topic.prototype.publish = function(messages, callback) { var path = this.name + ':publish'; this.makeReq_('POST', path, null, body, function(err, result) { if (err) { - callback(err); + callback(err, null, result); return; } - callback(null, result && result.messageIds || []); + callback(null, result && result.messageIds || [], result); }); }; @@ -205,7 +205,7 @@ Topic.prototype.publish = function(messages, callback) { * @param {function=} callback - The callback function. * * @example - * topic.delete(function(err) {}); + * topic.delete(function(err, apiResponse) {}); */ Topic.prototype.delete = function(callback) { callback = callback || util.noop; @@ -227,7 +227,7 @@ Topic.prototype.delete = function(callback) { * * @example * // Get all subscriptions for this topic. - * topic.getSubscriptions(function(err, subscriptions, nextQuery) { + * topic.getSubscriptions(function(err, subscriptions, nextQuery, apiResponse) { * // If `nextQuery` is non-null, there may be more results to fetch. To do * // so, run `topic.getSubscriptions(nextQuery, callback);`. * }); @@ -235,7 +235,7 @@ Topic.prototype.delete = function(callback) { * // Customize the query. * topic.getSubscriptions({ * pageSize: 3 - * }, function(err, subscriptions, nextQuery) {}); + * }, function(err, subscriptions, nextQuery, apiResponse) {}); */ Topic.prototype.getSubscriptions = function(query, callback) { var self = this; @@ -247,7 +247,7 @@ Topic.prototype.getSubscriptions = function(query, callback) { var path = this.name + '/subscriptions'; this.makeReq_('GET', path, query, true, function(err, result) { if (err) { - callback(err); + callback(err, null, null, result); return; } @@ -261,7 +261,7 @@ Topic.prototype.getSubscriptions = function(query, callback) { nextQuery = query; nextQuery.pageToken = result.nextPageToken; } - callback(null, subscriptions, nextQuery); + callback(null, subscriptions, nextQuery, result); }); }; @@ -290,14 +290,14 @@ Topic.prototype.getSubscriptions = function(query, callback) { * * @example * // Without specifying any options. - * topic.subscribe('new-subscription', function(err, subscription) {}); + * topic.subscribe('my-cool-sub', function(err, subscription, apiResponse) {}); * * // With options. - * topic.subscribe('new-subscription', { + * topic.subscribe('my-cool-sub', { * ackDeadlineSeconds: 90, * autoAck: true, * interval: 30 - * }, function(err, subscription) {}); + * }, function(err, subscription, apiResponse) {}); */ Topic.prototype.subscribe = function(name, options, callback) { var self = this; @@ -318,13 +318,14 @@ Topic.prototype.subscribe = function(name, options, callback) { } var path = Subscription.formatName_(this.projectId, name); - this.makeReq_('PUT', path, null, body, function(err) { + + this.makeReq_('PUT', path, null, body, function(err, result) { if (options.reuseExisting && err && err.code === 409) { - callback(null, self.subscription(name, options)); + callback(null, self.subscription(name, options), result); } else if (err) { - callback(err); + callback(err, null, result); } else { - callback(null, self.subscription(name, options)); + callback(null, self.subscription(name, options), result); } }); }; diff --git a/lib/storage/acl.js b/lib/storage/acl.js index d79d3b7c009..b2ea0de0ba1 100644 --- a/lib/storage/acl.js +++ b/lib/storage/acl.js @@ -211,7 +211,7 @@ nodeutil.inherits(Acl, AclRoleAccessorMethods); * myBucket.acl.add({ * entity: 'user-useremail@example.com', * role: storage.acl.OWNER_ROLE - * }, function(err, aclObject) {}); + * }, function(err, aclObject, apiResponse) {}); * * //- * // For file ACL operations, you can also specify a `generation` property. @@ -222,7 +222,7 @@ nodeutil.inherits(Acl, AclRoleAccessorMethods); * entity: 'user-useremail@example.com', * role: storage.acl.OWNER_ROLE, * generation: 1 - * }, function(err, aclObject) {}); + * }, function(err, aclObject, apiResponse) {}); */ Acl.prototype.add = function(options, callback) { var that = this; @@ -242,11 +242,11 @@ Acl.prototype.add = function(options, callback) { this.makeReq_('POST', '', query, body, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } - callback(null, that.makeAclObject_(resp)); + callback(null, that.makeAclObject_(resp), resp); }); }; @@ -264,7 +264,7 @@ Acl.prototype.add = function(options, callback) { * @example * myBucket.acl.delete({ * entity: 'user-useremail@example.com' - * }, function(err) {}); + * }, function(err, apiResponse) {}); * * //- * // For file ACL operations, you can also specify a `generation` property. @@ -272,7 +272,7 @@ Acl.prototype.add = function(options, callback) { * myFile.acl.delete({ * entity: 'user-useremail@example.com', * generation: 1 - * }, function(err) {}); + * }, function(err, apiResponse) {}); */ Acl.prototype.delete = function(options, callback) { var path = '/' + encodeURIComponent(options.entity); @@ -298,18 +298,19 @@ Acl.prototype.delete = function(options, callback) { * @param {string=} options.entity - Whose permissions will be fetched. * @param {int=} options.generation - **File Objects Only** Select a specific * revision of this file (as opposed to the latest version, the default). + * @param {function} callback - The callback function. * * @alias acl.get * * @example * myBucket.acl.get({ * entity: 'user-useremail@example.com' - * }, function(err, aclObject) {}); + * }, function(err, aclObject, apiResponse) {}); * * //- * // Get all access controls. * //- - * myBucket.acl.get(function(err, aclObjects) { + * myBucket.acl.get(function(err, aclObjects, apiResponse) { * // aclObjects = [ * // { * // entity: 'user-useremail@example.com', @@ -324,7 +325,7 @@ Acl.prototype.delete = function(options, callback) { * myFile.acl.get({ * entity: 'user-useremail@example.com', * generation: 1 - * } function(err, aclObject) {}); + * } function(err, aclObject, apiResponse) {}); */ Acl.prototype.get = function(options, callback) { var that = this; @@ -346,7 +347,7 @@ Acl.prototype.get = function(options, callback) { this.makeReq_('GET', path, query, null, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } @@ -358,7 +359,7 @@ Acl.prototype.get = function(options, callback) { results = that.makeAclObject_(results); } - callback(null, results); + callback(null, results, resp); }); }; @@ -381,7 +382,7 @@ Acl.prototype.get = function(options, callback) { * myBucket.acl.update({ * entity: 'user-useremail@example.com', * role: storage.acl.WRITER_ROLE - * }, function(err) {}); + * }, function(err, apiResponse) {}); * * //- * // For file ACL operations, you can also specify a `generation` property. @@ -390,7 +391,7 @@ Acl.prototype.get = function(options, callback) { * entity: 'user-useremail@example.com', * role: storage.acl.WRITER_ROLE, * generation: 1 - * }, function(err) {}); + * }, function(err, apiResponse) {}); */ Acl.prototype.update = function(options, callback) { var that = this; @@ -409,11 +410,11 @@ Acl.prototype.update = function(options, callback) { this.makeReq_('PUT', path, query, body, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } - callback(null, that.makeAclObject_(resp)); + callback(null, that.makeAclObject_(resp), resp); }); }; diff --git a/lib/storage/bucket.js b/lib/storage/bucket.js index c7db7235a5c..248b4fc6b86 100644 --- a/lib/storage/bucket.js +++ b/lib/storage/bucket.js @@ -226,7 +226,7 @@ function Bucket(storage, name) { * bucket.combine([ * 2013logs, * 2014logs - * ], allLogs, function(err, newFile) { + * ], allLogs, function(err, newFile, apiResponse) { * // newFile === allLogs * }); */ @@ -267,7 +267,7 @@ Bucket.prototype.combine = function(sources, destination, callback) { destination: { contentType: destination.metadata.contentType }, - sourceObjects: sources.map(function (source) { + sourceObjects: sources.map(function(source) { var sourceObject = { name: source.name }; @@ -279,13 +279,13 @@ Bucket.prototype.combine = function(sources, destination, callback) { return sourceObject; }) } - }, function(err) { + }, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } - callback(null, destination); + callback(null, destination, resp); }); function convertToFile(file) { @@ -303,7 +303,7 @@ Bucket.prototype.combine = function(sources, destination, callback) { * @param {function=} callback - The callback function. * * @example - * bucket.delete(function(err) {}); + * bucket.delete(function(err, apiResponse) {}); */ Bucket.prototype.delete = function(callback) { callback = callback || util.noop; @@ -362,7 +362,7 @@ Bucket.prototype.file = function(name) { * //- * bucket.getFiles({ * maxResults: 5 - * }, function(err, files, nextQuery) {}); + * }, function(err, files, nextQuery, apiResponse) {}); */ Bucket.prototype.getFiles = function(query, callback) { var that = this; @@ -372,7 +372,7 @@ Bucket.prototype.getFiles = function(query, callback) { } this.makeReq_('GET', '/o', query, true, function(err, resp) { if (err) { - callback(err); + callback(err, null, null, resp); return; } var files = (resp.items || []).map(function(item) { @@ -384,7 +384,7 @@ Bucket.prototype.getFiles = function(query, callback) { if (resp.nextPageToken) { nextQuery = extend({}, query, { pageToken: resp.nextPageToken }); } - callback(null, files, nextQuery); + callback(null, files, nextQuery, resp); }); }; @@ -396,17 +396,17 @@ Bucket.prototype.getFiles = function(query, callback) { * @param {function=} callback - The callback function. * * @example - * bucket.getMetadata(function(err, metadata) {}); + * bucket.getMetadata(function(err, metadata, apiResponse) {}); */ Bucket.prototype.getMetadata = function(callback) { callback = callback || util.noop; this.makeReq_('GET', '', null, true, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } this.metadata = resp; - callback(null, this.metadata); + callback(null, this.metadata, resp); }.bind(this)); }; @@ -633,7 +633,7 @@ Bucket.prototype.makePublic = function(options, callback) { * mainPageSuffix: 'http://example.com', * notFoundPage: 'http://example.com/404.html' * } - * }, function(err, metadata) {}); + * }, function(err, metadata, apiResponse) {}); */ Bucket.prototype.setMetadata = function(metadata, callback) { var that = this; @@ -641,13 +641,13 @@ Bucket.prototype.setMetadata = function(metadata, callback) { this.makeReq_('PATCH', '', null, metadata, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } that.metadata = resp; - callback(null, that.metadata); + callback(null, that.metadata, resp); }); }; @@ -683,7 +683,7 @@ Bucket.prototype.setMetadata = function(metadata, callback) { * //- * // The easiest way to upload a file. * //- - * bucket.upload('/local/path/image.png', function(err, file) { + * bucket.upload('/local/path/image.png', function(err, file, apiResponse) { * // Your bucket now contains: * // - "image.png" (with the contents of `/local/path/image.png') * @@ -705,9 +705,9 @@ Bucket.prototype.setMetadata = function(metadata, callback) { * } * }; * - * bucket.upload('/local/path/image.png', options, function(err, file) { + * bucket.upload('local-image.png', options, function(err, file) { * // Your bucket now contains: - * // - "new-image.png" (with the contents of `/local/path/image.png') + * // - "new-image.png" (with the contents of `local-image.png') * * // `file` is an instance of a File object that refers to your new file. * }); @@ -721,9 +721,9 @@ Bucket.prototype.setMetadata = function(metadata, callback) { * resumable: false * }; * - * bucket.upload('/local/path/image.png', options, function(err, newFile) { + * bucket.upload('local-img.png', options, function(err, newFile) { * // Your bucket now contains: - * // - "existing-file.png" (with the contents of `/local/path/image.png') + * // - "existing-file.png" (with the contents of `local-img.png') * * // Note: * // The `newFile` parameter is equal to `file`. @@ -778,7 +778,9 @@ Bucket.prototype.upload = function(localPath, options, callback) { resumable: resumable, metadata: metadata })) - .on('error', callback) + .on('error', function(err) { + callback(err); + }) .on('complete', function() { callback(null, newFile); }); diff --git a/lib/storage/file.js b/lib/storage/file.js index c5d7ca3407c..106ea06ce3c 100644 --- a/lib/storage/file.js +++ b/lib/storage/file.js @@ -137,7 +137,7 @@ function File(bucket, name, metadata) { * // If you pass in a string for the destination, the file is copied to its * // current bucket, under the new name provided. * //- - * file.copy('my-image-copy.png', function(err, copiedFile) { + * file.copy('my-image-copy.png', function(err, copiedFile, apiResponse) { * // `my-bucket` now contains: * // - "my-image.png" * // - "my-image-copy.png" @@ -151,7 +151,7 @@ function File(bucket, name, metadata) { * // using the same name. * //- * var anotherBucket = storage.bucket('another-bucket'); - * file.copy(anotherBucket, function(err, copiedFile) { + * file.copy(anotherBucket, function(err, copiedFile, apiResponse) { * // `my-bucket` still contains: * // - "my-image.png" * // @@ -167,7 +167,7 @@ function File(bucket, name, metadata) { * // bucket and filename. * //- * var anotherFile = anotherBucket.file('my-awesome-image.png'); - * file.copy(anotherFile, function(err, copiedFile) { + * file.copy(anotherFile, function(err, copiedFile, apiResponse) { * // `my-bucket` still contains: * // - "my-image.png" * // @@ -184,36 +184,37 @@ File.prototype.copy = function(destination, callback) { throw noDestinationError; } callback = callback || util.noop; + var destBucket; var destName; var newFile; + if (util.is(destination, 'string')) { destBucket = this.bucket; destName = destination; - } - if (destination.constructor && destination.constructor.name === 'Bucket') { + } else if (destination.constructor && + destination.constructor.name === 'Bucket') { destBucket = destination; destName = this.name; - } - if (destination instanceof File) { + } else if (destination instanceof File) { destBucket = destination.bucket; destName = destination.name; newFile = destination; - } - if (!destName) { + } else { throw noDestinationError; } + var path = util.format('/o/{srcName}/copyTo/b/{destBucket}/o/{destName}', { srcName: encodeURIComponent(this.name), destBucket: destBucket.name, destName: encodeURIComponent(destName) }); - this.makeReq_('POST', path, null, {}, function(err) { + this.makeReq_('POST', path, null, {}, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } - callback(null, newFile || destBucket.file(destName)); + callback(null, newFile || destBucket.file(destName), resp); }); }; @@ -311,9 +312,9 @@ File.prototype.createReadStream = function(options) { if (this.metadata.mediaLink) { createAuthorizedReq(this.metadata.mediaLink); } else { - this.getMetadata(function(err, metadata) { + this.getMetadata(function(err, metadata, resp) { if (err) { - done(err); + done(err, resp); return; } @@ -341,7 +342,7 @@ File.prototype.createReadStream = function(options) { that.bucket.storage.makeAuthorizedRequest_(reqOpts, { onAuthorized: function(err, authorizedReqOpts) { if (err) { - done(err); + done(err, null); return; } @@ -364,15 +365,15 @@ File.prototype.createReadStream = function(options) { }) .on('complete', function(res) { - util.handleResp(null, res, res.body, function(err) { + util.handleResp(null, res, res.body, function(err, resp) { if (err) { - done(err); + done(err, resp); return; } if (rangeRequest) { // Range requests can't receive data integrity checks. - done(null, res); + done(null, resp); return; } @@ -412,9 +413,9 @@ File.prototype.createReadStream = function(options) { ].join(' ')); mismatchError.code = 'CONTENT_DOWNLOAD_MISMATCH'; - done(mismatchError); + done(mismatchError, resp); } else { - done(null, res); + done(null, resp); } }); }) @@ -425,11 +426,11 @@ File.prototype.createReadStream = function(options) { } // End the stream, first emitting an error or complete event. - function done(err, response) { + function done(err) { if (err) { throughStream.emit('error', err); } else { - throughStream.emit('complete', response); + throughStream.emit('complete'); } throughStream.end(); @@ -472,7 +473,7 @@ File.prototype.createReadStream = function(options) { * fs.createReadStream('/Users/stephen/Photos/birthday-at-the-zoo/panda.jpg') * .pipe(image.createWriteStream()) * .on('error', function(err) {}) - * .on('complete', function() { + * .on('complete', function(metadata) { * // The file upload is complete. * }); * @@ -637,18 +638,19 @@ File.prototype.createWriteStream = function(options) { * @param {function=} callback - The callback function. * * @example - * file.delete(function(err) {}); + * file.delete(function(err, apiResponse) {}); */ File.prototype.delete = function(callback) { callback = callback || util.noop; var path = '/o/' + encodeURIComponent(this.name); - this.makeReq_('DELETE', path, null, true, function(err) { + + this.makeReq_('DELETE', path, null, true, function(err, resp) { if (err) { - callback(err); + callback(err, resp); return; } - callback(); - }.bind(this)); + callback(null, resp); + }); }; /** @@ -713,19 +715,21 @@ File.prototype.download = function(options, callback) { * @param {function=} callback - The callback function. * * @example - * file.getMetadata(function(err, metadata) {}); + * file.getMetadata(function(err, metadata, apiResponse) {}); */ File.prototype.getMetadata = function(callback) { + var self = this; callback = callback || util.noop; var path = '/o/' + encodeURIComponent(this.name); + this.makeReq_('GET', path, null, true, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } - this.metadata = resp; - callback(null, this.metadata); - }.bind(this)); + self.metadata = resp; + callback(null, self.metadata, resp); + }); }; /** @@ -746,6 +750,7 @@ File.prototype.getMetadata = function(callback) { * link will expire. * @param {string=} options.extensionHeaders - If these headers are used, the * server will check to make sure that the client provides matching values. + * @param {function=} callback - The callback function. * * @example * file.getSignedUrl({ @@ -808,7 +813,7 @@ File.prototype.getSignedUrl = function(options, callback) { * my: 'custom', * properties: 'go here' * } - * }, function(err, metadata) {}); + * }, function(err, metadata, apiResponse) {}); */ File.prototype.setMetadata = function(metadata, callback) { var that = this; @@ -817,13 +822,13 @@ File.prototype.setMetadata = function(metadata, callback) { this.makeReq_('PATCH', path, null, metadata, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } that.metadata = resp; - callback(null, that.metadata); + callback(null, that.metadata, resp); }); }; @@ -881,7 +886,7 @@ File.prototype.makePrivate = function(options, callback) { * @param {function=} callback - The callback function. * * @example - * file.makePublic(function(err) {}); + * file.makePublic(function(err, apiResponse) {}); */ File.prototype.makePublic = function(callback) { callback = callback || util.noop; @@ -889,8 +894,8 @@ File.prototype.makePublic = function(callback) { this.acl.add({ entity: 'allUsers', role: 'READER' - }, function(err) { - callback(err); + }, function(err, resp) { + callback(err, resp); }); }; diff --git a/lib/storage/index.js b/lib/storage/index.js index 39faa82c3e2..9db70aded8d 100644 --- a/lib/storage/index.js +++ b/lib/storage/index.js @@ -190,7 +190,7 @@ Storage.prototype.bucket = function(name) { * @param {function} callback - The callback function. * * @example - * storage.createBucket('new-bucket', function(err, bucket) { + * storage.createBucket('new-bucket', function(err, bucket, apiResponse) { * // `bucket` is a Bucket object. * }); * @@ -199,11 +199,14 @@ Storage.prototype.bucket = function(name) { * mainPageSuffix: '/unknown/', * maxAgeSeconds: 90 * }; - * storage.createBucket('new-bucket', metadata, function(err, bucket) { + * + * var callback = function(err, bucket, apiResponse) { * // `bucket` is a Bucket object. - * }); + * } + * storage.createBucket('new-bucket', metadata, callback); */ Storage.prototype.createBucket = function(name, metadata, callback) { + var self = this; if (!name) { throw new Error('A name is required to create a bucket.'); } @@ -217,15 +220,16 @@ Storage.prototype.createBucket = function(name, metadata, callback) { var body = extend(metadata, { name: name }); + this.makeReq_('POST', '', query, body, function(err, resp) { if (err) { - callback(err); + callback(err, null, resp); return; } - var bucket = this.bucket(name); + var bucket = self.bucket(name); bucket.metadata = resp; - callback(null, bucket); - }.bind(this)); + callback(null, bucket, resp); + }); }; /** @@ -242,7 +246,8 @@ Storage.prototype.createBucket = function(name, metadata, callback) { * storage.getBuckets(function(err, buckets, nextQuery) { * if (nextQuery) { * // nextQuery will be non-null if there are more results. - * storage.getBuckets(nextQuery, function(err, buckets, nextQuery) {}); + * var callback = function(err, buckets, nextQuery, apiResponse){}; + * storage.getBuckets(nextQuery, callback); * } * * // The `metadata` property is populated for you with the metadata at the @@ -251,7 +256,7 @@ Storage.prototype.createBucket = function(name, metadata, callback) { * * // However, in cases where you are concerned the metadata could have * // changed, use the `getMetadata` method. - * buckets[0].getMetadata(function(err, metadata) {}); + * buckets[0].getMetadata(function(err, metadata, apiResponse) {}); * }); * * //- @@ -259,7 +264,7 @@ Storage.prototype.createBucket = function(name, metadata, callback) { * //- * storage.getBuckets({ * maxResults: 5 - * }, function(err, buckets, nextQuery) {}); + * }, function(err, buckets, nextQuery, apiResponse) {}); */ Storage.prototype.getBuckets = function(query, callback) { var that = this; @@ -270,7 +275,7 @@ Storage.prototype.getBuckets = function(query, callback) { query.project = query.project || this.projectId; this.makeReq_('GET', '', query, null, function(err, resp) { if (err) { - callback(err); + callback(err, null, null, resp); return; } var buckets = (resp.items || []).map(function(item) { @@ -282,7 +287,7 @@ Storage.prototype.getBuckets = function(query, callback) { if (resp.nextPageToken) { nextQuery = extend({}, query, { pageToken: resp.nextPageToken }); } - callback(null, buckets, nextQuery); + callback(null, buckets, nextQuery, resp); }); }; diff --git a/test/bigquery/dataset.js b/test/bigquery/dataset.js index eb9e434e151..bf0213de331 100644 --- a/test/bigquery/dataset.js +++ b/test/bigquery/dataset.js @@ -89,6 +89,19 @@ describe('BigQuery/Dataset', function() { }); }); + it('should return an apiResponse', function(done) { + var resp = { tableReference: { tableId: TABLE_ID } }; + ds.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + var options = { id: TABLE_ID, schema: SCHEMA_OBJECT }; + ds.createTable(options, function(err, table, apiResponse) { + assert.ifError(err); + assert.deepEqual(apiResponse, resp); + done(); + }); + }); + it('should assign metadata to the Table object', function(done) { var metadata = { a: 'b', @@ -144,6 +157,17 @@ describe('BigQuery/Dataset', function() { done(); }); }); + + it('should pass apiResponse to callback', function(done) { + var resp = { success: true }; + ds.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + ds.delete(function(err, apiResponse) { + assert.deepEqual(apiResponse, { success: true }); + done(); + }); + }); }); describe('getMetadata', function() { @@ -193,6 +217,14 @@ describe('BigQuery/Dataset', function() { done(); }); }); + + it('should execute callback with apiResponse', function(done) { + ds.getMetadata(function(err, metadata, apiResponse) { + assert.ifError(err); + assert.deepEqual(apiResponse, METADATA); + done(); + }); + }); }); }); @@ -239,6 +271,17 @@ describe('BigQuery/Dataset', function() { }); }); + it('should return apiResponse', function(done) { + ds.makeReq_ = function(method, path, query, body, callback) { + callback(null, { tables: [{ id: 'tableName' }] }); + }; + ds.getTables(function(err, tables, nextQuery, apiResponse) { + assert.ifError(err); + assert.deepEqual(apiResponse, { tables: [{ id: 'tableName' }] }); + done(); + }); + }); + it('should assign metadata to the Table objects', function(done) { var tableObjects = [{ a: 'b', c: 'd', id: 'tableName' }]; ds.makeReq_ = function(method, path, query, body, callback) { @@ -387,6 +430,14 @@ describe('BigQuery/Dataset', function() { done(); }); }); + + it('should execute callback with apiResponse', function(done) { + ds.setMetadata(METADATA, function(err, metadata, apiResponse) { + assert.ifError(err); + assert.deepEqual(apiResponse, METADATA); + done(); + }); + }); }); }); diff --git a/test/bigquery/index.js b/test/bigquery/index.js index 5840eb15b47..74098231566 100644 --- a/test/bigquery/index.js +++ b/test/bigquery/index.js @@ -107,6 +107,18 @@ describe('BigQuery', function() { }); }); + it('should return an apiResponse', function(done) { + var resp = { success: true }; + bq.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + bq.createDataset(DATASET_ID, function(err, dataset, apiResponse) { + assert.ifError(err); + assert.deepEqual(apiResponse, resp); + done(); + }); + }); + it('should assign metadata to the Dataset object', function(done) { var metadata = { a: 'b', c: 'd' }; bq.makeReq_ = function(method, path, query, body, callback) { @@ -180,6 +192,18 @@ describe('BigQuery', function() { }); }); + it('should return Dataset objects', function(done) { + var resp = { success: true }; + bq.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + bq.getDatasets(function(err, datasets, nextQuery, apiResponse) { + assert.ifError(err); + assert.equal(apiResponse, resp); + done(); + }); + }); + it('should assign metadata to the Dataset objects', function(done) { var datasetObjects = [ { @@ -263,6 +287,18 @@ describe('BigQuery', function() { }); }); + it('should return apiResponse', function(done) { + var resp = { jobs: [{ id: JOB_ID }] }; + bq.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + bq.getJobs(function(err, jobs, nextQuery, apiResponse) { + assert.ifError(err); + assert.equal(resp, apiResponse); + done(); + }); + }); + it('should assign metadata to the Job objects', function(done) { var jobObjects = [{ a: 'b', c: 'd', id: JOB_ID }]; bq.makeReq_ = function(method, path, query, body, callback) { @@ -375,6 +411,17 @@ describe('BigQuery', function() { }); }); + it('should return apiResponse', function(done) { + bq.query({}, function(err, rows, nextQuery, apiResponse) { + assert.ifError(err); + assert.deepEqual(apiResponse, { + jobComplete: false, + jobReference: { jobId: JOB_ID } + }); + done(); + }); + }); + it('should not modify original options object', function(done) { bq.query(options, function(err) { assert.ifError(err); @@ -661,6 +708,20 @@ describe('BigQuery', function() { done(); }); }); + + it('should execute the callback with apiResponse', function(done) { + var jobsResource = { jobReference: { jobId: JOB_ID }, a: 'b', c: 'd' }; + + bq.makeReq_ = function(method, path, query, body, callback) { + callback(null, jobsResource); + }; + + bq.startQuery('query', function(err, job, apiResponse) { + assert.ifError(err); + assert.deepEqual(apiResponse, jobsResource); + done(); + }); + }); }); describe('makeReq_', function() { diff --git a/test/bigquery/job.js b/test/bigquery/job.js index 2c07e957c17..fb95520266b 100644 --- a/test/bigquery/job.js +++ b/test/bigquery/job.js @@ -95,6 +95,14 @@ describe('BigQuery/Job', function() { done(); }); }); + + it('should execute callback with apiResponse', function(done) { + job.getMetadata(function(err, metadata, apiResponse) { + assert.ifError(err); + assert.deepEqual(apiResponse, METADATA); + done(); + }); + }); }); }); diff --git a/test/bigquery/table.js b/test/bigquery/table.js index ab074b8f257..94e3bcadae2 100644 --- a/test/bigquery/table.js +++ b/test/bigquery/table.js @@ -217,6 +217,20 @@ describe('BigQuery/Table', function() { done(); }); }); + + it('should pass an apiResponse to the callback', function(done) { + var jobMetadata = { jobReference: { jobId: 'job-id' }, a: 'b', c: 'd' }; + + table.bigQuery.makeReq_ = function(method, path, query, body, callback) { + callback(null, jobMetadata); + }; + + table.copy(DEST_TABLE, function(err, job, apiResponse) { + assert.ifError(err); + assert.deepEqual(apiResponse, jobMetadata); + done(); + }); + }); }); describe('createReadStream', function() { @@ -431,6 +445,18 @@ describe('BigQuery/Table', function() { table.delete(done); }); + + it('should return apiResponse in callback', function(done) { + var resp = { success: true }; + table.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + + table.delete(function(err, apiResponse) { + assert.deepEqual(apiResponse, resp); + done(); + }); + }); }); describe('export', function() { @@ -552,6 +578,20 @@ describe('BigQuery/Table', function() { done(); }); }); + + it('should return apiResponse to callback', function(done) { + var jobMetadata = { jobReference: { jobId: 'job-id' }, a: 'b', c: 'd' }; + + table.bigQuery.makeReq_ = function(method, path, query, body, callback) { + callback(null, jobMetadata); + }; + + table.export(FILE, function(err, job, apiResponse) { + assert.ifError(err); + assert.deepEqual(apiResponse, jobMetadata); + done(); + }); + }); }); describe('getMetadata', function() { @@ -601,6 +641,14 @@ describe('BigQuery/Table', function() { done(); }); }); + + it('should execute callback with apiResponse', function(done) { + table.getMetadata(function(err, metadata, apiResponse) { + assert.ifError(err); + assert.deepEqual(apiResponse, METADATA); + done(); + }); + }); }); }); @@ -669,6 +717,22 @@ describe('BigQuery/Table', function() { }); }); + it('should return apiResponse in callback', function(done) { + var rows = [{ f: [{ v: 'stephen' }] }]; + var schema = { fields: [{ name: 'name', type: 'string' }] }; + table.metadata = { schema: schema }; + + table.makeReq_ = function(method, path, query, body, callback) { + callback(null, { rows: rows }); + }; + + table.getRows(function(err, rows, nextQuery, apiResponse) { + assert.ifError(err); + assert.deepEqual(apiResponse, { rows: [{ f: [{ v: 'stephen' }] }] }); + done(); + }); + }); + it('should pass nextQuery if pageToken is returned', function(done) { var options = { a: 'b', c: 'd' }; var pageToken = 'token'; @@ -814,6 +878,20 @@ describe('BigQuery/Table', function() { done(); }); }); + + it('should return apiResponse to callback', function(done) { + var jobMetadata = { jobReference: { jobId: 'job-id' }, a: 'b', c: 'd' }; + + table.bigQuery.makeReq_ = function(method, path, query, body, callback) { + callback(null, jobMetadata); + }; + + table.import(FILE, function(err, job, apiResponse) { + assert.ifError(err); + assert.deepEqual(apiResponse, jobMetadata); + done(); + }); + }); }); describe('insert', function() { @@ -860,6 +938,18 @@ describe('BigQuery/Table', function() { }); }); + it('should execute callback with apiResponse', function(done) { + table.makeReq_ = function(method, path, query, body, callback) { + callback(null, { insertErrors: [] }); + }; + + table.insert(data, function(err, insertErrors, apiResponse) { + assert.ifError(err); + assert.deepEqual(apiResponse, { insertErrors: [] }); + done(); + }); + }); + it('should return errors to the callback', function(done) { var row0Error = { message: 'Error.', reason: 'notFound' }; var row1Error = { message: 'Error.', reason: 'notFound' }; @@ -964,6 +1054,14 @@ describe('BigQuery/Table', function() { done(); }); }); + + it('should execute callback with apiResponse', function(done) { + table.setMetadata(METADATA, function(err, metadata, apiResponse) { + assert.ifError(err); + assert.deepEqual(apiResponse, METADATA); + done(); + }); + }); }); }); diff --git a/test/datastore/request.js b/test/datastore/request.js index 0ca2d091896..bd39a75d512 100644 --- a/test/datastore/request.js +++ b/test/datastore/request.js @@ -100,6 +100,17 @@ describe('Request', function() { }); }); + it('should return apiResponse in callback', function(done) { + request.makeReq_ = function(method, req, callback) { + callback(null, mockRespGet); + }; + request.get(key, function(err, entity, apiResponse) { + assert.ifError(err); + assert.deepEqual(mockRespGet, apiResponse); + done(); + }); + }); + it('should multi get by keys', function(done) { request.makeReq_ = function(method, req, callback) { assert.equal(method, 'lookup'); @@ -240,6 +251,37 @@ describe('Request', function() { ], done); }); + it('should return apiResponse in callback', function(done) { + var key = new entity.Key({ namespace: 'ns', path: ['Company'] }); + var mockCommitResponse = { + mutation_result: { + insert_auto_id_key: [ + { + partition_id: { + dataset_id: 's~project-id', + namespace: 'ns' + }, + path_element: [ + { + kind: 'Company', + id: 123, + name: null + } + ] + } + ] + } + }; + request.makeReq_ = function(method, req, callback) { + callback(null, mockCommitResponse); + }; + request.save({ key: key, data: {} }, function(err, apiResponse) { + assert.ifError(err); + assert.deepEqual(mockCommitResponse, apiResponse); + done(); + }); + }); + it('should not set an indexed value by default', function(done) { request.makeReq_ = function(method, req) { var property = req.mutation.upsert[0].property[0]; @@ -319,6 +361,18 @@ describe('Request', function() { request.delete(key, done); }); + it('should return apiResponse in callback', function(done) { + var resp = { success: true }; + request.makeReq_ = function(method, req, callback) { + callback(null, resp); + }; + request.delete(key, function(err, apiResponse) { + assert.ifError(err); + assert.deepEqual(resp, apiResponse); + done(); + }); + }); + it('should multi delete by keys', function(done) { request.makeReq_ = function(method, req, callback) { assert.equal(method, 'commit'); @@ -392,6 +446,18 @@ describe('Request', function() { }); }); + it('should execute callback with apiResponse', function(done) { + request.makeReq_ = function(method, req, callback) { + callback(null, mockResponse.withResults); + }; + + request.runQuery(query, function (err, entities, nextQuery, apiResponse) { + assert.ifError(err); + assert.deepEqual(mockResponse.withResults, apiResponse); + done(); + }); + }); + it('should return an empty string if no end cursor exists', function(done) { request.makeReq_ = function(method, req, callback) { callback(null, mockResponse.withResults); @@ -558,6 +624,23 @@ describe('Request', function() { }); }); + it('should return apiResponse in callback', function(done) { + var resp = { + key: [ + { path_element: [{ kind: 'Kind', id: 123 }] } + ] + }; + request.makeReq_ = function(method, req, callback) { + callback(null, resp); + }; + var incompleteKey = new entity.Key({ namespace: null, path: ['Kind'] }); + request.allocateIds(incompleteKey, 1, function(err, keys, apiResponse) { + assert.ifError(err); + assert.deepEqual(resp, apiResponse); + done(); + }); + }); + it('should throw if trying to allocate IDs with complete keys', function() { assert.throws(function() { request.allocateIds(key); diff --git a/test/datastore/transaction.js b/test/datastore/transaction.js index f4ee6b735e0..42ec46e4a5e 100644 --- a/test/datastore/transaction.js +++ b/test/datastore/transaction.js @@ -131,6 +131,19 @@ describe('Transaction', function() { done(); }); }); + + it('should pass apiResponse to callback', function(done) { + var resp = { success: true }; + transaction.makeReq_ = function(method, req, callback) { + callback = callback || req; + callback(null, resp); + }; + transaction.begin(function(err, apiResponse) { + assert.ifError(err); + assert.deepEqual(resp, apiResponse); + done(); + }); + }); }); describe('rollback', function() { @@ -158,6 +171,19 @@ describe('Transaction', function() { }); }); + it('should pass apiResponse to callback', function(done) { + var resp = { success: true }; + transaction.makeReq_ = function(method, req, callback) { + callback = callback || req; + callback(null, resp); + }; + transaction.rollback(function(err, apiResponse) { + assert.ifError(err); + assert.deepEqual(resp, apiResponse); + done(); + }); + }); + it('should set skipCommit', function(done) { transaction.makeReq_ = function(method, req, callback) { callback = callback || req; @@ -206,6 +232,19 @@ describe('Transaction', function() { }); }); + it('should pass apiResponse to callback', function(done) { + var resp = { success: true }; + transaction.makeReq_ = function(method, req, callback) { + callback = callback || req; + callback(null, resp); + }; + transaction.commit(function(err, apiResponse) { + assert.ifError(err); + assert.deepEqual(resp, apiResponse); + done(); + }); + }); + it('should group mutations & execute original methods', function() { var deleteArg1 = key(['Product', 123]); var deleteArg2 = key(['Product', 234]); diff --git a/test/pubsub/index.js b/test/pubsub/index.js index d52c69b1f81..e8b26ed6e7b 100644 --- a/test/pubsub/index.js +++ b/test/pubsub/index.js @@ -114,6 +114,17 @@ describe('PubSub', function() { assert.equal(err, error); }); }); + + it('should pass apiResponse to callback', function(done) { + var resp = { success: true }; + pubsub.makeReq_ = function(method, path, q, body, callback) { + callback(null, resp); + }; + pubsub.getTopics(function(err, topics, nextQuery, apiResponse) { + assert.equal(resp, apiResponse); + done(); + }); + }); }); describe('createTopic', function() { @@ -133,6 +144,17 @@ describe('PubSub', function() { assert(topic instanceof Topic); }); }); + + it('should pass apiResponse to callback', function(done) { + var resp = { success: true }; + pubsub.makeReq_ = function(method, path, q, body, callback) { + callback(null, resp); + }; + pubsub.createTopic('new-topic', function(err, topic, apiResponse) { + assert.equal(resp, apiResponse); + done(); + }); + }); }); describe('topic', function() { @@ -200,6 +222,17 @@ describe('PubSub', function() { assert.equal(err, error); }); }); + + it('should pass apiResponse to callback', function(done) { + var resp = { success: true }; + pubsub.makeReq_ = function(method, path, q, body, callback) { + callback(null, resp); + }; + pubsub.getSubscriptions(function(err, topics, nextQuery, apiResponse) { + assert.equal(resp, apiResponse); + done(); + }); + }); }); describe('makeReq_', function() { diff --git a/test/pubsub/subscription.js b/test/pubsub/subscription.js index cb403c6c137..df66e2648ef 100644 --- a/test/pubsub/subscription.js +++ b/test/pubsub/subscription.js @@ -174,6 +174,17 @@ describe('Subscription', function() { }; subscription.ack(1, done); }); + + it('should pass apiResponse to callback', function(done) { + var resp = { success: true }; + subscription.makeReq_ = function(method, path, qs, body, callback) { + callback(null, resp); + }; + subscription.ack(1, function(err, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); }); describe('pull', function() { @@ -250,6 +261,25 @@ describe('Subscription', function() { }); }); + it('should pass apiResponse to callback', function(done) { + var resp = { + receivedMessages: [{ + ackId: 1, + message: { + messageId: '123', + data: new Buffer('message').toString('base64') + } + }] + }; + subscription.makeReq_ = function(method, path, qs, body, callback) { + callback(null, resp); + }; + subscription.pull(function(err, msgs, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); + describe('autoAck false', function() { beforeEach(function() { subscription.autoAck = false; @@ -323,6 +353,31 @@ describe('Subscription', function() { it('should execute callback', function(done) { subscription.pull({}, done); }); + + it('should return pull response as apiResponse', function(done) { + var resp = { + receivedMessages: [{ + ackId: 1, + message: { + messageId: '123', + data: new Buffer('message').toString('base64') + } + }] + }; + + subscription.ack = function(id, callback) { + callback(null, { success: true }); + }; + + subscription.makeReq_ = function(method, path, qs, body, callback) { + callback(null, resp); + }; + + subscription.pull({}, function(err, msgs, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); }); }); @@ -392,6 +447,24 @@ describe('Subscription', function() { .startPulling_(); }); + it('should emit an error event with apiResponse', function(done) { + var error = new Error('Error.'); + var resp = { success: false }; + subscription.pull = function(options, callback) { + subscription.pull = function() {}; + setImmediate(function() { + callback(error, null, resp); + }); + }; + subscription + .once('error', function(err, apiResponse) { + assert.equal(err, error); + assert.deepEqual(resp, apiResponse); + done(); + }) + .startPulling_(); + }); + it('should emit a message event', function(done) { subscription.pull = function(options, callback) { callback(null, [{ hi: 'there' }]); @@ -402,6 +475,18 @@ describe('Subscription', function() { done(); }); }); + + it('should emit a message event with apiResponse', function(done) { + var resp = { success: true, msgs: [{ hi: 'there' }] }; + subscription.pull = function(options, callback) { + callback(null, [{ hi: 'there' }], resp); + }; + subscription + .once('message', function(msg, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); }); describe('delete', function() { @@ -450,6 +535,17 @@ describe('Subscription', function() { done(); }); }); + + it('should execute callback with apiResponse', function(done) { + var resp = { success: true }; + subscription.makeReq_ = function(method, path, qs, body, callback) { + callback(null, resp); + }; + subscription.delete(function(err, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); }); describe('setAckDeadline', function() { @@ -470,6 +566,17 @@ describe('Subscription', function() { }; subscription.setAckDeadline({}, done); }); + + it('should execute the callback with apiResponse', function(done) { + var resp = { success: true }; + subscription.makeReq_ = function(method, path, qs, body, callback) { + callback(null, resp); + }; + subscription.setAckDeadline({}, function(err, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); }); describe('formatMessage_', function() { diff --git a/test/pubsub/topic.js b/test/pubsub/topic.js index 9f281f0dd4f..cdd90154c87 100644 --- a/test/pubsub/topic.js +++ b/test/pubsub/topic.js @@ -165,6 +165,18 @@ describe('Topic', function() { topic.publish(messageObject, done); }); + + it('should execute callback with apiResponse', function(done) { + var resp = { success: true }; + topic.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + + topic.publish(messageObject, function(err, ackIds, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); }); describe('publish to non-existing topic', function() { @@ -220,6 +232,17 @@ describe('Topic', function() { }; topic.delete(done); }); + + it('should call the callback with apiResponse', function(done) { + var resp = { success: true }; + topic.makeReq_ = function(method, path, q, body, callback) { + callback(null, resp); + }; + topic.delete(function(err, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); }); describe('subscriptions', function() { @@ -228,7 +251,6 @@ describe('Topic', function() { var CONFIG = { autoAck: true, interval: 90 }; describe('getSubscriptions', function() { - it('should pass query', function(done) { var query = { pageToken: 1, maxResults: 3 }; topic.getSubscriptions = function(q) { @@ -245,6 +267,17 @@ describe('Topic', function() { }; topic.getSubscriptions({}, done); }); + + it('should pass apiResponse with callback', function(done) { + var resp = { success: true }; + topic.getSubscriptions = function(q, callback) { + callback(null, [], resp); + }; + topic.getSubscriptions({}, function(err, subs, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); }); describe('subscribe', function() { @@ -289,6 +322,17 @@ describe('Topic', function() { }); }); + it('should return apiResponse to the callback', function(done) { + var resp = { success: true }; + topic.makeReq_ = function(method, path, qs, body, callback) { + callback(null, resp); + }; + topic.subscribe(SUB_NAME, function(err, sub, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); + it('should create a new subscription', function(done) { topic.subscription = function(name) { assert.equal(name, SUB_NAME); diff --git a/test/storage/acl.js b/test/storage/acl.js index 03e92e653df..e2e2ba160f9 100644 --- a/test/storage/acl.js +++ b/test/storage/acl.js @@ -50,7 +50,6 @@ describe('storage/acl', function() { assert.equal(path, ''); assert.strictEqual(query, null); assert.deepEqual(body, { entity: ENTITY, role: ROLE }); - done(); }; @@ -87,6 +86,18 @@ describe('storage/acl', function() { done(); }); }); + + it('executes the callback with apiResponse', function(done) { + var resp = { success: true }; + acl.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + + acl.add({ entity: ENTITY, role: ROLE }, function(err, acls, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); }); describe('delete', function() { @@ -113,6 +124,18 @@ describe('storage/acl', function() { done(); }); }); + + it('should execute the callback with apiResponse', function(done) { + var resp = { success: true }; + acl.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + + acl.delete({ entity: ENTITY }, function(err, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); }); describe('get', function() { @@ -229,6 +252,18 @@ describe('storage/acl', function() { done(); }); }); + + it('should execute the callback with apiResponse', function(done) { + var resp = { success: true }; + acl.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + + acl.get(function(err, acls, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); }); describe('update', function() { @@ -274,6 +309,19 @@ describe('storage/acl', function() { done(); }); }); + + it('should execute the callback with apiResponse', function(done) { + var resp = { success: true }; + acl.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + + var config = { entity: ENTITY, role: ROLE }; + acl.update(config, function(err, acls, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); }); describe('makeAclObject_', function() { diff --git a/test/storage/bucket.js b/test/storage/bucket.js index 9333db5c63a..9e185308c32 100644 --- a/test/storage/bucket.js +++ b/test/storage/bucket.js @@ -285,6 +285,21 @@ describe('Bucket', function() { done(); }); }); + + it('should execute the callback with apiResponse', function(done) { + var sources = [bucket.file('1.txt'), bucket.file('2.txt')]; + var destination = 'destination.txt'; + var resp = { success: true }; + + bucket.storage.makeAuthorizedRequest_ = function(reqOpts, callback) { + callback(null, resp); + }; + + bucket.combine(sources, destination, function(err, obj, apiResponse) { + assert.equal(resp, apiResponse); + done(); + }); + }); }); describe('delete', function() { @@ -305,6 +320,17 @@ describe('Bucket', function() { }; bucket.delete(done); }); + + it('should execute callback with apiResponse', function(done) { + var resp = { success: true }; + bucket.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + bucket.delete(function(err, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); }); describe('file', function() { @@ -377,6 +403,17 @@ describe('Bucket', function() { }); }); + it('should return apiResponse in callback', function(done) { + var resp = { items: [{ name: 'fake-file-name' }] }; + bucket.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + bucket.getFiles(function(err, files, nextQuery, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); + it('should populate returned File object with metadata', function(done) { var fileMetadata = { name: 'filename', @@ -437,6 +474,17 @@ describe('Bucket', function() { done(); }); }); + + it('should pass apiResponse to callback', function(done) { + var resp = metadata; + bucket.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + bucket.getMetadata(function(err, fileMetadata, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); }); describe('makePublic', function() { @@ -591,6 +639,17 @@ describe('Bucket', function() { bucket.setMetadata(metadata, done); }); + it('should execute callback with apiResponse', function(done) { + var resp = { success: true }; + bucket.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + bucket.setMetadata(metadata, function(err, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); + it('should update internal metadata property', function() { bucket.makeReq_ = function(method, path, query, body, callback) { callback(null, metadata); diff --git a/test/storage/file.js b/test/storage/file.js index 857478ab290..a1dd7ae5ee8 100644 --- a/test/storage/file.js +++ b/test/storage/file.js @@ -217,8 +217,9 @@ describe('File', function() { describe('returned File object', function() { beforeEach(function() { + var resp = { success: true }; file.makeReq_ = function(method, path, qs, body, callback) { - callback(); + callback(null, resp); }; }); @@ -251,6 +252,14 @@ describe('File', function() { done(); }); }); + + it('should pass apiResponse into callback', function(done) { + var newBucket = new Bucket({}, 'new-bucket'); + file.copy(newBucket, function(err, copiedFile, apiResponse) { + assert.deepEqual({ success: true }, apiResponse); + done(); + }); + }); }); }); @@ -796,6 +805,17 @@ describe('File', function() { }; file.delete(done); }); + + it('should execute callback with apiResponse', function(done) { + var resp = { success: true }; + file.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + file.delete(function(err, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); }); describe('download', function() { @@ -960,6 +980,17 @@ describe('File', function() { file.getMetadata(done); }); + it('should execute callback with apiResponse', function(done) { + var resp = { success: true }; + file.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + file.getMetadata(function(err, metadata, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); + it('should update metadata property on object', function() { file.makeReq_ = function(method, path, query, body, callback) { callback(null, metadata); @@ -1070,6 +1101,17 @@ describe('File', function() { file.setMetadata(metadata, done); }); + it('should execute callback with apiResponse', function(done) { + var resp = { success: true }; + file.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + file.setMetadata(metadata, function(err, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); + it('should update internal metadata property', function() { file.makeReq_ = function(method, path, query, body, callback) { callback(null, metadata); diff --git a/test/storage/index.js b/test/storage/index.js index 92ba69f0424..3985eb6b731 100644 --- a/test/storage/index.js +++ b/test/storage/index.js @@ -116,6 +116,17 @@ describe('Storage', function() { done(); }); }); + + it('should execute callback with apiResponse', function(done) { + var resp = { success: true }; + storage.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + storage.createBucket(BUCKET_NAME, function(err, bucket, apiResponse) { + assert.equal(resp, apiResponse); + done(); + }); + }); }); describe('getBuckets', function() { @@ -174,6 +185,17 @@ describe('Storage', function() { }); }); + it('should return apiResponse', function(done) { + var resp = { items: [{ id: 'fake-bucket-name' }] }; + storage.makeReq_ = function(method, path, query, body, callback) { + callback(null, resp); + }; + storage.getBuckets(function(err, buckets, nextQuery, apiResponse) { + assert.deepEqual(resp, apiResponse); + done(); + }); + }); + it('should populate returned Bucket object with metadata', function(done) { var bucketMetadata = { id: 'bucketname', @@ -192,8 +214,4 @@ describe('Storage', function() { }); }); }); - - describe('makeReq_', function() { - - }); });