@fluidframework/sequence 2.33.0-333010 → 2.33.0

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.
Files changed (80) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/api-report/sequence.legacy.alpha.api.md +39 -39
  3. package/dist/intervalCollection.d.ts +7 -4
  4. package/dist/intervalCollection.d.ts.map +1 -1
  5. package/dist/intervalCollection.js +78 -31
  6. package/dist/intervalCollection.js.map +1 -1
  7. package/dist/intervalCollectionMap.d.ts +1 -0
  8. package/dist/intervalCollectionMap.d.ts.map +1 -1
  9. package/dist/intervalCollectionMap.js +9 -0
  10. package/dist/intervalCollectionMap.js.map +1 -1
  11. package/dist/intervalCollectionMapInterfaces.d.ts +1 -0
  12. package/dist/intervalCollectionMapInterfaces.d.ts.map +1 -1
  13. package/dist/intervalCollectionMapInterfaces.js.map +1 -1
  14. package/dist/intervalIndex/intervalIndex.d.ts +1 -1
  15. package/dist/intervalIndex/intervalIndex.js.map +1 -1
  16. package/dist/intervalIndex/overlappingIntervalsIndex.d.ts +1 -1
  17. package/dist/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
  18. package/dist/intervals/sequenceInterval.d.ts +3 -3
  19. package/dist/intervals/sequenceInterval.d.ts.map +1 -1
  20. package/dist/intervals/sequenceInterval.js +10 -9
  21. package/dist/intervals/sequenceInterval.js.map +1 -1
  22. package/dist/packageVersion.d.ts +1 -1
  23. package/dist/packageVersion.d.ts.map +1 -1
  24. package/dist/packageVersion.js +1 -1
  25. package/dist/packageVersion.js.map +1 -1
  26. package/dist/sequence.d.ts +4 -0
  27. package/dist/sequence.d.ts.map +1 -1
  28. package/dist/sequence.js +10 -0
  29. package/dist/sequence.js.map +1 -1
  30. package/dist/sharedIntervalCollection.d.ts +1 -1
  31. package/dist/sharedIntervalCollection.js.map +1 -1
  32. package/dist/sharedString.d.ts +0 -4
  33. package/dist/sharedString.d.ts.map +1 -1
  34. package/dist/sharedString.js +0 -11
  35. package/dist/sharedString.js.map +1 -1
  36. package/lib/intervalCollection.d.ts +7 -4
  37. package/lib/intervalCollection.d.ts.map +1 -1
  38. package/lib/intervalCollection.js +78 -31
  39. package/lib/intervalCollection.js.map +1 -1
  40. package/lib/intervalCollectionMap.d.ts +1 -0
  41. package/lib/intervalCollectionMap.d.ts.map +1 -1
  42. package/lib/intervalCollectionMap.js +9 -0
  43. package/lib/intervalCollectionMap.js.map +1 -1
  44. package/lib/intervalCollectionMapInterfaces.d.ts +1 -0
  45. package/lib/intervalCollectionMapInterfaces.d.ts.map +1 -1
  46. package/lib/intervalCollectionMapInterfaces.js.map +1 -1
  47. package/lib/intervalIndex/intervalIndex.d.ts +1 -1
  48. package/lib/intervalIndex/intervalIndex.js.map +1 -1
  49. package/lib/intervalIndex/overlappingIntervalsIndex.d.ts +1 -1
  50. package/lib/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
  51. package/lib/intervals/sequenceInterval.d.ts +3 -3
  52. package/lib/intervals/sequenceInterval.d.ts.map +1 -1
  53. package/lib/intervals/sequenceInterval.js +10 -9
  54. package/lib/intervals/sequenceInterval.js.map +1 -1
  55. package/lib/packageVersion.d.ts +1 -1
  56. package/lib/packageVersion.d.ts.map +1 -1
  57. package/lib/packageVersion.js +1 -1
  58. package/lib/packageVersion.js.map +1 -1
  59. package/lib/sequence.d.ts +4 -0
  60. package/lib/sequence.d.ts.map +1 -1
  61. package/lib/sequence.js +10 -0
  62. package/lib/sequence.js.map +1 -1
  63. package/lib/sharedIntervalCollection.d.ts +1 -1
  64. package/lib/sharedIntervalCollection.js.map +1 -1
  65. package/lib/sharedString.d.ts +0 -4
  66. package/lib/sharedString.d.ts.map +1 -1
  67. package/lib/sharedString.js +0 -11
  68. package/lib/sharedString.js.map +1 -1
  69. package/lib/tsdoc-metadata.json +1 -1
  70. package/package.json +18 -20
  71. package/src/intervalCollection.ts +112 -42
  72. package/src/intervalCollectionMap.ts +13 -0
  73. package/src/intervalCollectionMapInterfaces.ts +1 -0
  74. package/src/intervalIndex/intervalIndex.ts +1 -1
  75. package/src/intervalIndex/overlappingIntervalsIndex.ts +1 -1
  76. package/src/intervals/sequenceInterval.ts +14 -2
  77. package/src/packageVersion.ts +1 -1
  78. package/src/sequence.ts +15 -0
  79. package/src/sharedIntervalCollection.ts +1 -1
  80. package/src/sharedString.ts +0 -11
