@fluidframework/sequence 2.23.0 → 2.31.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 (189) hide show
  1. package/CHANGELOG.md +510 -495
  2. package/api-report/sequence.legacy.alpha.api.md +67 -5
  3. package/dist/IntervalCollectionValues.d.ts +3 -51
  4. package/dist/IntervalCollectionValues.d.ts.map +1 -1
  5. package/dist/IntervalCollectionValues.js +6 -49
  6. package/dist/IntervalCollectionValues.js.map +1 -1
  7. package/dist/index.d.ts +4 -4
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +1 -8
  10. package/dist/index.js.map +1 -1
  11. package/dist/intervalCollection.d.ts +292 -63
  12. package/dist/intervalCollection.d.ts.map +1 -1
  13. package/dist/intervalCollection.js +111 -193
  14. package/dist/intervalCollection.js.map +1 -1
  15. package/dist/intervalCollectionMap.d.ts +11 -32
  16. package/dist/intervalCollectionMap.d.ts.map +1 -1
  17. package/dist/intervalCollectionMap.js +37 -90
  18. package/dist/intervalCollectionMap.js.map +1 -1
  19. package/dist/intervalCollectionMapInterfaces.d.ts +10 -83
  20. package/dist/intervalCollectionMapInterfaces.d.ts.map +1 -1
  21. package/dist/intervalCollectionMapInterfaces.js.map +1 -1
  22. package/dist/intervalIndex/endpointInRangeIndex.d.ts +10 -11
  23. package/dist/intervalIndex/endpointInRangeIndex.d.ts.map +1 -1
  24. package/dist/intervalIndex/endpointInRangeIndex.js +4 -5
  25. package/dist/intervalIndex/endpointInRangeIndex.js.map +1 -1
  26. package/dist/intervalIndex/endpointIndex.d.ts +12 -13
  27. package/dist/intervalIndex/endpointIndex.d.ts.map +1 -1
  28. package/dist/intervalIndex/endpointIndex.js +4 -5
  29. package/dist/intervalIndex/endpointIndex.js.map +1 -1
  30. package/dist/intervalIndex/idIntervalIndex.d.ts +6 -12
  31. package/dist/intervalIndex/idIntervalIndex.d.ts.map +1 -1
  32. package/dist/intervalIndex/idIntervalIndex.js +0 -3
  33. package/dist/intervalIndex/idIntervalIndex.js.map +1 -1
  34. package/dist/intervalIndex/index.d.ts +2 -2
  35. package/dist/intervalIndex/index.d.ts.map +1 -1
  36. package/dist/intervalIndex/index.js.map +1 -1
  37. package/dist/intervalIndex/intervalIndex.d.ts +28 -1
  38. package/dist/intervalIndex/intervalIndex.d.ts.map +1 -1
  39. package/dist/intervalIndex/intervalIndex.js.map +1 -1
  40. package/dist/intervalIndex/overlappingIntervalsIndex.d.ts +30 -13
  41. package/dist/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -1
  42. package/dist/intervalIndex/overlappingIntervalsIndex.js +4 -5
  43. package/dist/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
  44. package/dist/intervalIndex/overlappingSequenceIntervalsIndex.d.ts.map +1 -1
  45. package/dist/intervalIndex/overlappingSequenceIntervalsIndex.js +1 -1
  46. package/dist/intervalIndex/overlappingSequenceIntervalsIndex.js.map +1 -1
  47. package/dist/intervalIndex/sequenceIntervalIndexes.d.ts +2 -2
  48. package/dist/intervalIndex/sequenceIntervalIndexes.d.ts.map +1 -1
  49. package/dist/intervalIndex/sequenceIntervalIndexes.js.map +1 -1
  50. package/dist/intervalIndex/startpointInRangeIndex.d.ts +10 -11
  51. package/dist/intervalIndex/startpointInRangeIndex.d.ts.map +1 -1
  52. package/dist/intervalIndex/startpointInRangeIndex.js +4 -5
  53. package/dist/intervalIndex/startpointInRangeIndex.js.map +1 -1
  54. package/dist/intervals/index.d.ts +2 -3
  55. package/dist/intervals/index.d.ts.map +1 -1
  56. package/dist/intervals/index.js +1 -6
  57. package/dist/intervals/index.js.map +1 -1
  58. package/dist/intervals/intervalUtils.d.ts +3 -25
  59. package/dist/intervals/intervalUtils.d.ts.map +1 -1
  60. package/dist/intervals/intervalUtils.js.map +1 -1
  61. package/dist/intervals/sequenceInterval.d.ts +3 -8
  62. package/dist/intervals/sequenceInterval.d.ts.map +1 -1
  63. package/dist/intervals/sequenceInterval.js +1 -9
  64. package/dist/intervals/sequenceInterval.js.map +1 -1
  65. package/dist/legacy.d.ts +4 -0
  66. package/dist/packageVersion.d.ts +1 -1
  67. package/dist/packageVersion.js +1 -1
  68. package/dist/packageVersion.js.map +1 -1
  69. package/dist/sequence.d.ts +4 -6
  70. package/dist/sequence.d.ts.map +1 -1
  71. package/dist/sequence.js +3 -5
  72. package/dist/sequence.js.map +1 -1
  73. package/dist/sharedIntervalCollection.d.ts +2 -63
  74. package/dist/sharedIntervalCollection.d.ts.map +1 -1
  75. package/dist/sharedIntervalCollection.js +0 -113
  76. package/dist/sharedIntervalCollection.js.map +1 -1
  77. package/dist/sharedString.d.ts.map +1 -1
  78. package/dist/sharedString.js +6 -6
  79. package/dist/sharedString.js.map +1 -1
  80. package/lib/IntervalCollectionValues.d.ts +3 -51
  81. package/lib/IntervalCollectionValues.d.ts.map +1 -1
  82. package/lib/IntervalCollectionValues.js +5 -47
  83. package/lib/IntervalCollectionValues.js.map +1 -1
  84. package/lib/index.d.ts +4 -4
  85. package/lib/index.d.ts.map +1 -1
  86. package/lib/index.js +2 -3
  87. package/lib/index.js.map +1 -1
  88. package/lib/intervalCollection.d.ts +292 -63
  89. package/lib/intervalCollection.d.ts.map +1 -1
  90. package/lib/intervalCollection.js +113 -191
  91. package/lib/intervalCollection.js.map +1 -1
  92. package/lib/intervalCollectionMap.d.ts +11 -32
  93. package/lib/intervalCollectionMap.d.ts.map +1 -1
  94. package/lib/intervalCollectionMap.js +39 -92
  95. package/lib/intervalCollectionMap.js.map +1 -1
  96. package/lib/intervalCollectionMapInterfaces.d.ts +10 -83
  97. package/lib/intervalCollectionMapInterfaces.d.ts.map +1 -1
  98. package/lib/intervalCollectionMapInterfaces.js.map +1 -1
  99. package/lib/intervalIndex/endpointInRangeIndex.d.ts +10 -11
  100. package/lib/intervalIndex/endpointInRangeIndex.d.ts.map +1 -1
  101. package/lib/intervalIndex/endpointInRangeIndex.js +5 -6
  102. package/lib/intervalIndex/endpointInRangeIndex.js.map +1 -1
  103. package/lib/intervalIndex/endpointIndex.d.ts +12 -13
  104. package/lib/intervalIndex/endpointIndex.d.ts.map +1 -1
  105. package/lib/intervalIndex/endpointIndex.js +5 -6
  106. package/lib/intervalIndex/endpointIndex.js.map +1 -1
  107. package/lib/intervalIndex/idIntervalIndex.d.ts +6 -12
  108. package/lib/intervalIndex/idIntervalIndex.d.ts.map +1 -1
  109. package/lib/intervalIndex/idIntervalIndex.js +0 -3
  110. package/lib/intervalIndex/idIntervalIndex.js.map +1 -1
  111. package/lib/intervalIndex/index.d.ts +2 -2
  112. package/lib/intervalIndex/index.d.ts.map +1 -1
  113. package/lib/intervalIndex/index.js.map +1 -1
  114. package/lib/intervalIndex/intervalIndex.d.ts +28 -1
  115. package/lib/intervalIndex/intervalIndex.d.ts.map +1 -1
  116. package/lib/intervalIndex/intervalIndex.js.map +1 -1
  117. package/lib/intervalIndex/overlappingIntervalsIndex.d.ts +30 -13
  118. package/lib/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -1
  119. package/lib/intervalIndex/overlappingIntervalsIndex.js +5 -6
  120. package/lib/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
  121. package/lib/intervalIndex/overlappingSequenceIntervalsIndex.d.ts.map +1 -1
  122. package/lib/intervalIndex/overlappingSequenceIntervalsIndex.js +2 -2
  123. package/lib/intervalIndex/overlappingSequenceIntervalsIndex.js.map +1 -1
  124. package/lib/intervalIndex/sequenceIntervalIndexes.d.ts +2 -2
  125. package/lib/intervalIndex/sequenceIntervalIndexes.d.ts.map +1 -1
  126. package/lib/intervalIndex/sequenceIntervalIndexes.js.map +1 -1
  127. package/lib/intervalIndex/startpointInRangeIndex.d.ts +10 -11
  128. package/lib/intervalIndex/startpointInRangeIndex.d.ts.map +1 -1
  129. package/lib/intervalIndex/startpointInRangeIndex.js +5 -6
  130. package/lib/intervalIndex/startpointInRangeIndex.js.map +1 -1
  131. package/lib/intervals/index.d.ts +2 -3
  132. package/lib/intervals/index.d.ts.map +1 -1
  133. package/lib/intervals/index.js +1 -2
  134. package/lib/intervals/index.js.map +1 -1
  135. package/lib/intervals/intervalUtils.d.ts +3 -25
  136. package/lib/intervals/intervalUtils.d.ts.map +1 -1
  137. package/lib/intervals/intervalUtils.js.map +1 -1
  138. package/lib/intervals/sequenceInterval.d.ts +3 -8
  139. package/lib/intervals/sequenceInterval.d.ts.map +1 -1
  140. package/lib/intervals/sequenceInterval.js +0 -8
  141. package/lib/intervals/sequenceInterval.js.map +1 -1
  142. package/lib/legacy.d.ts +4 -0
  143. package/lib/packageVersion.d.ts +1 -1
  144. package/lib/packageVersion.js +1 -1
  145. package/lib/packageVersion.js.map +1 -1
  146. package/lib/sequence.d.ts +4 -6
  147. package/lib/sequence.d.ts.map +1 -1
  148. package/lib/sequence.js +3 -5
  149. package/lib/sequence.js.map +1 -1
  150. package/lib/sharedIntervalCollection.d.ts +2 -63
  151. package/lib/sharedIntervalCollection.d.ts.map +1 -1
  152. package/lib/sharedIntervalCollection.js +1 -110
  153. package/lib/sharedIntervalCollection.js.map +1 -1
  154. package/lib/sharedString.d.ts.map +1 -1
  155. package/lib/sharedString.js +6 -6
  156. package/lib/sharedString.js.map +1 -1
  157. package/lib/tsdoc-metadata.json +1 -1
  158. package/package.json +20 -23
  159. package/src/IntervalCollectionValues.ts +10 -93
  160. package/src/index.ts +6 -17
  161. package/src/intervalCollection.ts +524 -343
  162. package/src/intervalCollectionMap.ts +72 -140
  163. package/src/intervalCollectionMapInterfaces.ts +13 -104
  164. package/src/intervalIndex/endpointInRangeIndex.ts +17 -29
  165. package/src/intervalIndex/endpointIndex.ts +19 -31
  166. package/src/intervalIndex/idIntervalIndex.ts +15 -25
  167. package/src/intervalIndex/index.ts +2 -1
  168. package/src/intervalIndex/intervalIndex.ts +30 -1
  169. package/src/intervalIndex/overlappingIntervalsIndex.ts +50 -27
  170. package/src/intervalIndex/overlappingSequenceIntervalsIndex.ts +2 -3
  171. package/src/intervalIndex/sequenceIntervalIndexes.ts +2 -2
  172. package/src/intervalIndex/startpointInRangeIndex.ts +17 -29
  173. package/src/intervals/index.ts +0 -3
  174. package/src/intervals/intervalUtils.ts +3 -38
  175. package/src/intervals/sequenceInterval.ts +2 -12
  176. package/src/packageVersion.ts +1 -1
  177. package/src/sequence.ts +8 -20
  178. package/src/sharedIntervalCollection.ts +5 -183
  179. package/src/sharedString.ts +6 -24
  180. package/dist/intervals/interval.d.ts +0 -76
  181. package/dist/intervals/interval.d.ts.map +0 -1
  182. package/dist/intervals/interval.js +0 -167
  183. package/dist/intervals/interval.js.map +0 -1
  184. package/lib/intervals/interval.d.ts +0 -76
  185. package/lib/intervals/interval.d.ts.map +0 -1
  186. package/lib/intervals/interval.js +0 -162
  187. package/lib/intervals/interval.js.map +0 -1
  188. package/prettier.config.cjs +0 -8
  189. package/src/intervals/interval.ts +0 -226
