diff --git a/.npmignore b/.npmignore index 1f58457a84f..9ff91652b5f 100644 --- a/.npmignore +++ b/.npmignore @@ -1,4 +1,5 @@ test coverage regression -test.js \ No newline at end of file +test.js +key.json \ No newline at end of file diff --git a/README.md b/README.md index c3b8667033a..195c214e9e2 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,11 @@ If you're running this client on Google Compute Engine, you need to construct a ~~~~ js var gcloud = require('gcloud'), datastore = gcloud.datastore, - ds = new datastore.Dataset({ projectId: YOUR_PROJECT_ID }); + ds = new datastore.Dataset({ + projectId: YOUR_PROJECT_ID, + /* namespace is optional, if not provided the default is used. */ + namespace: 'namespace1' + }); ~~~~ Elsewhere, initiate with project ID and private key downloaded from Developer's Console. @@ -85,6 +89,8 @@ Elsewhere, initiate with project ID and private key downloaded from Developer's var gcloud = require('gcloud'), ds = new gcloud.datastore.Dataset({ projectId: YOUR_PROJECT_ID, + /* namespace is optional, if not provided the default is used. */ + namespace: 'namespace1', keyFilename: '/path/to/the/key.json' }); ~~~~ @@ -98,12 +104,12 @@ TODO Get operations require a valid key to retrieve the key identified entity from Datastore. Skip to the "Querying" section if you'd like to learn more about querying against Datastore. ~~~~ js -ds.get(datastore.key('Company', 123), function(err, entity) {}); +ds.get(ds.key('Company', 123), function(err, entity) {}); // alternatively, you can retrieve multiple entities at once. ds.get([ - datastore.key('Company', 123), - datastore.key('Product', 'Computer') + ds.key('Company', 123), + ds.key('Product', 'Computer') ], function(err, entities) {}); ~~~~ @@ -113,15 +119,15 @@ To learn more about keys and incomplete keys, skip to the Keys section. ~~~~ js ds.save({ - key: datastore.key('Company', null), data: {/*...*/} + key: ds.key('Company', null), data: {/*...*/} }, function(err, key) { // First arg is an incomplete key for Company kind. // console.log(key) will output ['Company', 599900452312]. }); // alternatively, you can save multiple entities at once. ds.save([ - { key: datastore.key('Company', 123), data: {/*...*/} }, - { key: datastore.key('Product', 'Computer'), data: {/*...*/} } + { key: ds.key('Company', 123), data: {/*...*/} }, + { key: ds.key('Product', 'Computer'), data: {/*...*/} } ], function(err, keys) { // if the first key was incomplete, keys[0] will return the generated key. }); @@ -135,10 +141,10 @@ ds.delete(['Company', 599900452312], function(err) {}); // alternatively, you can delete multiple entities of different // kinds at once. ds.delete([ - datastore.key('Company', 599900452312), - datastore.key('Company', 599900452315), - datastore.key('Office', 'mtv'), - datastore.key('Company', 123, 'Employee', 'jbd') + ds.key('Company', 599900452312), + ds.key('Company', 599900452315), + ds.key('Office', 'mtv'), + ds.key('Company', 123, 'Employee', 'jbd') ], function(err) {}); ~~~~ @@ -177,14 +183,14 @@ stored as properties is not currently supported. ~~~~ js var q = ds.createQuery('Company') - .filter('__key__ =', datastore.key('Company', 'Google')) + .filter('__key__ =', ds.key('Company', 'Google')) ~~~~ In order to filter by ancestors, use `hasAncestor` helper. ~~~ js var q = ds.createQuery('Child') - .hasAncestor(datastore.key('Parent', 123)); + .hasAncestor(ds.key('Parent', 123)); ~~~ ##### Sorting @@ -225,19 +231,24 @@ You can generate IDs without creating entities. The following call will create 100 new IDs from the Company kind which exists under the default namespace. ~~~~ js -ds.allocateIds(datastore.key('Company', null), 100, function(err, keys) { +ds.allocateIds(ds.key('Company', null), 100, function(err, keys) { }); ~~~~ -You may prefer to create IDs from a non-default namespace by providing -an incomplete key with a namespace. Similar to the previous example, the -call below will create 100 new IDs, but from the Company kind that exists +You may prefer to create IDs from a non-default namespace. + +Initialize a `Dataset` object with a namespace and allocate IDS. +Similar to the previous example, the call below will create 100 +new IDs, but from the Company kind that exists under the "ns-test" namespace. ~~~~ js -var incompleteKey = datastore.key('ns-test', 'Company', null); -ds.allocateIds(incompleteKey, 100, function(err, keys) { +var ds = new gcloud.datastore.Dataset({ + // ... + namespace: 'ns-test' +}); +ds.allocateIds(ds.key('Company', null), 100, function(err, keys) { }); ~~~~ diff --git a/lib/datastore/dataset.js b/lib/datastore/dataset.js index 4a8027df1e9..b2ff0498b12 100644 --- a/lib/datastore/dataset.js +++ b/lib/datastore/dataset.js @@ -55,28 +55,30 @@ var SCOPES = [ * @alias module:datastore/dataset * * @param {object} options - * @param {string} options.id - Dataset ID. This is your project ID from the - * Google Developers Console. + * @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 * from the Google Developers Console. + * @param {string=} options.namespace - Namespace. If none provided, the default + * namespace is used. * * @example * ```js * var dataset = new Dataset({ - * id: 'my-project', + * projectId: 'my-project', * keyFileName: '/path/to/keyfile.json' * }); * ``` */ function Dataset(opts) { opts = opts || {}; - var id = opts.projectId; this.connection = new conn.Connection({ keyFilename: opts.keyFilename, scopes: SCOPES }); - this.id = id; + this.id = opts.projectId; + this.namespace = opts.namespace || null; this.transaction = this.createTransaction_(); } @@ -88,17 +90,12 @@ function Dataset(opts) { * @example * ```js * var query = dataset.createQuery(['Lion', 'Chimp']); - * var zooQuery = dataset.createQuery('zoo', ['Lion', 'Chimp']); * ``` * @return {module:datastore/query} */ -Dataset.prototype.createQuery = function(ns, kinds) { - if (!kinds) { - kinds = ns; - ns = ''; - } +Dataset.prototype.createQuery = function(kinds) { kinds = util.arrayize(kinds); - return new Query(ns, kinds); + return new Query(kinds); }; /** @@ -204,7 +201,7 @@ Dataset.prototype.runQuery = function(q, callback) { * dataset.transaction(function(transaction, done) { * // From the `transaction` object, execute dataset methods as usual. * // Call `done` when you're ready to commit all of the changes. - * transaction.get(datastore.key('Company', 123), function(err, entity) { + * transaction.get(ds.key('Company', 123), function(err, entity) { * if (err) { * transaction.rollback(done); * return; @@ -235,15 +232,8 @@ Dataset.prototype.runInTransaction = function(fn, callback) { * @example * ```js * // The following call will create 100 new IDs from the Company kind, which - * // exists under the default namespace. - * var incompleteKey = datastore.key('Company', null); - * dataset.allocateIds(incompleteKey, 100, function(err, keys) {}); - * - * // You may prefer to create IDs from a non-default namespace by providing an - * // incomplete key with a namespace. Similar to the previous example, the call - * // below will create 100 new IDs, but from the Company kind that exists under - * // the "ns-test" namespace. - * var incompleteKey = datastore.key('ns-test', 'Company', null); + * // exists under the dataset's namespace. + * var incompleteKey = ds.key('Company', null); * dataset.allocateIds(incompleteKey, 100, function(err, keys) {}); * ``` */ @@ -251,9 +241,11 @@ Dataset.prototype.allocateIds = function(incompleteKey, n, callback) { if (entity.isKeyComplete(incompleteKey)) { throw new Error('An incomplete key should be provided.'); } + // TODO(jbd): Add namespace to keys. var incompleteKeys = []; + var proto = entity.keyToKeyProto(incompleteKey); for (var i = 0; i < n; i++) { - incompleteKeys.push(entity.keyToKeyProto(incompleteKey)); + incompleteKeys.push(proto); } this.transaction.makeReq( 'allocateIds', @@ -270,6 +262,44 @@ Dataset.prototype.allocateIds = function(incompleteKey, n, callback) { }); }; +/** + * @borrows {module:datastore/entity~Key} as key + * + * @example + * ```js + * var key = ds.key('Company', 123); + * ``` + */ +Dataset.prototype.key = function() { + return new entity.Key(this.namespace, [].slice.call(arguments)); +}; + +/** + * @borrows {module:datastore/entity~Int} as int + * + * @example + * ```js + * var anInteger = ds.int(7); + * ``` + */ +Dataset.prototype.int = function(value) { + return new entity.Int(value); +}; + +/** + * Helper function to get a Datastore Double object. + * + * @borrows {module:datastore/entity~Double} as double + * + * @example + * ```js + * var aDouble = ds.double(7); + * ``` + */ +Dataset.prototype.double = function(value) { + return new entity.Double(value); +}; + /** * Create a new Transaction object using the existing connection and dataset. * @@ -277,7 +307,7 @@ Dataset.prototype.allocateIds = function(incompleteKey, n, callback) { * @return {module:datastore/transaction} */ Dataset.prototype.createTransaction_ = function() { - return new Transaction(this.connection, this.id); + return new Transaction(this.connection, this.id, this.namespace); }; /** diff --git a/lib/datastore/entity.js b/lib/datastore/entity.js index 87804994ed6..24a1ace6710 100644 --- a/lib/datastore/entity.js +++ b/lib/datastore/entity.js @@ -93,15 +93,12 @@ var SIGN_TO_ORDER = { * * @example * ```js - * var key = new Key('Company', 123); + * var key = new Key('ns', ['Kind, 123]); * ``` */ -function Key() { - if (arguments.length > 1) { - this.path_ = [].slice.call(arguments); - } else { - this.path_ = arguments[0]; - } +function Key(namespace, path) { + this.namespace = namespace; + this.path = path; } module.exports.Key = Key; @@ -220,15 +217,16 @@ module.exports.entityFromEntityProto = entityFromEntityProto; * ``` */ function keyFromKeyProto(proto) { - var keyPath = []; + var ns = null; if (proto.partition_id && proto.partition_id.namespace) { - keyPath.push(proto.partition_id.namespace); + ns = proto.partition_id.namespace; } - proto.path_element.forEach(function(path) { - keyPath.push(path.kind); - keyPath.push(Number(path.id) || path.name || null); + var path = []; + proto.path_element.forEach(function(el) { + path.push(el.kind); + path.push(Number(el.id) || el.name || null); }); - return new Key(keyPath); + return new Key(ns, path); } module.exports.keyFromKeyProto = keyFromKeyProto; @@ -243,7 +241,7 @@ module.exports.keyFromKeyProto = keyFromKeyProto; * * @example * ```js - * var keyProto = keyToKeyProto(new Key('Company', 1)); + * var keyProto = keyToKeyProto(new Key(null, 'Company', 1)); * * // keyProto: * // { @@ -257,21 +255,19 @@ module.exports.keyFromKeyProto = keyFromKeyProto; * ``` */ function keyToKeyProto(key) { - var keyPath = key.path_; - if (keyPath.length < 2) { + var proto = {}; + if (key.path.length < 2) { throw new Error('A key should contain at least a kind and an identifier.'); } - var namespace = null; - var start = 0; - if (keyPath.length % 2 === 1) { - // the first item is the namespace - namespace = keyPath[0]; - start = 1; + if (key.namespace) { + proto.partition_id = { + namespace: key.namespace + }; } var path = []; - for (var i = start; i < (keyPath.length - start); i += 2) { - var p = { kind: keyPath[i] }; - var val = keyPath[i+1]; + for (var i = 0; i < key.path.length; i += 2) { + var p = { kind: key.path[i] }; + var val = key.path[i+1]; if (val) { // if not numeric, set key name. if (isNaN(val)) { @@ -282,14 +278,7 @@ function keyToKeyProto(key) { } path.push(p); } - var proto = { - path_element: path - }; - if (namespace) { - proto.partition_id = { - namespace: namespace - }; - } + proto.path_element = path; return proto; } @@ -342,8 +331,8 @@ module.exports.formatArray = formatArray; * * @example * ```js - * isKeyComplete(new Key('Company', 'Google')); // true - * isKeyComplete(new Key('Company', null)); // false + * isKeyComplete(new Key(ns, ['Company', 'Google'])); // true + * isKeyComplete(new Key(ns, ['Company', null])); // false * ``` */ module.exports.isKeyComplete = function(key) { diff --git a/lib/datastore/index.js b/lib/datastore/index.js index 08b7ebea6e7..0aadd0ffe2f 100644 --- a/lib/datastore/index.js +++ b/lib/datastore/index.js @@ -20,9 +20,6 @@ 'use strict'; -/** @type module:datastore/entity */ -var entity = require('./entity'); - /** @alias module:datastore */ var datastore = {}; @@ -36,42 +33,4 @@ var datastore = {}; */ datastore.Dataset = require('./dataset'); -/** - * @borrows {module:datastore/entity~Key} as key - * - * @example - * ```js - * var key = dataset.key('Company', 123); - * ``` - */ -datastore.key = function() { - return new entity.Key([].slice.call(arguments)); -}; - -/** - * @borrows {module:datastore/entity~Int} as int - * - * @example - * ```js - * var anInteger = dataset.int(7); - * ``` - */ -datastore.int = function(value) { - return new entity.Int(value); -}; - -/** - * Helper function to get a Datastore Double object. - * - * @borrows {module:datastore/entity~Double} as double - * - * @example - * ```js - * var aDouble = dataset.double(7); - * ``` - */ -datastore.double = function(value) { - return new entity.Double(value); -}; - module.exports = datastore; diff --git a/lib/datastore/query.js b/lib/datastore/query.js index 96d1d061eac..a0c41d7ca26 100644 --- a/lib/datastore/query.js +++ b/lib/datastore/query.js @@ -28,17 +28,14 @@ var util = require('../common/util.js'); * @constructor * @alias module:datastore/query * - * @param {string=} namespace - Namespace to query entities from. * @param {string[]} kinds - Kinds to query. * * @example * ```js * var query = new Query(['Lion', 'Chimp']); - * var zooQuery = new Query('zoo', ['Lion', 'Chimp']); * ``` */ -function Query(namespace, kinds) { - this.namespace = namespace; +function Query(kinds) { this.kinds = kinds; this.filters = []; @@ -77,7 +74,7 @@ function Query(namespace, kinds) { * * // To filter by key, use `__key__` for the property name. Filter on keys * // stored as properties is not currently supported. - * var keyQuery = query.filter('__key__ =', datastore.key('Company', 'Google')); + * var keyQuery = query.filter('__key__ =', ds.key('Company', 'Google')); * ``` */ Query.prototype.filter = function(filter, value) { @@ -100,7 +97,7 @@ Query.prototype.filter = function(filter, value) { * * @example * ```js - * var ancestoryQuery = query.hasAncestor(datastore.key('Parent', 123)); + * var ancestoryQuery = query.hasAncestor(ds.key('Parent', 123)); * ``` */ Query.prototype.hasAncestor = function(key) { diff --git a/lib/datastore/transaction.js b/lib/datastore/transaction.js index 7876d7be6a2..5e36c319071 100644 --- a/lib/datastore/transaction.js +++ b/lib/datastore/transaction.js @@ -54,6 +54,8 @@ var MODE_TRANSACTIONAL = 'TRANSACTIONAL'; * to Google Cloud Datastore. * @param {string} datasetId - Dataset ID. This is your project ID from the * Google Developers Console. + * @param {string=} namespace - Namespace to run transaction operations at. If + * no namespace is provided, the default namespace is used. * * @example * ```js @@ -62,9 +64,10 @@ var MODE_TRANSACTIONAL = 'TRANSACTIONAL'; * var transaction = new Transaction(myConnection, 'my-project-id'); * ``` */ -function Transaction(conn, datasetId) { +function Transaction(conn, datasetId, namespace) { this.conn = conn; this.datasetId = datasetId; + this.namespace = namespace; // the default transaction has no id. // if id is not set, run operations non-transactional. this.id = null; @@ -82,7 +85,7 @@ function Transaction(conn, datasetId) { * ```js * transaction.begin(function(err) { * // Perform Datastore operations as usual. - * transaction.get(datastore.key('Company', 123), function(err, entity) { + * transaction.get(ds.key('Company', 123), function(err, entity) { * // Commit the transaction. * transaction.finalize(function(err) {}); * @@ -200,16 +203,17 @@ Transaction.prototype.finalize = function(callback) { * // These examples work with both a Transaction object and a Dataset object. * * // Get a single entity. - * transaction.get(datastore.key('Company', 123), function(err, entity)); + * transaction.get(ds.key('Company', 123), function(err, entity)); * * // Get multiple entities at once. * transaction.get([ - * datastore.key('Company', 123), - * datastore.key('Product', 'Computer') + * ds.key('Company', 123), + * ds.key('Product', 'Computer') * ], function(err, entities) {}); * ``` */ Transaction.prototype.get = function(keys, callback) { + // TODO(jbd): Add namespace. var isMultipleRequest = Array.isArray(keys); keys = isMultipleRequest ? keys : [keys]; callback = callback || util.noop; @@ -245,7 +249,7 @@ Transaction.prototype.get = function(keys, callback) { * * // Save a single entity. * transaction.save({ - * key: datastore.key('Company', null), + * key: ds.key('Company', null), * data: { * rating: '10' * } @@ -257,13 +261,13 @@ Transaction.prototype.get = function(keys, callback) { * // Save multiple entities at once. * transaction.save([ * { - * key: datastore.key('Company', 123), + * key: ds.key('Company', 123), * data: { * HQ: 'Dallas, TX' * } * }, * { - * key: datastore.key('Product', 'Computer'), + * key: ds.key('Product', 'Computer'), * data: { * vendor: 'Dell' * } @@ -322,12 +326,12 @@ Transaction.prototype.save = function(entities, callback) { * // These examples work with both a Transaction object and a Dataset object. * * // Delete a single entity. - * transaction.delete(datastore.key('Company', 123), function(err) {}); + * transaction.delete(ds.key('Company', 123), function(err) {}); * * // Delete multiple entities at once. * transaction.delete([ - * datastore.key('Company', 123), - * datastore.key('Product', 'Computer') + * ds.key('Company', 123), + * ds.key('Product', 'Computer') * ], function(err) {}); * ``` */ @@ -379,9 +383,9 @@ Transaction.prototype.runQuery = function(q, callback) { }, query: entity.queryToQueryProto(q) }; - if (q.namespace) { + if (this.namespace) { req.partition_id = { - namespace: q.namespace + namespace: this.namespace }; } req = new pb.RunQueryRequest(req); diff --git a/package.json b/package.json index 537845620be..f4aaffd4d1c 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,6 @@ "istanbul": "^0.3.0", "jshint": "^2.5.2", "mocha": "^1.21.3", - "sandboxed-module": "^1.0.1", "tmp": "0.0.24", "coveralls": "^2.11.1" }, diff --git a/regression/datastore.js b/regression/datastore.js index 845a12a4327..bbb9642b2cd 100644 --- a/regression/datastore.js +++ b/regression/datastore.js @@ -28,7 +28,7 @@ var entity = require('../lib/datastore/entity.js'); describe('datastore', function() { it('should allocate IDs', function(done) { - ds.allocateIds(datastore.key('Kind', null), 10, function(err, keys) { + ds.allocateIds(ds.key('Kind', null), 10, function(err, keys) { assert.ifError(err); assert.equal(keys.length, 10); assert.equal(entity.isKeyComplete(keys[0]), true); @@ -48,10 +48,10 @@ describe('datastore', function() { }; it('should save/get/delete with a key name', function(done) { - var postKey = datastore.key('Post', 'post1'); + var postKey = ds.key('Post', 'post1'); ds.save({ key: postKey, data: post }, function(err, key) { assert.ifError(err); - assert.equal(key.path_[1], 'post1'); + assert.equal(key.path[1], 'post1'); ds.get(key, function(err, entity) { assert.ifError(err); assert.deepEqual(entity.data, post); @@ -64,13 +64,13 @@ describe('datastore', function() { }); it('should save/get/delete with a numeric key id', function(done) { - var postKey = datastore.key('Post', 123456789); + var postKey = ds.key('Post', 123456789); ds.save({ key: postKey, data: post }, function(err, key) { assert.ifError(err); - assert.equal(key.path_[1], 123456789); + assert.equal(key.path[1], 123456789); ds.get(key, function(err, entity) { assert.ifError(err); assert.deepEqual(entity.data, post); @@ -84,16 +84,16 @@ describe('datastore', function() { it('should save/get/delete with a generated key id', function(done) { ds.save({ - key: datastore.key('Post', null), + key: ds.key('Post', null), data: post }, function(err, key) { assert.ifError(err); - var assignedId = key.path_[1]; + var assignedId = key.path[1]; assert(assignedId); - ds.get(datastore.key('Post', assignedId), function(err, entity) { + ds.get(ds.key('Post', assignedId), function(err, entity) { assert.ifError(err); assert.deepEqual(entity.data, post); - ds.delete(datastore.key('Post', assignedId), function(err) { + ds.delete(ds.key('Post', assignedId), function(err) { assert.ifError(err); done(); }); @@ -111,15 +111,15 @@ describe('datastore', function() { wordCount: 450, rating: 4.5, }; - var key = datastore.key('Post', null); + var key = ds.key('Post', null); ds.save([ { key: key, data: post }, { key: key, data: post2 } ], function(err, keys) { assert.ifError(err); assert.equal(keys.length,2); - var firstKey = datastore.key('Post', keys[0].path_[1]); - var secondKey = datastore.key('Post', keys[1].path_[1]); + var firstKey = ds.key('Post', keys[0].path[1]); + var secondKey = ds.key('Post', keys[1].path[1]); ds.get([firstKey, secondKey], function(err, entities) { assert.ifError(err); assert.equal(entities.length, 2); @@ -135,7 +135,7 @@ describe('datastore', function() { it('should be able to save keys as a part of entity and query by key', function(done) { - var personKey = datastore.key('Person', 'name'); + var personKey = ds.key('Person', 'name'); ds.save({ key: personKey, data: { @@ -158,14 +158,14 @@ describe('datastore', function() { describe('querying the datastore', function() { var keys = [ - datastore.key('Character', 'Rickard'), - datastore.key('Character', 'Rickard', 'Character', 'Eddard'), - datastore.key('Character', 'Catelyn'), - datastore.key('Character', 'Eddard', 'Character', 'Arya'), - datastore.key('Character', 'Eddard', 'Character', 'Sansa'), - datastore.key('Character', 'Eddard', 'Character', 'Robb'), - datastore.key('Character', 'Eddard', 'Character', 'Bran'), - datastore.key('Character', 'Eddard', 'Character', 'Jon Snow') + ds.key('Character', 'Rickard'), + ds.key('Character', 'Rickard', 'Character', 'Eddard'), + ds.key('Character', 'Catelyn'), + ds.key('Character', 'Eddard', 'Character', 'Arya'), + ds.key('Character', 'Eddard', 'Character', 'Sansa'), + ds.key('Character', 'Eddard', 'Character', 'Robb'), + ds.key('Character', 'Eddard', 'Character', 'Bran'), + ds.key('Character', 'Eddard', 'Character', 'Jon Snow') ]; var characters = [{ @@ -265,7 +265,7 @@ describe('datastore', function() { it('should filter by ancestor', function(done) { var q = ds.createQuery('Character') - .hasAncestor(datastore.key('Character', 'Eddard')); + .hasAncestor(ds.key('Character', 'Eddard')); ds.runQuery(q, function(err, entities) { assert.ifError(err); assert.equal(entities.length, 5); @@ -275,7 +275,7 @@ describe('datastore', function() { it('should filter by key', function(done) { var q = ds.createQuery('Character') - .filter('__key__ =', datastore.key('Character', 'Rickard')); + .filter('__key__ =', ds.key('Character', 'Rickard')); ds.runQuery(q, function(err, entities) { assert.ifError(err); assert.equal(entities.length, 1); @@ -370,7 +370,7 @@ describe('datastore', function() { describe('transactions', function() { it('should run in a transaction', function(done) { - var key = datastore.key('Company', 'Google'); + var key = ds.key('Company', 'Google'); var obj = { url: 'www.google.com' }; diff --git a/test/datastore/dataset.js b/test/datastore/dataset.js index 4f78500e15b..76c4b537f0d 100644 --- a/test/datastore/dataset.js +++ b/test/datastore/dataset.js @@ -25,6 +25,33 @@ var mockRespGet = require('../testdata/response_get.json'); var Transaction = require('../../lib/datastore/transaction.js'); describe('Dataset', function() { + + it('should provide an Int builder', function(done) { + var ds = new datastore.Dataset({ projectId: 'test' }); + assert.strictEqual(ds.int(6).val_, 6); + done(); + }); + + it('should provide a Double builder', function(done) { + var ds = new datastore.Dataset({ projectId: 'test' }); + assert.strictEqual(ds.int(6.4).val_, 6.4); + done(); + }); + + it('should provide a Key builder', function(done) { + var ds = new datastore.Dataset({ projectId: 'test' }); + var dsNS = new datastore.Dataset({ projectId: 'test', namespace: 'ns' }); + + var key = ds.key('Kind', 123); + var keyNS = dsNS.key('Kind', 123); + + assert.strictEqual(key.namespace, null); + assert.deepEqual(key.path, ['Kind', 123]); + assert.strictEqual(keyNS.namespace, 'ns'); + assert.deepEqual(keyNS.path, ['Kind', 123]); + done(); + }); + it('should get by key', function(done) { var ds = new datastore.Dataset({ projectId: 'test' }); ds.transaction.makeReq = function(method, proto, typ, callback) { @@ -32,9 +59,9 @@ describe('Dataset', function() { assert.equal(proto.key.length, 1); callback(null, mockRespGet); }; - ds.get(datastore.key('Kind', 123), function(err, entity) { + ds.get(ds.key('Kind', 123), function(err, entity) { var data = entity.data; - assert.deepEqual(entity.key.path_, ['Kind', 5732568548769792]); + assert.deepEqual(entity.key.path, ['Kind', 5732568548769792]); assert.strictEqual(data.author, 'Silvano'); assert.strictEqual(data.isDraft, false); assert.deepEqual(data.publishedAt, new Date(978336000000)); @@ -49,11 +76,11 @@ describe('Dataset', function() { assert.equal(proto.key.length, 1); callback(null, mockRespGet); }; - var key = datastore.key('Kind', 5732568548769792); + var key = ds.key('Kind', 5732568548769792); ds.get([key], function(err, entities) { var entity = entities[0]; var data = entity.data; - assert.deepEqual(entity.key.path_, ['Kind', 5732568548769792]); + assert.deepEqual(entity.key.path, ['Kind', 5732568548769792]); assert.strictEqual(data.author, 'Silvano'); assert.strictEqual(data.isDraft, false); assert.deepEqual(data.publishedAt, new Date(978336000000)); @@ -68,7 +95,7 @@ describe('Dataset', function() { assert.equal(!!proto.mutation.delete, true); callback(); }; - ds.delete(datastore.key('Kind', 123), done); + ds.delete(ds.key('Kind', 123), done); }); it('should multi delete by keys', function(done) { @@ -79,8 +106,8 @@ describe('Dataset', function() { callback(); }; ds.delete([ - datastore.key('Kind', 123), - datastore.key('Kind', 345) + ds.key('Kind', 123), + ds.key('Kind', 345) ], done); }); @@ -91,7 +118,7 @@ describe('Dataset', function() { assert.equal(proto.mutation.insert_auto_id.length, 1); callback(); }; - var key = datastore.key('Kind', null); + var key = ds.key('Kind', null); ds.save({ key: key, data: {} }, done); }); @@ -106,8 +133,8 @@ describe('Dataset', function() { callback(); }; ds.save([ - { key: datastore.key('Kind', 123), data: { k: 'v' } }, - { key: datastore.key('Kind', 456), data: { k: 'v' } } + { key: ds.key('Kind', 123), data: { k: 'v' } }, + { key: ds.key('Kind', 456), data: { k: 'v' } } ], done); }); @@ -126,8 +153,8 @@ describe('Dataset', function() { ] }); }; - ds.allocateIds(datastore.key('Kind', null), 1, function(err, ids) { - assert.deepEqual(ids[0], datastore.key('Kind', 123)); + ds.allocateIds(ds.key('Kind', null), 1, function(err, ids) { + assert.deepEqual(ids[0], ds.key('Kind', 123)); done(); }); }); @@ -135,7 +162,7 @@ describe('Dataset', function() { it('should throw if trying to allocate IDs with complete keys', function() { var ds = new datastore.Dataset({ projectId: 'test' }); assert.throws(function() { - ds.allocateIds(datastore.key('Kind', 123)); + ds.allocateIds(ds.key('Kind', 123)); }); }); @@ -229,7 +256,7 @@ describe('Dataset', function() { ds.runQuery(query, function (err, entities) { assert.ifError(err); - assert.deepEqual(entities[0].key.path_, ['Kind', 5732568548769792]); + assert.deepEqual(entities[0].key.path, ['Kind', 5732568548769792]); var data = entities[0].data; assert.strictEqual(data.author, 'Silvano'); diff --git a/test/datastore/entity.js b/test/datastore/entity.js index 708aaf30815..0fc20989e31 100644 --- a/test/datastore/entity.js +++ b/test/datastore/entity.js @@ -19,8 +19,10 @@ 'use strict'; var assert = require('assert'); -var entity = require('../../lib/datastore/entity.js'); var datastore = require('../../lib/datastore'); +var entity = require('../../lib/datastore/entity.js'); + +var Key = entity.Key; var blogPostMetadata = { title: { kind: String, indexed: true }, @@ -159,26 +161,26 @@ describe('keyFromKeyProto', function() { it('should handle keys hierarchically', function(done) { var key = entity.keyFromKeyProto(protoH); - assert.deepEqual(key, datastore.key('Test', 'Kind', 111, 'Kind2', 'name')); + assert.deepEqual(key, new Key('Test', ['Kind', 111, 'Kind2', 'name'])); done(); }); it('should handle incomplete keys hierarchically', function(done) { var key = entity.keyFromKeyProto(protoHIncomplete); - assert.deepEqual(key, datastore.key('Test', 'Kind', null, 'Kind2', null)); + assert.deepEqual(key, new Key('Test', ['Kind', null, 'Kind2', null])); done(); }); it('should not set namespace if default', function(done) { var key = entity.keyFromKeyProto(proto); - assert.deepEqual(key, datastore.key('Kind', 'Name')); + assert.deepEqual(key, new Key(null, ['Kind', 'Name'])); done(); }); }); describe('keyToKeyProto', function() { it('should handle hierarchical key definitions', function(done) { - var key = datastore.key('Kind1', 1, 'Kind2', 'name'); + var key = new Key(null, ['Kind1', 1, 'Kind2', 'name']); var proto = entity.keyToKeyProto(key); assert.strictEqual(proto.partition_id, undefined); assert.strictEqual(proto.path_element[0].kind, 'Kind1'); @@ -191,7 +193,7 @@ describe('keyToKeyProto', function() { }); it('should detect the namespace of the hierarchical keys', function(done) { - var key = datastore.key('Namespace', 'Kind1', 1, 'Kind2', 'name'); + var key = new Key('Namespace', ['Kind1', 1, 'Kind2', 'name']); var proto = entity.keyToKeyProto(key); assert.strictEqual(proto.partition_id.namespace, 'Namespace'); assert.strictEqual(proto.path_element[0].kind, 'Kind1'); @@ -204,8 +206,8 @@ describe('keyToKeyProto', function() { }); it('should handle incomplete keys with & without namespaces', function(done) { - var key = datastore.key('Kind1', null); - var keyWithNS = datastore.key('Namespace', 'Kind1', null); + var key = new Key(null, ['Kind1', null]); + var keyWithNS = new Key('Namespace', ['Kind1', null]); var proto = entity.keyToKeyProto(key); var protoWithNS = entity.keyToKeyProto(keyWithNS); @@ -222,9 +224,10 @@ describe('keyToKeyProto', function() { done(); }); - it('should throw if key contains less than 2 items', function() { + it('should throw if key contains path that has less than two items', + function() { assert.throws(function() { - entity.keyToKeyProto(['Kind']); + entity.keyToKeyProto(new Key(null, ['Kind'])); }); }); }); @@ -232,10 +235,10 @@ describe('keyToKeyProto', function() { describe('isKeyComplete', function() { it('should ret true if kind and an identifier have !0 vals', function(done) { [ - { key: datastore.key('Kind1', null), expected: false }, - { key: datastore.key('Kind1', 3), expected: true }, - { key: datastore.key('Namespace', 'Kind1', null), expected: false }, - { key: datastore.key('Namespace', 'Kind1', 'name'), expected: true } + { key: new Key(null, ['Kind1', null]), expected: false }, + { key: new Key(null, ['Kind1', 3]), expected: true }, + { key: new Key('Namespace', ['Kind1', null]), expected: false }, + { key: new Key('Namespace', ['Kind1', 'name']), expected: true } ].forEach(function(test) { assert.strictEqual(entity.isKeyComplete(test.key), test.expected); }); @@ -247,7 +250,7 @@ describe('entityFromEntityProto', function() { it('should support boolean, integer, double, string, entity and list values', function(done) { var obj = entity.entityFromEntityProto(entityProto); - assert.deepEqual(obj.linkedTo, datastore.key('Kind', 'another')); + assert.deepEqual(obj.linkedTo, new Key(null, ['Kind', 'another'])); assert.strictEqual(obj.name, 'Some name'); assert.strictEqual(obj.flagged, false); assert.strictEqual(obj.count, 5); @@ -260,8 +263,7 @@ describe('entityFromEntityProto', function() { }); describe('entityToEntityProto', function() { - it( - 'should support boolean, integer, double, string, entity and list values', + it('should support boolean, integer, double, string, entity and list values', function(done) { var now = new Date(); var proto = entity.entityToEntityProto({ @@ -305,7 +307,7 @@ describe('queryToQueryProto', function() { var ds = new datastore.Dataset({ projectId: 'project-id' }); var q = ds.createQuery('Kind1') .filter('name =', 'John') - .hasAncestor(datastore.key('Kind2', 'somename')); + .hasAncestor(ds.key('Kind2', 'somename')); var proto = entity.queryToQueryProto(q); assert.deepEqual(proto, queryFilterProto); done(); diff --git a/test/datastore/index.js b/test/datastore/index.js index a71fa6e3913..3e1f34a0f19 100644 --- a/test/datastore/index.js +++ b/test/datastore/index.js @@ -18,39 +18,11 @@ 'use strict'; -var entity = { - Int: function(val) { - entity.intCalledWith = val; - }, - Double: function(val) { - entity.doubleCalledWith = val; - }, - intCalledWith: null, - doubleCalledWith: null -}; - var assert = require('assert'); -var datastore = require('sandboxed-module') - .require('../../lib/datastore/index.js', { - requires: { - './entity': entity - } - }); +var datastore = require('../../lib/datastore/index.js'); describe('Datastore', function() { it('should expose Dataset class', function() { assert.equal(typeof datastore.Dataset, 'function'); }); - - it('should expose Int builder', function() { - var anInt = 7; - datastore.int(anInt); - assert.equal(entity.intCalledWith, anInt); - }); - - it('should expose Double builder', function() { - var aDouble = 7.0; - datastore.double(aDouble); - assert.equal(entity.doubleCalledWith, aDouble); - }); }); diff --git a/test/datastore/query.js b/test/datastore/query.js index 7f2efa59507..bae101af326 100644 --- a/test/datastore/query.js +++ b/test/datastore/query.js @@ -26,29 +26,10 @@ var queryProto = require('../testdata/proto_query.json'); describe('Query', function() { var ds = new datastore.Dataset({ projectId: 'my-project-id' }); - it('should use default namespace if none is specified', function(done) { - var q = ds.createQuery(['kind1']); - assert.equal(q.namespace, ''); - done(); - }); - - it('should use support custom namespaces', function(done) { - var q = ds.createQuery('ns', ['kind1']); - assert.equal(q.namespace, 'ns'); - done(); - }); - it('should support querying multiple kinds', function(done) { var q = ds.createQuery(['kind1', 'kind2']); - var qNS = ds.createQuery('ns', ['kind1', 'kind2']); - - assert.strictEqual(q.namespace, ''); assert.equal(q.kinds[0], 'kind1'); assert.equal(q.kinds[1], 'kind2'); - - assert.equal(qNS.namespace, 'ns'); - assert.equal(qNS.kinds[0], 'kind1'); - assert.equal(qNS.kinds[1], 'kind2'); done(); }); @@ -120,7 +101,7 @@ describe('Query', function() { it('should be converted to a query proto successfully', function(done) { var q = ds.createQuery(['Kind']) .select(['name', 'count']) - .filter('count >=', datastore.int(5)) + .filter('count >=', ds.int(5)) .filter('name =', 'Burcu') .order('-count') .groupBy(['count'])