@@ -109,7 +109,7 @@ export class LocalIntervalCollection {
109
109
  this.removeIntervalFromIndexes(interval);
110
110
  this.removeIntervalListeners(interval);
111
111
  }
112
- addInterval(id, start, end, props, op) {
112
+ addInterval(id, start, end, props, op, rollback) {
113
113
  // This check is intended to prevent scenarios where a random interval is created and then
114
114
  // inserted into a collection. The aim is to ensure that the collection is created first
115
115
  // then the user can create/add intervals based on the collection
@@ -117,7 +117,7 @@ export class LocalIntervalCollection {
117
117
  props[reservedRangeLabelsKey][0] !== this.label) {
118
118
  throw new LoggingError("Adding an interval that belongs to another interval collection is not permitted");
119
119
  }
120
- const interval = createSequenceInterval(this.label, id, start, end, this.client, IntervalType.SlideOnRemove, op, undefined, this.options.mergeTreeReferencesCanSlideToEndpoint, props);
120
+ const interval = createSequenceInterval(this.label, id, start, end, this.client, IntervalType.SlideOnRemove, op, undefined, this.options.mergeTreeReferencesCanSlideToEndpoint, props, rollback);
121
121
  this.add(interval);
122
122
  return interval;
123
123
  }
@@ -255,6 +255,54 @@ export class IntervalCollection extends TypedEventEmitter {
255
255
  }
256
256
  return true;
257
257
  }
