From 2fbac9316ce77951cef178a15218932afd21af6e Mon Sep 17 00:00:00 2001 From: Ryan Seys Date: Fri, 19 Sep 2014 02:39:07 -0400 Subject: [PATCH 1/8] Refactor Transaction and Dataset --- lib/datastore/dataset.js | 127 +---------- lib/datastore/datastore_request.js | 330 +++++++++++++++++++++++++++++ lib/datastore/transaction.js | 312 +-------------------------- test/datastore/dataset.js | 28 +-- test/datastore/transaction.js | 8 +- 5 files changed, 366 insertions(+), 439 deletions(-) create mode 100644 lib/datastore/datastore_request.js diff --git a/lib/datastore/dataset.js b/lib/datastore/dataset.js index 35290fc1367..2f1a53c075f 100644 --- a/lib/datastore/dataset.js +++ b/lib/datastore/dataset.js @@ -55,6 +55,7 @@ var Transaction = require('./transaction.js'); * @private */ var util = require('../common/util.js'); +var nodeutil = require('util'); /** * Scopes for Google Datastore access. @@ -66,6 +67,8 @@ var SCOPES = [ 'https://www.googleapis.com/auth/userinfo.email' ]; +var DatastoreRequester = require('./datastore_request.js'); + /** * Interact with a dataset from the * [Google Cloud Datastore]{@link https://developers.google.com/datastore/}. @@ -101,11 +104,13 @@ function Dataset(options) { keyFilename: options.keyFilename, scopes: SCOPES }); + this.projectId = options.projectId; this.namespace = options.namespace; - this.transaction = this.createTransaction_(); } +nodeutil.inherits(Dataset, DatastoreRequester); + /** * Helper to create a Key object, scoped to the dataset's namespace by default. * @@ -166,117 +171,6 @@ Dataset.prototype.createQuery = function(namespace, kinds) { return new Query(namespace, util.arrayize(kinds)); }; -/** - * Retrieve the entities identified with the specified key(s) in the current - * transaction. Get operations require a valid key to retrieve the - * key-identified entity from Datastore. - * - * @borrows {module:datastore/transaction#get} as get - * - * @param {Key|Key[]} key - Datastore key object(s). - * @param {function} callback - The callback function. - * - * @example - * dataset.get([ - * dataset.key(['Company', 123]), - * dataset.key(['Product', 'Computer']) - * ], function(err, entities) {}); - */ -Dataset.prototype.get = function(key, callback) { - this.transaction.get(key, callback); -}; - -/** - * Insert or update the specified object(s) in the current transaction. If a - * key is incomplete, its associated object is inserted and its generated - * identifier is returned to the callback. - * - * @borrows {module:datastore/transaction#save} as save - * - * @param {object|object[]} entities - Datastore key object(s). - * @param {Key} entities.key - Datastore key object. - * @param {object} entities.data - Data to save with the provided key. - * @param {function} callback - The callback function. - * - * @example - * // Save a single entity. - * dataset.save({ - * key: dataset.key('Company'), - * data: { - * rating: '10' - * } - * }, function(err, key) { - * // Because we gave an incomplete key as an argument, `key` will be - * // populated with the complete, generated key. - * }); - * - * // Save multiple entities at once. - * dataset.save([ - * { - * key: dataset.key(['Company', 123]), - * data: { - * HQ: 'Dallas, TX' - * } - * }, - * { - * key: dataset.key(['Product', 'Computer']), - * data: { - * vendor: 'Dell' - * } - * } - * ], function(err, keys) {}); - */ -Dataset.prototype.save = function(key, obj, callback) { - this.transaction.save(key, obj, callback); -}; - -/** - * Delete all entities identified with the specified key(s) in the current - * transaction. - * - * @param {Key|Key[]} key - Datastore key object(s). - * @param {function} callback - The callback function. - * - * @borrows {module:datastore/transaction#delete} as delete - * - * @example - * // Delete a single entity. - * dataset.delete(dataset.key(['Company', 123]), function(err) {}); - * - * // Delete multiple entities at once. - * dataset.delete([ - * dataset.key(['Company', 123]), - * dataset.key(['Product', 'Computer']) - * ], function(err) {}); - */ -Dataset.prototype.delete = function(key, callback) { - this.transaction.delete(key, callback); -}; - -/** - * Datastore allows you to query entities by kind, filter them by property - * filters, and sort them by a property name. Projection and pagination are also - * supported. If more results are available, a query to retrieve the next page - * is provided to the callback function. - * - * @borrows {module:datastore/transaction#runQuery} as runQuery - * - * @param {module:datastore/query} query - Query object. - * @param {function} callback - The callback function. - * - * @example - * // Retrieve 5 companies. - * dataset.runQuery(queryObject, function(err, entities, nextQuery) { - * // `nextQuery` is not null if there are more results. - * if (nextQuery) { - * dataset.runQuery(nextQuery, function(err, entities, nextQuery) {}); - * } - * }); - */ -Dataset.prototype.runQuery = function(q, callback) { - this.transaction.runQuery(q, callback); -}; - /** * Run a function in the context of a new transaction. Transactions allow you to * perform multiple operations, committing your changes atomically. @@ -342,7 +236,8 @@ Dataset.prototype.allocateIds = function(incompleteKey, n, callback) { for (var i = 0; i < n; i++) { incompleteKeys.push(entity.keyToKeyProto(incompleteKey)); } - this.transaction.makeReq( + + this.createRequest( 'allocateIds', new pb.AllocateIdsRequest({ key: incompleteKeys }), pb.AllocateIdsResponse, function(err, resp) { @@ -358,12 +253,6 @@ Dataset.prototype.allocateIds = function(incompleteKey, n, callback) { }); }; -/** - * Create a new Transaction object using the existing connection and dataset. - * - * @return {module:datastore/transaction} - * @private - */ Dataset.prototype.createTransaction_ = function() { return new Transaction(this.connection, this.projectId); }; diff --git a/lib/datastore/datastore_request.js b/lib/datastore/datastore_request.js new file mode 100644 index 00000000000..0a34ca46559 --- /dev/null +++ b/lib/datastore/datastore_request.js @@ -0,0 +1,330 @@ +/*! + * Copyright 2014 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +var https = require('https'); + +/** @type module:datastore/entity */ +var entity = require('./entity.js'); + +/** @type module:datastore/pb */ +var pb = require('./pb.js'); + +/** @type module:common/util */ +var util = require('../common/util.js'); + +/** @const {string} Host to send with API requests. */ +var GOOGLE_APIS_HOST = 'www.googleapis.com'; + +/** @const {string} Non-transaction mode key. */ +var MODE_NON_TRANSACTIONAL = 'NON_TRANSACTIONAL'; + +/** @const {string} Transaction mode key. */ +var MODE_TRANSACTIONAL = 'TRANSACTIONAL'; + + +/** + * @type module:common/util + * @private + */ +var util = require('../common/util.js'); + +function DatastoreRequester() {} + +/** + * Retrieve the entities identified with the specified key(s) in the current + * transaction. Get operations require a valid key to retrieve the + * key-identified entity from Datastore. + * + * @param {Key|Key[]} key - Datastore key object(s). + * @param {function} callback - The callback function. + * + * @example + * // These examples work with both a Transaction object and a Dataset object. + * + * // Get a single entity. + * transaction.get(dataset.key(['Company', 123]), function(err, entity) {}); + * + * // Get multiple entities at once. + * transaction.get([ + * dataset.key(['Company', 123]), + * dataset.key(['Product', 'Computer']) + * ], function(err, entities) {}); + */ +DatastoreRequester.prototype.get = function(keys, callback) { + var isMultipleRequest = Array.isArray(keys); + keys = isMultipleRequest ? keys : [keys]; + callback = callback || util.noop; + var req = new pb.LookupRequest({ + key: keys.map(entity.keyToKeyProto) + }); + var res = pb.LookupResponse; + if (this.id) { + req.transaction = this.id; + } + this.createRequest('lookup', req, res, function(err, resp) { + if (err) { + callback(err); + return; + } + var found = entity.formatArray(resp.found); + if (isMultipleRequest && resp.deferred && resp.deferred.length) { + // There may be more results. Call `.get` again, and append the results. + this.get( + resp.deferred.map(entity.keyFromKeyProto), function (err, entities) { + if (err) { + callback(err); + return; + } + if (resp) { + found = (found || []).concat(entities); + } + callback(null, found); + }); + return; + } + callback(null, isMultipleRequest ? found : found[0]); + }.bind(this)); +}; + +/** + * Insert or update the specified object(s) in the current transaction. If a + * key is incomplete, its associated object is inserted and its generated + * identifier is returned to the callback. + * + * @param {object|object[]} entities - Datastore key object(s). + * @param {Key} entities.key - Datastore key object. + * @param {object} entities.data - Data to save with the provided key. + * @param {function} callback - The callback function. + * + * @example + * // These examples work with both a Transaction object and a Dataset object. + * + * // Save a single entity. + * transaction.save({ + * key: dataset.key('Company'), + * data: { + * rating: '10' + * } + * }, function(err, key) { + * // Because we gave an incomplete key as an argument, `key` will be + * // populated with the complete, generated key. + * }); + * + * // Save multiple entities at once. + * transaction.save([ + * { + * key: dataset.key(['Company', 123]), + * data: { + * HQ: 'Dallas, TX' + * } + * }, + * { + * key: dataset.key(['Product', 'Computer']), + * data: { + * vendor: 'Dell' + * } + * } + * ], function(err, keys) {}); + */ +DatastoreRequester.prototype.save = function(entities, callback) { + var isMultipleRequest = Array.isArray(entities); + entities = isMultipleRequest ? entities : [entities]; + var insertIndexes = []; + var keys = entities.map(function(entityObject) { + return entityObject.key; + }); + var req = { + mode: MODE_NON_TRANSACTIONAL, + mutation: entities.reduce(function(acc, entityObject, index) { + var ent = entity.entityToEntityProto(entityObject.data); + ent.key = entity.keyToKeyProto(entityObject.key); + if (entity.isKeyComplete(entityObject.key)) { + acc.upsert.push(ent); + } else { + insertIndexes.push(index); + acc.insert_auto_id.push(ent); + } + return acc; + }.bind(this), { upsert: [], insert_auto_id: [] }) + }; + if (this.id) { + req.transaction = this.id; + req.mode = MODE_TRANSACTIONAL; + } + req = new pb.CommitRequest(req); + var res = pb.CommitResponse; + this.createRequest('commit', req, res, function(err, resp) { + if (err || !resp) { + callback(err); + return; + } + var autoInserted = (resp.mutation_result.insert_auto_id_key || []); + autoInserted.forEach(function(key, index) { + keys[insertIndexes[index]] = entity.keyFromKeyProto(key); + }); + callback(null, isMultipleRequest ? keys : keys[0]); + }); +}; + +/** + * Delete all entities identified with the specified key(s) in the current + * transaction. + * + * @param {Key|Key[]} key - Datastore key object(s). + * @param {function} callback - The callback function. + * + * @example + * // These examples work with both a Transaction object and a Dataset object. + * + * // Delete a single entity. + * transaction.delete(dataset.key(['Company', 123]), function(err) {}); + * + * // Delete multiple entities at once. + * transaction.delete([ + * dataset.key(['Company', 123]), + * dataset.key(['Product', 'Computer']) + * ], function(err) {}); + */ +DatastoreRequester.prototype.delete = function(keys, callback) { + var isMultipleRequest = Array.isArray(keys); + keys = isMultipleRequest ? keys : [keys]; + callback = callback || util.noop; + + var req = { + mode: MODE_NON_TRANSACTIONAL, + mutation: { + delete: keys.map(entity.keyToKeyProto) + } + }; + if (this.id) { + req.transaction = this.id; + req.mode = MODE_TRANSACTIONAL; + } + req = new pb.CommitRequest(req); + var res = pb.CommitResponse; + this.createRequest('commit', req, res, callback); +}; + +/** + * Datastore allows you to query entities by kind, filter them by property + * filters, and sort them by a property name. Projection and pagination are also + * supported. If more results are available, a query to retrieve the next page + * is provided to the callback function. + * + * @param {module:datastore/query} query - Query object. + * @param {function} callback - The callback function. + * + * @example + * // Retrieve 5 companies. + * transaction.runQuery(queryObject, function(err, entities, nextQuery) { + * // `nextQuery` is not null if there are more results. + * if (nextQuery) { + * transaction.runQuery(nextQuery, function(err, entities, nextQuery) {}); + * } + * }); + */ + +DatastoreRequester.prototype.runQuery = function(q, callback) { + callback = callback || util.noop; + var req = { + read_options: {}, + query: entity.queryToQueryProto(q) + }; + + if(this.id) { + req.read_options.transaction = this.id; + } + if (q.namespace) { + req.partition_id = { + namespace: q.namespace + }; + } + req = new pb.RunQueryRequest(req); + var res = pb.RunQueryResponse; + + this.createRequest('runQuery', req, res, function(err, resp) { + if (err || !resp.batch || !resp.batch.entity_result) { + callback(err); + return; + } + var nextQuery = null; + if (resp.batch.end_cursor) { + var cursor = resp.batch.end_cursor.toBase64(); + if (cursor !== q.startVal) { + nextQuery = q.start(cursor).offset(0); + } + } + callback(null, entity.formatArray(resp.batch.entity_result), nextQuery); + }); +}; + + +/** + * Make a request to the API endpoint. + * + * @param {string} method - Transaction action (allocateIds, commit, etc.). + * @param {object} req - Request configuration object. + * @param {function} callbcak - The callback function. + * + * @example + * var deleteRequest = { + * MODE: 'NON_TRANSACTIONAL', + * mutation: { + * delete: [] // datastore key objects. + * } + * }; + * transaction.makeReq('commit', deleteRequest, function(err) {}); + */ +DatastoreRequester.prototype.createRequest = + function(method, req, respType, cb) { + // TODO: Handle non-HTTP 200 cases. + cb = cb || util.noop; + this.connection.createAuthorizedReq({ + method: 'POST', + host: GOOGLE_APIS_HOST, + path: '/datastore/v1beta2/datasets/' + this.projectId + '/' + method, + headers: { + 'content-type': 'application/x-protobuf' + } + }, function(err, request) { + if (err) { + cb(err); + return; + } + var remoteStream = https.request(request, function(resp) { + var buffer = new Buffer(''); + resp.on('data', function(chunk) { + buffer = Buffer.concat([buffer, chunk]); + }); + resp.on('end', function() { + util.handleResp(null, resp, buffer.toString(), function(err) { + if (err) { + cb(err); + return; + } + cb(null, respType.decode(buffer)); + }); + }); + }); + remoteStream.on('error', cb); + remoteStream.write(req.toBuffer()); + remoteStream.end(); + }); +}; + +module.exports = DatastoreRequester; diff --git a/lib/datastore/transaction.js b/lib/datastore/transaction.js index db9db825a9d..b20f21ba30a 100644 --- a/lib/datastore/transaction.js +++ b/lib/datastore/transaction.js @@ -21,25 +21,15 @@ 'use strict'; -var https = require('https'); - -/** @type module:datastore/entity */ -var entity = require('./entity.js'); - /** @type module:datastore/pb */ var pb = require('./pb.js'); /** @type module:common/util */ var util = require('../common/util.js'); -/** @const {string} Host to send with API requests. */ -var GOOGLE_APIS_HOST = 'www.googleapis.com'; - -/** @const {string} Non-transaction mode key. */ -var MODE_NON_TRANSACTIONAL = 'NON_TRANSACTIONAL'; +var nodeutil = require('util'); -/** @const {string} Transaction mode key. */ -var MODE_TRANSACTIONAL = 'TRANSACTIONAL'; +var DatastoreRequester = require('./datastore_request.js'); /** * Build a Transaction object. Transactions will generally be built for you by @@ -53,7 +43,7 @@ var MODE_TRANSACTIONAL = 'TRANSACTIONAL'; * * @param {module:common/connection.Connection} conn - An authorized connection * to Google Cloud Datastore. - * @param {string} datasetId - Dataset ID. This is your project ID from the + * @param {string} projectId - Dataset ID. This is your project ID from the * Google Developers Console. * * @example @@ -61,15 +51,17 @@ var MODE_TRANSACTIONAL = 'TRANSACTIONAL'; * var myConnection = new Connection({}); * var transaction = new Transaction(myConnection, 'my-project-id'); */ -function Transaction(conn, datasetId) { +function Transaction(conn, projectId) { this.conn = conn; - this.datasetId = datasetId; + this.projectId = projectId; // the default transaction has no id. // if id is not set, run operations non-transactional. this.id = null; this.isFinalized = false; } +nodeutil.inherits(Transaction, DatastoreRequester); + /** * Begin a remote transaction and identify the current transaction instance with * the remote transaction's ID. @@ -94,7 +86,7 @@ Transaction.prototype.begin = function(callback) { var that = this; var req = new pb.BeginTransactionRequest(); var res = pb.BeginTransactionResponse; - this.makeReq('beginTransaction', req, res, function(err, resp) { + this.createRequest('beginTransaction', req, res, function(err, resp) { if (err) { callback(err); return; @@ -123,7 +115,7 @@ Transaction.prototype.rollback = function(callback) { var that = this; var req = new pb.RollbackRequest({ transaction: this.id }); var res = pb.RollbackResponse; - this.makeReq('rollback', req, res, function(err) { + this.createRequest('rollback', req, res, function(err) { if (err) { callback(err); return; @@ -152,7 +144,7 @@ Transaction.prototype.commit = function(callback) { var that = this; var req = new pb.CommitRequest({ transaction: this.id }); var res = pb.CommitResponse; - this.makeReq('commit', req, res, function(err) { + this.createRequest('commit', req, res, function(err) { if (err) { callback(err); return; @@ -184,238 +176,6 @@ Transaction.prototype.finalize = function(callback) { setImmediate(callback); }; -/** - * Retrieve the entities identified with the specified key(s) in the current - * transaction. Get operations require a valid key to retrieve the - * key-identified entity from Datastore. - * - * @param {Key|Key[]} key - Datastore key object(s). - * @param {function} callback - The callback function. - * - * @example - * // These examples work with both a Transaction object and a Dataset object. - * - * // Get a single entity. - * transaction.get(dataset.key(['Company', 123]), function(err, entity) {}); - * - * // Get multiple entities at once. - * transaction.get([ - * dataset.key(['Company', 123]), - * dataset.key(['Product', 'Computer']) - * ], function(err, entities) {}); - */ -Transaction.prototype.get = function(keys, callback) { - var isMultipleRequest = Array.isArray(keys); - keys = isMultipleRequest ? keys : [keys]; - callback = callback || util.noop; - var req = new pb.LookupRequest({ - key: keys.map(entity.keyToKeyProto) - }); - var res = pb.LookupResponse; - if (this.id) { - req.transaction = this.id; - } - this.makeReq('lookup', req, res, function(err, resp) { - if (err) { - callback(err); - return; - } - var found = entity.formatArray(resp.found); - if (isMultipleRequest && resp.deferred && resp.deferred.length) { - // There may be more results. Call `.get` again, and append the results. - this.get( - resp.deferred.map(entity.keyFromKeyProto), function (err, entities) { - if (err) { - callback(err); - return; - } - if (resp) { - found = (found || []).concat(entities); - } - callback(null, found); - }); - return; - } - callback(null, isMultipleRequest ? found : found[0]); - }.bind(this)); -}; - -/** - * Insert or update the specified object(s) in the current transaction. If a - * key is incomplete, its associated object is inserted and its generated - * identifier is returned to the callback. - * - * @param {object|object[]} entities - Datastore key object(s). - * @param {Key} entities.key - Datastore key object. - * @param {object} entities.data - Data to save with the provided key. - * @param {function} callback - The callback function. - * - * @example - * // These examples work with both a Transaction object and a Dataset object. - * - * // Save a single entity. - * transaction.save({ - * key: dataset.key('Company'), - * data: { - * rating: '10' - * } - * }, function(err, key) { - * // Because we gave an incomplete key as an argument, `key` will be - * // populated with the complete, generated key. - * }); - * - * // Save multiple entities at once. - * transaction.save([ - * { - * key: dataset.key(['Company', 123]), - * data: { - * HQ: 'Dallas, TX' - * } - * }, - * { - * key: dataset.key(['Product', 'Computer']), - * data: { - * vendor: 'Dell' - * } - * } - * ], function(err, keys) {}); - */ -Transaction.prototype.save = function(entities, callback) { - var isMultipleRequest = Array.isArray(entities); - entities = isMultipleRequest ? entities : [entities]; - var insertIndexes = []; - var keys = entities.map(function(entityObject) { - return entityObject.key; - }); - var req = { - mode: MODE_NON_TRANSACTIONAL, - mutation: entities.reduce(function(acc, entityObject, index) { - var ent = entity.entityToEntityProto(entityObject.data); - ent.key = entity.keyToKeyProto(entityObject.key); - if (entity.isKeyComplete(entityObject.key)) { - acc.upsert.push(ent); - } else { - insertIndexes.push(index); - acc.insert_auto_id.push(ent); - } - return acc; - }.bind(this), { upsert: [], insert_auto_id: [] }) - }; - if (this.id) { - req.transaction = this.id; - req.mode = MODE_TRANSACTIONAL; - } - req = new pb.CommitRequest(req); - var res = pb.CommitResponse; - this.makeReq('commit', req, res, function(err, resp) { - if (err || !resp) { - callback(err); - return; - } - if (this.id) { - this.isFinalized = true; - } - var autoInserted = (resp.mutation_result.insert_auto_id_key || []); - autoInserted.forEach(function(key, index) { - keys[insertIndexes[index]] = entity.keyFromKeyProto(key); - }); - callback(null, isMultipleRequest ? keys : keys[0]); - }.bind(this)); -}; - -/** - * Delete all entities identified with the specified key(s) in the current - * transaction. - * - * @param {Key|Key[]} key - Datastore key object(s). - * @param {function} callback - The callback function. - * - * @example - * // These examples work with both a Transaction object and a Dataset object. - * - * // Delete a single entity. - * transaction.delete(dataset.key(['Company', 123]), function(err) {}); - * - * // Delete multiple entities at once. - * transaction.delete([ - * dataset.key(['Company', 123]), - * dataset.key(['Product', 'Computer']) - * ], function(err) {}); - */ -Transaction.prototype.delete = function(keys, callback) { - var isMultipleRequest = Array.isArray(keys); - keys = isMultipleRequest ? keys : [keys]; - callback = callback || util.noop; - - var req = { - mode: MODE_NON_TRANSACTIONAL, - mutation: { - delete: keys.map(entity.keyToKeyProto) - } - }; - if (this.id) { - req.transaction = this.id; - req.mode = MODE_TRANSACTIONAL; - } - req = new pb.CommitRequest(req); - var res = pb.CommitResponse; - this.makeReq('commit', req, res, function(err, response) { - if (this.id) { - this.isFinalized = true; - } - callback(err, response); - }.bind(this)); -}; - -/** - * Datastore allows you to query entities by kind, filter them by property - * filters, and sort them by a property name. Projection and pagination are also - * supported. If more results are available, a query to retrieve the next page - * is provided to the callback function. - * - * @param {module:datastore/query} query - Query object. - * @param {function} callback - The callback function. - * - * @example - * // Retrieve 5 companies. - * transaction.runQuery(queryObject, function(err, entities, nextQuery) { - * // `nextQuery` is not null if there are more results. - * if (nextQuery) { - * transaction.runQuery(nextQuery, function(err, entities, nextQuery) {}); - * } - * }); - */ -Transaction.prototype.runQuery = function(q, callback) { - callback = callback || util.noop; - var req = { - read_options: { - transaction: this.id - }, - query: entity.queryToQueryProto(q) - }; - if (q.namespace) { - req.partition_id = { - namespace: q.namespace - }; - } - req = new pb.RunQueryRequest(req); - var res = pb.RunQueryResponse; - this.makeReq('runQuery', req, res, function(err, resp) { - if (err || !resp.batch || !resp.batch.entity_result) { - callback(err); - return; - } - var nextQuery = null; - if (resp.batch.end_cursor) { - var cursor = resp.batch.end_cursor.toBase64(); - if (cursor !== q.startVal) { - nextQuery = q.start(cursor).offset(0); - } - } - callback(null, entity.formatArray(resp.batch.entity_result), nextQuery); - }); -}; - /** * mapQuery * @@ -425,56 +185,4 @@ Transaction.prototype.mapQuery = function() { throw new Error('not yet implemented'); }; -/** - * Make a request to the API endpoint. - * - * @param {string} method - Transaction action (allocateIds, commit, etc.). - * @param {object} req - Request configuration object. - * @param {function} callbcak - The callback function. - * - * @example - * var deleteRequest = { - * MODE: 'NON_TRANSACTIONAL', - * mutation: { - * delete: [] // datastore key objects. - * } - * }; - * transaction.makeReq('commit', deleteRequest, function(err) {}); - */ -Transaction.prototype.makeReq = function(method, req, respType, callback) { - // TODO: Handle non-HTTP 200 cases. - callback = callback || util.noop; - this.conn.createAuthorizedReq({ - method: 'POST', - host: GOOGLE_APIS_HOST, - path: '/datastore/v1beta2/datasets/' + this.datasetId + '/' + method, - headers: { - 'content-type': 'application/x-protobuf' - } - }, function(err, request) { - if (err) { - callback(err); - return; - } - var remoteStream = https.request(request, function(resp) { - var buffer = new Buffer(''); - resp.on('data', function(chunk) { - buffer = Buffer.concat([buffer, chunk]); - }); - resp.on('end', function() { - util.handleResp(null, resp, buffer.toString(), function(err) { - if (err) { - callback(err); - return; - } - callback(null, respType.decode(buffer)); - }); - }); - }); - remoteStream.on('error', callback); - remoteStream.write(req.toBuffer()); - remoteStream.end(); - }); -}; - module.exports = Transaction; diff --git a/test/datastore/dataset.js b/test/datastore/dataset.js index 7b8695f45af..9296ee02d3f 100644 --- a/test/datastore/dataset.js +++ b/test/datastore/dataset.js @@ -94,7 +94,7 @@ describe('Dataset', function() { it('should get by key', function(done) { var ds = datastore.dataset({ projectId: 'test' }); - ds.transaction.makeReq = function(method, proto, typ, callback) { + ds.createRequest = function(method, proto, typ, callback) { assert.equal(method, 'lookup'); assert.equal(proto.key.length, 1); callback(null, mockRespGet); @@ -111,7 +111,7 @@ describe('Dataset', function() { it('should multi get by keys', function(done) { var ds = datastore.dataset({ projectId: 'test' }); - ds.transaction.makeReq = function(method, proto, typ, callback) { + ds.createRequest = function(method, proto, typ, callback) { assert.equal(method, 'lookup'); assert.equal(proto.key.length, 1); callback(null, mockRespGet); @@ -133,7 +133,7 @@ describe('Dataset', function() { var key = ds.key(['Kind', 5732568548769792]); var key2 = ds.key(['Kind', 5732568548769792]); var lookupCount = 0; - ds.transaction.makeReq = function(method, proto, typ, callback) { + ds.createRequest = function(method, proto, typ, callback) { lookupCount++; assert.equal(method, 'lookup'); if (mockRespGet.deferred.length) { @@ -153,7 +153,7 @@ describe('Dataset', function() { it('should delete by key', function(done) { var ds = datastore.dataset({ projectId: 'test' }); - ds.transaction.makeReq = function(method, proto, typ, callback) { + ds.createRequest = function(method, proto, typ, callback) { assert.equal(method, 'commit'); assert.equal(!!proto.mutation.delete, true); callback(); @@ -163,7 +163,7 @@ describe('Dataset', function() { it('should multi delete by keys', function(done) { var ds = datastore.dataset({ projectId: 'test' }); - ds.transaction.makeReq = function(method, proto, typ, callback) { + ds.createRequest = function(method, proto, typ, callback) { assert.equal(method, 'commit'); assert.equal(proto.mutation.delete.length, 2); callback(); @@ -176,7 +176,7 @@ describe('Dataset', function() { it('should save with incomplete key', function(done) { var ds = datastore.dataset({ projectId: 'test' }); - ds.transaction.makeReq = function(method, proto, typ, callback) { + ds.createRequest = function(method, proto, typ, callback) { assert.equal(method, 'commit'); assert.equal(proto.mutation.insert_auto_id.length, 1); callback(); @@ -187,7 +187,7 @@ describe('Dataset', function() { it('should save with keys', function(done) { var ds = datastore.dataset({ projectId: 'test' }); - ds.transaction.makeReq = function(method, proto, typ, callback) { + ds.createRequest = function(method, proto, typ, callback) { assert.equal(method, 'commit'); assert.equal(proto.mutation.upsert.length, 2); assert.equal(proto.mutation.upsert[0].property[0].name, 'k'); @@ -203,7 +203,7 @@ describe('Dataset', function() { it('should produce proper allocate IDs req protos', function(done) { var ds = datastore.dataset({ projectId: 'test' }); - ds.transaction.makeReq = function(method, proto, typ, callback) { + ds.createRequest = function(method, proto, typ, callback) { assert.equal(method, 'allocateIds'); assert.equal(proto.key.length, 1); assert.deepEqual(proto.key[0], { @@ -237,7 +237,7 @@ describe('Dataset', function() { ds = datastore.dataset({ projectId: 'test' }); ds.createTransaction_ = function() { transaction = new Transaction(); - transaction.makeReq = function(method, proto, typ, callback) { + transaction.createRequest = function(method, proto, typ, callback) { assert.equal(method, 'beginTransaction'); callback(null, { transaction: '' }); }; @@ -257,7 +257,7 @@ describe('Dataset', function() { it('should commit the transaction when done', function() { ds.runInTransaction(function(t, done) { - transaction.makeReq = function(method) { + transaction.createRequest = function(method) { assert.equal(method, 'commit'); }; done(); @@ -325,7 +325,7 @@ describe('Dataset', function() { describe('errors', function() { it('should handle upstream errors', function() { var upstreamError = new Error('upstream error.'); - ds.transaction.makeReq = function(method, proto, typ, callback) { + ds.createRequest = function(method, proto, typ, callback) { assert.equal(method, 'runQuery'); callback(upstreamError); }; @@ -336,7 +336,7 @@ describe('Dataset', function() { }); it('should handle missing results error', function() { - ds.transaction.makeReq = function(method, proto, typ, callback) { + ds.createRequest = function(method, proto, typ, callback) { assert.equal(method, 'runQuery'); callback('simulated-error', mockResponse.withoutResults); }; @@ -348,7 +348,7 @@ describe('Dataset', function() { }); it('should execute callback with results', function() { - ds.transaction.makeReq = function(method, proto, typ, callback) { + ds.createRequest = function(method, proto, typ, callback) { assert.equal(method, 'runQuery'); callback(null, mockResponse.withResults); }; @@ -365,7 +365,7 @@ describe('Dataset', function() { }); it('should return a new query if results remain', function() { - ds.transaction.makeReq = function(method, proto, typ, callback) { + ds.createRequest = function(method, proto, typ, callback) { assert.equal(method, 'runQuery'); callback(null, mockResponse.withResultsAndEndCursor); }; diff --git a/test/datastore/transaction.js b/test/datastore/transaction.js index c273c7a1e1d..4c36f4f388e 100644 --- a/test/datastore/transaction.js +++ b/test/datastore/transaction.js @@ -31,7 +31,7 @@ describe('Transaction', function() { }); it('should begin', function(done) { - transaction.makeReq = function(method, proto, respType, callback) { + transaction.createRequest = function(method, proto, respType, callback) { assert.equal(method, 'beginTransaction'); callback(null, 'some-id'); }; @@ -40,7 +40,7 @@ describe('Transaction', function() { it('should rollback', function(done) { transaction.id = 'some-id'; - transaction.makeReq = function(method, proto, respType, callback) { + transaction.createRequest = function(method, proto, respType, callback) { assert.equal(method, 'rollback'); assert.equal( proto.transaction.toBase64(), @@ -55,7 +55,7 @@ describe('Transaction', function() { it('should commit', function(done) { transaction.id = 'some-id'; - transaction.makeReq = function(method, proto, respType, callback) { + transaction.createRequest = function(method, proto, respType, callback) { assert.equal(method, 'commit'); assert.equal( proto.transaction.toBase64(), @@ -69,7 +69,7 @@ describe('Transaction', function() { }); it('should be committed if not rolled back', function(done) { - transaction.makeReq = function(method) { + transaction.createRequest = function(method) { assert.equal(method, 'commit'); done(); }; From 06eca8677cf0828155f5464864d403d9dfa7599e Mon Sep 17 00:00:00 2001 From: Ryan Seys Date: Sat, 27 Sep 2014 14:56:05 -0400 Subject: [PATCH 2/8] Fix this.connection --- lib/datastore/transaction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/datastore/transaction.js b/lib/datastore/transaction.js index b20f21ba30a..4b1d4318950 100644 --- a/lib/datastore/transaction.js +++ b/lib/datastore/transaction.js @@ -52,7 +52,7 @@ var DatastoreRequester = require('./datastore_request.js'); * var transaction = new Transaction(myConnection, 'my-project-id'); */ function Transaction(conn, projectId) { - this.conn = conn; + this.connection = conn; this.projectId = projectId; // the default transaction has no id. // if id is not set, run operations non-transactional. From 6bb7c61282a705f67cf514d31431308486e2af61 Mon Sep 17 00:00:00 2001 From: Ryan Seys Date: Sat, 27 Sep 2014 16:35:13 -0400 Subject: [PATCH 3/8] DatastoreRequester --> DatastoreRequest --- lib/datastore/dataset.js | 4 ++-- lib/datastore/datastore_request.js | 16 +++++++++------- lib/datastore/transaction.js | 4 ++-- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/lib/datastore/dataset.js b/lib/datastore/dataset.js index 2f1a53c075f..da2feb0717f 100644 --- a/lib/datastore/dataset.js +++ b/lib/datastore/dataset.js @@ -67,7 +67,7 @@ var SCOPES = [ 'https://www.googleapis.com/auth/userinfo.email' ]; -var DatastoreRequester = require('./datastore_request.js'); +var DatastoreRequest = require('./datastore_request.js'); /** * Interact with a dataset from the @@ -109,7 +109,7 @@ function Dataset(options) { this.namespace = options.namespace; } -nodeutil.inherits(Dataset, DatastoreRequester); +nodeutil.inherits(Dataset, DatastoreRequest); /** * Helper to create a Key object, scoped to the dataset's namespace by default. diff --git a/lib/datastore/datastore_request.js b/lib/datastore/datastore_request.js index 0a34ca46559..d45122eca6c 100644 --- a/lib/datastore/datastore_request.js +++ b/lib/datastore/datastore_request.js @@ -43,7 +43,9 @@ var MODE_TRANSACTIONAL = 'TRANSACTIONAL'; */ var util = require('../common/util.js'); -function DatastoreRequester() {} +function DatastoreRequest() { + +} /** * Retrieve the entities identified with the specified key(s) in the current @@ -65,7 +67,7 @@ function DatastoreRequester() {} * dataset.key(['Product', 'Computer']) * ], function(err, entities) {}); */ -DatastoreRequester.prototype.get = function(keys, callback) { +DatastoreRequest.prototype.get = function(keys, callback) { var isMultipleRequest = Array.isArray(keys); keys = isMultipleRequest ? keys : [keys]; callback = callback || util.noop; @@ -141,7 +143,7 @@ DatastoreRequester.prototype.get = function(keys, callback) { * } * ], function(err, keys) {}); */ -DatastoreRequester.prototype.save = function(entities, callback) { +DatastoreRequest.prototype.save = function(entities, callback) { var isMultipleRequest = Array.isArray(entities); entities = isMultipleRequest ? entities : [entities]; var insertIndexes = []; @@ -200,7 +202,7 @@ DatastoreRequester.prototype.save = function(entities, callback) { * dataset.key(['Product', 'Computer']) * ], function(err) {}); */ -DatastoreRequester.prototype.delete = function(keys, callback) { +DatastoreRequest.prototype.delete = function(keys, callback) { var isMultipleRequest = Array.isArray(keys); keys = isMultipleRequest ? keys : [keys]; callback = callback || util.noop; @@ -239,7 +241,7 @@ DatastoreRequester.prototype.delete = function(keys, callback) { * }); */ -DatastoreRequester.prototype.runQuery = function(q, callback) { +DatastoreRequest.prototype.runQuery = function(q, callback) { callback = callback || util.noop; var req = { read_options: {}, @@ -290,7 +292,7 @@ DatastoreRequester.prototype.runQuery = function(q, callback) { * }; * transaction.makeReq('commit', deleteRequest, function(err) {}); */ -DatastoreRequester.prototype.createRequest = +DatastoreRequest.prototype.createRequest = function(method, req, respType, cb) { // TODO: Handle non-HTTP 200 cases. cb = cb || util.noop; @@ -327,4 +329,4 @@ DatastoreRequester.prototype.createRequest = }); }; -module.exports = DatastoreRequester; +module.exports = DatastoreRequest; diff --git a/lib/datastore/transaction.js b/lib/datastore/transaction.js index 4b1d4318950..a1c74d9a64d 100644 --- a/lib/datastore/transaction.js +++ b/lib/datastore/transaction.js @@ -29,7 +29,7 @@ var util = require('../common/util.js'); var nodeutil = require('util'); -var DatastoreRequester = require('./datastore_request.js'); +var DatastoreRequest = require('./datastore_request.js'); /** * Build a Transaction object. Transactions will generally be built for you by @@ -60,7 +60,7 @@ function Transaction(conn, projectId) { this.isFinalized = false; } -nodeutil.inherits(Transaction, DatastoreRequester); +nodeutil.inherits(Transaction, DatastoreRequest); /** * Begin a remote transaction and identify the current transaction instance with From 52fc5bc90df42b938c94112c9082a5dad9177437 Mon Sep 17 00:00:00 2001 From: Ryan Seys Date: Sat, 27 Sep 2014 21:17:02 -0400 Subject: [PATCH 4/8] Rename datastore_request to request and fix various cosmetic errors --- lib/datastore/dataset.js | 17 ++++++++++++++--- .../{datastore_request.js => request.js} | 12 ++++++++---- lib/datastore/transaction.js | 10 +++++++--- 3 files changed, 29 insertions(+), 10 deletions(-) rename lib/datastore/{datastore_request.js => request.js} (99%) diff --git a/lib/datastore/dataset.js b/lib/datastore/dataset.js index da2feb0717f..f5c0edab5f2 100644 --- a/lib/datastore/dataset.js +++ b/lib/datastore/dataset.js @@ -20,6 +20,8 @@ 'use strict'; +var nodeutil = require('util'); + /** * @type module:common/connection * @private @@ -55,7 +57,12 @@ var Transaction = require('./transaction.js'); * @private */ var util = require('../common/util.js'); -var nodeutil = require('util'); + +/** + * @type module:datastore/request + * @private + */ +var DatastoreRequest = require('./request'); /** * Scopes for Google Datastore access. @@ -67,8 +74,6 @@ var SCOPES = [ 'https://www.googleapis.com/auth/userinfo.email' ]; -var DatastoreRequest = require('./datastore_request.js'); - /** * Interact with a dataset from the * [Google Cloud Datastore]{@link https://developers.google.com/datastore/}. @@ -253,6 +258,12 @@ Dataset.prototype.allocateIds = function(incompleteKey, n, callback) { }); }; +/** + * Create a new Transaction object using the existing connection and dataset. + * + * @return {module:datastore/transaction} + * @private + */ Dataset.prototype.createTransaction_ = function() { return new Transaction(this.connection, this.projectId); }; diff --git a/lib/datastore/datastore_request.js b/lib/datastore/request.js similarity index 99% rename from lib/datastore/datastore_request.js rename to lib/datastore/request.js index d45122eca6c..f2df763dd49 100644 --- a/lib/datastore/datastore_request.js +++ b/lib/datastore/request.js @@ -14,6 +14,11 @@ * limitations under the License. */ +/** + * @private + * @module datastore/request + */ + 'use strict'; var https = require('https'); @@ -43,9 +48,7 @@ var MODE_TRANSACTIONAL = 'TRANSACTIONAL'; */ var util = require('../common/util.js'); -function DatastoreRequest() { - -} +function DatastoreRequest() {} /** * Retrieve the entities identified with the specified key(s) in the current @@ -251,11 +254,13 @@ DatastoreRequest.prototype.runQuery = function(q, callback) { if(this.id) { req.read_options.transaction = this.id; } + if (q.namespace) { req.partition_id = { namespace: q.namespace }; } + req = new pb.RunQueryRequest(req); var res = pb.RunQueryResponse; @@ -275,7 +280,6 @@ DatastoreRequest.prototype.runQuery = function(q, callback) { }); }; - /** * Make a request to the API endpoint. * diff --git a/lib/datastore/transaction.js b/lib/datastore/transaction.js index a1c74d9a64d..874a70ad4b1 100644 --- a/lib/datastore/transaction.js +++ b/lib/datastore/transaction.js @@ -21,15 +21,19 @@ 'use strict'; +var nodeutil = require('util'); + /** @type module:datastore/pb */ var pb = require('./pb.js'); /** @type module:common/util */ var util = require('../common/util.js'); -var nodeutil = require('util'); - -var DatastoreRequest = require('./datastore_request.js'); +/** + * @type module:datastore/request + * @private + */ +var DatastoreRequest = require('./request'); /** * Build a Transaction object. Transactions will generally be built for you by From b0800de39c8df757e84c5f0ff0c1065796b07345 Mon Sep 17 00:00:00 2001 From: Ryan Seys Date: Sat, 27 Sep 2014 21:50:45 -0400 Subject: [PATCH 5/8] Linting galore in datastore --- lib/datastore/dataset.js | 12 +++++++++--- lib/datastore/request.js | 22 ++++++++++------------ lib/datastore/transaction.js | 11 ++++++----- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/lib/datastore/dataset.js b/lib/datastore/dataset.js index f5c0edab5f2..ca3db99efea 100644 --- a/lib/datastore/dataset.js +++ b/lib/datastore/dataset.js @@ -62,7 +62,7 @@ var util = require('../common/util.js'); * @type module:datastore/request * @private */ -var DatastoreRequest = require('./request'); +var DatastoreRequest = require('./request.js'); /** * Scopes for Google Datastore access. @@ -81,7 +81,7 @@ var SCOPES = [ * @constructor * @alias module:datastore/dataset * - * @param {object=} options + * @param {object=} options options object * @param {string=} options.projectId - Dataset ID. This is your project ID from * the Google Developers Console. * @param {string=} options.keyFilename - Full path to the JSON key downloaded @@ -145,6 +145,8 @@ nodeutil.inherits(Dataset, DatastoreRequest); * namespace: 'My-NS', * path: ['Company', 123] * }); + * + * @return {Key} A newly created Key from the options given. */ Dataset.prototype.key = function(options) { options = util.is(options, 'object') ? options : { @@ -254,7 +256,7 @@ Dataset.prototype.allocateIds = function(incompleteKey, n, callback) { (resp.key || []).forEach(function(k) { keys.push(entity.keyFromKeyProto(k)); }); - callback(null ,keys); + callback(null, keys); }); }; @@ -268,4 +270,8 @@ Dataset.prototype.createTransaction_ = function() { return new Transaction(this.connection, this.projectId); }; +/** + * Exports Dataset + * @type {Dataset} + */ module.exports = Dataset; diff --git a/lib/datastore/request.js b/lib/datastore/request.js index f2df763dd49..2f5acb7a5c1 100644 --- a/lib/datastore/request.js +++ b/lib/datastore/request.js @@ -41,13 +41,6 @@ var MODE_NON_TRANSACTIONAL = 'NON_TRANSACTIONAL'; /** @const {string} Transaction mode key. */ var MODE_TRANSACTIONAL = 'TRANSACTIONAL'; - -/** - * @type module:common/util - * @private - */ -var util = require('../common/util.js'); - function DatastoreRequest() {} /** @@ -55,7 +48,7 @@ function DatastoreRequest() {} * transaction. Get operations require a valid key to retrieve the * key-identified entity from Datastore. * - * @param {Key|Key[]} key - Datastore key object(s). + * @param {Key|Key[]} keys - Datastore key object(s). * @param {function} callback - The callback function. * * @example @@ -90,7 +83,7 @@ DatastoreRequest.prototype.get = function(keys, callback) { if (isMultipleRequest && resp.deferred && resp.deferred.length) { // There may be more results. Call `.get` again, and append the results. this.get( - resp.deferred.map(entity.keyFromKeyProto), function (err, entities) { + resp.deferred.map(entity.keyFromKeyProto), function(err, entities) { if (err) { callback(err); return; @@ -231,7 +224,7 @@ DatastoreRequest.prototype.delete = function(keys, callback) { * supported. If more results are available, a query to retrieve the next page * is provided to the callback function. * - * @param {module:datastore/query} query - Query object. + * @param {module:datastore/query} q - Query object. * @param {function} callback - The callback function. * * @example @@ -251,7 +244,7 @@ DatastoreRequest.prototype.runQuery = function(q, callback) { query: entity.queryToQueryProto(q) }; - if(this.id) { + if (this.id) { req.read_options.transaction = this.id; } @@ -285,7 +278,8 @@ DatastoreRequest.prototype.runQuery = function(q, callback) { * * @param {string} method - Transaction action (allocateIds, commit, etc.). * @param {object} req - Request configuration object. - * @param {function} callbcak - The callback function. + * @param {object} respType - Response type.s + * @param {function} cb - The callback function. * * @example * var deleteRequest = { @@ -333,4 +327,8 @@ DatastoreRequest.prototype.createRequest = }); }; +/** + * Exports DatastoreRequest + * @type {DatastoreRequest} + */ module.exports = DatastoreRequest; diff --git a/lib/datastore/transaction.js b/lib/datastore/transaction.js index 874a70ad4b1..637ce9a7a57 100644 --- a/lib/datastore/transaction.js +++ b/lib/datastore/transaction.js @@ -29,11 +29,8 @@ var pb = require('./pb.js'); /** @type module:common/util */ var util = require('../common/util.js'); -/** - * @type module:datastore/request - * @private - */ -var DatastoreRequest = require('./request'); +/** @type module:datastore/request */ +var DatastoreRequest = require('./request.js'); /** * Build a Transaction object. Transactions will generally be built for you by @@ -189,4 +186,8 @@ Transaction.prototype.mapQuery = function() { throw new Error('not yet implemented'); }; +/** + * Exports Transaction + * @type {Transaction} + */ module.exports = Transaction; From 6ac220e0e1e82ea3e00e118ed1376aeae1f3585a Mon Sep 17 00:00:00 2001 From: Ryan Seys Date: Mon, 29 Sep 2014 10:54:45 -0400 Subject: [PATCH 6/8] Update documentation for DatastoreRequest --- lib/datastore/dataset.js | 6 +----- lib/datastore/request.js | 18 ++++++++++++++---- lib/datastore/transaction.js | 4 ---- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/datastore/dataset.js b/lib/datastore/dataset.js index ca3db99efea..1397388dd7c 100644 --- a/lib/datastore/dataset.js +++ b/lib/datastore/dataset.js @@ -81,7 +81,7 @@ var SCOPES = [ * @constructor * @alias module:datastore/dataset * - * @param {object=} options options object + * @param {object=} options - Configuration object. * @param {string=} options.projectId - Dataset ID. This is your project ID from * the Google Developers Console. * @param {string=} options.keyFilename - Full path to the JSON key downloaded @@ -270,8 +270,4 @@ Dataset.prototype.createTransaction_ = function() { return new Transaction(this.connection, this.projectId); }; -/** - * Exports Dataset - * @type {Dataset} - */ module.exports = Dataset; diff --git a/lib/datastore/request.js b/lib/datastore/request.js index 2f5acb7a5c1..332ec0854fc 100644 --- a/lib/datastore/request.js +++ b/lib/datastore/request.js @@ -41,6 +41,20 @@ var MODE_NON_TRANSACTIONAL = 'NON_TRANSACTIONAL'; /** @const {string} Transaction mode key. */ var MODE_TRANSACTIONAL = 'TRANSACTIONAL'; +/** + * Handles request logic for Datastore. + * + * Creates requests to the Dataset endpoint. Designed to be inherited by + * datastore.Dataset and datastore.Transaction objects. + * + * @constructor + * @alias module:datastore/request + * + * @example + * // Inherit in Dataset and Transaction + * require('util').inherits(Dataset, DatastoreRequest); + * require('util').inherits(Transaction, DatastoreRequest); + */ function DatastoreRequest() {} /** @@ -327,8 +341,4 @@ DatastoreRequest.prototype.createRequest = }); }; -/** - * Exports DatastoreRequest - * @type {DatastoreRequest} - */ module.exports = DatastoreRequest; diff --git a/lib/datastore/transaction.js b/lib/datastore/transaction.js index 637ce9a7a57..f4bba30c651 100644 --- a/lib/datastore/transaction.js +++ b/lib/datastore/transaction.js @@ -186,8 +186,4 @@ Transaction.prototype.mapQuery = function() { throw new Error('not yet implemented'); }; -/** - * Exports Transaction - * @type {Transaction} - */ module.exports = Transaction; From 5d85faea4f240bceb34b11c9422e4a87299ed24f Mon Sep 17 00:00:00 2001 From: Stephen Sawchuk Date: Tue, 30 Sep 2014 09:51:35 -0400 Subject: [PATCH 7/8] include transaction in the docs. --- docs/components/docs/docs-directives.js | 12 + docs/components/docs/docs-services.js | 24 + docs/components/docs/docs-values.js | 54 ++ docs/components/docs/docs.html | 22 +- docs/components/docs/docs.js | 229 ++--- docs/index.html | 4 + docs/lib/semver.js | 1098 +++++++++++++++++++++++ lib/datastore/dataset.js | 56 +- lib/datastore/request.js | 117 ++- lib/datastore/transaction.js | 56 +- package.json | 2 +- test/datastore/dataset.js | 28 +- test/datastore/transaction.js | 8 +- 13 files changed, 1479 insertions(+), 231 deletions(-) create mode 100644 docs/components/docs/docs-directives.js create mode 100644 docs/components/docs/docs-services.js create mode 100644 docs/components/docs/docs-values.js create mode 100644 docs/lib/semver.js diff --git a/docs/components/docs/docs-directives.js b/docs/components/docs/docs-directives.js new file mode 100644 index 00000000000..0295fb30f33 --- /dev/null +++ b/docs/components/docs/docs-directives.js @@ -0,0 +1,12 @@ +angular.module('gcloud.docs') + .directive('docsExample', function($compile) { + 'use strict'; + + return { + link: function(scope, element, attr) { + scope.$watch(attr.ngBindHtml, function() { + $compile(element.contents())(scope); + }, true); + } + }; + }); diff --git a/docs/components/docs/docs-services.js b/docs/components/docs/docs-services.js new file mode 100644 index 00000000000..e4dd9847722 --- /dev/null +++ b/docs/components/docs/docs-services.js @@ -0,0 +1,24 @@ +angular.module('gcloud.docs') + .factory('getLinks', function(pages) { + 'use strict'; + + return function(version) { + var baseUrl = '#/docs/' + version; + var VERSIONS = pages.VERSIONS; + var versions; + var match; + if (!version || version === 'master') { + versions = Object.keys(VERSIONS); + match = versions[versions.length - 1]; + } else { + match = Object.keys(VERSIONS).filter(semver.satisfies.bind(null, version))[0]; + } + return VERSIONS[match] + .map(function(module) { + if (pages[module]._url) { + pages[module].url = pages[module]._url.replace('{baseUrl}', baseUrl); + } + return pages[module]; + }); + }; + }); diff --git a/docs/components/docs/docs-values.js b/docs/components/docs/docs-values.js new file mode 100644 index 00000000000..fc3f9952daa --- /dev/null +++ b/docs/components/docs/docs-values.js @@ -0,0 +1,54 @@ +angular.module('gcloud.docs') + .value('pages', { + gcloud: { + title: 'gcloud', + _url: '{baseUrl}' + }, + + datastore: { + title: 'Datastore', + _url: '{baseUrl}/datastore', + pages: [ + { + title: 'Dataset', + url: '/dataset' + }, + { + title: 'Query', + url: '/query' + } + ] + }, + + datastoreWithTransaction: { + title: 'Datastore', + _url: '{baseUrl}/datastore', + pages: [ + { + title: 'Dataset', + url: '/dataset' + }, + { + title: 'Transaction', + url: '/transaction' + }, + { + title: 'Query', + url: '/query' + } + ] + }, + + storage: { + title: 'Storage', + _url: '{baseUrl}/storage' + }, + + VERSIONS: { + // Give a version with/without a comparator, anything semver: + // https://github.com/npm/node-semver#versions + // List should be in ascending order. + '<=0.7.1': ['gcloud', 'datastore', 'storage'], + '>0.7.1': ['gcloud', 'datastoreWithTransaction', 'storage'] + } + }); diff --git a/docs/components/docs/docs.html b/docs/components/docs/docs.html index be0e1e0d3f5..eb6ead22cab 100644 --- a/docs/components/docs/docs.html +++ b/docs/components/docs/docs.html @@ -45,13 +45,13 @@

However, if you're running your app elsewhere, you will need to provide this information.

- // App Engine and Compute Engine - var gcloud = require('gcloud'); +// App Engine and Compute Engine +var gcloud = require('gcloud'); - // Elsewhere - var gcloud = require('gcloud')({ - keyFilename: '/path/to/keyfile.json' - });
+// Elsewhere +var gcloud = require('gcloud')({ + keyFilename: '/path/to/keyfile.json' +});

In any environment, you are free to provide these and other default properties, which eventually will be passed to the gcloud sub-modules (Datastore, Storage, etc.).

@@ -98,8 +98,7 @@

ng-if="method.name[0].toUpperCase() !== method.name[0]"> + ng-href="{{activeUrl + '?method=' + method.name}}"># {{method.name}}

@@ -118,9 +117,8 @@

Parameters

Returns

Example

-
+

@@ -135,7 +133,7 @@

Example