@fluidframework/sequence 2.0.0-internal.4.2.1 → 2.0.0-internal.4.4.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 (69) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/defaultMap.d.ts +3 -2
  3. package/dist/defaultMap.d.ts.map +1 -1
  4. package/dist/defaultMap.js +4 -3
  5. package/dist/defaultMap.js.map +1 -1
  6. package/dist/defaultMapInterfaces.d.ts +12 -1
  7. package/dist/defaultMapInterfaces.d.ts.map +1 -1
  8. package/dist/defaultMapInterfaces.js.map +1 -1
  9. package/dist/index.d.ts +3 -2
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +11 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/intervalCollection.d.ts +199 -46
  14. package/dist/intervalCollection.d.ts.map +1 -1
  15. package/dist/intervalCollection.js +164 -78
  16. package/dist/intervalCollection.js.map +1 -1
  17. package/dist/packageVersion.d.ts +1 -1
  18. package/dist/packageVersion.js +1 -1
  19. package/dist/packageVersion.js.map +1 -1
  20. package/dist/revertibles.d.ts +104 -0
  21. package/dist/revertibles.d.ts.map +1 -0
  22. package/dist/revertibles.js +374 -0
  23. package/dist/revertibles.js.map +1 -0
  24. package/dist/sequence.d.ts +2 -2
  25. package/dist/sequence.d.ts.map +1 -1
  26. package/dist/sequence.js +3 -3
  27. package/dist/sequence.js.map +1 -1
  28. package/dist/sharedIntervalCollection.d.ts.map +1 -1
  29. package/dist/sharedIntervalCollection.js +1 -1
  30. package/dist/sharedIntervalCollection.js.map +1 -1
  31. package/lib/defaultMap.d.ts +3 -2
  32. package/lib/defaultMap.d.ts.map +1 -1
  33. package/lib/defaultMap.js +4 -3
  34. package/lib/defaultMap.js.map +1 -1
  35. package/lib/defaultMapInterfaces.d.ts +12 -1
  36. package/lib/defaultMapInterfaces.d.ts.map +1 -1
  37. package/lib/defaultMapInterfaces.js.map +1 -1
  38. package/lib/index.d.ts +3 -2
  39. package/lib/index.d.ts.map +1 -1
  40. package/lib/index.js +2 -1
  41. package/lib/index.js.map +1 -1
  42. package/lib/intervalCollection.d.ts +199 -46
  43. package/lib/intervalCollection.d.ts.map +1 -1
  44. package/lib/intervalCollection.js +164 -78
  45. package/lib/intervalCollection.js.map +1 -1
  46. package/lib/packageVersion.d.ts +1 -1
  47. package/lib/packageVersion.js +1 -1
  48. package/lib/packageVersion.js.map +1 -1
  49. package/lib/revertibles.d.ts +104 -0
  50. package/lib/revertibles.d.ts.map +1 -0
  51. package/lib/revertibles.js +364 -0
  52. package/lib/revertibles.js.map +1 -0
  53. package/lib/sequence.d.ts +2 -2
  54. package/lib/sequence.d.ts.map +1 -1
  55. package/lib/sequence.js +3 -3
  56. package/lib/sequence.js.map +1 -1
  57. package/lib/sharedIntervalCollection.d.ts.map +1 -1
  58. package/lib/sharedIntervalCollection.js +1 -1
  59. package/lib/sharedIntervalCollection.js.map +1 -1
  60. package/package.json +38 -14
  61. package/src/defaultMap.ts +4 -1
  62. package/src/defaultMapInterfaces.ts +13 -1
  63. package/src/index.ts +16 -1
  64. package/src/intervalCollection.ts +370 -57
  65. package/src/packageVersion.ts +1 -1
  66. package/src/revertibles.ts +572 -0
  67. package/src/sequence.ts +12 -3
  68. package/src/sharedIntervalCollection.ts +3 -2
  69. package/.vscode/launch.json +0 -16
