sharedb 5.0.1 → 5.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client/doc.js CHANGED
@@ -295,7 +295,7 @@ Doc.prototype._handleFetch = function(error, snapshot) {
295
295
  var callbacks = this.pendingFetch;
296
296
  this.pendingFetch = [];
297
297
  var callback = this.inflightFetch.shift();
298
- if (callback) callbacks.push(callback);
298
+ if (callback) callbacks.unshift(callback);
299
299
  if (callbacks.length) {
300
300
  callback = function(error) {
301
301
  util.callEach(callbacks, error);
@@ -110,7 +110,7 @@ SubmitRequest.prototype.submit = function(callback) {
110
110
  // must get the past ops and check their src and seq values to
111
111
  // differentiate.
112
112
  request._fetchCreateOpVersion(function(error, version) {
113
- if (err) return callback(err);
113
+ if (error) return callback(error);
114
114
  if (version == null) {
115
115
  callback(request.alreadyCreatedError());
116
116
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sharedb",
3
- "version": "5.0.1",
3
+ "version": "5.0.3",
4
4
  "description": "JSON OT database backend",
5
5
  "main": "lib/index.js",
6
6
  "dependencies": {
@@ -101,6 +101,27 @@ describe('Doc', function() {
101
101
  doc.fetch(finish);
102
102
  doc.fetch(finish);
103
103
  });
104
+ it('callbacks called in correct order when fetching and applying ops in quick succession', function(done) {
105
+ var connection = this.connection;
106
+ var doc = connection.get('dogs', 'fido');
107
+ doc.create({name: 'fido'});
108
+ var order = '';
109
+ doc.fetch(function() {
110
+ order += 'A';
111
+ });
112
+ doc.submitOp([{p: ['snacks'], oi: true}]);
113
+ doc.fetch(function() {
114
+ order += 'B';
115
+ });
116
+ doc.submitOp([{p: ['color'], oi: 'gray'}]);
117
+ doc.fetch(function() {
118
+ order += 'C';
119
+ });
120
+ doc.whenNothingPending(function() {
121
+ expect(order).to.eql('ABC');
122
+ done();
123
+ });
124
+ });
104
125
  });
105
126
 
106
127
  describe('when connection closed', function() {
@@ -172,5 +172,43 @@ module.exports = function(options) {
172
172
  });
173
173
  });
174
174
  });
175
+
176
+ it('snapshot fetch from query does not advance version of doc with pending ops', function(done) {
177
+ var backend = this.backend;
178
+ backend.connect(null, null, function(connection1) {
179
+ backend.connect(null, null, function(connection2) {
180
+ var doc = connection1.get('dogs', 'fido');
181
+ var doc2 = connection2.get('dogs', 'fido');
182
+ doc.create({name: 'kido'}, function(err) {
183
+ if (err) return done(err);
184
+ doc2.fetch(function(err) {
185
+ if (err) return done(err);
186
+ doc2.submitOp({p: ['name', 0], si: 'f'}, function(err) {
187
+ if (err) return done(err);
188
+ expect(doc2.data).eql({name: 'fkido'});
189
+ doc.connection.createFetchQuery('dogs', {}, null, function(err) {
190
+ if (err) return done(err);
191
+ doc.resume();
192
+ });
193
+ });
194
+ });
195
+ });
196
+ process.nextTick(function() {
197
+ doc.pause();
198
+ doc.submitOp({p: ['name', 0], sd: 'k'}, function(err) {
199
+ if (err) return done(err);
200
+ doc.pause();
201
+ doc2.fetch(function(err) {
202
+ if (err) return done(err);
203
+ expect(doc2.version).equal(3);
204
+ expect(doc2.data).eql({name: 'fido'});
205
+ done();
206
+ });
207
+ });
208
+ doc.del();
209
+ });
210
+ });
211
+ });
212
+ });
175
213
  });
176
214
  };
@@ -6,7 +6,6 @@ var deserializedType = require('./deserialized-type');
6
6
  var numberType = require('./number-type');
7
7
  var errorHandler = require('../util').errorHandler;
8
8
  var richText = require('rich-text');
9
- var MemoryDB = require('../../lib/db/memory');
10
9
  types.register(deserializedType.type);
11
10
  types.register(deserializedType.type2);
12
11
  types.register(numberType.type);
@@ -14,8 +13,15 @@ types.register(richText.type);
14
13
 