@@ -4,7 +4,6 @@
4
4
  */
5
5
 
6
6
  /* eslint-disable no-bitwise */
7
- /* eslint-disable import/no-deprecated */
8
7
 
9
8
  import { TypedEventEmitter } from "@fluid-internal/client-utils";
10
9
  import { IEvent } from "@fluidframework/core-interfaces";
@@ -21,7 +20,6 @@ import {
21
20
  UnassignedSequenceNumber,
22
21
  UniversalSequenceNumber,
23
22
  addProperties,
24
- createMap,
25
23
  getSlideToSegoff,
26
24
  refTypeIncludesFlag,
27
25
  reservedRangeLabelsKey,
@@ -30,49 +28,49 @@ import {
30
28
  endpointPosAndSide,
31
29
  PropertiesManager,
32
30
  type ISegmentInternal,
31
+ createMap,
33
32
  } from "@fluidframework/merge-tree/internal";
34
33
  import { LoggingError, UsageError } from "@fluidframework/telemetry-utils/internal";
35
34
  import { v4 as uuid } from "uuid";
36
35
 
37
36
  import {
38
- IIntervalCollectionFactory,
39
37
  IIntervalCollectionOperation,
40
- IIntervalCollectionType,
41
38
  IMapMessageLocalMetadata,
42
- IValueOpEmitter,
43
39
  SequenceOptions,
40
+ type IIntervalCollectionTypeOperationValue,
44
41
  } from "./intervalCollectionMapInterfaces.js";
45
42
  import {
43
+ createIdIntervalIndex,
46
44
  EndpointIndex,
47
- IEndpointIndex,
48
- IIdIntervalIndex,
49
- IOverlappingIntervalsIndex,
50
- IntervalIndex,
51
45
  OverlappingIntervalsIndex,
52
- createIdIntervalIndex,
46
+ type IEndpointIndex,
47
+ type IIdIntervalIndex,
48
+ // eslint-disable-next-line import/no-deprecated
49
+ type IntervalIndex,
50
+ type ISequenceOverlappingIntervalsIndex,
51
+ type SequenceIntervalIndex,
53
52
  } from "./intervalIndex/index.js";
54
53
  import {
55
54
  CompressedSerializedInterval,
56
- IIntervalHelpers,
57
- ISerializableInterval,
58
55
  ISerializedInterval,
59
- Interval,
60
- IntervalOpType,
56
+ IntervalDeltaOpType,
61
57
  IntervalStickiness,
62
58
  IntervalType,
63
59
  SequenceInterval,
64
60
  SequenceIntervalClass,
65
61
  SerializedIntervalDelta,
66
- createInterval,
67
62
  createPositionReferenceFromSegoff,
63
+ createSequenceInterval,
68
64
  endReferenceSlidingPreference,
69
- sequenceIntervalHelpers,
70
65
  startReferenceSlidingPreference,
66
+ type ISerializableInterval,
71
67
  type ISerializableIntervalPrivate,
72
68
  } from "./intervals/index.js";
73
69
 
74
70
  export const reservedIntervalIdKey = "intervalId";
75
71
 
72
+ export type ISerializedIntervalCollectionV1 = ISerializedInterval[];
73
+
76
74
  export interface ISerializedIntervalCollectionV2 {
77
75
  label: string;
78
76
  version: 2;
@@ -166,40 +164,26 @@ export function computeStickinessFromSide(
166
164
  return stickiness as IntervalStickiness;
167
165
  }
168
166
 
169
- export function createIntervalIndex() {
170
- const helpers: IIntervalHelpers<Interval> = {
171
- create: createInterval,
172
- };
173
- const lc = new LocalIntervalCollection<Interval>(
174
- undefined as any as Client,
175
- "",
176
- helpers,
177
- {},
178
- );
179
- return lc;
180
- }
181
-
182
- export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
167
+ export class LocalIntervalCollection {
183
168
  private static readonly legacyIdPrefix = "legacy";
184
- public readonly overlappingIntervalsIndex: IOverlappingIntervalsIndex<TInterval>;
185
- public readonly idIntervalIndex: IIdIntervalIndex<TInterval>;
186
- public readonly endIntervalIndex: IEndpointIndex<TInterval>;
187
- private readonly indexes: Set<IntervalIndex<TInterval>>;
169
+ public readonly overlappingIntervalsIndex: ISequenceOverlappingIntervalsIndex;
170
+ public readonly idIntervalIndex: IIdIntervalIndex;
171
+ public readonly endIntervalIndex: IEndpointIndex;
172
+ private readonly indexes: Set<SequenceIntervalIndex>;
188
173
 
189
174
  constructor(
190
175
  private readonly client: Client,
191
176
  private readonly label: string,
192
- private readonly helpers: IIntervalHelpers<TInterval>,
193
177
  private readonly options: Partial<SequenceOptions>,
194
178
  /** Callback invoked each time one of the endpoints of an interval slides. */
195
179
  private readonly onPositionChange?: (
196
- interval: TInterval,
197
- previousInterval: TInterval,
180
+ interval: SequenceIntervalClass,
181
+ previousInterval: SequenceIntervalClass,
198
182
  ) => void,
199
183
  ) {
200
- this.overlappingIntervalsIndex = new OverlappingIntervalsIndex(client, helpers);
201
- this.idIntervalIndex = createIdIntervalIndex<TInterval>();
202
- this.endIntervalIndex = new EndpointIndex(client, helpers);
184
+ this.overlappingIntervalsIndex = new OverlappingIntervalsIndex(client);
185
+ this.idIntervalIndex = createIdIntervalIndex();
186
+ this.endIntervalIndex = new EndpointIndex(client);
203
187
  this.indexes = new Set([
204
188
  this.overlappingIntervalsIndex,
205
189
  this.idIntervalIndex,
@@ -245,21 +229,21 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
245
229
  return id;
246
230
  }
247
231
 
248
- private removeIntervalFromIndexes(interval: TInterval) {
232
+ private removeIntervalFromIndexes(interval: SequenceIntervalClass) {
249
233
  for (const index of this.indexes) {
250
234
  index.remove(interval);
251
235
  }
252
236
  }
253
237
 
254
- public appendIndex(index: IntervalIndex<TInterval>) {
238
+ public appendIndex(index: SequenceIntervalIndex) {
255
239
  this.indexes.add(index);
256
240
  }
257
241
 
258
- public removeIndex(index: IntervalIndex<TInterval>): boolean {
242
+ public removeIndex(index: SequenceIntervalIndex): boolean {
259
243
  return this.indexes.delete(index);
260
244
  }
261
245
 
262
- public removeExistingInterval(interval: TInterval) {
246
+ public removeExistingInterval(interval: SequenceIntervalClass) {
263
247
  this.removeIntervalFromIndexes(interval);
264
248
  this.removeIntervalListeners(interval);
265
249
  }
@@ -269,8 +253,8 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
269
253
  end: SequencePlace,
270
254
  intervalType: IntervalType,
271
255
  op?: ISequencedDocumentMessage,
272
- ): TInterval {
273
- return this.helpers.create(
256
+ ): SequenceIntervalClass {
257
+ return createSequenceInterval(
274
258
  this.label,
275
259
  start,
276
260
  end,
@@ -289,7 +273,7 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
289
273
  props?: PropertySet,
290
274
  op?: ISequencedDocumentMessage,
291
275
  ) {
292
- const interval: TInterval = this.createInterval(start, end, intervalType, op);
276
+ const interval: SequenceIntervalClass = this.createInterval(start, end, intervalType, op);
293
277
  if (interval) {
294
278
  if (!interval.properties) {
295
279
  interval.properties = createMap<any>();
@@ -315,27 +299,25 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
315
299
  return interval;
316
300
  }
317
301
 
318
- private linkEndpointsToInterval(interval: TInterval): void {
319
- if (interval instanceof SequenceIntervalClass) {
320
- interval.start.addProperties({ interval });
321
- interval.end.addProperties({ interval });
322
- }
302
+ private linkEndpointsToInterval(interval: SequenceIntervalClass): void {
303
+ interval.start.addProperties({ interval });
304
+ interval.end.addProperties({ interval });
323
305
  }
324
306
 
325
- private addIntervalToIndexes(interval: TInterval) {
307
+ private addIntervalToIndexes(interval: SequenceIntervalClass) {
326
308
  for (const index of this.indexes) {
327
309
  index.add(interval);
328
310
  }
329
311
  }
330
312
 
331
- public add(interval: TInterval): void {
313
+ public add(interval: SequenceIntervalClass): void {
332
314
  this.linkEndpointsToInterval(interval);
333
315
  this.addIntervalToIndexes(interval);
334
316
  this.addIntervalListeners(interval);
335
317
  }
336
318
 
337
319
  public changeInterval(
338
- interval: TInterval,
320
+ interval: SequenceIntervalClass,
339
321
  start: SequencePlace | undefined,
340
322
  end: SequencePlace | undefined,
341
323
  op?: ISequencedDocumentMessage,
@@ -348,7 +330,7 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
348
330
  op,
349
331
  localSeq,
350
332
  this.options.mergeTreeReferencesCanSlideToEndpoint,
351
- ) as TInterval | undefined;
333
+ );
352
334
  if (newInterval) {
353
335
  this.removeExistingInterval(interval);
354
336
  this.add(newInterval);
@@ -356,7 +338,12 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
356
338
  return newInterval;
357
339
  }
358
340
 
359
- public serialize(): ISerializedIntervalCollectionV2 {
341
+ public serialize(
342
+ version: "1" | "2",
343
+ ): ISerializedIntervalCollectionV1 | ISerializedIntervalCollectionV2 {
344
+ if (version === "1") {
345
+ return Array.from(this.idIntervalIndex, (interval) => interval.serialize());
346
+ }
360
347
  return {
361
348
  label: this.label,
362
349
  intervals: Array.from(this.idIntervalIndex, (interval) =>
@@ -366,7 +353,7 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
366
353
  };
367
354
  }
368
355
 
369
- private addIntervalListeners(interval: TInterval) {
356
+ private addIntervalListeners(interval: SequenceIntervalClass) {
370
357
  const cloneRef = (ref: LocalReferencePosition) => {
371
358
  const segment = ref.getSegment();
372
359
  if (segment === undefined) {
@@ -385,193 +372,87 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
385
372
  ref.canSlideToEndpoint,
386
373
  );
387
374
  };
388
- if (interval instanceof SequenceIntervalClass) {
389
- let previousInterval: (TInterval & SequenceIntervalClass) | undefined;
390
- let pendingChanges = 0;
391
- interval.addPositionChangeListeners(
392
- () => {
393
- pendingChanges++;
394
- // Note: both start and end can change and invoke beforeSlide on each endpoint before afterSlide.
395
- if (!previousInterval) {
396
- previousInterval = interval.clone() as TInterval & SequenceIntervalClass;
397
- previousInterval.start = cloneRef(previousInterval.start);
398
- previousInterval.end = cloneRef(previousInterval.end);
399
- this.removeIntervalFromIndexes(interval);
400
- }
401
- },
402
- () => {
403
- assert(
404
- previousInterval !== undefined,
405
- 0x3fa /* Invalid interleaving of before/after slide */,
406
- );
407
- pendingChanges--;
408
- if (pendingChanges === 0) {
409
- this.addIntervalToIndexes(interval);
410
- this.onPositionChange?.(interval, previousInterval);
411
- previousInterval = undefined;
412
- }
413
- },
414
- );
415
- }
416
- }
417
-
418
- private removeIntervalListeners(interval: TInterval) {
419
- if (interval instanceof SequenceIntervalClass) {
420
- interval.removePositionChangeListeners();
421
- }
422
- }
423
- }
424
-
425
- class SequenceIntervalCollectionFactory
426
- implements IIntervalCollectionFactory<SequenceInterval>
427
- {
428
- public load(
429
- emitter: IValueOpEmitter,
430
- raw: ISerializedInterval[] | ISerializedIntervalCollectionV2 = [],
431
- options?: Partial<SequenceOptions>,
432
- ): IntervalCollection<SequenceInterval> {
433
- return new IntervalCollection<SequenceInterval>(
434
- sequenceIntervalHelpers,
435
- true,
436
- emitter,
437
- raw,
438
- options,
375
+ let previousInterval: SequenceIntervalClass | undefined;
376
+ let pendingChanges = 0;
377
+ interval.addPositionChangeListeners(
378
+ () => {
379
+ pendingChanges++;
380
+ // Note: both start and end can change and invoke beforeSlide on each endpoint before afterSlide.
381
+ if (!previousInterval) {
382
+ previousInterval = interval.clone();
383
+ previousInterval.start = cloneRef(previousInterval.start);
384
+ previousInterval.end = cloneRef(previousInterval.end);
385
+ this.removeIntervalFromIndexes(interval);
386
+ }
387
+ },
388
+ () => {
389
+ assert(
390
+ previousInterval !== undefined,
391
+ 0x3fa /* Invalid interleaving of before/after slide */,
392
+ );
393
+ pendingChanges--;
394
+ if (pendingChanges === 0) {
395
+ this.addIntervalToIndexes(interval);
396
+ this.onPositionChange?.(interval, previousInterval);
397
+ previousInterval = undefined;
398
+ }
399
+ },
439
400
  );
440
401
  }
441
402
 
442
- public store(
443
- value: IntervalCollection<SequenceInterval>,
444
- ): ISerializedInterval[] | ISerializedIntervalCollectionV2 {
445
- return value.serializeInternal();
446
- }
447
- }
448
-
449
- export class SequenceIntervalCollectionValueType
450
- implements IIntervalCollectionType<SequenceInterval>
451
- {
452
- public static Name = "sharedStringIntervalCollection";
453
-
454
- public get name(): string {
455
- return SequenceIntervalCollectionValueType.Name;
456
- }
457
-
458
- public get factory(): IIntervalCollectionFactory<SequenceInterval> {
459
- return SequenceIntervalCollectionValueType._factory;
460
- }
461
-
462
- public get ops(): Map<IntervalOpType, IIntervalCollectionOperation<SequenceInterval>> {
463
- return SequenceIntervalCollectionValueType._ops;
464
- }
465
-
466
- private static readonly _factory: IIntervalCollectionFactory<SequenceInterval> =
467
- new SequenceIntervalCollectionFactory();
468
-
469
- private static readonly _ops = makeOpsMap<SequenceInterval>();
470
- }
471
-
472
- class IntervalCollectionFactory implements IIntervalCollectionFactory<Interval> {
473
- public load(
474
- emitter: IValueOpEmitter,
475
- raw: ISerializedInterval[] | ISerializedIntervalCollectionV2 = [],
476
- options?: Partial<SequenceOptions>,
477
- ): IntervalCollection<Interval> {
478
- const helpers: IIntervalHelpers<Interval> = {
479
- create: createInterval,
480
- };
481
- const collection = new IntervalCollection<Interval>(helpers, false, emitter, raw, options);
482
- collection.attachGraph(undefined as any as Client, "");
483
- return collection;
484
- }
485
-
486
- public store(value: IntervalCollection<Interval>): ISerializedIntervalCollectionV2 {
487
- return value.serializeInternal();
403
+ private removeIntervalListeners(interval: SequenceIntervalClass) {
404
+ interval.removePositionChangeListeners();
488
405
  }
489
406
  }
490
407
 
491
- export class IntervalCollectionValueType implements IIntervalCollectionType<Interval> {
492
- public static Name = "sharedIntervalCollection";
493
-
494
- public get name(): string {
495
- return IntervalCollectionValueType.Name;
496
- }
497
-
498
- public get factory(): IIntervalCollectionFactory<Interval> {
499
- return IntervalCollectionValueType._factory;
500
- }
501
-
502
- public get ops(): Map<IntervalOpType, IIntervalCollectionOperation<Interval>> {
503
- return IntervalCollectionValueType._ops;
408
+ const rebase: IIntervalCollectionOperation["rebase"] = (collection, op, localOpMetadata) => {
409
+ const { localSeq } = localOpMetadata;
410
+ const rebasedValue = collection.rebaseLocalInterval(op.opName, op.value, localSeq);
411
+ if (rebasedValue === undefined) {
412
+ return undefined;
504
413
  }
505
-
506
- private static readonly _factory: IIntervalCollectionFactory<Interval> =
507
- new IntervalCollectionFactory();
508
- private static readonly _ops = makeOpsMap<Interval>();
509
- }
510
-
511
- export function makeOpsMap<T extends ISerializableInterval>(): Map<
512
- IntervalOpType,
513
- IIntervalCollectionOperation<T>
514
- > {
515
- const rebase: IIntervalCollectionOperation<T>["rebase"] = (
516
- collection,
517
- op,
518
- localOpMetadata,
519
- ) => {
520
- const { localSeq } = localOpMetadata;
521
- const rebasedValue = collection.rebaseLocalInterval(op.opName, op.value, localSeq);
522
- if (rebasedValue === undefined) {
523
- return undefined;
524
- }
525
- const rebasedOp = { ...op, value: rebasedValue };
526
- return { rebasedOp, rebasedLocalOpMetadata: localOpMetadata };
527
- };
528
-
529
- return new Map<IntervalOpType, IIntervalCollectionOperation<T>>([
530
- [
531
- IntervalOpType.ADD,
532
- {
533
- process: (collection, params, local, op, localOpMetadata) => {
534
- // if params is undefined, the interval was deleted during
535
- // rebasing
536
- if (!params) {
537
- return;
538
- }
539
- assert(op !== undefined, 0x3fb /* op should exist here */);
540
- collection.ackAdd(params, local, op, localOpMetadata);
541
- },
542
- rebase,
543
- },
544
- ],
545
- [
546
- IntervalOpType.DELETE,
547
- {
548
- process: (collection, params, local, op) => {
549
- assert(op !== undefined, 0x3fc /* op should exist here */);
550
- collection.ackDelete(params, local, op);
551
- },
552
- rebase: (collection, op, localOpMetadata) => {
553
- // Deletion of intervals is based on id, so requires no rebasing.
554
- return { rebasedOp: op, rebasedLocalOpMetadata: localOpMetadata };
555
- },
556
- },
557
- ],
558
- [
559
- IntervalOpType.CHANGE,
560
- {
561
- process: (collection, params, local, op, localOpMetadata) => {
562
- // if params is undefined, the interval was deleted during
563
- // rebasing
564
- if (!params) {
565
- return;
566
- }
567
- assert(op !== undefined, 0x3fd /* op should exist here */);
568
- collection.ackChange(params, local, op, localOpMetadata);
569
- },
570
- rebase,
571
- },
572
- ],
573
- ]);
574
- }
414
+ const rebasedOp = { ...op, value: rebasedValue };
415
+ return { rebasedOp, rebasedLocalOpMetadata: localOpMetadata };
416
+ };
417
+
418
+ export const opsMap: Record<IntervalDeltaOpType, IIntervalCollectionOperation> = {
419
+ [IntervalDeltaOpType.ADD]: {
420
+ process: (collection, params, local, op, localOpMetadata) => {
421
+ // if params is undefined, the interval was deleted during
422
+ // rebasing
423
+ if (!params) {
424
+ return;
425
+ }
426
+ assert(op !== undefined, 0x3fb /* op should exist here */);
427
+ collection.ackAdd(params, local, op, localOpMetadata);
428
+ },
429
+ rebase,
430
+ },
431
+
432
+ [IntervalDeltaOpType.DELETE]: {
433
+ process: (collection, params, local, op) => {
434
+ assert(op !== undefined, 0x3fc /* op should exist here */);
435
+ collection.ackDelete(params, local, op);
436
+ },
437
+ rebase: (collection, op, localOpMetadata) => {
438
+ // Deletion of intervals is based on id, so requires no rebasing.
439
+ return { rebasedOp: op, rebasedLocalOpMetadata: localOpMetadata };
440
+ },
441
+ },
442
+
443
+ [IntervalDeltaOpType.CHANGE]: {
444
+ process: (collection, params, local, op, localOpMetadata) => {
445
+ // if params is undefined, the interval was deleted during
446
+ // rebasing
447
+ if (!params) {
448
+ return;
449
+ }
450
+ assert(op !== undefined, 0x3fd /* op should exist here */);
451
+ collection.ackChange(params, local, op, localOpMetadata);
452
+ },
453
+ rebase,
454
+ },
455
+ };
575
456
 
576
457
  /**
577
458
  * @legacy
@@ -579,14 +460,12 @@ export function makeOpsMap<T extends ISerializableInterval>(): Map<
579
460
  */
580
461
  export type DeserializeCallback = (properties: PropertySet) => void;
581
462
 
582
- class IntervalCollectionIterator<TInterval extends ISerializableInterval>
583
- implements Iterator<TInterval>
584
- {
585
- private readonly results: TInterval[];
463
+ class IntervalCollectionIterator implements Iterator<SequenceIntervalClass> {
464
+ private readonly results: SequenceIntervalClass[];
586
465
  private index: number;
587
466
 
588
467
  constructor(
589
- collection: IntervalCollection<TInterval>,
468
+ collection: IntervalCollection,
590
469
  iteratesForward: boolean = true,
591
470
  start?: number,
592
471
  end?: number,
@@ -597,7 +476,7 @@ class IntervalCollectionIterator<TInterval extends ISerializableInterval>
597
476
  collection.gatherIterationResults(this.results, iteratesForward, start, end);
598
477
  }
599
478
 
600
- public next(): IteratorResult<TInterval> {
479
+ public next(): IteratorResult<SequenceIntervalClass> {
601
480
  if (this.index < this.results.length) {
602
481
  return {
603
482
  value: this.results[this.index++],
@@ -616,6 +495,7 @@ class IntervalCollectionIterator<TInterval extends ISerializableInterval>
616
495
  * Change events emitted by `IntervalCollection`s
617
496
  * @legacy
618
497
  * @alpha
498
+ * @remarks The generic version of this interface is no longer used and will be removed. Use {@link ISequenceIntervalCollectionEvents} instead.
619
499
  */
620
500
  export interface IIntervalCollectionEvent<TInterval extends ISerializableInterval>
621
501
  extends IEvent {
@@ -697,11 +577,96 @@ export interface IIntervalCollectionEvent<TInterval extends ISerializableInterva
697
577
  ): void;
698
578
  }
699
579
 
580
+ /**
581
+ * Change events emitted by `IntervalCollection`s
582
+ * @legacy
583
+ * @alpha
584
+ */
585
+ export interface ISequenceIntervalCollectionEvents extends IEvent {
586
+ /**
587
+ * This event is invoked whenever the endpoints of an interval may have changed.
588
+ * This can happen on:
589
+ * - local endpoint modification
590
+ * - ack of a remote endpoint modification
591
+ * - position change due to segment sliding (slides due to mergeTree segment deletion will always appear local)
592
+ * The `interval` argument reflects the new values.
593
+ * `previousInterval` contains transient `ReferencePosition`s at the same location as the interval's original
594
+ * endpoints. These references should be used for position information only.
595
+ * `local` reflects whether the change originated locally.
596
+ * `op` is defined if and only if the server has acked this change.
597
+ * `slide` is true if the change is due to sliding on removal of position
598
+ */
599
+ (
600
+ event: "changeInterval",
601
+ listener: (
602
+ interval: SequenceInterval,
603
+ previousInterval: SequenceInterval,
604
+ local: boolean,
605
+ op: ISequencedDocumentMessage | undefined,
606
+ slide: boolean,
607
+ ) => void,
608
+ ): void;
609
+ /**
610
+ * This event is invoked whenever an interval is added or removed from the collection.
611
+ * `local` reflects whether the change originated locally.
612
+ * `op` is defined if and only if the server has acked this change.
613
+ */
614
+ (
615
+ event: "addInterval" | "deleteInterval",
616
+ listener: (
617
+ interval: SequenceInterval,
618
+ local: boolean,
619
+ op: ISequencedDocumentMessage | undefined,
620
+ ) => void,
621
+ ): void;
622
+ /**
623
+ * This event is invoked whenever an interval's properties have changed.
624
+ * `interval` reflects the state of the updated properties.
625
+ * `propertyDeltas` is a map-like whose keys contain all values that were changed, and whose
626
+ * values contain all previous values of the property set.
627
+ * This object can be used directly in a call to `changeProperties` to revert the property change if desired.
628
+ * `local` reflects whether the change originated locally.
629
+ * `op` is defined if and only if the server has acked this change.
630
+ */
631
+ (
632
+ event: "propertyChanged",
633
+ listener: (
634
+ interval: SequenceInterval,
635
+ propertyDeltas: PropertySet,
636
+ local: boolean,
637
+ op: ISequencedDocumentMessage | undefined,
638
+ ) => void,
639
+ ): void;
640
+ /**
641
+ * This event is invoked whenever an interval's endpoints or properties (or both) have changed.
642
+ * `interval` reflects the state of the updated endpoints or properties.
643
+ * `propertyDeltas` is a map-like whose keys contain all values that were changed, and whose
644
+ * values contain all previous values of the property set.
645
+ * This object can be used directly in a call to `changeProperties` to revert the property change if desired.
646
+ * 'previousInterval' contains transient `ReferencePosition`s at the same location as the interval's original
647
+ * endpoints. These references should be used for position information only. In the case of a property change
648
+ * only, this argument should be undefined.
649
+ * `local` reflects whether the change originated locally.
650
+ * `slide` is true if the change is due to sliding on removal of position.
651
+ */
652
+ (
653
+ event: "changed",
654
+ listener: (
655
+ interval: SequenceInterval,
656
+ propertyDeltas: PropertySet,
657
+ previousInterval: SequenceInterval | undefined,
658
+ local: boolean,
659
+ slide: boolean,
660
+ ) => void,
661
+ ): void;
662
+ }
663
+
700
664
  /**
701
665
  * Collection of intervals that supports addition, modification, removal, and efficient spatial querying.
702
666
  * Changes to this collection will be incur updates on collaborating clients (i.e. they are not local-only).
703
667
  * @legacy
704
668
  * @alpha
669
+ * @deprecated The generic version of this interface is no longer used and will be removed. Use {@link ISequenceIntervalCollection} instead.
705
670
  */
706
671
  export interface IIntervalCollection<TInterval extends ISerializableInterval>
707
672
  extends TypedEventEmitter<IIntervalCollectionEvent<TInterval>> {
@@ -714,6 +679,7 @@ export interface IIntervalCollection<TInterval extends ISerializableInterval>
714
679
  * @remarks After attaching an index to an interval collection, applications should typically store this
715
680
  * index somewhere in their in-memory data model for future reference and querying.
716
681
  */
682
+ // eslint-disable-next-line import/no-deprecated
717
683
  attachIndex(index: IntervalIndex<TInterval>): void;
718
684
  /**
719
685
  * Detaches an index from this collection.
@@ -722,6 +688,7 @@ export interface IIntervalCollection<TInterval extends ISerializableInterval>
722
688
  *
723
689
  * @returns `false` if the target index cannot be found in the indexes, otherwise remove all intervals in the index and return `true`.
724
690
  */
691
+ // eslint-disable-next-line import/no-deprecated
725
692
  detachIndex(index: IntervalIndex<TInterval>): boolean;
726
693
  /**
727
694
  * @returns the interval in this collection that has the provided `id`.
@@ -913,15 +880,231 @@ export interface IIntervalCollection<TInterval extends ISerializableInterval>
913
880
  nextInterval(pos: number): TInterval | undefined;
914
881
  }
915
882
 
883
+ /**
884
+ * Collection of intervals that supports addition, modification, removal, and efficient spatial querying.
885
+ * Changes to this collection will be incur updates on collaborating clients (i.e. they are not local-only).
886
+ * @legacy
887
+ * @alpha
888
+ */
889
+ export interface ISequenceIntervalCollection
890
+ extends TypedEventEmitter<ISequenceIntervalCollectionEvents> {
891
+ readonly attached: boolean;
892
+ /**
893
+ * Attaches an index to this collection.
894
+ * All intervals which are part of this collection will be added to the index, and the index will automatically
895
+ * be updated when this collection updates due to local or remote changes.
896
+ *
897
+ * @remarks After attaching an index to an interval collection, applications should typically store this
898
+ * index somewhere in their in-memory data model for future reference and querying.
899
+ */
900
+ attachIndex(index: SequenceIntervalIndex): void;
901
+ /**
902
+ * Detaches an index from this collection.
903
+ * All intervals which are part of this collection will be removed from the index, and updates to this collection
904
+ * due to local or remote changes will no longer incur updates to the index.
905
+ *
906
+ * @returns `false` if the target index cannot be found in the indexes, otherwise remove all intervals in the index and return `true`.
907
+ */
908
+ detachIndex(index: SequenceIntervalIndex): boolean;
909
+ /**
910
+ * @returns the interval in this collection that has the provided `id`.
911
+ * If no interval in the collection has this `id`, returns `undefined`.
912
+ */
913
+ getIntervalById(id: string): SequenceInterval | undefined;
914
+ /**
915
+ * Creates a new interval and add it to the collection.
916
+ * @param start - interval start position (inclusive)
917
+ * @param end - interval end position (exclusive)
918
+ * @param props - properties of the interval
919
+ * @returns - the created interval
920
+ * @remarks See documentation on {@link SequenceInterval} for comments on
921
+ * interval endpoint semantics: there are subtleties with how the current
922
+ * half-open behavior is represented.
923
+ *
924
+ * Note that intervals may behave unexpectedly if the entire contents
925
+ * of the string are deleted. In this case, it is possible for one endpoint
926
+ * of the interval to become detached, while the other remains on the string.
927
+ *
928
+ * By adjusting the `side` and `pos` values of the `start` and `end` parameters,
929
+ * it is possible to control whether the interval expands to include content
930
+ * inserted at its start or end.
931
+ *
932
+ * See {@link @fluidframework/merge-tree#SequencePlace} for more details on the model.
933
+ *
934
+ * @example
935
+ *
936
+ * Given the string "ABCD":
937
+ *
938
+ *```typescript
939
+ * // Refers to "BC". If any content is inserted before B or after C, this
940
+ * // interval will include that content
941
+ * //
942
+ * // Picture:
943
+ * // \{start\} - A[- B - C -]D - \{end\}
944
+ * // \{start\} - A - B - C - D - \{end\}
945
+ * collection.add(\{ pos: 0, side: Side.After \}, \{ pos: 3, side: Side.Before \}, IntervalType.SlideOnRemove);
946
+ * // Equivalent to specifying the same positions and Side.Before.
947
+ * // Refers to "ABC". Content inserted after C will be included in the
948
+ * // interval, but content inserted before A will not.
949
+ * // \{start\} -[A - B - C -]D - \{end\}
950
+ * // \{start\} - A - B - C - D - \{end\}
951
+ * collection.add(0, 3, IntervalType.SlideOnRemove);
952
+ *```
953
+ *
954
+ * In the case of the first example, if text is deleted,
955
+ *
956
+ * ```typescript
957
+ * // Delete the character "B"
958
+ * string.removeRange(1, 2);
959
+ * ```
960
+ *
961
+ * The start point of the interval will slide to the position immediately
962
+ * before "C", and the same will be true.
963
+ *
964
+ * ```
965
+ * \{start\} - A[- C -]D - \{end\}
966
+ * ```
967
+ *
968
+ * In this case, text inserted immediately before "C" would be included in
969
+ * the interval.
970
+ *
971
+ * ```typescript
972
+ * string.insertText(1, "EFG");
973
+ * ```
974
+ *
975
+ * With the string now being,
976
+ *
977
+ * ```
978
+ * \{start\} - A[- E - F - G - C -]D - \{end\}
979
+ * ```
980
+ *
981
+ * @privateRemarks TODO: ADO:5205 the above comment regarding behavior in
982
+ * the case that the entire interval has been deleted should be resolved at
983
+ * the same time as this ticket
984
+ */
985
+ add({
986
+ start,
987
+ end,
988
+ props,
989
+ }: {
990
+ start: SequencePlace;
991
+ end: SequencePlace;
992
+ props?: PropertySet;
993
+ }): SequenceInterval;
994
+ /**
995
+ * Removes an interval from the collection.
996
+ * @param id - Id of the interval to remove
997
+ * @returns the removed interval
998
+ */
999
+ removeIntervalById(id: string): SequenceInterval | undefined;
1000
+ /**
1001
+ * Changes the endpoints, properties, or both of an existing interval.
1002
+ * @param id - Id of the Interval to change
1003
+ * @returns the interval that was changed, if it existed in the collection.
1004
+ * Pass the desired new start position, end position, and/or properties in an object. Start and end positions must be changed
1005
+ * simultaneously - they must either both be specified or both undefined. To only change the properties, leave both endpoints
1006
+ * undefined. To only change the endpoints, leave the properties undefined.
1007
+ */
1008
+ change(
1009
+ id: string,
1010
+ { start, end, props }: { start?: SequencePlace; end?: SequencePlace; props?: PropertySet },
1011
+ ): SequenceInterval | undefined;
1012
+
1013
+ attachDeserializer(onDeserialize: DeserializeCallback): void;
1014
+ /**
1015
+ * @returns an iterator over all intervals in this collection.
1016
+ */
1017
+ [Symbol.iterator](): Iterator<SequenceInterval>;
1018
+
1019
+ /**
1020
+ * @returns a forward iterator over all intervals in this collection with start point equal to `startPosition`.
1021
+ */
1022
+ CreateForwardIteratorWithStartPosition(startPosition: number): Iterator<SequenceInterval>;
1023
+
1024
+ /**
1025
+ * @returns a backward iterator over all intervals in this collection with start point equal to `startPosition`.
1026
+ */
1027
+ CreateBackwardIteratorWithStartPosition(startPosition: number): Iterator<SequenceInterval>;
1028
+
1029
+ /**
1030
+ * @returns a forward iterator over all intervals in this collection with end point equal to `endPosition`.
1031
+ */
1032
+ CreateForwardIteratorWithEndPosition(endPosition: number): Iterator<SequenceInterval>;
1033
+
1034
+ /**
1035
+ * @returns a backward iterator over all intervals in this collection with end point equal to `endPosition`.
1036
+ */
1037
+ CreateBackwardIteratorWithEndPosition(endPosition: number): Iterator<SequenceInterval>;
1038
+
1039
+ /**
1040
+ * Gathers iteration results that optionally match a start/end criteria into the provided array.
1041
+ * @param results - Array to gather the results into. In lieu of a return value, this array will be populated with
1042
+ * intervals matching the query upon edit.
1043
+ * @param iteratesForward - whether or not iteration should be in the forward direction
1044
+ * @param start - If provided, only match intervals whose start point is equal to `start`.
1045
+ * @param end - If provided, only match intervals whose end point is equal to `end`.
1046
+ */
1047
+ gatherIterationResults(
1048
+ results: SequenceInterval[],
1049
+ iteratesForward: boolean,
1050
+ start?: number,
1051
+ end?: number,
1052
+ ): void;
1053
+
1054
+ /**
1055
+ * @deprecated - Users must manually attach the corresponding interval index to utilize this functionality, for instance:
1056
+ *
1057
+ * ```typescript
1058
+ * const overlappingIntervalsIndex = createOverlappingIntervalsIndex(sharedString);
1059
+ * collection.attachIndex(overlappingIntervalsIndex)
1060
+ * const result = overlappingIntervalsIndex.findOverlappingIntervals(start, end);
1061
+ * ```
1062
+ *
1063
+ * @returns an array of all intervals in this collection that overlap with the interval
1064
+ * `[startPosition, endPosition]`.
1065
+ */
1066
+ findOverlappingIntervals(startPosition: number, endPosition: number): SequenceInterval[];
1067
+
1068
+ /**
1069
+ * Applies a function to each interval in this collection.
1070
+ */
1071
+ map(fn: (interval: SequenceInterval) => void): void;
1072
+
1073
+ /**
1074
+ * @deprecated - due to the forthcoming change where the endpointIndex will no longer be
1075
+ * automatically added to the collection. Users are advised to independently attach the
1076
+ * index to the collection and utilize the API accordingly, for instance:
1077
+ * ```typescript
1078
+ * const endpointIndex = createEndpointIndex(sharedString);
1079
+ * collection.attachIndex(endpointIndex);
1080
+ * const result1 = endpointIndex.previousInterval(pos);
1081
+ * ```
1082
+ * If an index is used repeatedly, applications should generally attach it once and store it in memory.
1083
+ */
1084
+ previousInterval(pos: number): SequenceInterval | undefined;
1085
+
1086
+ /**
1087
+ * @deprecated - due to the forthcoming change where the endpointIndex will no longer be
1088
+ * automatically added to the collection. Users are advised to independently attach the
1089
+ * index to the collection and utilize the API accordingly, for instance:
1090
+ * ```typescript
1091
+ * const endpointIndex = createEndpointIndex(sharedString);
1092
+ * collection.attachIndex(endpointIndex);
1093
+ * const result2 = endpointIndex.nextInterval(pos);
1094
+ * ```
1095
+ */
1096
+ nextInterval(pos: number): SequenceInterval | undefined;
1097
+ }
1098
+
916
1099
  /**
917
1100
  * {@inheritdoc IIntervalCollection}
918
1101
  */
919
- export class IntervalCollection<TInterval extends ISerializableInterval>
920
- extends TypedEventEmitter<IIntervalCollectionEvent<TInterval>>
921
- implements IIntervalCollection<TInterval>
1102
+ export class IntervalCollection
1103
+ extends TypedEventEmitter<ISequenceIntervalCollectionEvents>
1104
+ implements ISequenceIntervalCollection
922
1105
  {
923
- private savedSerializedIntervals?: ISerializedInterval[];
924
- private localCollection: LocalIntervalCollection<TInterval> | undefined;
1106
+ private savedSerializedIntervals?: ISerializedIntervalCollectionV1;
1107
+ private localCollection: LocalIntervalCollection | undefined;
925
1108
  private onDeserialize: DeserializeCallback | undefined;
926
1109
  private client: Client | undefined;
927
1110
  private readonly localSeqToSerializedInterval = new Map<
@@ -932,13 +1115,13 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
932
1115
  number,
933
1116
  ISerializedInterval | SerializedIntervalDelta
934
1117
  >();
935
- private readonly pendingChangesStart: Map<string, ISerializedInterval[]> = new Map<
1118
+ private readonly pendingChangesStart: Map<string, ISerializedIntervalCollectionV1> = new Map<
936
1119
  string,
937
- ISerializedInterval[]
1120
+ ISerializedIntervalCollectionV1
938
1121
  >();
939
- private readonly pendingChangesEnd: Map<string, ISerializedInterval[]> = new Map<
1122
+ private readonly pendingChangesEnd: Map<string, ISerializedIntervalCollectionV1> = new Map<
940
1123
  string,
941
- ISerializedInterval[]
1124
+ ISerializedIntervalCollectionV1
942
1125
  >();
943
1126
 
944
1127
  public get attached(): boolean {
@@ -946,10 +1129,11 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
946
1129
  }
947
1130
 
948
1131
  constructor(
949
- private readonly helpers: IIntervalHelpers<TInterval>,
950
- private readonly requiresClient: boolean,
951
- private readonly emitter: IValueOpEmitter,
952
- serializedIntervals: ISerializedInterval[] | ISerializedIntervalCollectionV2,
1132
+ private readonly submitDelta: (
1133
+ op: IIntervalCollectionTypeOperationValue,
1134
+ md: IMapMessageLocalMetadata,
1135
+ ) => void,
1136
+ serializedIntervals: ISerializedIntervalCollectionV1 | ISerializedIntervalCollectionV2,
953
1137
  private readonly options: Partial<SequenceOptions> = {},
954
1138
  ) {
955
1139
  super();
@@ -964,7 +1148,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
964
1148
  /**
965
1149
  * {@inheritdoc IIntervalCollection.attachIndex}
966
1150
  */
967
- public attachIndex(index: IntervalIndex<TInterval>): void {
1151
+ public attachIndex(index: SequenceIntervalIndex): void {
968
1152
  if (!this.attached) {
969
1153
  throw new LoggingError("The local interval collection must exist");
970
1154
  }
@@ -978,7 +1162,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
978
1162
  /**
979
1163
  * {@inheritdoc IIntervalCollection.detachIndex}
980
1164
  */
981
- public detachIndex(index: IntervalIndex<TInterval>): boolean {
1165
+ public detachIndex(index: SequenceIntervalIndex): boolean {
982
1166
  if (!this.attached) {
983
1167
  throw new LoggingError("The local interval collection must exist");
984
1168
  }
@@ -1068,7 +1252,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1068
1252
  throw new LoggingError("Only supports one Sequence attach");
1069
1253
  }
1070
1254
 
1071
- if (client === undefined && this.requiresClient) {
1255
+ if (client === undefined) {
1072
1256
  throw new LoggingError("Client required for this collection");
1073
1257
  }
1074
1258
 
@@ -1082,10 +1266,9 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1082
1266
  });
1083
1267
  }
1084
1268
 
1085
- this.localCollection = new LocalIntervalCollection<TInterval>(
1269
+ this.localCollection = new LocalIntervalCollection(
1086
1270
  client,
1087
1271
  label,
1088
- this.helpers,
1089
1272
  this.options,
1090
1273
  (interval, previousInterval) => this.emitChange(interval, previousInterval, true, true),
1091
1274
  );
@@ -1108,7 +1291,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1108
1291
  typeof endPos === "number" && endSide !== undefined
1109
1292
  ? { pos: endPos, side: endSide }
1110
1293
  : endPos;
1111
- const interval = this.helpers.create(
1294
+ const interval = createSequenceInterval(
1112
1295
  label,
1113
1296
  start,
1114
1297
  end,
@@ -1139,8 +1322,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1139
1322
  }
1140
1323
 
1141
1324
  private emitChange(
1142
- interval: TInterval,
1143
- previousInterval: TInterval,
1325
+ interval: SequenceIntervalClass,
1326
+ previousInterval: SequenceIntervalClass,
1144
1327
  local: boolean,
1145
1328
  slide: boolean,
1146
1329
  op?: ISequencedDocumentMessage,
@@ -1148,27 +1331,21 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1148
1331
  // Temporarily make references transient so that positional queries work (non-transient refs
1149
1332
  // on resolve to DetachedPosition on any segments that don't contain them). The original refType
1150
1333
  // is restored as single-endpoint changes re-use previous references.
1151
- let startRefType: ReferenceType;
1152
- let endRefType: ReferenceType;
1153
- if (previousInterval instanceof SequenceIntervalClass) {
1154
- startRefType = previousInterval.start.refType;
1155
- endRefType = previousInterval.end.refType;
1156
- previousInterval.start.refType = ReferenceType.Transient;
1157
- previousInterval.end.refType = ReferenceType.Transient;
1158
- this.emit("changeInterval", interval, previousInterval, local, op, slide);
1159
- this.emit("changed", interval, undefined, previousInterval ?? undefined, local, slide);
1160
- previousInterval.start.refType = startRefType;
1161
- previousInterval.end.refType = endRefType;
1162
- } else {
1163
- this.emit("changeInterval", interval, previousInterval, local, op, slide);
1164
- this.emit("changed", interval, undefined, previousInterval ?? undefined, local, slide);
1165
- }
1334
+
1335
+ const startRefType = previousInterval.start.refType;
1336
+ const endRefType = previousInterval.end.refType;
1337
+ previousInterval.start.refType = ReferenceType.Transient;
1338
+ previousInterval.end.refType = ReferenceType.Transient;
1339
+ this.emit("changeInterval", interval, previousInterval, local, op, slide);
1340
+ this.emit("changed", interval, undefined, previousInterval ?? undefined, local, slide);
1341
+ previousInterval.start.refType = startRefType;
1342
+ previousInterval.end.refType = endRefType;
1166
1343
  }
1167
1344
 
1168
1345
  /**
1169
1346
  * {@inheritdoc IIntervalCollection.getIntervalById}
1170
1347
  */
1171
- public getIntervalById(id: string): ISerializableIntervalPrivate<TInterval> | undefined {
1348
+ public getIntervalById(id: string): ISerializableIntervalPrivate | undefined {
1172
1349
  if (!this.localCollection) {
1173
1350
  throw new LoggingError("attach must be called before accessing intervals");
1174
1351
  }
@@ -1197,7 +1374,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1197
1374
  start: SequencePlace;
1198
1375
  end: SequencePlace;
1199
1376
  props?: PropertySet;
1200
- }): TInterval {
1377
+ }): SequenceIntervalClass {
1201
1378
  if (!this.localCollection) {
1202
1379
  throw new LoggingError("attach must be called prior to adding intervals");
1203
1380
  }
@@ -1216,7 +1393,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1216
1393
 
1217
1394
  this.assertStickinessEnabled(start, end);
1218
1395
 
1219
- const interval: TInterval = this.localCollection.addInterval(
1396
+ const interval: SequenceIntervalClass = this.localCollection.addInterval(
1220
1397
  toSequencePlace(startPos, startSide),
1221
1398
  toSequencePlace(endPos, endSide),
1222
1399
  IntervalType.SlideOnRemove,
@@ -1224,7 +1401,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1224
1401
  );
1225
1402
 
1226
1403
  if (interval) {
1227
- if (!this.isCollaborating && interval instanceof SequenceIntervalClass) {
1404
+ if (!this.isCollaborating) {
1228
1405
  setSlideOnRemove(interval.start);
1229
1406
  setSlideOnRemove(interval.end);
1230
1407
  }
@@ -1242,8 +1419,16 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1242
1419
  if (this.isCollaborating) {
1243
1420
  this.localSeqToSerializedInterval.set(localSeq, serializedInterval);
1244
1421
  }
1245
- // Local ops get submitted to the server. Remote ops have the deserializer run.
1246
- this.emitter.emit("add", undefined, serializedInterval, { localSeq });
1422
+
1423
+ this.submitDelta(
1424
+ {
1425
+ opName: "add",
1426
+ value: serializedInterval,
1427
+ },
1428
+ {
1429
+ localSeq,
1430
+ },
1431
+ );
1247
1432
  }
1248
1433
 
1249
1434
  this.emit("addInterval", interval, true, undefined);
@@ -1252,7 +1437,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1252
1437
  }
1253
1438
 
1254
1439
  private deleteExistingInterval(
1255
- interval: TInterval,
1440
+ interval: SequenceIntervalClass,
1256
1441
  local: boolean,
1257
1442
  op?: ISequencedDocumentMessage,
1258
1443
  ) {
@@ -1265,9 +1450,15 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1265
1450
  if (interval) {
1266
1451
  // Local ops get submitted to the server. Remote ops have the deserializer run.
1267
1452
  if (local) {
1268
- this.emitter.emit("delete", undefined, interval.serialize(), {
1269
- localSeq: this.getNextLocalSeq(),
1270
- });
1453
+ this.submitDelta(
1454
+ {
1455
+ opName: "delete",
1456
+ value: interval.serialize(),
1457
+ },
1458
+ {
1459
+ localSeq: this.getNextLocalSeq(),
1460
+ },
1461
+ );
1271
1462
  } else {
1272
1463
  if (this.onDeserialize) {
1273
1464
  this.onDeserialize(interval);
@@ -1281,7 +1472,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1281
1472
  /**
1282
1473
  * {@inheritdoc IIntervalCollection.removeIntervalById}
1283
1474
  */
1284
- public removeIntervalById(id: string): TInterval | undefined {
1475
+ public removeIntervalById(id: string): SequenceIntervalClass | undefined {
1285
1476
  if (!this.localCollection) {
1286
1477
  throw new LoggingError("Attach must be called before accessing intervals");
1287
1478
  }
@@ -1297,7 +1488,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1297
1488
  public change(
1298
1489
  id: string,
1299
1490
  { start, end, props }: { start?: SequencePlace; end?: SequencePlace; props?: PropertySet },
1300
- ): TInterval | undefined {
1491
+ ): SequenceIntervalClass | undefined {
1301
1492
  if (!this.localCollection) {
1302
1493
  throw new LoggingError("Attach must be called before accessing intervals");
1303
1494
  }
@@ -1325,7 +1516,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1325
1516
  const interval = this.getIntervalById(id);
1326
1517
  if (interval) {
1327
1518
  let deltaProps: PropertySet | undefined;
1328
- let newInterval: TInterval | undefined;
1519
+ let newInterval: SequenceIntervalClass | undefined;
1329
1520
  if (props !== undefined) {
1330
1521
  interval.propertyManager ??= new PropertiesManager();
1331
1522
  deltaProps = interval.propertyManager.handleProperties(
@@ -1338,7 +1529,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1338
1529
  }
1339
1530
  if (start !== undefined && end !== undefined) {
1340
1531
  newInterval = this.localCollection.changeInterval(interval, start, end);
1341
- if (!this.isCollaborating && newInterval instanceof SequenceIntervalClass) {
1532
+ if (!this.isCollaborating && newInterval !== undefined) {
1342
1533
  setSlideOnRemove(newInterval.start);
1343
1534
  setSlideOnRemove(newInterval.end);
1344
1535
  }
@@ -1361,7 +1552,15 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1361
1552
  this.localSeqToSerializedInterval.set(localSeq, serializedInterval);
1362
1553
  }
1363
1554
 
1364
- this.emitter.emit("change", undefined, serializedInterval, { localSeq });
1555
+ this.submitDelta(
1556
+ {
1557
+ opName: "change",
1558
+ value: serializedInterval,
1559
+ },
1560
+ {
1561
+ localSeq,
1562
+ },
1563
+ );
1365
1564
  if (deltaProps !== undefined) {
1366
1565
  this.emit("propertyChanged", interval, deltaProps, true, undefined);
1367
1566
  this.emit(
@@ -1376,10 +1575,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1376
1575
  if (newInterval) {
1377
1576
  this.addPendingChange(id, serializedInterval);
1378
1577
  this.emitChange(newInterval, interval, true, false);
1379
- if (interval instanceof SequenceIntervalClass) {
1380
- this.client?.removeLocalReferencePosition(interval.start);
1381
- this.client?.removeLocalReferencePosition(interval.end);
1382
- }
1578
+ this.client?.removeLocalReferencePosition(interval.start);
1579
+ this.client?.removeLocalReferencePosition(interval.end);
1383
1580
  }
1384
1581
  return newInterval;
1385
1582
  }
@@ -1482,8 +1679,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1482
1679
  // strip it out of the properties here.
1483
1680
  const { [reservedIntervalIdKey]: id, ...newProps } = serializedInterval.properties ?? {};
1484
1681
  assert(id !== undefined, 0x3fe /* id must exist on the interval */);
1485
- const interval: ISerializableIntervalPrivate<TInterval> | undefined =
1486
- this.getIntervalById(id);
1682
+ const interval: ISerializableIntervalPrivate | undefined = this.getIntervalById(id);
1487
1683
  if (!interval) {
1488
1684
  // The interval has been removed locally; no-op.
1489
1685
  return;
@@ -1623,11 +1819,6 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1623
1819
  }
1624
1820
 
1625
1821
  if (localInterval !== undefined) {
1626
- // we know we must be using `SequenceInterval` because `this.client` exists
1627
- assert(
1628
- localInterval instanceof SequenceIntervalClass,
1629
- 0x3a0 /* localInterval must be `SequenceInterval` when used with client */,
1630
- );
1631
1822
  // The rebased op may place this interval's endpoints on different segments. Calling `changeInterval` here
1632
1823
  // updates the local client's state to be consistent with the emitted op.
1633
1824
  this.localCollection?.changeInterval(
@@ -1668,12 +1859,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1668
1859
  return value;
1669
1860
  }
1670
1861
 
1671
- private ackInterval(interval: TInterval, op: ISequencedDocumentMessage): void {
1672
- // Only SequenceIntervals need potential sliding
1673
- if (!(interval instanceof SequenceIntervalClass)) {
1674
- return;
1675
- }
1676
-
1862
+ private ackInterval(interval: SequenceIntervalClass, op: ISequencedDocumentMessage): void {
1677
1863
  if (
1678
1864
  !refTypeIncludesFlag(interval.start, ReferenceType.StayOnRemove) &&
1679
1865
  !refTypeIncludesFlag(interval.end, ReferenceType.StayOnRemove)
@@ -1711,7 +1897,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1711
1897
  }
1712
1898
 
1713
1899
  // `interval`'s endpoints will get modified in-place, so clone it prior to doing so for event emission.
1714
- const oldInterval = interval.clone() as TInterval & SequenceInterval;
1900
+ const oldInterval = interval.clone();
1715
1901
 
1716
1902
  // In this case, where we change the start or end of an interval,
1717
1903
  // it is necessary to remove and re-add the interval listeners.
@@ -1764,7 +1950,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1764
1950
  oldSeg?.localRefs?.addLocalRef(oldInterval.end, oldInterval.end.getOffset());
1765
1951
  }
1766
1952
  this.localCollection.add(interval);
1767
- this.emitChange(interval, oldInterval as TInterval, true, true, op);
1953
+ this.emitChange(interval, oldInterval, true, true, op);
1768
1954
  }
1769
1955
  }
1770
1956
 
@@ -1794,7 +1980,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1794
1980
 
1795
1981
  this.localCollection.ensureSerializedId(serializedInterval);
1796
1982
 
1797
- const interval: TInterval = this.localCollection.addInterval(
1983
+ const interval: SequenceIntervalClass = this.localCollection.addInterval(
1798
1984
  toSequencePlace(serializedInterval.start, serializedInterval.startSide ?? Side.Before),
1799
1985
  toSequencePlace(serializedInterval.end, serializedInterval.endSide ?? Side.Before),
1800
1986
  serializedInterval.intervalType,
@@ -1836,19 +2022,21 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1836
2022
  }
1837
2023
  }
1838
2024
 
1839
- public serializeInternal(): ISerializedIntervalCollectionV2 {
2025
+ public serializeInternal(
2026
+ version: "1" | "2",
2027
+ ): ISerializedIntervalCollectionV1 | ISerializedIntervalCollectionV2 {
1840
2028
  if (!this.localCollection) {
1841
2029
  throw new LoggingError("attachSequence must be called");
1842
2030
  }
1843
2031
 
1844
- return this.localCollection.serialize();
2032
+ return this.localCollection.serialize(version);
1845
2033
  }
1846
2034
 
1847
2035
  /**
1848
2036
  * @returns an iterator over all intervals in this collection.
1849
2037
  */
1850
- public [Symbol.iterator](): IntervalCollectionIterator<TInterval> {
1851
- const iterator = new IntervalCollectionIterator<TInterval>(this);
2038
+ public [Symbol.iterator](): IntervalCollectionIterator {
2039
+ const iterator = new IntervalCollectionIterator(this);
1852
2040
  return iterator;
1853
2041
  }
1854
2042
 
@@ -1857,8 +2045,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1857
2045
  */
1858
2046
  public CreateForwardIteratorWithStartPosition(
1859
2047
  startPosition: number,
1860
- ): IntervalCollectionIterator<TInterval> {
1861
- const iterator = new IntervalCollectionIterator<TInterval>(this, true, startPosition);
2048
+ ): IntervalCollectionIterator {
2049
+ const iterator = new IntervalCollectionIterator(this, true, startPosition);
1862
2050
  return iterator;
1863
2051
  }
1864
2052
 
@@ -1867,8 +2055,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1867
2055
  */
1868
2056
  public CreateBackwardIteratorWithStartPosition(
1869
2057
  startPosition: number,
1870
- ): IntervalCollectionIterator<TInterval> {
1871
- const iterator = new IntervalCollectionIterator<TInterval>(this, false, startPosition);
2058
+ ): IntervalCollectionIterator {
2059
+ const iterator = new IntervalCollectionIterator(this, false, startPosition);
1872
2060
  return iterator;
1873
2061
  }
1874
2062
 
@@ -1877,13 +2065,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1877
2065
  */
1878
2066
  public CreateForwardIteratorWithEndPosition(
1879
2067
  endPosition: number,
1880
- ): IntervalCollectionIterator<TInterval> {
1881
- const iterator = new IntervalCollectionIterator<TInterval>(
1882
- this,
1883
- true,
1884
- undefined,
1885
- endPosition,
1886
- );
2068
+ ): IntervalCollectionIterator {
2069
+ const iterator = new IntervalCollectionIterator(this, true, undefined, endPosition);
1887
2070
  return iterator;
1888
2071
  }
1889
2072
 
@@ -1892,13 +2075,8 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1892
2075
  */
1893
2076
  public CreateBackwardIteratorWithEndPosition(
1894
2077
  endPosition: number,
1895
- ): IntervalCollectionIterator<TInterval> {
1896
- const iterator = new IntervalCollectionIterator<TInterval>(
1897
- this,
1898
- false,
1899
- undefined,
1900
- endPosition,
1901
- );
2078
+ ): IntervalCollectionIterator {
2079
+ const iterator = new IntervalCollectionIterator(this, false, undefined, endPosition);
1902
2080
  return iterator;
1903
2081
  }
1904
2082
 
@@ -1906,7 +2084,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1906
2084
  * {@inheritdoc IIntervalCollection.gatherIterationResults}
1907
2085
  */
1908
2086
  public gatherIterationResults(
1909
- results: TInterval[],
2087
+ results: SequenceIntervalClass[],
1910
2088
  iteratesForward: boolean,
1911
2089
  start?: number,
1912
2090
  end?: number,
@@ -1926,7 +2104,10 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1926
2104
  /**
1927
2105
  * {@inheritdoc IIntervalCollection.findOverlappingIntervals}
1928
2106
  */
1929
- public findOverlappingIntervals(startPosition: number, endPosition: number): TInterval[] {
2107
+ public findOverlappingIntervals(
2108
+ startPosition: number,
2109
+ endPosition: number,
2110
+ ): SequenceInterval[] {
1930
2111
  if (!this.localCollection) {
1931
2112
  throw new LoggingError("attachSequence must be called");
1932
2113
  }
@@ -1940,7 +2121,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1940
2121
  /**
1941
2122
  * {@inheritdoc IIntervalCollection.map}
1942
2123
  */
1943
- public map(fn: (interval: TInterval) => void) {
2124
+ public map(fn: (interval: SequenceIntervalClass) => void) {
1944
2125
  if (!this.localCollection) {
1945
2126
  throw new LoggingError("attachSequence must be called");
1946
2127
  }
@@ -1953,7 +2134,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1953
2134
  /**
1954
2135
  * {@inheritdoc IIntervalCollection.previousInterval}
1955
2136
  */
1956
- public previousInterval(pos: number): TInterval | undefined {
2137
+ public previousInterval(pos: number): SequenceInterval | undefined {
1957
2138
  if (!this.localCollection) {
1958
2139
  throw new LoggingError("attachSequence must be called");
1959
2140
  }
@@ -1964,7 +2145,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1964
2145
  /**
1965
2146
  * {@inheritdoc IIntervalCollection.nextInterval}
1966
2147
  */
1967
- public nextInterval(pos: number): TInterval | undefined {
2148
+ public nextInterval(pos: number): SequenceInterval | undefined {
1968
2149
  if (!this.localCollection) {
1969
2150
  throw new LoggingError("attachSequence must be called");
1970
2151
  }
@@ -1992,7 +2173,7 @@ export interface IntervalLocator {
1992
2173
  /**
1993
2174
  * Interval within that collection
1994
2175
  */
1995
- interval: SequenceInterval;
2176
+ interval: SequenceIntervalClass;
1996
2177
  }
1997
2178
 
1998
2179
  /**