Skip to content

Commit 1e9dcce

Browse files
datastore: scope Key creation to include NS. fixes googleapis#116.
1 parent 6207a6d commit 1e9dcce

File tree

5 files changed

+87
-65
lines changed

5 files changed

+87
-65
lines changed

lib/datastore/dataset.js

+26-9
Original file line numberDiff line numberDiff line change
@@ -54,32 +54,49 @@ var SCOPES = [
5454
* @constructor
5555
* @alias module:datastore/dataset
5656
*
57-
* @param {object} options
58-
* @param {string} options.id - Dataset ID. This is your project ID from the
59-
* Google Developers Console.
57+
* @param {object=} options
58+
* @param {string} options.projectId - Dataset ID. This is your project ID from
59+
* the Google Developers Console.
6060
* @param {string} options.keyFileName - Full path to the JSON key downloaded
6161
* from the Google Developers Console.
62+
* @param {string} options.namespace - Namespace to isolate transactions to.
6263
*
6364
* @example
6465
* ```js
6566
* var dataset = new Dataset({
66-
* id: 'my-project',
67+
* projectId: 'my-project',
6768
* keyFileName: '/path/to/keyfile.json'
6869
* });
6970
* ```
7071
*/
71-
function Dataset(opts) {
72-
opts = opts || {};
73-
var id = opts.projectId;
72+
function Dataset(options) {
73+
options = options || {};
7474

7575
this.connection = new conn.Connection({
76-
keyFilename: opts.keyFilename,
76+
keyFilename: options.keyFilename,
7777
scopes: SCOPES
7878
});
79-
this.id = id;
79+
this.id = options.projectId;
80+
this.ns = options.namespace;
8081
this.transaction = this.createTransaction_();
8182
}
8283

84+
/**
85+
* Helper to create a Key object, scoped to the namespace if present.
86+
*
87+
* @example
88+
* ```js
89+
* var key = dataset.key('Company', 123);
90+
* ```
91+
*/
92+
Dataset.prototype.key = function() {
93+
return new entity.Key({
94+
namespace: this.ns,
95+
path: [].slice.call(arguments)
96+
});
97+
};
98+
99+
83100
/**
84101
* Create a query from the current dataset to query the specified kinds.
85102
*

lib/datastore/entity.js

+19-20
Original file line numberDiff line numberDiff line change
@@ -89,18 +89,22 @@ var SIGN_TO_ORDER = {
8989
* Build a Datastore Key object.
9090
*
9191
* @constructor
92-
* @param {...*} - Key descriptors.
92+
* @param {object} - Configuration object.
93+
* @param {...*} options.path - Key path.
94+
* @param {string=} options.namespace - Optional namespace.
9395
*
9496
* @example
9597
* ```js
9698
* var key = new Key('Company', 123);
9799
* ```
98100
*/
99-
function Key() {
100-
if (arguments.length > 1) {
101-
this.path_ = [].slice.call(arguments);
101+
function Key(options) {
102+
this.namespace_ = options.namespace;
103+
104+
if (options.path.length > 1) {
105+
this.path_ = [].slice.call(options.path);
102106
} else {
103-
this.path_ = arguments[0];
107+
this.path_ = options.path[0];
104108
}
105109
}
106110

@@ -220,15 +224,17 @@ module.exports.entityFromEntityProto = entityFromEntityProto;
220224
* ```
221225
*/
222226
function keyFromKeyProto(proto) {
223-
var keyPath = [];
227+
var keyOptions = {
228+
path: []
229+
};
224230
if (proto.partition_id && proto.partition_id.namespace) {
225-
keyPath.push(proto.partition_id.namespace);
231+
keyOptions.namespace = proto.partition_id.namespace;
226232
}
227233
proto.path_element.forEach(function(path) {
228-
keyPath.push(path.kind);
229-
keyPath.push(Number(path.id) || path.name || null);
234+
keyOptions.path.push(path.kind);
235+
keyOptions.path.push(Number(path.id) || path.name || null);
230236
});
231-
return new Key(keyPath);
237+
return new Key(keyOptions);
232238
}
233239

234240
module.exports.keyFromKeyProto = keyFromKeyProto;
@@ -261,15 +267,8 @@ function keyToKeyProto(key) {
261267
if (keyPath.length < 2) {
262268
throw new Error('A key should contain at least a kind and an identifier.');
263269
}
264-
var namespace = null;
265-
var start = 0;
266-
if (keyPath.length % 2 === 1) {
267-
// the first item is the namespace
268-
namespace = keyPath[0];
269-
start = 1;
270-
}
271270
var path = [];
272-
for (var i = start; i < (keyPath.length - start); i += 2) {
271+
for (var i = 0; i < keyPath.length; i += 2) {
273272
var p = { kind: keyPath[i] };
274273
var val = keyPath[i+1];
275274
if (val) {
@@ -285,9 +284,9 @@ function keyToKeyProto(key) {
285284
var proto = {
286285
path_element: path
287286
};
288-
if (namespace) {
287+
if (key.namespace_) {
289288
proto.partition_id = {
290-
namespace: namespace
289+
namespace: key.namespace_
291290
};
292291
}
293292
return proto;

lib/datastore/index.js

-12
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,6 @@ var datastore = {};
3636
*/
3737
datastore.Dataset = require('./dataset');
3838

39-
/**
40-
* @borrows {module:datastore/entity~Key} as key
41-
*
42-
* @example
43-
* ```js
44-
* var key = dataset.key('Company', 123);
45-
* ```
46-
*/
47-
datastore.key = function() {
48-
return new entity.Key([].slice.call(arguments));
49-
};
50-
5139
/**
5240
* @borrows {module:datastore/entity~Int} as int
5341
*

test/datastore/dataset.js

+11-11
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ describe('Dataset', function() {
3232
assert.equal(proto.key.length, 1);
3333
callback(null, mockRespGet);
3434
};
35-
ds.get(datastore.key('Kind', 123), function(err, entity) {
35+
ds.get(ds.key('Kind', 123), function(err, entity) {
3636
var data = entity.data;
3737
assert.deepEqual(entity.key.path_, ['Kind', 5732568548769792]);
3838
assert.strictEqual(data.author, 'Silvano');
@@ -49,7 +49,7 @@ describe('Dataset', function() {
4949
assert.equal(proto.key.length, 1);
5050
callback(null, mockRespGet);
5151
};
52-
var key = datastore.key('Kind', 5732568548769792);
52+
var key = ds.key('Kind', 5732568548769792);
5353
ds.get([key], function(err, entities) {
5454
var entity = entities[0];
5555
var data = entity.data;
@@ -68,7 +68,7 @@ describe('Dataset', function() {
6868
assert.equal(!!proto.mutation.delete, true);
6969
callback();
7070
};
71-
ds.delete(datastore.key('Kind', 123), done);
71+
ds.delete(ds.key('Kind', 123), done);
7272
});
7373

7474
it('should multi delete by keys', function(done) {
@@ -79,8 +79,8 @@ describe('Dataset', function() {
7979
callback();
8080
};
8181
ds.delete([
82-
datastore.key('Kind', 123),
83-
datastore.key('Kind', 345)
82+
ds.key('Kind', 123),
83+
ds.key('Kind', 345)
8484
], done);
8585
});
8686

@@ -91,7 +91,7 @@ describe('Dataset', function() {
9191
assert.equal(proto.mutation.insert_auto_id.length, 1);
9292
callback();
9393
};
94-
var key = datastore.key('Kind', null);
94+
var key = ds.key('Kind', null);
9595
ds.save({ key: key, data: {} }, done);
9696
});
9797

@@ -106,8 +106,8 @@ describe('Dataset', function() {
106106
callback();
107107
};
108108
ds.save([
109-
{ key: datastore.key('Kind', 123), data: { k: 'v' } },
110-
{ key: datastore.key('Kind', 456), data: { k: 'v' } }
109+
{ key: ds.key('Kind', 123), data: { k: 'v' } },
110+
{ key: ds.key('Kind', 456), data: { k: 'v' } }
111111
], done);
112112
});
113113

@@ -126,16 +126,16 @@ describe('Dataset', function() {
126126
]
127127
});
128128
};
129-
ds.allocateIds(datastore.key('Kind', null), 1, function(err, ids) {
130-
assert.deepEqual(ids[0], datastore.key('Kind', 123));
129+
ds.allocateIds(ds.key('Kind', null), 1, function(err, ids) {
130+
assert.deepEqual(ids[0], ds.key('Kind', 123));
131131
done();
132132
});
133133
});
134134

135135
it('should throw if trying to allocate IDs with complete keys', function() {
136136
var ds = new datastore.Dataset({ projectId: 'test' });
137137
assert.throws(function() {
138-
ds.allocateIds(datastore.key('Kind', 123));
138+
ds.allocateIds(ds.key('Kind', 123));
139139
});
140140
});
141141

test/datastore/entity.js

+31-13
Original file line numberDiff line numberDiff line change
@@ -159,26 +159,32 @@ describe('keyFromKeyProto', function() {
159159

160160
it('should handle keys hierarchically', function(done) {
161161
var key = entity.keyFromKeyProto(protoH);
162-
assert.deepEqual(key, datastore.key('Test', 'Kind', 111, 'Kind2', 'name'));
162+
assert.deepEqual(key, new entity.Key({
163+
namespace: 'Test',
164+
path: [ 'Kind', 111, 'Kind2', 'name' ]
165+
}));
163166
done();
164167
});
165168

166169
it('should handle incomplete keys hierarchically', function(done) {
167170
var key = entity.keyFromKeyProto(protoHIncomplete);
168-
assert.deepEqual(key, datastore.key('Test', 'Kind', null, 'Kind2', null));
171+
assert.deepEqual(key, new entity.Key({
172+
namespace: 'Test',
173+
path: [ 'Kind', null, 'Kind2', null ]
174+
}));
169175
done();
170176
});
171177

172178
it('should not set namespace if default', function(done) {
173179
var key = entity.keyFromKeyProto(proto);
174-
assert.deepEqual(key, datastore.key('Kind', 'Name'));
180+
assert.deepEqual(key, new entity.Key({ path: [ 'Kind', 'Name' ] }));
175181
done();
176182
});
177183
});
178184

179185
describe('keyToKeyProto', function() {
180186
it('should handle hierarchical key definitions', function(done) {
181-
var key = datastore.key('Kind1', 1, 'Kind2', 'name');
187+
var key = new entity.Key({ path: [ 'Kind1', 1, 'Kind2', 'name' ] });
182188
var proto = entity.keyToKeyProto(key);
183189
assert.strictEqual(proto.partition_id, undefined);
184190
assert.strictEqual(proto.path_element[0].kind, 'Kind1');
@@ -191,7 +197,10 @@ describe('keyToKeyProto', function() {
191197
});
192198

193199
it('should detect the namespace of the hierarchical keys', function(done) {
194-
var key = datastore.key('Namespace', 'Kind1', 1, 'Kind2', 'name');
200+
var key = new entity.Key({
201+
namespace: 'Namespace',
202+
path: [ 'Kind1', 1, 'Kind2', 'name' ]
203+
});
195204
var proto = entity.keyToKeyProto(key);
196205
assert.strictEqual(proto.partition_id.namespace, 'Namespace');
197206
assert.strictEqual(proto.path_element[0].kind, 'Kind1');
@@ -204,8 +213,11 @@ describe('keyToKeyProto', function() {
204213
});
205214

206215
it('should handle incomplete keys with & without namespaces', function(done) {
207-
var key = datastore.key('Kind1', null);
208-
var keyWithNS = datastore.key('Namespace', 'Kind1', null);
216+
var key = new entity.Key({ path: [ 'Kind1', null ] });
217+
var keyWithNS = new entity.Key({
218+
namespace: 'Namespace',
219+
path: [ 'Kind1', null ]
220+
});
209221

210222
var proto = entity.keyToKeyProto(key);
211223
var protoWithNS = entity.keyToKeyProto(keyWithNS);
@@ -232,10 +244,16 @@ describe('keyToKeyProto', function() {
232244
describe('isKeyComplete', function() {
233245
it('should ret true if kind and an identifier have !0 vals', function(done) {
234246
[
235-
{ key: datastore.key('Kind1', null), expected: false },
236-
{ key: datastore.key('Kind1', 3), expected: true },
237-
{ key: datastore.key('Namespace', 'Kind1', null), expected: false },
238-
{ key: datastore.key('Namespace', 'Kind1', 'name'), expected: true }
247+
{ key: new entity.Key({ path: [ 'Kind1', null ] }), expected: false },
248+
{ key: new entity.Key({ path: [ 'Kind1', 3 ] }), expected: true },
249+
{ key: new entity.Key({
250+
namespace: 'Namespace',
251+
path: [ 'Kind1', null ]
252+
}), expected: false },
253+
{ key: new entity.Key({
254+
namespace: 'Namespace',
255+
path: [ 'Kind1', 'name' ]
256+
}), expected: true }
239257
].forEach(function(test) {
240258
assert.strictEqual(entity.isKeyComplete(test.key), test.expected);
241259
});
@@ -247,7 +265,7 @@ describe('entityFromEntityProto', function() {
247265
it('should support boolean, integer, double, string, entity and list values',
248266
function(done) {
249267
var obj = entity.entityFromEntityProto(entityProto);
250-
assert.deepEqual(obj.linkedTo, datastore.key('Kind', 'another'));
268+
assert.deepEqual(obj.linkedTo, new entity.Key({ path: [ 'Kind', 'another' ] }));
251269
assert.strictEqual(obj.name, 'Some name');
252270
assert.strictEqual(obj.flagged, false);
253271
assert.strictEqual(obj.count, 5);
@@ -305,7 +323,7 @@ describe('queryToQueryProto', function() {
305323
var ds = new datastore.Dataset({ projectId: 'project-id' });
306324
var q = ds.createQuery('Kind1')
307325
.filter('name =', 'John')
308-
.hasAncestor(datastore.key('Kind2', 'somename'));
326+
.hasAncestor(new entity.Key({ path: [ 'Kind2', 'somename' ] }));
309327
var proto = entity.queryToQueryProto(q);
310328
assert.deepEqual(proto, queryFilterProto);
311329
done();

0 commit comments

Comments
 (0)