15
14
  module.exports = function() {
16
15
  describe('client submit', function() {
16
+ var id;
17
+ var idCount = 0;
18
+
19
+ beforeEach(function() {
20
+ id = 'dog-' + idCount++;
21
+ });
22
+
17
23
  it('can fetch an uncreated doc', function(done) {
18
- var doc = this.backend.connect().get('dogs', 'fido');
24
+ var doc = this.backend.connect().get('dogs', id);
19
25
  expect(doc.data).equal(undefined);
20
26
  expect(doc.version).equal(null);
21
27
  doc.fetch(function(err) {
@@ -27,7 +33,7 @@ module.exports = function() {
27
33
  });
28
34
 
29
35
  it('can fetch then create a new doc', function(done) {
30
- var doc = this.backend.connect().get('dogs', 'fido');
36
+ var doc = this.backend.connect().get('dogs', id);
31
37
  doc.fetch(function(err) {
32
38
  if (err) return done(err);
33
39
  doc.create({age: 3}, function(err) {
@@ -40,7 +46,7 @@ module.exports = function() {
40
46
  });
41
47
 
42
48
  it('can create a new doc without fetching', function(done) {
43
- var doc = this.backend.connect().get('dogs', 'fido');
49
+ var doc = this.backend.connect().get('dogs', id);
44
50
  doc.create({age: 3}, function(err) {
45
51
  if (err) return done(err);
46
52
  expect(doc.data).eql({age: 3});
@@ -55,7 +61,7 @@ module.exports = function() {
55
61
  foo: 'bar'
56
62
  };
57
63
  var getSnapshotSpy = sinon.spy(this.backend.db, 'getSnapshot');
58
- connection.get('dogs', 'fido').create({age: 3}, function(err) {
64
+ connection.get('dogs', id).create({age: 3}, function(err) {
59
65
  if (err) return done(err);
60
66
  expect(getSnapshotSpy.firstCall.args[3]).to.haveOwnProperty('agentCustom').that.deep.equals({foo: 'bar'});
61
67
  done();
@@ -63,7 +69,7 @@ module.exports = function() {
63
69
  });
64
70
 
65
71
  it('can create then delete then create a doc', function(done) {
66
- var doc = this.backend.connect().get('dogs', 'fido');
72
+ var doc = this.backend.connect().get('dogs', id);
67
73
  doc.create({age: 3}, function(err) {
68
74
  if (err) return done(err);
69
75
  expect(doc.data).eql({age: 3});
@@ -85,7 +91,7 @@ module.exports = function() {
85
91
  });
86
92
 
87
93
  it('can create then submit an op', function(done) {
88
- var doc = this.backend.connect().get('dogs', 'fido');
94
+ var doc = this.backend.connect().get('dogs', id);
89
95
  doc.create({age: 3}, function(err) {
90
96
  if (err) return done(err);
91
97
  doc.submitOp({p: ['age'], na: 2}, function(err) {
@@ -98,7 +104,7 @@ module.exports = function() {
98
104
  });
99
105
 
100
106
  it('can create then submit an op sync', function(done) {
101
- var doc = this.backend.connect().get('dogs', 'fido');
107
+ var doc = this.backend.connect().get('dogs', id);
102
108
  doc.create({age: 3});
103
109
  expect(doc.data).eql({age: 3});
104
110
  expect(doc.version).eql(null);
@@ -109,7 +115,7 @@ module.exports = function() {
109
115
  });
110
116
 
111
117
  it('submitting an op from a future version fails', function(done) {
112
- var doc = this.backend.connect().get('dogs', 'fido');
118
+ var doc = this.backend.connect().get('dogs', id);
113
119
  doc.create({age: 3}, function(err) {
114
120
  if (err) return done(err);
115
121
  doc.version++;
@@ -121,7 +127,7 @@ module.exports = function() {
121
127
  });
122
128
 
123
129
  it('cannot submit op on an uncreated doc', function(done) {
124
- var doc = this.backend.connect().get('dogs', 'fido');
130
+ var doc = this.backend.connect().get('dogs', id);
125
131
  doc.submitOp({p: ['age'], na: 2}, function(err) {
126
132
  expect(err).instanceOf(Error);
127
133
  done();
@@ -129,7 +135,7 @@ module.exports = function() {
129
135
  });
130
136
 
131
137
  it('cannot delete an uncreated doc', function(done) {
132
- var doc = this.backend.connect().get('dogs', 'fido');
138
+ var doc = this.backend.connect().get('dogs', id);
133
139
  doc.del(function(err) {
134
140
  expect(err).instanceOf(Error);
135
141
  done();
@@ -137,7 +143,7 @@ module.exports = function() {
137
143
  });
138
144
 
139
145
  it('ops submitted sync get composed', function(done) {
140
- var doc = this.backend.connect().get('dogs', 'fido');
146
+ var doc = this.backend.connect().get('dogs', id);
141
147
  doc.create({age: 3});
142
148
  doc.submitOp({p: ['age'], na: 2});
143
149
  doc.submitOp({p: ['age'], na: 2}, function(err) {
@@ -164,7 +170,7 @@ module.exports = function() {
164
170
  });
165
171
 
166
172
  it('does not compose ops when doc.preventCompose is true', function(done) {
167
- var doc = this.backend.connect().get('dogs', 'fido');
173
+ var doc = this.backend.connect().get('dogs', id);
168
174
  doc.preventCompose = true;
169
175
  doc.create({age: 3});
170
176
  doc.submitOp({p: ['age'], na: 2});
@@ -185,7 +191,7 @@ module.exports = function() {
185
191
  });
186
192
 
187
193
  it('resumes composing after doc.preventCompose is set back to false', function(done) {
188
- var doc = this.backend.connect().get('dogs', 'fido');
194
+ var doc = this.backend.connect().get('dogs', id);
189
195
  doc.preventCompose = true;
190
196
  doc.create({age: 3});
191
197
  doc.submitOp({p: ['age'], na: 2});
@@ -215,8 +221,8 @@ module.exports = function() {
215
221
 
216
222
  describe('no snapshot metadata available', function() {
217
223
  beforeEach(function() {
218
- var getSnapshot = MemoryDB.prototype.getSnapshot;
219
- sinon.stub(MemoryDB.prototype, 'getSnapshot')
224
+ var getSnapshot = this.backend.db.getSnapshot;
225
+ sinon.stub(this.backend.db, 'getSnapshot')
220
226
  .callsFake(function() {
221
227
  var args = Array.from(arguments);
222
228
  var callback = args.pop();
@@ -233,11 +239,32 @@ module.exports = function() {
233
239
  });
234
240
 
235
241
  runCreateTests();
242
+
243
+ it('returns errors if the database cannot get committed op version', function(done) {
244
+ sinon.stub(this.backend.db, 'getCommittedOpVersion')
245
+ .callsFake(function() {
246
+ var args = Array.from(arguments);
247
+ var callback = args.pop();
248
+ callback(new Error('uh-oh'));
249
+ });
250
+
251
+ var doc1 = this.backend.connect().get('dogs', 'fido');
252
+ var doc2 = this.backend.connect().get('dogs', 'fido');
253
+ async.series([
254
+ doc1.create.bind(doc1, {age: 3}),
255
+ function(next) {
256
+ doc2.create({name: 'Fido'}, function(error) {
257
+ expect(error.message).to.equal('uh-oh');
258
+ next();
259
+ });
260
+ }
261
+ ], done);
262
+ });
236
263
  });
237
264
 
238
265
  function runCreateTests() {
239
266
  it('can create a new doc then fetch', function(done) {
240
- var doc = this.backend.connect().get('dogs', 'fido');
267
+ var doc = this.backend.connect().get('dogs', id);
241
268
  doc.create({age: 3}, function(err) {
242
269
  if (err) return done(err);
243
270
  doc.fetch(function(err) {
@@ -250,7 +277,7 @@ module.exports = function() {
250
277
  });
251
278
 
252
279
  it('calling create on the same doc twice fails', function(done) {
253
- var doc = this.backend.connect().get('dogs', 'fido');
280
+ var doc = this.backend.connect().get('dogs', id);
254
281
  doc.create({age: 3}, function(err) {
255
282
  if (err) return done(err);
256
283
  doc.create({age: 4}, function(err) {
@@ -263,8 +290,8 @@ module.exports = function() {
263
290
  });
264
291
 
265
292
  it('trying to create an already created doc without fetching fails and fetches', function(done) {
266
- var doc = this.backend.connect().get('dogs', 'fido');
267
- var doc2 = this.backend.connect().get('dogs', 'fido');
293
+ var doc = this.backend.connect().get('dogs', id);
294
+ var doc2 = this.backend.connect().get('dogs', id);
268
295
  doc.create({age: 3}, function(err) {
269
296
  if (err) return done(err);
270
297
  doc2.create({age: 4}, function(err) {
@@ -289,19 +316,23 @@ module.exports = function() {
289
316
  next();
290
317
  });
291
318
 
292
- var doc = connection.get('dogs', 'fido');
293
- doc.create({age: 3}, function(error) {
294
- expect(doc.version).to.equal(1);
295
- done(error);
319
+ var count = 0;
320
+ backend.use('reply', function(message, next) {
321
+ next();
322
+ if (message.reply.a === 'op') count++;
323
+ if (count === 2) done();
296
324
  });
325
+
326
+ var doc = connection.get('dogs', id);
327
+ doc.create({age: 10}, errorHandler(done));
297
328
  });
298
329
 
299
330
  it('does not fail when resubmitting a create op on a doc that was deleted', function(done) {
300
331
  var backend = this.backend;
301
332
  var connection1 = backend.connect();
302
333
  var connection2 = backend.connect();
303
- var doc1 = connection1.get('dogs', 'fido');
304
- var doc2 = connection2.get('dogs', 'fido');
334
+ var doc1 = connection1.get('dogs', id);
335
+ var doc2 = connection2.get('dogs', id);
305
336
 
306
337
  async.series([
307
338
  doc1.create.bind(doc1, {age: 3}),
@@ -328,8 +359,8 @@ module.exports = function() {
328
359
  });
329
360
 
330
361
  it('server fetches and transforms by already committed op', function(done) {
331
- var doc = this.backend.connect().get('dogs', 'fido');
332
- var doc2 = this.backend.connect().get('dogs', 'fido');
362
+ var doc = this.backend.connect().get('dogs', id);
363
+ var doc2 = this.backend.connect().get('dogs', id);
333
364
  doc.create({age: 3}, function(err) {
334
365
  if (err) return done(err);
335
366
  doc2.fetch(function(err) {
@@ -351,8 +382,8 @@ module.exports = function() {
351
382
  this.backend.db.getOpsToSnapshot = function(collection, id, from, snapshot, options, callback) {
352
383
  callback(null, []);
353
384
  };
354
- var doc = this.backend.connect().get('dogs', 'fido');
355
- var doc2 = this.backend.connect().get('dogs', 'fido');
385
+ var doc = this.backend.connect().get('dogs', id);
386
+ var doc2 = this.backend.connect().get('dogs', id);
356
387
  doc.create({age: 3}, function(err) {
357
388
  if (err) return done(err);
358
389
  doc2.fetch(function(err) {
@@ -376,8 +407,8 @@ module.exports = function() {
376
407
  callback(null, ops);
377
408
  });
378
409
  };
379
- var doc = this.backend.connect().get('dogs', 'fido');
380
- var doc2 = this.backend.connect().get('dogs', 'fido');
410
+ var doc = this.backend.connect().get('dogs', id);
411
+ var doc2 = this.backend.connect().get('dogs', id);
381
412
  doc.create({age: 3}, function(err) {
382
413
  if (err) return done(err);
383
414
  doc2.fetch(function(err) {
@@ -407,7 +438,7 @@ module.exports = function() {
407
438
 
408
439
  it('resends create when disconnected before ack', function(done) {
409
440
  var backend = this.backend;
410
- var doc = backend.connect().get('dogs', 'fido');
441
+ var doc = backend.connect().get('dogs', id);
411
442
  doc.create({age: 3}, function(err) {
412
443
  if (err) return done(err);
413
444
  expect(doc.version).equal(1);
@@ -419,13 +450,13 @@ module.exports = function() {
419
450
 
420
451
  it('resent create on top of deleted doc gets proper starting version', function(done) {
421
452
  var backend = this.backend;
422
- var doc = backend.connect().get('dogs', 'fido');
453
+ var doc = backend.connect().get('dogs', id);
423
454
  doc.create({age: 4}, function(err) {
424
455
  if (err) return done(err);
425
456
  doc.del(function(err) {
426
457
  if (err) return done(err);
427
458
 
428
- var doc2 = backend.connect().get('dogs', 'fido');
459
+ var doc2 = backend.connect().get('dogs', id);
429
460
  doc2.create({age: 3}, function(err) {
430
461
  if (err) return done(err);
431
462
  expect(doc2.version).equal(3);
@@ -439,7 +470,7 @@ module.exports = function() {
439
470
 
440
471
  it('resends delete when disconnected before ack', function(done) {
441
472
  var backend = this.backend;
442
- var doc = backend.connect().get('dogs', 'fido');
473
+ var doc = backend.connect().get('dogs', id);
443
474
  doc.create({age: 3}, function(err) {
444
475
  if (err) return done(err);
445
476
  doc.del(function(err) {
@@ -454,7 +485,7 @@ module.exports = function() {
454
485
 
455
486
  it('op submitted during inflight create does not compose and gets flushed', function(done) {
456
487
  this.backend.connect(null, null, function(connection) {
457
- var doc = connection.get('dogs', 'fido');
488
+ var doc = connection.get('dogs', id);
458
489
  doc.create({age: 3});
459
490
  // Submit an op after message is sent but before server has a chance to reply
460
491
  process.nextTick(function() {
@@ -469,8 +500,8 @@ module.exports = function() {
469
500
  });
470
501
 
471
502
  it('can commit then fetch in a new connection to get the same data', function(done) {
472
- var doc = this.backend.connect().get('dogs', 'fido');
473
- var doc2 = this.backend.connect().get('dogs', 'fido');
503
+ var doc = this.backend.connect().get('dogs', id);
504
+ var doc2 = this.backend.connect().get('dogs', id);
474
505
  doc.create({age: 3}, function(err) {
475
506
  if (err) return done(err);
476
507
  doc2.fetch(function(err) {
@@ -486,8 +517,8 @@ module.exports = function() {
486
517
  });
487
518
 
488
519
  it('an op submitted concurrently is transformed by the first', function(done) {
489
- var doc = this.backend.connect().get('dogs', 'fido');
490
- var doc2 = this.backend.connect().get('dogs', 'fido');
520
+ var doc = this.backend.connect().get('dogs', id);
521
+ var doc2 = this.backend.connect().get('dogs', id);
491
522
  doc.create({age: 3}, function(err) {
492
523
  if (err) return done(err);
493
524
  doc2.fetch(function(err) {
@@ -522,8 +553,8 @@ module.exports = function() {
522
553
  });
523
554
 
524
555
  it('second of two concurrent creates is rejected', function(done) {
525
- var doc = this.backend.connect().get('dogs', 'fido');
526
- var doc2 = this.backend.connect().get('dogs', 'fido');
556
+ var doc = this.backend.connect().get('dogs', id);
557
+ var doc2 = this.backend.connect().get('dogs', id);
527
558
  var count = 0;
528
559
  doc.create({age: 3}, function(err) {
529
560
  count++;
@@ -554,8 +585,8 @@ module.exports = function() {
554
585
  });
555
586
 
556
587
  it('concurrent delete operations transform', function(done) {
557
- var doc = this.backend.connect().get('dogs', 'fido');
558
- var doc2 = this.backend.connect().get('dogs', 'fido');
588
+ var doc = this.backend.connect().get('dogs', id);
589
+ var doc2 = this.backend.connect().get('dogs', id);
559
590
  doc.create({age: 3}, function(err) {
560
591
  if (err) return done(err);
561
592
  doc2.fetch(function(err) {
@@ -591,8 +622,8 @@ module.exports = function() {
591
622
 
592
623
  it('submits retry below the backend.maxSubmitRetries threshold', function(done) {
593
624
  this.backend.maxSubmitRetries = 10;
594
- var doc = this.backend.connect().get('dogs', 'fido');
595
- var doc2 = this.backend.connect().get('dogs', 'fido');
625
+ var doc = this.backend.connect().get('dogs', id);
626
+ var doc2 = this.backend.connect().get('dogs', id);
596
627
  doc.create({age: 3}, function(err) {
597
628
  if (err) return done(err);
598
629
  doc2.fetch(function(err) {
@@ -612,8 +643,8 @@ module.exports = function() {
612
643
  it('submits fail above the backend.maxSubmitRetries threshold', function(done) {
613
644
  var backend = this.backend;
614
645
  this.backend.maxSubmitRetries = 0;
615
- var doc = this.backend.connect().get('dogs', 'fido');
616
- var doc2 = this.backend.connect().get('dogs', 'fido');
646
+ var doc = this.backend.connect().get('dogs', id);
647
+ var doc2 = this.backend.connect().get('dogs', id);
617
648
  doc.create({age: 3}, function(err) {
618
649
  if (err) return done(err);
619
650
  doc2.fetch(function(err) {
@@ -653,8 +684,8 @@ module.exports = function() {
653
684
  });
654
685
 
655
686
  it('pending delete transforms incoming ops', function(done) {
656
- var doc = this.backend.connect().get('dogs', 'fido');
657
- var doc2 = this.backend.connect().get('dogs', 'fido');
687
+ var doc = this.backend.connect().get('dogs', id);
688
+ var doc2 = this.backend.connect().get('dogs', id);
658
689
  doc.create({age: 3}, function(err) {
659
690
  if (err) return done(err);
660
691
  doc2.fetch(function(err) {
@@ -680,8 +711,8 @@ module.exports = function() {
680
711
  });
681
712
 
682
713
  it('pending delete transforms incoming delete', function(done) {
683
- var doc = this.backend.connect().get('dogs', 'fido');
684
- var doc2 = this.backend.connect().get('dogs', 'fido');
714
+ var doc = this.backend.connect().get('dogs', id);
715
+ var doc2 = this.backend.connect().get('dogs', id);
685
716
  doc.create({age: 3}, function(err) {
686
717
  if (err) return done(err);
687
718
  doc2.fetch(function(err) {
@@ -707,8 +738,8 @@ module.exports = function() {
707
738
  });
708
739
 
709
740
  it('submitting op after delete returns error', function(done) {
710
- var doc = this.backend.connect().get('dogs', 'fido');
711
- var doc2 = this.backend.connect().get('dogs', 'fido');
741
+ var doc = this.backend.connect().get('dogs', id);
742
+ var doc2 = this.backend.connect().get('dogs', id);
712
743
  doc.create({age: 3}, function(err) {
713
744
  if (err) return done(err);
714
745
  doc2.fetch(function(err) {
@@ -727,8 +758,8 @@ module.exports = function() {
727
758
  });
728
759
 
729
760
  it('transforming pending op by server delete returns error', function(done) {
730
- var doc = this.backend.connect().get('dogs', 'fido');
731
- var doc2 = this.backend.connect().get('dogs', 'fido');
761
+ var doc = this.backend.connect().get('dogs', id);
762
+ var doc2 = this.backend.connect().get('dogs', id);
732
763
  doc.create({age: 3}, function(err) {
733
764
  if (err) return done(err);
734
765
  doc2.fetch(function(err) {
@@ -749,8 +780,8 @@ module.exports = function() {
749
780
  });
750
781
 
751
782
  it('transforming pending op by server create returns error', function(done) {
752
- var doc = this.backend.connect().get('dogs', 'fido');
753
- var doc2 = this.backend.connect().get('dogs', 'fido');
783
+ var doc = this.backend.connect().get('dogs', id);
784
+ var doc2 = this.backend.connect().get('dogs', id);
754
785
  doc.create({age: 3}, function(err) {
755
786
  if (err) return done(err);
756
787
  doc.del(function(err) {
@@ -774,8 +805,8 @@ module.exports = function() {
774
805
  });
775
806
 
776
807
  it('second client can create following delete', function(done) {
777
- var doc = this.backend.connect().get('dogs', 'fido');
778
- var doc2 = this.backend.connect().get('dogs', 'fido');
808
+ var doc = this.backend.connect().get('dogs', id);
809
+ var doc2 = this.backend.connect().get('dogs', id);
779
810
  doc.create({age: 3}, function(err) {
780
811
  if (err) return done(err);
781
812
  doc.del(function(err) {
@@ -791,28 +822,28 @@ module.exports = function() {
791
822
  });
792
823
 
793
824
  it('doc.pause() prevents ops from being sent', function(done) {
794
- var doc = this.backend.connect().get('dogs', 'fido');
825
+ var doc = this.backend.connect().get('dogs', id);
795
826
  doc.pause();
796
827
  doc.create({age: 3}, done);
797
828
  done();
798
829
  });
799
830
 
800
831
  it('can call doc.resume() without pausing', function(done) {
801
- var doc = this.backend.connect().get('dogs', 'fido');
832
+ var doc = this.backend.connect().get('dogs', id);
802
833
  doc.resume();
803
834
  doc.create({age: 3}, done);
804
835
  });
805
836
 
806
837
  it('doc.resume() resumes sending ops after pause', function(done) {
807
- var doc = this.backend.connect().get('dogs', 'fido');
838
+ var doc = this.backend.connect().get('dogs', id);
808
839
  doc.pause();
809
840
  doc.create({age: 3}, done);
810
841
  doc.resume();
811
842
  });
812
843
 
813
844
  it('pending ops are transformed by ops from other clients', function(done) {
814
- var doc = this.backend.connect().get('dogs', 'fido');
815
- var doc2 = this.backend.connect().get('dogs', 'fido');
845
+ var doc = this.backend.connect().get('dogs', id);
846
+ var doc2 = this.backend.connect().get('dogs', id);
816
847
  doc.create({age: 3}, function(err) {
817
848
  if (err) return done(err);
818
849
  doc2.fetch(function(err) {
@@ -867,7 +898,7 @@ module.exports = function() {
867
898
  });
868
899
 
869
900
  it('snapshot fetch does not revert the version of deleted doc without pending ops', function(done) {
870
- var doc = this.backend.connect().get('dogs', 'fido');
901
+ var doc = this.backend.connect().get('dogs', id);
871
902
  this.backend.use('readSnapshots', function(request, next) {
872
903
  doc.create({age: 3});
873
904
  doc.del(next);
@@ -880,7 +911,7 @@ module.exports = function() {
880
911
  });
881
912
 
882
913
  it('snapshot fetch does not revert the version of deleted doc with pending ops', function(done) {
883
- var doc = this.backend.connect().get('dogs', 'fido');
914
+ var doc = this.backend.connect().get('dogs', id);
884
915
  this.backend.use('readSnapshots', function(request, next) {
885
916
  doc.create({age: 3}, function(err) {
886
917
  if (err) return done(err);
@@ -898,49 +929,11 @@ module.exports = function() {
898
929
  });
899
930
  });
900
931
 
901
- it('snapshot fetch from query does not advance version of doc with pending ops', function(done) {
902
- var backend = this.backend;
903
- backend.connect(null, null, function(connection1) {
904
- backend.connect(null, null, function(connection2) {
905
- var doc = connection1.get('dogs', 'fido');
906
- var doc2 = connection2.get('dogs', 'fido');
907
- doc.create({name: 'kido'}, function(err) {
908
- if (err) return done(err);
909
- doc2.fetch(function(err) {
910
- if (err) return done(err);
911
- doc2.submitOp({p: ['name', 0], si: 'f'}, function(err) {
912
- if (err) return done(err);
913
- expect(doc2.data).eql({name: 'fkido'});
914
- doc.connection.createFetchQuery('dogs', {}, null, function(err) {
915
- if (err) return done(err);
916
- doc.resume();
917
- });
918
- });
919
- });
920
- });
921
- process.nextTick(function() {
922
- doc.pause();
923
- doc.submitOp({p: ['name', 0], sd: 'k'}, function(err) {
924
- if (err) return done(err);
925
- doc.pause();
926
- doc2.fetch(function(err) {
927
- if (err) return done(err);
928
- expect(doc2.version).equal(3);
929
- expect(doc2.data).eql({name: 'fido'});
930
- done();
931
- });
932
- });
933
- doc.del();
934
- });
935
- });
936
- });
937
- });
938
-
939
932
  it('passing an error in submit middleware rejects a create and calls back with the erorr', function(done) {
940
933
  this.backend.use('submit', function(request, next) {
941
934
  next({message: 'Custom error'});
942
935
  });
943
- var doc = this.backend.connect().get('dogs', 'fido');
936
+ var doc = this.backend.connect().get('dogs', id);
944
937
  doc.create({age: 3}, function(err) {
945
938
  expect(err.message).equal('Custom error');
946
939
  expect(doc.version).equal(0);
@@ -955,7 +948,7 @@ module.exports = function() {
955
948
  this.backend.use('submit', function(request, next) {
956
949
  next({message: 'Custom error'});
957
950
  });
958
- var doc = this.backend.connect().get('dogs', 'fido');
951
+ var doc = this.backend.connect().get('dogs', id);
959
952
  doc.create({age: 3});
960
953
  expect(doc.version).equal(null);
961
954
  expect(doc.data).eql({age: 3});
@@ -974,7 +967,7 @@ module.exports = function() {
974
967
  if (submitCount === 1) return next({message: 'Custom error'});
975
968
  next();
976
969
  });
977
- var doc = this.backend.connect().get('dogs', 'fido');
970
+ var doc = this.backend.connect().get('dogs', id);
978
971
  async.parallel([
979
972
  function(cb) {
980
973
  doc.create({age: 3}, function(err) {
@@ -1011,7 +1004,7 @@ module.exports = function() {
1011
1004
  });
1012
1005
 
1013
1006
  var connection = this.backend.connect();
1014
- var doc = connection.get('dogs', 'fido');
1007
+ var doc = connection.get('dogs', id);
1015
1008
  doc.preventCompose = true;
1016
1009
 
1017
1010
  doc.create({age: 3}, function(error) {
@@ -1027,7 +1020,7 @@ module.exports = function() {
1027
1020
  this.backend.use('submit', function(request, next) {
1028
1021
  next(request.rejectedError());
1029
1022
  });
1030
- var doc = this.backend.connect().get('dogs', 'fido');
1023
+ var doc = this.backend.connect().get('dogs', id);
1031
1024
  doc.create({age: 3}, function(err) {
1032
1025
  if (err) return done(err);
1033
1026
  expect(doc.version).equal(0);
@@ -1042,7 +1035,7 @@ module.exports = function() {
1042
1035
  this.backend.use('submit', function(request, next) {
1043
1036
  next(request.rejectedError());
1044
1037
  });
1045
- var doc = this.backend.connect().get('dogs', 'fido');
1038
+ var doc = this.backend.connect().get('dogs', id);
1046
1039
  doc.create({age: 3});
1047
1040
  expect(doc.version).equal(null);
1048
1041
  expect(doc.data).eql({age: 3});
@@ -1063,7 +1056,7 @@ module.exports = function() {
1063
1056
  });
1064
1057
 
1065
1058
  var connection = this.backend.connect();
1066
- var doc = connection.get('dogs', 'fido');
1059
+ var doc = connection.get('dogs', id);
1067
1060
  doc.preventCompose = true;
1068
1061
 
1069
1062
  doc.create({age: 3});
@@ -1081,7 +1074,7 @@ module.exports = function() {
1081
1074
  if ('op' in request.op) return next({message: 'Custom error'});
1082
1075
  next();
1083
1076
  });
1084
- var doc = this.backend.connect().get('dogs', 'fido');
1077
+ var doc = this.backend.connect().get('dogs', id);
1085
1078
  doc.create({age: 3}, function(err) {
1086
1079
  if (err) return done(err);
1087
1080
  doc.submitOp({p: ['age'], na: 1}, function(err) {
@@ -1100,7 +1093,7 @@ module.exports = function() {
1100
1093
  if ('op' in request.op) return next({message: 'Custom error'});
1101
1094
  next();
1102
1095
  });
1103
- var doc = this.backend.connect().get('dogs', 'fido');
1096
+ var doc = this.backend.connect().get('dogs', id);
1104
1097
  doc.create({age: 3}, function(err) {
1105
1098
  if (err) return done(err);
1106
1099
  doc.submitOp({p: ['age'], na: 1});
@@ -1122,7 +1115,7 @@ module.exports = function() {
1122
1115
  if (submitCount === 2) return next({message: 'Custom error'});
1123
1116
  next();
1124
1117
  });
1125
- var doc = this.backend.connect().get('dogs', 'fido');
1118
+ var doc = this.backend.connect().get('dogs', id);
1126
1119
  doc.create({age: 3}, function(err) {
1127
1120
  if (err) return done(err);
1128
1121
  async.parallel([
@@ -1156,7 +1149,7 @@ module.exports = function() {
1156
1149
  if ('op' in request.op) return next(request.rejectedError());
1157
1150
  next();
1158
1151
  });
1159
- var doc = this.backend.connect().get('dogs', 'fido');
1152
+ var doc = this.backend.connect().get('dogs', id);
1160
1153
  doc.create({age: 3}, function(err) {
1161
1154
  if (err) return done(err);
1162
1155
  doc.submitOp({p: ['age'], na: 1}, function(err) {
@@ -1179,7 +1172,7 @@ module.exports = function() {
1179
1172
  }
1180
1173
  next();
1181
1174
  });
1182
- var doc = this.backend.connect().get('dogs', 'fido');
1175
+ var doc = this.backend.connect().get('dogs', id);
1183
1176
  doc.preventCompose = true;
1184
1177
 
1185
1178
  doc.create({age: 3}, function(err) {
@@ -1209,7 +1202,7 @@ module.exports = function() {
1209
1202
  }
1210
1203
  next();
1211
1204
  });
1212
- var doc = this.backend.connect().get('dogs', 'fido');
1205
+ var doc = this.backend.connect().get('dogs', id);
1213
1206
  doc.preventCompose = true;
1214
1207
 
1215
1208
  doc.create({ops: [{insert: 'Scrappy'}]}, 'rich-text', function(err) {
@@ -1234,7 +1227,7 @@ module.exports = function() {
1234
1227
  if ('op' in request.op) return next(request.rejectedError());
1235
1228
  next();
1236
1229
  });
1237
- var doc = this.backend.connect().get('dogs', 'fido');
1230
+ var doc = this.backend.connect().get('dogs', id);
1238
1231
  doc.create({age: 3}, function(err) {
1239
1232
  if (err) return done(err);
1240
1233
  doc.submitOp({p: ['age'], na: 1});
@@ -1253,8 +1246,8 @@ module.exports = function() {
1253
1246
  if (request.op) delete request.op.op;
1254
1247
  next();
1255
1248
  });
1256
- var doc = this.backend.connect().get('dogs', 'fido');
1257
- var doc2 = this.backend.connect().get('dogs', 'fido');
1249
+ var doc = this.backend.connect().get('dogs', id);
1250
+ var doc2 = this.backend.connect().get('dogs', id);
1258
1251
  doc.create({age: 3}, function(err) {
1259
1252
  if (err) return done(err);
1260
1253
  doc.submitOp({p: ['age'], na: 1}, function(err) {
@@ -1274,7 +1267,7 @@ module.exports = function() {
1274
1267
  });
1275
1268
 
1276
1269
  it('submitting an invalid op message returns error', function(done) {
1277
- var doc = this.backend.connect().get('dogs', 'fido');
1270
+ var doc = this.backend.connect().get('dogs', id);
1278
1271
  doc.create({age: 3}, function(err) {
1279
1272
  if (err) return done(err);
1280
1273
  doc._submit({}, null, function(err) {
@@ -1285,7 +1278,7 @@ module.exports = function() {
1285
1278
  });
1286
1279
 
1287
1280
  it('allows snapshot and op to be a non-object', function(done) {
1288
- var doc = this.backend.connect().get('dogs', 'fido');
1281
+ var doc = this.backend.connect().get('dogs', id);
1289
1282
  doc.create(5, numberType.type.uri, function(err) {
1290
1283
  if (err) return done(err);
1291
1284
  expect(doc.data).to.equal(5);
@@ -1299,7 +1292,7 @@ module.exports = function() {
1299
1292
 
1300
1293
  describe('type.deserialize', function() {
1301
1294
  it('can create a new doc', function(done) {
1302
- var doc = this.backend.connect().get('dogs', 'fido');
1295
+ var doc = this.backend.connect().get('dogs', id);
1303
1296
  doc.create([3], deserializedType.type.uri, function(err) {
1304
1297
  if (err) return done(err);
1305
1298
  expect(doc.data).instanceOf(deserializedType.Node);
@@ -1311,10 +1304,10 @@ module.exports = function() {
1311
1304
 
1312
1305
  it('is stored serialized in backend', function(done) {
1313
1306
  var db = this.backend.db;
1314
- var doc = this.backend.connect().get('dogs', 'fido');
1307
+ var doc = this.backend.connect().get('dogs', id);
1315
1308
  doc.create([3], deserializedType.type.uri, function(err) {
1316
1309
  if (err) return done(err);
1317
- db.getSnapshot('dogs', 'fido', null, null, function(err, snapshot) {
1310
+ db.getSnapshot('dogs', id, null, null, function(err, snapshot) {
1318
1311
  if (err) return done(err);
1319
1312
  expect(snapshot.data).eql([3]);
1320
1313
  done();
@@ -1323,8 +1316,8 @@ module.exports = function() {
1323
1316
  });
1324
1317
 
1325
1318
  it('deserializes on fetch', function(done) {
1326
- var doc = this.backend.connect().get('dogs', 'fido');
1327
- var doc2 = this.backend.connect().get('dogs', 'fido');
1319
+ var doc = this.backend.connect().get('dogs', id);
1320
+ var doc2 = this.backend.connect().get('dogs', id);
1328
1321
  doc.create([3], deserializedType.type.uri, function(err) {
1329
1322
  if (err) return done(err);
1330
1323
  doc2.fetch(function(err) {
@@ -1338,7 +1331,7 @@ module.exports = function() {
1338
1331
  });
1339
1332
 
1340
1333
  it('can create then submit an op', function(done) {
1341
- var doc = this.backend.connect().get('dogs', 'fido');
1334
+ var doc = this.backend.connect().get('dogs', id);
1342
1335
  doc.create([3], deserializedType.type.uri, function(err) {
1343
1336
  if (err) return done(err);
1344
1337
  doc.submitOp({insert: 0, value: 2}, function(err) {
@@ -1352,8 +1345,8 @@ module.exports = function() {
1352
1345
  });
1353
1346
 
1354
1347
  it('server fetches and transforms by already committed op', function(done) {
1355
- var doc = this.backend.connect().get('dogs', 'fido');
1356
- var doc2 = this.backend.connect().get('dogs', 'fido');
1348
+ var doc = this.backend.connect().get('dogs', id);
1349
+ var doc2 = this.backend.connect().get('dogs', id);
1357
1350
  doc.create([3], deserializedType.type.uri, function(err) {
1358
1351
  if (err) return done(err);
1359
1352
  doc2.fetch(function(err) {
@@ -1376,7 +1369,7 @@ module.exports = function() {
1376
1369
 
1377
1370
  describe('type.createDeserialized', function() {
1378
1371
  it('can create a new doc', function(done) {
1379
- var doc = this.backend.connect().get('dogs', 'fido');
1372
+ var doc = this.backend.connect().get('dogs', id);
1380
1373
  doc.create([3], deserializedType.type2.uri, function(err) {
1381
1374
  if (err) return done(err);
1382
1375
  expect(doc.data).instanceOf(deserializedType.Node);
@@ -1387,7 +1380,7 @@ module.exports = function() {
1387
1380
  });
1388
1381
 
1389
1382
  it('can create a new doc from deserialized form', function(done) {
1390
- var doc = this.backend.connect().get('dogs', 'fido');
1383
+ var doc = this.backend.connect().get('dogs', id);
1391
1384
  doc.create(new deserializedType.Node(3), deserializedType.type2.uri, function(err) {
1392
1385
  if (err) return done(err);
1393
1386
  expect(doc.data).instanceOf(deserializedType.Node);
@@ -1404,9 +1397,9 @@ module.exports = function() {
1404
1397
 
1405
1398
  beforeEach(function(done) {
1406
1399
  var connection = this.backend.connect();
1407
- doc = connection.get('dogs', 'fido');
1400
+ doc = connection.get('dogs', id);
1408
1401
  var remoteConnection = this.backend.connect();
1409
- remoteDoc = remoteConnection.get('dogs', 'fido');
1402
+ remoteDoc = remoteConnection.get('dogs', id);
1410
1403
 
1411
1404
  async.series([
1412
1405
  doc.create.bind(doc, {name: 'fido'}),
package/test/db.js CHANGED
@@ -61,9 +61,9 @@ module.exports = function(options) {
61
61
  if (options.getQuery) {
62
62
  require('./client/query-subscribe')({getQuery: options.getQuery});
63
63
  require('./client/query')({getQuery: options.getQuery});
64
+ require('./client/projections')({getQuery: options.getQuery});
64
65
  }
65
66
 
66
- require('./client/projections')({getQuery: options.getQuery});
67
67
  require('./client/submit')();
68
68
  require('./client/submit-json1')();
69
69
  require('./client/subscribe')();
@@ -650,111 +650,111 @@ module.exports = function(options) {
650
650
  });
651
651
  });
652
652
 
653
- describe('query', function() {
654
- it('query returns data in the collection', function(done) {
655
- var snapshot = {v: 1, type: 'json0', data: {x: 5, y: 6}, m: null};
656
- var db = this.db;
657
- db.commit('testcollection', 'test', {v: 0, create: {}}, snapshot, null, function(err) {
658
- if (err) return done(err);
659
- db.query('testcollection', {x: 5}, null, null, function(err, results) {
653
+ if (options.getQuery) {
654
+ describe('query', function() {
655
+ it('query returns data in the collection', function(done) {
656
+ var snapshot = {v: 1, type: 'json0', data: {x: 5, y: 6}, m: null};
657
+ var db = this.db;
658
+ db.commit('testcollection', 'test', {v: 0, create: {}}, snapshot, null, function(err) {
660
659
  if (err) return done(err);
661
- delete results[0].id;
662
- expect(results).eql([snapshot]);
663
- done();
660
+ db.query('testcollection', {x: 5}, null, null, function(err, results) {
661
+ if (err) return done(err);
662
+ delete results[0].id;
663
+ expect(results).eql([snapshot]);
664
+ done();
665
+ });
664
666
  });
665
667
  });
666
- });
667
668
 
668
- it('query returns nothing when there is no data', function(done) {
669
- this.db.query('testcollection', {x: 5}, null, null, function(err, results) {
670
- if (err) return done(err);
671
- expect(results).eql([]);
672
- done();
669
+ it('query returns nothing when there is no data', function(done) {
670
+ this.db.query('testcollection', {x: 5}, null, null, function(err, results) {
671
+ if (err) return done(err);
672
+ expect(results).eql([]);
673
+ done();
674
+ });
673
675
  });
674
- });
675
676
 
676
- it('query does not return committed metadata by default', function(done) {
677
- var db = this.db;
678
- commitSnapshotWithMetadata(db, function(err) {
679
- if (err) return done(err);
680
- db.query('testcollection', {x: 5}, null, null, function(err, results) {
677
+ it('query does not return committed metadata by default', function(done) {
678
+ var db = this.db;
679
+ commitSnapshotWithMetadata(db, function(err) {
681
680
  if (err) return done(err);
682
- expect(results[0].m).equal(null);
683
- done();
681
+ db.query('testcollection', {x: 5}, null, null, function(err, results) {
682
+ if (err) return done(err);
683
+ expect(results[0].m).equal(null);
684
+ done();
685
+ });
684
686
  });
685
687
  });
686
- });
687
688
 
688
- it('query returns metadata when option is true', function(done) {
689
- var db = this.db;
690
- commitSnapshotWithMetadata(db, function(err) {
691
- if (err) return done(err);
692
- db.query('testcollection', {x: 5}, null, {metadata: true}, function(err, results) {
689
+ it('query returns metadata when option is true', function(done) {
690
+ var db = this.db;
691
+ commitSnapshotWithMetadata(db, function(err) {
693
692
  if (err) return done(err);
694
- expect(results[0].m).eql({test: 3});
695
- done();
693
+ db.query('testcollection', {x: 5}, null, {metadata: true}, function(err, results) {
694
+ if (err) return done(err);
695
+ expect(results[0].m).eql({test: 3});
696
+ done();
697
+ });
696
698
  });
697
699
  });
698
700
  });
699
- });
700
701
 
701
- describe('projections', function() {
702
- it('query returns only projected fields', function(done) {
703
- if (!this.db.projectsSnapshot) return done();
702
+ describe('projections', function() {
703
+ it('query returns only projected fields', function(done) {
704
+ if (!this.db.projectsSnapshot) return done();
704
705
 
705
- var snapshot = {type: 'json0', v: 1, data: {x: 5, y: 6}};
706
- var db = this.db;
707
- db.commit('testcollection', 'test', {v: 0, create: {}}, snapshot, null, function(err) {
708
- if (err) return done(err);
709
- db.query('testcollection', {x: 5}, {y: true}, null, function(err, results) {
706
+ var snapshot = {type: 'json0', v: 1, data: {x: 5, y: 6}};
707
+ var db = this.db;
708
+ db.commit('testcollection', 'test', {v: 0, create: {}}, snapshot, null, function(err) {
710
709
  if (err) return done(err);
711
- expect(results).eql([{type: 'json0', v: 1, data: {y: 6}, id: 'test'}]);
712
- done();
710
+ db.query('testcollection', {x: 5}, {y: true}, null, function(err, results) {
711
+ if (err) return done(err);
712
+ expect(results).eql([{type: 'json0', v: 1, data: {y: 6}, id: 'test'}]);
713
+ done();
714
+ });
713
715
  });
714
716
  });
715
- });
716
717
 
717
- it('query returns no data for matching documents if fields is empty', function(done) {
718
- if (!this.db.projectsSnapshot) return done();
718
+ it('query returns no data for matching documents if fields is empty', function(done) {
719
+ if (!this.db.projectsSnapshot) return done();
719
720
 
720
- var snapshot = {type: 'json0', v: 1, data: {x: 5, y: 6}};
721
- var db = this.db;
722
- db.commit('testcollection', 'test', {v: 0, create: {}}, snapshot, null, function(err) {
723
- if (err) return done(err);
724
- db.query('testcollection', {x: 5}, {}, null, function(err, results) {
721
+ var snapshot = {type: 'json0', v: 1, data: {x: 5, y: 6}};
722
+ var db = this.db;
723
+ db.commit('testcollection', 'test', {v: 0, create: {}}, snapshot, null, function(err) {
725
724
  if (err) return done(err);
726
- expect(results).eql([{type: 'json0', v: 1, data: {}, id: 'test'}]);
727
- done();
725
+ db.query('testcollection', {x: 5}, {}, null, function(err, results) {
726
+ if (err) return done(err);
727
+ expect(results).eql([{type: 'json0', v: 1, data: {}, id: 'test'}]);
728
+ done();
729
+ });
728
730
  });
729
731
  });
730
- });
731
732
 
732
- it('query does not return committed metadata by default with projection', function(done) {
733
- var db = this.db;
734
- commitSnapshotWithMetadata(db, function(err) {
735
- if (err) return done(err);
736
- db.query('testcollection', {x: 5}, {x: true}, null, function(err, results) {
733
+ it('query does not return committed metadata by default with projection', function(done) {
734
+ var db = this.db;
735
+ commitSnapshotWithMetadata(db, function(err) {
737
736
  if (err) return done(err);
738
- expect(results[0].m).equal(null);
739
- done();
737
+ db.query('testcollection', {x: 5}, {x: true}, null, function(err, results) {
738
+ if (err) return done(err);
739
+ expect(results[0].m).equal(null);
740
+ done();
741
+ });
740
742
  });
741
743
  });
742
- });
743
744
 
744
- it('query returns metadata when option is true with projection', function(done) {
745
- var db = this.db;
746
- commitSnapshotWithMetadata(db, function(err) {
747
- if (err) return done(err);
748
- db.query('testcollection', {x: 5}, {x: true}, {metadata: true}, function(err, results) {
745
+ it('query returns metadata when option is true with projection', function(done) {
746
+ var db = this.db;
747
+ commitSnapshotWithMetadata(db, function(err) {
749
748
  if (err) return done(err);
750
- expect(results[0].m).eql({test: 3});
751
- done();
749
+ db.query('testcollection', {x: 5}, {x: true}, {metadata: true}, function(err, results) {
750
+ if (err) return done(err);
751
+ expect(results[0].m).eql({test: 3});
752
+ done();
753
+ });
752
754
  });
753
755
  });
754
756
  });
755
- });
756
757
 
757
- if (options.getQuery) {
758
758
  describe('queryPoll', function() {
759
759
  it('returns data in the collection', function(done) {
760
760
  var snapshot = {v: 1, type: 'json0', data: {x: 5, y: 6}};