258
+ rollback(op, localOpMetadata) {
259
+ const { opName, value } = op;
260
+ const { id, properties } = getSerializedProperties(value);
261
+ const { localSeq, previous } = localOpMetadata;
262
+ switch (opName) {
263
+ case "add": {
264
+ const interval = this.getIntervalById(id);
265
+ if (interval) {
266
+ this.deleteExistingInterval({ interval, local: true, rollback: true });
267
+ }
268
+ break;
269
+ }
270
+ case "change": {
271
+ assert(previous !== undefined, 0xb7c /* must have previous for change */);
272
+ const endpointsChanged = value.start !== undefined && value.end !== undefined;
273
+ const start = endpointsChanged
274
+ ? toOptionalSequencePlace(previous.start, previous.startSide)
275
+ : undefined;
276
+ const end = endpointsChanged
277
+ ? toOptionalSequencePlace(previous.end, previous.endSide)
278
+ : undefined;
279
+ this.change(id, {
280
+ start,
281
+ end,
282
+ props: Object.keys(properties).length > 0 ? properties : undefined,
283
+ rollback: true,
284
+ });
285
+ this.localSeqToSerializedInterval.delete(localSeq);
286
+ if (endpointsChanged) {
287
+ this.removePendingChange(value);
288
+ }
289
+ break;
290
+ }
291
+ case "delete": {
292
+ assert(previous !== undefined, 0xb7d /* must have previous for delete */);
293
+ this.add({
294
+ id,
295
+ start: toSequencePlace(previous.start, previous.startSide),
296
+ end: toSequencePlace(previous.end, previous.endSide),
297
+ props: Object.keys(properties).length > 0 ? properties : undefined,
298
+ rollback: true,
299
+ });
300
+ break;
301
+ }
302
+ default:
303
+ unreachableCase(opName);
304
+ }
305
+ }
258
306
  process(op, local, message, localOpMetadata) {
259
307
  const { opName, value } = op;
260
308
  switch (opName) {
@@ -422,7 +470,7 @@ export class IntervalCollection extends TypedEventEmitter {
422
470
  /**
423
471
  * {@inheritdoc IIntervalCollection.add}
424
472
  */
425
- add({ id, start, end, props, }) {
473
+ add({ id, start, end, props, rollback, }) {
426
474
  if (!this.localCollection) {
427
475
  throw new LoggingError("attach must be called prior to adding intervals");
428
476
  }
@@ -432,7 +480,7 @@ export class IntervalCollection extends TypedEventEmitter {
432
480
  startSide !== undefined &&
433
481
  endSide !== undefined, 0x793 /* start and end cannot be undefined because they were not passed in as undefined */);
434
482
  this.assertStickinessEnabled(start, end);
435
- const interval = this.localCollection.addInterval(id ?? uuid(), toSequencePlace(startPos, startSide), toSequencePlace(endPos, endSide), props);
483
+ const interval = this.localCollection.addInterval(id ?? uuid(), toSequencePlace(startPos, startSide), toSequencePlace(endPos, endSide), props, undefined, rollback);
436
484
  if (interval) {
437
485
  if (!this.isCollaborating) {
438
486
  setSlideOnRemove(interval.start);
@@ -440,20 +488,20 @@ export class IntervalCollection extends TypedEventEmitter {
440
488
  }
441
489
  const serializedInterval = interval.serialize();
442
490
  const localSeq = this.getNextLocalSeq();
443
- if (this.isCollaborating) {
491
+ if (this.isCollaborating && rollback !== true) {
444
492
  this.localSeqToSerializedInterval.set(localSeq, serializedInterval);
493
+ this.submitDelta({
494
+ opName: "add",
495
+ value: serializedInterval,
496
+ }, {
497
+ localSeq,
498
+ });
445
499
  }
446
- this.submitDelta({
447
- opName: "add",
448
- value: serializedInterval,
449
- }, {
450
- localSeq,
451
- });
452
500
  }
453
501
  this.emit("addInterval", interval, true, undefined);
454
502
  return interval;
455
503
  }
456
- deleteExistingInterval(interval, local, op) {
504
+ deleteExistingInterval({ interval, local, op, rollback, }) {
457
505
  if (!this.localCollection) {
458
506
  throw new LoggingError("Attach must be called before accessing intervals");
459
507
  }
@@ -461,12 +509,13 @@ export class IntervalCollection extends TypedEventEmitter {
461
509
  this.localCollection.removeExistingInterval(interval);
462
510
  if (interval) {
463
511
  // Local ops get submitted to the server. Remote ops have the deserializer run.
464
- if (local) {
512
+ if (local && rollback !== true) {
465
513
  this.submitDelta({
466
514
  opName: "delete",
467
515
  value: interval.serialize(),
468
516
  }, {
469
517
  localSeq: this.getNextLocalSeq(),
518
+ previous: interval.serialize(),
470
519
  });
471
520
  }
472
521
  else {
@@ -486,14 +535,14 @@ export class IntervalCollection extends TypedEventEmitter {
486
535
  }
487
536
  const interval = this.localCollection.idIntervalIndex.getIntervalById(id);
488
537
  if (interval) {
489
- this.deleteExistingInterval(interval, true, undefined);
538
+ this.deleteExistingInterval({ interval, local: true });
490
539
  }
491
540
  return interval;
492
541
  }
493
542
  /**
494
543
  * {@inheritdoc IIntervalCollection.change}
495
544
  */
496
- change(id, { start, end, props }) {
545
+ change(id, { start, end, props, rollback, }) {
497
546
  if (!this.localCollection) {
498
547
  throw new LoggingError("Attach must be called before accessing intervals");
499
548
  }
@@ -515,7 +564,7 @@ export class IntervalCollection extends TypedEventEmitter {
515
564
  let deltaProps;
516
565
  let newInterval;
517
566
  if (props !== undefined) {
518
- deltaProps = interval.changeProperties(props);
567
+ deltaProps = interval.changeProperties(props, undefined, rollback);
519
568
  }
520
569
  const changeEndpoints = start !== undefined && end !== undefined;
521
570
  if (changeEndpoints) {
@@ -525,27 +574,25 @@ export class IntervalCollection extends TypedEventEmitter {
525
574
  setSlideOnRemove(newInterval.end);
526
575
  }
527
576
  }
528
- // Emit a property bag containing the ID and the other (if any) properties changed
529
- const serializedInterval = (newInterval ?? interval).serializeDelta({
530
- props,
531
- includeEndpoints: changeEndpoints,
532
- });
533
- const localSeq = this.getNextLocalSeq();
534
- if (this.isCollaborating) {
577
+ if (this.isCollaborating && rollback !== true) {
578
+ // Emit a property bag containing the ID and the other (if any) properties changed
579
+ const serializedInterval = (newInterval ?? interval).serializeDelta({ props, includeEndpoints: changeEndpoints });
580
+ const localSeq = this.getNextLocalSeq();
535
581
  this.localSeqToSerializedInterval.set(localSeq, serializedInterval);
582
+ this.addPendingChange(id, serializedInterval);
583
+ this.submitDelta({
584
+ opName: "change",
585
+ value: serializedInterval,
586
+ }, {
587
+ localSeq,
588
+ previous: interval.serialize(),
589
+ });
536
590
  }
537
- this.submitDelta({
538
- opName: "change",
539
- value: serializedInterval,
540
- }, {
541
- localSeq,
542
- });
543
591
  if (deltaProps !== undefined) {
544
592
  this.emit("propertyChanged", interval, deltaProps, true, undefined);
545
593
  this.emit("changed", newInterval ?? interval, deltaProps, newInterval ? interval : undefined, true, false);
546
594
  }
547
595
  if (newInterval) {
548
- this.addPendingChange(id, serializedInterval);
549
596
  this.emitChange(newInterval, interval, true, false);
550
597
  this.client?.removeLocalReferencePosition(interval.start);
551
598
  this.client?.removeLocalReferencePosition(interval.end);
@@ -841,7 +888,7 @@ export class IntervalCollection extends TypedEventEmitter {
841
888
  const { id } = getSerializedProperties(serializedInterval);
842
889
  const interval = this.localCollection.idIntervalIndex.getIntervalById(id);
843
890
  if (interval) {
844
- this.deleteExistingInterval(interval, local, op);
891
+ this.deleteExistingInterval({ interval, local, op });
845
892
  }
846
893
  }
847
894
  serializeInternal(version) {