@@ -16,11 +16,22 @@ var __rest = (this && this.__rest) || function (s, e) {
16
16
  /* eslint-disable no-bitwise */
17
17
  import { assert, TypedEventEmitter } from "@fluidframework/common-utils";
18
18
  import { UsageError } from "@fluidframework/container-utils";
19
- import { addProperties, compareReferencePositions, createMap, MergeTreeDeltaType, minReferencePosition, PropertiesManager, RedBlackTree, ReferenceType, refTypeIncludesFlag, reservedRangeLabelsKey, UnassignedSequenceNumber, maxReferencePosition, createDetachedLocalReferencePosition, DetachedReferencePosition, } from "@fluidframework/merge-tree";
19
+ import { addProperties, compareReferencePositions, createMap, MergeTreeDeltaType, minReferencePosition, PropertiesManager, RedBlackTree, ReferenceType, refTypeIncludesFlag, reservedRangeLabelsKey, UnassignedSequenceNumber, maxReferencePosition, createDetachedLocalReferencePosition, DetachedReferencePosition, SlidingPreference, } from "@fluidframework/merge-tree";
20
20
  import { LoggingError } from "@fluidframework/telemetry-utils";
21
21
  import { v4 as uuid } from "uuid";
22
22
  import { IntervalTree } from "./intervalTree";
23
23
  const reservedIntervalIdKey = "intervalId";
24
+ /**
25
+ * Values are used in persisted formats (ops) and revertibles.
26
+ * @alpha
27
+ */
28
+ export const IntervalOpType = {
29
+ ADD: "add",
30
+ DELETE: "delete",
31
+ CHANGE: "change",
32
+ PROPERTY_CHANGED: "propertyChanged",
33
+ POSITION_REMOVE: "positionRemove",
34
+ };
24
35
  export var IntervalType;
25
36
  (function (IntervalType) {
26
37
  IntervalType[IntervalType["Simple"] = 0] = "Simple";
@@ -49,6 +60,7 @@ function decompressInterval(interval, label) {
49
60
  sequenceNumber: interval[2],
50
61
  intervalType: interval[3],
51
62
  properties: Object.assign(Object.assign({}, interval[4]), { [reservedRangeLabelsKey]: [label] }),
63
+ stickiness: interval[5],
52
64
  };
53
65
  }
54
66
  /**
@@ -57,14 +69,57 @@ function decompressInterval(interval, label) {
57
69
  */
58
70
  function compressInterval(interval) {
59
71
  const { start, end, sequenceNumber, intervalType, properties } = interval;
60
- return [
72
+ const base = [
61
73
  start,
62
74
  end,
63
75
  sequenceNumber,
64
76
  intervalType,
65
77
  Object.assign(Object.assign({}, properties), { [reservedRangeLabelsKey]: undefined }),
66
78
  ];
79
+ if (interval.stickiness !== undefined && interval.stickiness !== IntervalStickiness.END) {
80
+ base.push(interval.stickiness);
81
+ }
82
+ return base;
83
+ }
84
+ function startReferenceSlidingPreference(stickiness) {
85
+ // if any start stickiness, prefer sliding backwards
86
+ return (stickiness & IntervalStickiness.START) !== 0
87
+ ? SlidingPreference.BACKWARD
88
+ : SlidingPreference.FORWARD;
89
+ }
90
+ function endReferenceSlidingPreference(stickiness) {
91
+ // if any end stickiness, prefer sliding forwards
92
+ return (stickiness & IntervalStickiness.END) !== 0
93
+ ? SlidingPreference.FORWARD
94
+ : SlidingPreference.BACKWARD;
67
95
  }
96
+ /**
97
+ * Determines how an interval should expand when segments are inserted adjacent
98
+ * to the range it spans
99
+ *
100
+ * Note that interval stickiness is currently an experimental feature and must
101
+ * be explicitly enabled with the `intervalStickinessEnabled` flag
102
+ */
103
+ export const IntervalStickiness = {
104
+ /**
105
+ * Interval does not expand to include adjacent segments
106
+ */
107
+ NONE: 0b00,
108
+ /**
109
+ * Interval expands to include segments inserted adjacent to the start
110
+ */
111
+ START: 0b01,
112
+ /**
113
+ * Interval expands to include segments inserted adjacent to the end
114
+ *
115
+ * This is the default stickiness
116
+ */
117
+ END: 0b10,
118
+ /**
119
+ * Interval expands to include all segments inserted adjacent to it
120
+ */
121
+ FULL: 0b11,
122
+ };
68
123
  /**
69
124
  * Serializable interval whose endpoints are plain-old numbers.
70
125
  */
@@ -254,11 +309,12 @@ export class SequenceInterval {
254
309
  * End endpoint of this interval.
255
310
  * @remarks - This endpoint can be resolved into a character position using the SharedString it's a part of.
256
311
  */
257
- end, intervalType, props) {
312
+ end, intervalType, props, stickiness = IntervalStickiness.END) {
258
313
  this.client = client;
259
314
  this.start = start;
260
315
  this.end = end;
261
316
  this.intervalType = intervalType;
317
+ this.stickiness = stickiness;
262
318
  this.propertyManager = new PropertiesManager();
263
319
  this.properties = {};
264
320
  if (props) {
@@ -310,13 +366,16 @@ export class SequenceInterval {
310
366
  if (this.properties) {
311
367
  serializedInterval.properties = this.properties;
312
368
  }
369
+ if (this.stickiness !== IntervalStickiness.END) {
370
+ serializedInterval.stickiness = this.stickiness;
371
+ }
313
372
  return serializedInterval;
314
373
  }
315
374
  /**
316
375
  * {@inheritDoc IInterval.clone}
317
376
  */
318
377
  clone() {
319
- return new SequenceInterval(this.client, this.start, this.end, this.intervalType, this.properties);
378
+ return new SequenceInterval(this.client, this.start, this.end, this.intervalType, this.properties, this.stickiness);
320
379
  }
321
380
  /**
322
381
  * {@inheritDoc IInterval.compare}
@@ -400,7 +459,7 @@ export class SequenceInterval {
400
459
  * {@inheritDoc IInterval.modify}
401
460
  * @deprecated - This API was never intended to be public and will be marked internal in a future release.
402
461
  */
403
- modify(label, start, end, op, localSeq) {
462
+ modify(label, start, end, op, localSeq, stickiness = IntervalStickiness.END) {
404
463
  const getRefType = (baseType) => {
405
464
  let refType = baseType;
406
465
  if (op === undefined) {
@@ -411,14 +470,14 @@ export class SequenceInterval {
411
470
  };
412
471
  let startRef = this.start;
413
472
  if (start !== undefined) {
414
- startRef = createPositionReference(this.client, start, getRefType(this.start.refType), op, undefined, localSeq);
473
+ startRef = createPositionReference(this.client, start, getRefType(this.start.refType), op, undefined, localSeq, startReferenceSlidingPreference(stickiness));
415
474
  if (this.start.properties) {
416
475
  startRef.addProperties(this.start.properties);
417
476
  }
418
477
  }
419
478
  let endRef = this.end;
420
479
  if (end !== undefined) {
421
- endRef = createPositionReference(this.client, end, getRefType(this.end.refType), op, undefined, localSeq);
480
+ endRef = createPositionReference(this.client, end, getRefType(this.end.refType), op, undefined, localSeq, endReferenceSlidingPreference(stickiness));
422
481
  if (this.end.properties) {
423
482
  endRef.addProperties(this.end.properties);
424
483
  }
@@ -439,9 +498,9 @@ export class SequenceInterval {
439
498
  }
440
499
  }
441
500
  }
442
- function createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot) {
501
+ function createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot, slidingPreference) {
443
502
  if (segoff.segment) {
444
- const ref = client.createLocalReferencePosition(segoff.segment, segoff.offset, refType, undefined);
503
+ const ref = client.createLocalReferencePosition(segoff.segment, segoff.offset, refType, undefined, slidingPreference);
445
504
  return ref;
446
505
  }
447
506
  // Creating references on detached segments is allowed for:
@@ -457,7 +516,7 @@ function createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq
457
516
  }
458
517
  return createDetachedLocalReferencePosition(refType);
459
518
  }
460
- function createPositionReference(client, pos, refType, op, fromSnapshot, localSeq) {
519
+ function createPositionReference(client, pos, refType, op, fromSnapshot, localSeq, slidingPreference) {
461
520
  let segoff;
462
521
  if (op) {
463
522
  assert((refType & ReferenceType.SlideOnRemove) !== 0, 0x2f5 /* op create references must be SlideOnRemove */);
@@ -471,9 +530,9 @@ function createPositionReference(client, pos, refType, op, fromSnapshot, localSe
471
530
  assert((refType & ReferenceType.SlideOnRemove) === 0 || !!fromSnapshot, 0x2f6 /* SlideOnRemove references must be op created */);
472
531
  segoff = client.getContainingSegment(pos, undefined, localSeq);
473
532
  }
474
- return createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot);
533
+ return createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot, slidingPreference);
475
534
  }
476
- export function createSequenceInterval(label, start, end, client, intervalType, op, fromSnapshot) {
535
+ export function createSequenceInterval(label, start, end, client, intervalType, op, fromSnapshot, stickiness = IntervalStickiness.END) {
477
536
  let beginRefType = ReferenceType.RangeBegin;
478
537
  let endRefType = ReferenceType.RangeEnd;
479
538
  if (intervalType === IntervalType.Transient) {
@@ -497,14 +556,14 @@ export function createSequenceInterval(label, start, end, client, intervalType,
497
556
  endRefType |= ReferenceType.StayOnRemove;
498
557
  }
499
558
  }
500
- const startLref = createPositionReference(client, start, beginRefType, op, fromSnapshot);
501
- const endLref = createPositionReference(client, end, endRefType, op, fromSnapshot);
559
+ const startLref = createPositionReference(client, start, beginRefType, op, fromSnapshot, undefined, startReferenceSlidingPreference(stickiness));
560
+ const endLref = createPositionReference(client, end, endRefType, op, fromSnapshot, undefined, endReferenceSlidingPreference(stickiness));
502
561
  const rangeProp = {
503
562
  [reservedRangeLabelsKey]: [label],
504
563
  };
505
564
  startLref.addProperties(rangeProp);
506
565
  endLref.addProperties(rangeProp);
507
- const ival = new SequenceInterval(client, startLref, endLref, intervalType, rangeProp);
566
+ const ival = new SequenceInterval(client, startLref, endLref, intervalType, rangeProp, stickiness);
508
567
  return ival;
509
568
  }
510
569
  export function createIntervalIndex() {
@@ -673,11 +732,11 @@ export class LocalIntervalCollection {
673
732
  this.overlappingIntervalsIndex = new OverlappingIntervalsIndex(client, helpers);
674
733
  this.idIntervalIndex = new IdIntervalIndex();
675
734
  this.endIntervalIndex = new EndpointIndex(client, helpers);
676
- this.indexes = [
735
+ this.indexes = new Set([
677
736
  this.overlappingIntervalsIndex,
678
737
  this.idIntervalIndex,
679
738
  this.endIntervalIndex,
680
- ];
739
+ ]);
681
740
  }
682
741
  createLegacyId(start, end) {
683
742
  // Create a non-unique ID based on start and end to be used on intervals that come from legacy clients
@@ -717,17 +776,23 @@ export class LocalIntervalCollection {
717
776
  index.remove(interval);
718
777
  }
719
778
  }
779
+ appendIndex(index) {
780
+ this.indexes.add(index);
781
+ }
782
+ removeIndex(index) {
783
+ return this.indexes.delete(index);
784
+ }
720
785
  removeExistingInterval(interval) {
721
786
  this.removeIntervalFromIndexes(interval);
722
787
  this.removeIntervalListeners(interval);
723
788
  }
724
- createInterval(start, end, intervalType, op) {
725
- return this.helpers.create(this.label, start, end, this.client, intervalType, op);
789
+ createInterval(start, end, intervalType, op, stickiness = IntervalStickiness.END) {
790
+ return this.helpers.create(this.label, start, end, this.client, intervalType, op, undefined, stickiness);
726
791
  }
727
- addInterval(start, end, intervalType, props, op) {
792
+ addInterval(start, end, intervalType, props, op, stickiness = IntervalStickiness.END) {
728
793
  var _a;
729
794
  var _b;
730
- const interval = this.createInterval(start, end, intervalType, op);
795
+ const interval = this.createInterval(start, end, intervalType, op, stickiness);
731
796
  if (interval) {
732
797
  if (!interval.properties) {
733
798
  interval.properties = createMap();
@@ -780,7 +845,7 @@ export class LocalIntervalCollection {
780
845
  // either, so this must be special-cased.
781
846
  return ref;
782
847
  }
783
- return this.client.createLocalReferencePosition(segment, ref.getOffset(), ReferenceType.Transient, ref.properties);
848
+ return this.client.createLocalReferencePosition(segment, ref.getOffset(), ReferenceType.Transient, ref.properties, ref.slidingPreference);
784
849
  };
785
850
  if (interval instanceof SequenceInterval) {
786
851
  let previousInterval;
@@ -815,12 +880,12 @@ export class LocalIntervalCollection {
815
880
  LocalIntervalCollection.legacyIdPrefix = "legacy";
816
881
  export const compareSequenceIntervalEnds = (a, b) => compareReferencePositions(a.end, b.end);
817
882
  class SequenceIntervalCollectionFactory {
818
- load(emitter, raw = []) {
883
+ load(emitter, raw = [], options) {
819
884
  const helpers = {
820
885
  compareEnds: compareSequenceIntervalEnds,
821
886
  create: createSequenceInterval,
822
887
  };
823
- return new IntervalCollection(helpers, true, emitter, raw);
888
+ return new IntervalCollection(helpers, true, emitter, raw, options);
824
889
  }
825
890
  store(value) {
826
891
  return value.serializeInternal();
@@ -841,7 +906,7 @@ SequenceIntervalCollectionValueType.Name = "sharedStringIntervalCollection";
841
906
  SequenceIntervalCollectionValueType._factory = new SequenceIntervalCollectionFactory();
842
907
  SequenceIntervalCollectionValueType._ops = makeOpsMap();
843
908
  const compareIntervalEnds = (a, b) => a.end - b.end;
844
- function createInterval(label, start, end, client) {
909
+ function createInterval(label, start, end, client, intervalType, op, fromSnapshot) {
845
910
  const rangeProp = {};
846
911
  if (label && label.length > 0) {
847
912
  rangeProp[reservedRangeLabelsKey] = [label];
@@ -849,12 +914,12 @@ function createInterval(label, start, end, client) {
849
914
  return new Interval(start, end, rangeProp);
850
915
  }
851
916
  class IntervalCollectionFactory {
852
- load(emitter, raw = []) {
917
+ load(emitter, raw = [], options) {
853
918
  const helpers = {
854
919
  compareEnds: compareIntervalEnds,
855
920
  create: createInterval,
856
921
  };
857
- const collection = new IntervalCollection(helpers, false, emitter, raw);
922
+ const collection = new IntervalCollection(helpers, false, emitter, raw, options);
858
923
  collection.attachGraph(undefined, "");
859
924
  return collection;
860
925
  }
@@ -885,7 +950,7 @@ export function makeOpsMap() {
885
950
  };
886
951
  return new Map([
887
952
  [
888
- "add",
953
+ IntervalOpType.ADD,
889
954
  {
890
955
  process: (collection, params, local, op, localOpMetadata) => {
891
956
  // if params is undefined, the interval was deleted during
@@ -900,7 +965,7 @@ export function makeOpsMap() {
900
965
  },
901
966
  ],
902
967
  [
903
- "delete",
968
+ IntervalOpType.DELETE,
904
969
  {
905
970
  process: (collection, params, local, op) => {
906
971
  assert(op !== undefined, 0x3fc /* op should exist here */);
@@ -913,7 +978,7 @@ export function makeOpsMap() {
913
978
  },
914
979
  ],
915
980
  [
916
- "change",
981
+ IntervalOpType.CHANGE,
917
982
  {
918
983
  process: (collection, params, local, op, localOpMetadata) => {
919
984
  // if params is undefined, the interval was deleted during
@@ -929,6 +994,10 @@ export function makeOpsMap() {
929
994
  ],
930
995
  ]);
931
996
  }
997
+ /**
998
+ * @deprecated - Public export will be removed. Use an appropriate iterator creation method on
999
+ * {@link IIntervalCollection} to iterate intervals instead.
1000
+ */
932
1001
  export class IntervalCollectionIterator {
933
1002
  constructor(collection, iteratesForward = true, start, end) {
934
1003
  this.results = [];
@@ -949,19 +1018,16 @@ export class IntervalCollectionIterator {
949
1018
  }
950
1019
  }
951
1020
  /**
952
- * Collection of intervals that supports addition, modification, removal, and efficient spatial querying.
953
- * This class is not a DDS in its own right, but emits events on mutating operations such that it's possible to
954
- * integrate into a DDS.
955
- * This aligns with its usage in `SharedSegmentSequence`, which allows associating intervals to positions in the
956
- * sequence DDS which are broadcast to all other clients in an eventually consistent fashion.
1021
+ * @deprecated - Use {@link IIntervalCollection} instead.
957
1022
  */
958
1023
  export class IntervalCollection extends TypedEventEmitter {
959
1024
  /** @internal */
960
- constructor(helpers, requiresClient, emitter, serializedIntervals) {
1025
+ constructor(helpers, requiresClient, emitter, serializedIntervals, options = {}) {
961
1026
  super();
962
1027
  this.helpers = helpers;
963
1028
  this.requiresClient = requiresClient;
964
1029
  this.emitter = emitter;
1030
+ this.options = options;
965
1031
  this.localSeqToSerializedInterval = new Map();
966
1032
  this.localSeqToRebasedInterval = new Map();
967
1033
  this.pendingChangesStart = new Map();
@@ -973,6 +1039,36 @@ export class IntervalCollection extends TypedEventEmitter {
973
1039
  get attached() {
974
1040
  return !!this.localCollection;
975
1041
  }
1042
+ /**
1043
+ * {@inheritdoc IIntervalCollection.attachIndex}
1044
+ */
1045
+ attachIndex(index) {
1046
+ var _a;
1047
+ if (!this.attached) {
1048
+ throw new LoggingError("The local interval collection must exist");
1049
+ }
1050
+ for (const interval of this) {
1051
+ index.add(interval);
1052
+ }
1053
+ (_a = this.localCollection) === null || _a === void 0 ? void 0 : _a.appendIndex(index);
1054
+ }
1055
+ /**
1056
+ * {@inheritdoc IIntervalCollection.detachIndex}
1057
+ */
1058
+ detachIndex(index) {
1059
+ var _a;
1060
+ if (!this.attached) {
1061
+ throw new LoggingError("The local interval collection must exist");
1062
+ }
1063
+ // Avoid removing intervals if the index does not exist
1064
+ if (!((_a = this.localCollection) === null || _a === void 0 ? void 0 : _a.removeIndex(index))) {
1065
+ return false;
1066
+ }
1067
+ for (const interval of this) {
1068
+ index.remove(interval);
1069
+ }
1070
+ return true;
1071
+ }
976
1072
  rebasePositionWithSegmentSlide(pos, seqNumberFrom, localSeq) {
977
1073
  var _a;
978
1074
  if (!this.client) {
@@ -1028,8 +1124,8 @@ export class IntervalCollection extends TypedEventEmitter {
1028
1124
  if (this.savedSerializedIntervals) {
1029
1125
  for (const serializedInterval of this.savedSerializedIntervals) {
1030
1126
  this.localCollection.ensureSerializedId(serializedInterval);
1031
- const { start, end, intervalType, properties } = serializedInterval;
1032
- const interval = this.helpers.create(label, start, end, client, intervalType, undefined, true);
1127
+ const { start, end, intervalType, properties, stickiness } = serializedInterval;
1128
+ const interval = this.helpers.create(label, start, end, client, intervalType, undefined, true, stickiness);
1033
1129
  if (properties) {
1034
1130
  interval.addProperties(properties);
1035
1131
  }
@@ -1067,8 +1163,7 @@ export class IntervalCollection extends TypedEventEmitter {
1067
1163
  }
1068
1164
  }
1069
1165
  /**
1070
- * @returns the interval in this collection that has the provided `id`.
1071
- * If no interval in the collection has this `id`, returns `undefined`.
1166
+ * {@inheritdoc IIntervalCollection.getIntervalById}
1072
1167
  */
1073
1168
  getIntervalById(id) {
1074
1169
  if (!this.localCollection) {
@@ -1077,16 +1172,9 @@ export class IntervalCollection extends TypedEventEmitter {
1077
1172
  return this.localCollection.idIntervalIndex.getIntervalById(id);
1078
1173
  }
1079
1174
  /**
1080
- * Creates a new interval and add it to the collection.
1081
- * @param start - interval start position (inclusive)
1082
- * @param end - interval end position (exclusive)
1083
- * @param intervalType - type of the interval. All intervals are SlideOnRemove. Intervals may not be Transient.
1084
- * @param props - properties of the interval
1085
- * @returns - the created interval
1086
- * @remarks - See documentation on {@link SequenceInterval} for comments on interval endpoint semantics: there are subtleties
1087
- * with how the current half-open behavior is represented.
1175
+ * {@inheritdoc IIntervalCollection.add}
1088
1176
  */
1089
- add(start, end, intervalType, props) {
1177
+ add(start, end, intervalType, props, stickiness = IntervalStickiness.END) {
1090
1178
  var _a, _b;
1091
1179
  if (!this.localCollection) {
1092
1180
  throw new LoggingError("attach must be called prior to adding intervals");
@@ -1094,7 +1182,10 @@ export class IntervalCollection extends TypedEventEmitter {
1094
1182
  if (intervalType & IntervalType.Transient) {
1095
1183
  throw new LoggingError("Can not add transient intervals");
1096
1184
  }
1097
- const interval = this.localCollection.addInterval(start, end, intervalType, props);
1185
+ if (stickiness !== IntervalStickiness.END && !this.options.intervalStickinessEnabled) {
1186
+ throw new UsageError("attempted to set interval stickiness without enabling `intervalStickinessEnabled` feature flag");
1187
+ }
1188
+ const interval = this.localCollection.addInterval(start, end, intervalType, props, undefined, stickiness);
1098
1189
  if (interval) {
1099
1190
  const serializedInterval = {
1100
1191
  end,
@@ -1102,6 +1193,7 @@ export class IntervalCollection extends TypedEventEmitter {
1102
1193
  properties: interval.properties,
1103
1194
  sequenceNumber: (_b = (_a = this.client) === null || _a === void 0 ? void 0 : _a.getCurrentSeq()) !== null && _b !== void 0 ? _b : 0,
1104
1195
  start,
1196
+ stickiness,
1105
1197
  };
1106
1198
  const localSeq = this.getNextLocalSeq();
1107
1199
  this.localSeqToSerializedInterval.set(localSeq, serializedInterval);
@@ -1133,9 +1225,7 @@ export class IntervalCollection extends TypedEventEmitter {
1133
1225
  this.emit("deleteInterval", interval, local, op);
1134
1226
  }
1135
1227
  /**
1136
- * Removes an interval from the collection.
1137
- * @param id - Id of the interval to remove
1138
- * @returns the removed interval
1228
+ * {@inheritdoc IIntervalCollection.removeIntervalById}
1139
1229
  */
1140
1230
  removeIntervalById(id) {
1141
1231
  if (!this.localCollection) {
@@ -1148,10 +1238,7 @@ export class IntervalCollection extends TypedEventEmitter {
1148
1238
  return interval;
1149
1239
  }
1150
1240
  /**
1151
- * Changes the properties on an existing interval.
1152
- * @param id - Id of the interval whose properties should be changed
1153
- * @param props - Property set to apply to the interval. Shallow merging is used between any existing properties
1154
- * and `prop`, i.e. the interval will end up with a property object equivalent to `{ ...oldProps, ...props }`.
1241
+ * {@inheritdoc IIntervalCollection.changeProperties}
1155
1242
  */
1156
1243
  changeProperties(id, props) {
1157
1244
  if (!this.attached) {
@@ -1181,11 +1268,7 @@ export class IntervalCollection extends TypedEventEmitter {
1181
1268
  }
1182
1269
  }
1183
1270
  /**
1184
- * Changes the endpoints of an existing interval.
1185
- * @param id - Id of the interval to change
1186
- * @param start - New start value, if defined. `undefined` signifies this endpoint should be left unchanged.
1187
- * @param end - New end value, if defined. `undefined` signifies this endpoint should be left unchanged.
1188
- * @returns the interval that was changed, if it existed in the collection.
1271
+ * {@inheritdoc IIntervalCollection.change}
1189
1272
  */
1190
1273
  change(id, start, end) {
1191
1274
  if (!this.localCollection) {
@@ -1340,6 +1423,9 @@ export class IntervalCollection extends TypedEventEmitter {
1340
1423
  throw new LoggingError("attachSequence must be called");
1341
1424
  }
1342
1425
  }
1426
+ /**
1427
+ * {@inheritdoc IIntervalCollection.attachDeserializer}
1428
+ */
1343
1429
  attachDeserializer(onDeserialize) {
1344
1430
  // If no deserializer is specified can skip all processing work
1345
1431
  if (!onDeserialize) {
@@ -1460,7 +1546,7 @@ export class IntervalCollection extends TypedEventEmitter {
1460
1546
  }
1461
1547
  if (needsStartUpdate) {
1462
1548
  const props = interval.start.properties;
1463
- interval.start = createPositionReferenceFromSegoff(this.client, newStart, interval.start.refType, op);
1549
+ interval.start = createPositionReferenceFromSegoff(this.client, newStart, interval.start.refType, op, startReferenceSlidingPreference(interval.stickiness));
1464
1550
  if (props) {
1465
1551
  interval.start.addProperties(props);
1466
1552
  }
@@ -1472,7 +1558,7 @@ export class IntervalCollection extends TypedEventEmitter {
1472
1558
  }
1473
1559
  if (needsEndUpdate) {
1474
1560
  const props = interval.end.properties;
1475
- interval.end = createPositionReferenceFromSegoff(this.client, newEnd, interval.end.refType, op);
1561
+ interval.end = createPositionReferenceFromSegoff(this.client, newEnd, interval.end.refType, op, endReferenceSlidingPreference(interval.stickiness));
1476
1562
  if (props) {
1477
1563
  interval.end.addProperties(props);
1478
1564
  }
@@ -1503,7 +1589,7 @@ export class IntervalCollection extends TypedEventEmitter {
1503
1589
  throw new LoggingError("attachSequence must be called");
1504
1590
  }
1505
1591
  this.localCollection.ensureSerializedId(serializedInterval);
1506
- const interval = this.localCollection.addInterval(serializedInterval.start, serializedInterval.end, serializedInterval.intervalType, serializedInterval.properties, op);
1592
+ const interval = this.localCollection.addInterval(serializedInterval.start, serializedInterval.end, serializedInterval.intervalType, serializedInterval.properties, op, serializedInterval.stickiness);
1507
1593
  if (interval) {
1508
1594
  if (this.onDeserialize) {
1509
1595
  this.onDeserialize(interval);
@@ -1546,40 +1632,35 @@ export class IntervalCollection extends TypedEventEmitter {
1546
1632
  return iterator;
1547
1633
  }
1548
1634
  /**
1549
- * @returns a forward iterator over all intervals in this collection with start point equal to `startPosition`.
1635
+ * {@inheritdoc IIntervalCollection.CreateForwardIteratorWithStartPosition}
1550
1636
  */
1551
1637
  CreateForwardIteratorWithStartPosition(startPosition) {
1552
1638
  const iterator = new IntervalCollectionIterator(this, true, startPosition);
1553
1639
  return iterator;
1554
1640
  }
1555
1641
  /**
1556
- * @returns a backward iterator over all intervals in this collection with start point equal to `startPosition`.
1642
+ * {@inheritdoc IIntervalCollection.CreateBackwardIteratorWithStartPosition}
1557
1643
  */
1558
1644
  CreateBackwardIteratorWithStartPosition(startPosition) {
1559
1645
  const iterator = new IntervalCollectionIterator(this, false, startPosition);
1560
1646
  return iterator;
1561
1647
  }
1562
1648
  /**
1563
- * @returns a forward iterator over all intervals in this collection with end point equal to `endPosition`.
1649
+ * {@inheritdoc IIntervalCollection.CreateForwardIteratorWithEndPosition}
1564
1650
  */
1565
1651
  CreateForwardIteratorWithEndPosition(endPosition) {
1566
1652
  const iterator = new IntervalCollectionIterator(this, true, undefined, endPosition);
1567
1653
  return iterator;
1568
1654
  }
1569
1655
  /**
1570
- * @returns a backward iterator over all intervals in this collection with end point equal to `endPosition`.
1656
+ * {@inheritdoc IIntervalCollection.CreateBackwardIteratorWithEndPosition}
1571
1657
  */
1572
1658
  CreateBackwardIteratorWithEndPosition(endPosition) {
1573
1659
  const iterator = new IntervalCollectionIterator(this, false, undefined, endPosition);
1574
1660
  return iterator;
1575
1661
  }
1576
1662
  /**
1577
- * Gathers iteration results that optionally match a start/end criteria into the provided array.
1578
- * @param results - Array to gather the results into. In lieu of a return value, this array will be populated with
1579
- * intervals matching the query upon edit.
1580
- * @param iteratesForward - whether or not iteration should be in the forward direction
1581
- * @param start - If provided, only match intervals whose start point is equal to `start`.
1582
- * @param end - If provided, only match intervals whose end point is equal to `end`.
1663
+ * {@inheritdoc IIntervalCollection.gatherIterationResults}
1583
1664
  */
1584
1665
  gatherIterationResults(results, iteratesForward, start, end) {
1585
1666
  if (!this.localCollection) {
@@ -1588,8 +1669,7 @@ export class IntervalCollection extends TypedEventEmitter {
1588
1669
  this.localCollection.overlappingIntervalsIndex.gatherIterationResults(results, iteratesForward, start, end);
1589
1670
  }
1590
1671
  /**
1591
- * @returns an array of all intervals in this collection that overlap with the interval
1592
- * `[startPosition, endPosition]`.
1672
+ * {@inheritdoc IIntervalCollection.findOverlappingIntervals}
1593
1673
  */
1594
1674
  findOverlappingIntervals(startPosition, endPosition) {
1595
1675
  if (!this.localCollection) {
@@ -1598,7 +1678,7 @@ export class IntervalCollection extends TypedEventEmitter {
1598
1678
  return this.localCollection.overlappingIntervalsIndex.findOverlappingIntervals(startPosition, endPosition);
1599
1679
  }
1600
1680
  /**
1601
- * Applies a function to each interval in this collection.
1681
+ * {@inheritdoc IIntervalCollection.map}
1602
1682
  */
1603
1683
  map(fn) {
1604
1684
  if (!this.localCollection) {
@@ -1608,12 +1688,18 @@ export class IntervalCollection extends TypedEventEmitter {
1608
1688
  fn(interval);
1609
1689
  }
1610
1690
  }
1691
+ /**
1692
+ * {@inheritdoc IIntervalCollection.previousInterval}
1693
+ */
1611
1694
  previousInterval(pos) {
1612
1695
  if (!this.localCollection) {
1613
1696
  throw new LoggingError("attachSequence must be called");
1614
1697
  }
1615
1698
  return this.localCollection.endIntervalIndex.previousInterval(pos);
1616
1699
  }
1700
+ /**
1701
+ * {@inheritdoc IIntervalCollection.nextInterval}
1702
+ */
1617
1703
  nextInterval(pos) {
1618
1704
  if (!this.localCollection) {
1619
1705
  throw new LoggingError("attachSequence must be called");