@fluidframework/sequence 1.0.1 → 1.1.0-75972
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -6
- package/dist/defaultMap.d.ts +2 -6
- package/dist/defaultMap.d.ts.map +1 -1
- package/dist/defaultMap.js +27 -37
- package/dist/defaultMap.js.map +1 -1
- package/dist/defaultMapInterfaces.d.ts +24 -3
- package/dist/defaultMapInterfaces.d.ts.map +1 -1
- package/dist/defaultMapInterfaces.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/intervalCollection.d.ts +72 -8
- package/dist/intervalCollection.d.ts.map +1 -1
- package/dist/intervalCollection.js +325 -155
- package/dist/intervalCollection.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/sequence.d.ts +4 -5
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +11 -15
- package/dist/sequence.js.map +1 -1
- package/dist/sharedIntervalCollection.d.ts.map +1 -1
- package/dist/sharedIntervalCollection.js +1 -1
- package/dist/sharedIntervalCollection.js.map +1 -1
- package/dist/sharedSequence.js.map +1 -1
- package/dist/sparsematrix.js +2 -2
- package/dist/sparsematrix.js.map +1 -1
- package/lib/defaultMap.d.ts +2 -6
- package/lib/defaultMap.d.ts.map +1 -1
- package/lib/defaultMap.js +27 -37
- package/lib/defaultMap.js.map +1 -1
- package/lib/defaultMapInterfaces.d.ts +24 -3
- package/lib/defaultMapInterfaces.d.ts.map +1 -1
- package/lib/defaultMapInterfaces.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/intervalCollection.d.ts +72 -8
- package/lib/intervalCollection.d.ts.map +1 -1
- package/lib/intervalCollection.js +325 -155
- package/lib/intervalCollection.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/sequence.d.ts +4 -5
- package/lib/sequence.d.ts.map +1 -1
- package/lib/sequence.js +11 -15
- package/lib/sequence.js.map +1 -1
- package/lib/sharedIntervalCollection.d.ts.map +1 -1
- package/lib/sharedIntervalCollection.js +1 -1
- package/lib/sharedIntervalCollection.js.map +1 -1
- package/lib/sharedSequence.js.map +1 -1
- package/lib/sparsematrix.js +2 -2
- package/lib/sparsematrix.js.map +1 -1
- package/package.json +19 -43
- package/src/defaultMap.ts +39 -41
- package/src/defaultMapInterfaces.ts +28 -3
- package/src/index.ts +3 -0
- package/src/intervalCollection.ts +447 -181
- package/src/packageVersion.ts +1 -1
- package/src/sequence.ts +17 -21
- package/src/sharedIntervalCollection.ts +3 -2
- package/src/sharedSequence.ts +1 -1
- package/src/sparsematrix.ts +2 -2
|
@@ -20,6 +20,7 @@ exports.IntervalCollection = exports.IntervalCollectionIterator = exports.Interv
|
|
|
20
20
|
const common_utils_1 = require("@fluidframework/common-utils");
|
|
21
21
|
const container_utils_1 = require("@fluidframework/container-utils");
|
|
22
22
|
const merge_tree_1 = require("@fluidframework/merge-tree");
|
|
23
|
+
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
23
24
|
const uuid_1 = require("uuid");
|
|
24
25
|
const reservedIntervalIdKey = "intervalId";
|
|
25
26
|
var IntervalType;
|
|
@@ -39,10 +40,39 @@ var IntervalType;
|
|
|
39
40
|
*/
|
|
40
41
|
IntervalType[IntervalType["Transient"] = 4] = "Transient";
|
|
41
42
|
})(IntervalType = exports.IntervalType || (exports.IntervalType = {}));
|
|
43
|
+
/**
|
|
44
|
+
* Decompress an interval after loading a summary from JSON. The exact format
|
|
45
|
+
* of this compression is unspecified and subject to change
|
|
46
|
+
*/
|
|
47
|
+
function decompressInterval(interval, label) {
|
|
48
|
+
return {
|
|
49
|
+
start: interval[0],
|
|
50
|
+
end: interval[1],
|
|
51
|
+
sequenceNumber: interval[2],
|
|
52
|
+
intervalType: interval[3],
|
|
53
|
+
properties: Object.assign(Object.assign({}, interval[4]), { [merge_tree_1.reservedRangeLabelsKey]: label }),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Compress an interval prior to serialization as JSON. The exact format of this
|
|
58
|
+
* compression is unspecified and subject to change
|
|
59
|
+
*/
|
|
60
|
+
function compressInterval(interval) {
|
|
61
|
+
const { start, end, sequenceNumber, intervalType, properties } = interval;
|
|
62
|
+
return [
|
|
63
|
+
start,
|
|
64
|
+
end,
|
|
65
|
+
sequenceNumber,
|
|
66
|
+
intervalType,
|
|
67
|
+
Object.assign(Object.assign({}, properties), { [merge_tree_1.reservedRangeLabelsKey]: undefined }),
|
|
68
|
+
];
|
|
69
|
+
}
|
|
42
70
|
class Interval {
|
|
43
71
|
constructor(start, end, props) {
|
|
44
72
|
this.start = start;
|
|
45
73
|
this.end = end;
|
|
74
|
+
this.propertyManager = new merge_tree_1.PropertiesManager();
|
|
75
|
+
this.properties = {};
|
|
46
76
|
if (props) {
|
|
47
77
|
this.addProperties(props);
|
|
48
78
|
}
|
|
@@ -125,12 +155,7 @@ class Interval {
|
|
|
125
155
|
}
|
|
126
156
|
addProperties(newProps, collaborating = false, seq, op) {
|
|
127
157
|
if (newProps) {
|
|
128
|
-
|
|
129
|
-
this.propertyManager = new merge_tree_1.PropertiesManager();
|
|
130
|
-
}
|
|
131
|
-
if (!this.properties) {
|
|
132
|
-
this.properties = (0, merge_tree_1.createMap)();
|
|
133
|
-
}
|
|
158
|
+
this.initializeProperties();
|
|
134
159
|
return this.propertyManager.addProperties(this.properties, newProps, op, seq, collaborating);
|
|
135
160
|
}
|
|
136
161
|
}
|
|
@@ -141,7 +166,20 @@ class Interval {
|
|
|
141
166
|
// Return undefined to indicate that no change is necessary.
|
|
142
167
|
return;
|
|
143
168
|
}
|
|
144
|
-
|
|
169
|
+
const newInterval = new Interval(startPos, endPos);
|
|
170
|
+
if (this.properties) {
|
|
171
|
+
newInterval.initializeProperties();
|
|
172
|
+
this.propertyManager.copyTo(this.properties, newInterval.properties, newInterval.propertyManager);
|
|
173
|
+
}
|
|
174
|
+
return newInterval;
|
|
175
|
+
}
|
|
176
|
+
initializeProperties() {
|
|
177
|
+
if (!this.propertyManager) {
|
|
178
|
+
this.propertyManager = new merge_tree_1.PropertiesManager();
|
|
179
|
+
}
|
|
180
|
+
if (!this.properties) {
|
|
181
|
+
this.properties = (0, merge_tree_1.createMap)();
|
|
182
|
+
}
|
|
145
183
|
}
|
|
146
184
|
}
|
|
147
185
|
exports.Interval = Interval;
|
|
@@ -150,10 +188,41 @@ class SequenceInterval {
|
|
|
150
188
|
this.start = start;
|
|
151
189
|
this.end = end;
|
|
152
190
|
this.intervalType = intervalType;
|
|
191
|
+
this.propertyManager = new merge_tree_1.PropertiesManager();
|
|
192
|
+
this.properties = {};
|
|
153
193
|
if (props) {
|
|
154
194
|
this.addProperties(props);
|
|
155
195
|
}
|
|
156
196
|
}
|
|
197
|
+
/**
|
|
198
|
+
* @internal
|
|
199
|
+
* Subscribes to position change events on this interval if there are no current listeners.
|
|
200
|
+
*/
|
|
201
|
+
addPositionChangeListeners(beforePositionChange, afterPositionChange) {
|
|
202
|
+
var _a, _b;
|
|
203
|
+
var _c, _d;
|
|
204
|
+
if (this.callbacks === undefined) {
|
|
205
|
+
this.callbacks = {
|
|
206
|
+
beforePositionChange,
|
|
207
|
+
afterPositionChange,
|
|
208
|
+
};
|
|
209
|
+
const startCbs = (_a = (_c = this.start).callbacks) !== null && _a !== void 0 ? _a : (_c.callbacks = {});
|
|
210
|
+
const endCbs = (_b = (_d = this.end).callbacks) !== null && _b !== void 0 ? _b : (_d.callbacks = {});
|
|
211
|
+
startCbs.beforeSlide = endCbs.beforeSlide = beforePositionChange;
|
|
212
|
+
startCbs.afterSlide = endCbs.afterSlide = afterPositionChange;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* @internal
|
|
217
|
+
* Removes the currently subscribed position change listeners.
|
|
218
|
+
*/
|
|
219
|
+
removePositionChangeListeners() {
|
|
220
|
+
if (this.callbacks) {
|
|
221
|
+
this.callbacks = undefined;
|
|
222
|
+
this.start.callbacks = undefined;
|
|
223
|
+
this.end.callbacks = undefined;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
157
226
|
serialize(client) {
|
|
158
227
|
const startPosition = this.start.toPosition();
|
|
159
228
|
const endPosition = this.end.toPosition();
|
|
@@ -217,12 +286,7 @@ class SequenceInterval {
|
|
|
217
286
|
return new SequenceInterval(this.start.min(b.start), this.end.max(b.end), this.intervalType);
|
|
218
287
|
}
|
|
219
288
|
addProperties(newProps, collab = false, seq, op) {
|
|
220
|
-
|
|
221
|
-
this.propertyManager = new merge_tree_1.PropertiesManager();
|
|
222
|
-
}
|
|
223
|
-
if (!this.properties) {
|
|
224
|
-
this.properties = (0, merge_tree_1.createMap)();
|
|
225
|
-
}
|
|
289
|
+
this.initializeProperties();
|
|
226
290
|
return this.propertyManager.addProperties(this.properties, newProps, op, seq, collab);
|
|
227
291
|
}
|
|
228
292
|
overlapsPos(bstart, bend) {
|
|
@@ -231,18 +295,41 @@ class SequenceInterval {
|
|
|
231
295
|
return (endPos > bstart) && (startPos < bend);
|
|
232
296
|
}
|
|
233
297
|
modify(label, start, end, op) {
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
298
|
+
const getRefType = (baseType) => {
|
|
299
|
+
let refType = baseType;
|
|
300
|
+
if (op === undefined) {
|
|
301
|
+
refType &= ~merge_tree_1.ReferenceType.SlideOnRemove;
|
|
302
|
+
refType |= merge_tree_1.ReferenceType.StayOnRemove;
|
|
303
|
+
}
|
|
304
|
+
return refType;
|
|
305
|
+
};
|
|
306
|
+
let startRef = this.start;
|
|
307
|
+
if (start !== undefined) {
|
|
308
|
+
startRef = createPositionReference(this.start.getClient(), start, getRefType(this.start.refType), op);
|
|
309
|
+
startRef.addProperties(this.start.properties);
|
|
310
|
+
}
|
|
311
|
+
let endRef = this.end;
|
|
312
|
+
if (end !== undefined) {
|
|
313
|
+
endRef = createPositionReference(this.end.getClient(), end, getRefType(this.end.refType), op);
|
|
314
|
+
endRef.addProperties(this.end.properties);
|
|
315
|
+
}
|
|
316
|
+
startRef.pairedRef = endRef;
|
|
317
|
+
endRef.pairedRef = startRef;
|
|
318
|
+
const newInterval = new SequenceInterval(startRef, endRef, this.intervalType);
|
|
241
319
|
if (this.properties) {
|
|
242
|
-
newInterval.
|
|
320
|
+
newInterval.initializeProperties();
|
|
321
|
+
this.propertyManager.copyTo(this.properties, newInterval.properties, newInterval.propertyManager);
|
|
243
322
|
}
|
|
244
323
|
return newInterval;
|
|
245
324
|
}
|
|
325
|
+
initializeProperties() {
|
|
326
|
+
if (!this.propertyManager) {
|
|
327
|
+
this.propertyManager = new merge_tree_1.PropertiesManager();
|
|
328
|
+
}
|
|
329
|
+
if (!this.properties) {
|
|
330
|
+
this.properties = (0, merge_tree_1.createMap)();
|
|
331
|
+
}
|
|
332
|
+
}
|
|
246
333
|
}
|
|
247
334
|
exports.SequenceInterval = SequenceInterval;
|
|
248
335
|
function createPositionReferenceFromSegoff(client, segoff, refType, op) {
|
|
@@ -327,11 +414,15 @@ function createIntervalIndex(conflict) {
|
|
|
327
414
|
}
|
|
328
415
|
exports.createIntervalIndex = createIntervalIndex;
|
|
329
416
|
class LocalIntervalCollection {
|
|
330
|
-
constructor(client, label, helpers
|
|
417
|
+
constructor(client, label, helpers,
|
|
418
|
+
/** Callback invoked each time one of the endpoints of an interval slides. */
|
|
419
|
+
onPositionChange) {
|
|
331
420
|
this.client = client;
|
|
332
421
|
this.label = label;
|
|
333
422
|
this.helpers = helpers;
|
|
423
|
+
this.onPositionChange = onPositionChange;
|
|
334
424
|
this.intervalTree = new merge_tree_1.IntervalTree();
|
|
425
|
+
this.intervalIdMap = new Map();
|
|
335
426
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
336
427
|
this.endIntervalTree = new merge_tree_1.RedBlackTree(helpers.compareEnds);
|
|
337
428
|
}
|
|
@@ -339,7 +430,7 @@ class LocalIntervalCollection {
|
|
|
339
430
|
this.conflictResolver = conflictResolver;
|
|
340
431
|
this.endConflictResolver =
|
|
341
432
|
(key, currentKey) => {
|
|
342
|
-
const ival =
|
|
433
|
+
const ival = conflictResolver(key, currentKey);
|
|
343
434
|
return {
|
|
344
435
|
data: ival,
|
|
345
436
|
key: ival,
|
|
@@ -354,13 +445,22 @@ class LocalIntervalCollection {
|
|
|
354
445
|
// without ID's.
|
|
355
446
|
return `${LocalIntervalCollection.legacyIdPrefix}${start}-${end}`;
|
|
356
447
|
}
|
|
448
|
+
/**
|
|
449
|
+
* Validates that a serialized interval has the ID property. Creates an ID
|
|
450
|
+
* if one does not already exist
|
|
451
|
+
*
|
|
452
|
+
* @param serializedInterval - The interval to be checked
|
|
453
|
+
* @returns The interval's existing or newly created id
|
|
454
|
+
*/
|
|
357
455
|
ensureSerializedId(serializedInterval) {
|
|
358
456
|
var _a;
|
|
359
|
-
|
|
457
|
+
let id = (_a = serializedInterval.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
|
|
458
|
+
if (id === undefined) {
|
|
360
459
|
// An interval came over the wire without an ID, so create a non-unique one based on start/end.
|
|
361
460
|
// This will allow all clients to refer to this interval consistently.
|
|
461
|
+
id = this.createLegacyId(serializedInterval.start, serializedInterval.end);
|
|
362
462
|
const newProps = {
|
|
363
|
-
[reservedIntervalIdKey]:
|
|
463
|
+
[reservedIntervalIdKey]: id,
|
|
364
464
|
};
|
|
365
465
|
serializedInterval.properties = (0, merge_tree_1.addProperties)(serializedInterval.properties, newProps);
|
|
366
466
|
}
|
|
@@ -370,6 +470,7 @@ class LocalIntervalCollection {
|
|
|
370
470
|
enumerable: true,
|
|
371
471
|
writable: false,
|
|
372
472
|
});
|
|
473
|
+
return id;
|
|
373
474
|
}
|
|
374
475
|
mapUntil(fn) {
|
|
375
476
|
this.intervalTree.mapUntil(fn);
|
|
@@ -463,9 +564,16 @@ class LocalIntervalCollection {
|
|
|
463
564
|
this.endIntervalTree.remove(transientInterval);
|
|
464
565
|
return transientInterval;
|
|
465
566
|
}
|
|
466
|
-
|
|
567
|
+
removeIntervalFromIndex(interval) {
|
|
467
568
|
this.intervalTree.removeExisting(interval);
|
|
468
569
|
this.endIntervalTree.remove(interval);
|
|
570
|
+
const id = interval.getIntervalId();
|
|
571
|
+
(0, common_utils_1.assert)(id !== undefined, 0x311 /* expected id to exist on interval */);
|
|
572
|
+
this.intervalIdMap.delete(id);
|
|
573
|
+
}
|
|
574
|
+
removeExistingInterval(interval) {
|
|
575
|
+
this.removeIntervalFromIndex(interval);
|
|
576
|
+
this.removeIntervalListeners(interval);
|
|
469
577
|
}
|
|
470
578
|
createInterval(start, end, intervalType, op) {
|
|
471
579
|
return this.helpers.create(this.label, start, end, this.client, intervalType, op);
|
|
@@ -487,8 +595,9 @@ class LocalIntervalCollection {
|
|
|
487
595
|
}
|
|
488
596
|
return interval;
|
|
489
597
|
}
|
|
490
|
-
|
|
491
|
-
|
|
598
|
+
addIntervalToIndex(interval) {
|
|
599
|
+
const id = interval.getIntervalId();
|
|
600
|
+
(0, common_utils_1.assert)(id !== undefined, 0x2c0 /* "ID must be created before adding interval to collection" */);
|
|
492
601
|
// Make the ID immutable.
|
|
493
602
|
Object.defineProperty(interval.properties, reservedIntervalIdKey, {
|
|
494
603
|
configurable: false,
|
|
@@ -497,17 +606,14 @@ class LocalIntervalCollection {
|
|
|
497
606
|
});
|
|
498
607
|
this.intervalTree.put(interval, this.conflictResolver);
|
|
499
608
|
this.endIntervalTree.put(interval, interval, this.endConflictResolver);
|
|
609
|
+
this.intervalIdMap.set(id, interval);
|
|
610
|
+
}
|
|
611
|
+
add(interval) {
|
|
612
|
+
this.addIntervalToIndex(interval);
|
|
613
|
+
this.addIntervalListeners(interval);
|
|
500
614
|
}
|
|
501
615
|
getIntervalById(id) {
|
|
502
|
-
|
|
503
|
-
this.mapUntil((interval) => {
|
|
504
|
-
if (interval.getIntervalId() === id) {
|
|
505
|
-
result = interval;
|
|
506
|
-
return false;
|
|
507
|
-
}
|
|
508
|
-
return true;
|
|
509
|
-
});
|
|
510
|
-
return result;
|
|
616
|
+
return this.intervalIdMap.get(id);
|
|
511
617
|
}
|
|
512
618
|
changeInterval(interval, start, end, op) {
|
|
513
619
|
const newInterval = interval.modify(this.label, start, end, op);
|
|
@@ -520,7 +626,25 @@ class LocalIntervalCollection {
|
|
|
520
626
|
serialize() {
|
|
521
627
|
const client = this.client;
|
|
522
628
|
const intervals = this.intervalTree.intervals.keys();
|
|
523
|
-
return
|
|
629
|
+
return {
|
|
630
|
+
label: this.label,
|
|
631
|
+
intervals: intervals.map((interval) => compressInterval(interval.serialize(client))),
|
|
632
|
+
version: 2,
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
addIntervalListeners(interval) {
|
|
636
|
+
if (interval instanceof SequenceInterval) {
|
|
637
|
+
interval.addPositionChangeListeners(() => this.removeIntervalFromIndex(interval), () => {
|
|
638
|
+
var _a;
|
|
639
|
+
this.addIntervalToIndex(interval);
|
|
640
|
+
(_a = this.onPositionChange) === null || _a === void 0 ? void 0 : _a.call(this, interval);
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
removeIntervalListeners(interval) {
|
|
645
|
+
if (interval instanceof SequenceInterval) {
|
|
646
|
+
interval.removePositionChangeListeners();
|
|
647
|
+
}
|
|
524
648
|
}
|
|
525
649
|
}
|
|
526
650
|
exports.LocalIntervalCollection = LocalIntervalCollection;
|
|
@@ -552,37 +676,12 @@ class SequenceIntervalCollectionValueType {
|
|
|
552
676
|
exports.SequenceIntervalCollectionValueType = SequenceIntervalCollectionValueType;
|
|
553
677
|
SequenceIntervalCollectionValueType.Name = "sharedStringIntervalCollection";
|
|
554
678
|
SequenceIntervalCollectionValueType._factory = new SequenceIntervalCollectionFactory();
|
|
555
|
-
SequenceIntervalCollectionValueType._ops =
|
|
556
|
-
"add",
|
|
557
|
-
{
|
|
558
|
-
process: (value, params, local, op) => {
|
|
559
|
-
value.ackAdd(params, local, op);
|
|
560
|
-
},
|
|
561
|
-
},
|
|
562
|
-
],
|
|
563
|
-
[
|
|
564
|
-
"delete",
|
|
565
|
-
{
|
|
566
|
-
process: (value, params, local, op) => {
|
|
567
|
-
value.ackDelete(params, local, op);
|
|
568
|
-
},
|
|
569
|
-
},
|
|
570
|
-
],
|
|
571
|
-
[
|
|
572
|
-
"change",
|
|
573
|
-
{
|
|
574
|
-
process: (value, params, local, op) => {
|
|
575
|
-
value.ackChange(params, local, op);
|
|
576
|
-
},
|
|
577
|
-
},
|
|
578
|
-
]]);
|
|
679
|
+
SequenceIntervalCollectionValueType._ops = makeOpsMap();
|
|
579
680
|
const compareIntervalEnds = (a, b) => a.end - b.end;
|
|
580
681
|
function createInterval(label, start, end, client) {
|
|
581
|
-
|
|
582
|
-
if (label &&
|
|
583
|
-
rangeProp =
|
|
584
|
-
[merge_tree_1.reservedRangeLabelsKey]: [label],
|
|
585
|
-
};
|
|
682
|
+
const rangeProp = {};
|
|
683
|
+
if (label && label.length > 0) {
|
|
684
|
+
rangeProp[merge_tree_1.reservedRangeLabelsKey] = [label];
|
|
586
685
|
}
|
|
587
686
|
return new Interval(start, end, rangeProp);
|
|
588
687
|
}
|
|
@@ -614,30 +713,45 @@ class IntervalCollectionValueType {
|
|
|
614
713
|
exports.IntervalCollectionValueType = IntervalCollectionValueType;
|
|
615
714
|
IntervalCollectionValueType.Name = "sharedIntervalCollection";
|
|
616
715
|
IntervalCollectionValueType._factory = new IntervalCollectionFactory();
|
|
617
|
-
IntervalCollectionValueType._ops =
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
716
|
+
IntervalCollectionValueType._ops = makeOpsMap();
|
|
717
|
+
function makeOpsMap() {
|
|
718
|
+
const rebase = (collection, op, localOpMetadata) => {
|
|
719
|
+
const { localSeq } = localOpMetadata;
|
|
720
|
+
const rebasedValue = collection.rebaseLocalInterval(op.opName, op.value, localSeq);
|
|
721
|
+
const rebasedOp = Object.assign(Object.assign({}, op), { value: rebasedValue });
|
|
722
|
+
return { rebasedOp, rebasedLocalOpMetadata: localOpMetadata };
|
|
723
|
+
};
|
|
724
|
+
return new Map([[
|
|
725
|
+
"add",
|
|
726
|
+
{
|
|
727
|
+
process: (collection, params, local, op) => {
|
|
728
|
+
collection.ackAdd(params, local, op);
|
|
729
|
+
},
|
|
730
|
+
rebase,
|
|
622
731
|
},
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
732
|
+
],
|
|
733
|
+
[
|
|
734
|
+
"delete",
|
|
735
|
+
{
|
|
736
|
+
process: (collection, params, local, op) => {
|
|
737
|
+
collection.ackDelete(params, local, op);
|
|
738
|
+
},
|
|
739
|
+
rebase: (collection, op, localOpMetadata) => {
|
|
740
|
+
// Deletion of intervals is based on id, so requires no rebasing.
|
|
741
|
+
return { rebasedOp: op, rebasedLocalOpMetadata: localOpMetadata };
|
|
742
|
+
},
|
|
630
743
|
},
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
744
|
+
],
|
|
745
|
+
[
|
|
746
|
+
"change",
|
|
747
|
+
{
|
|
748
|
+
process: (collection, params, local, op) => {
|
|
749
|
+
collection.ackChange(params, local, op);
|
|
750
|
+
},
|
|
751
|
+
rebase,
|
|
638
752
|
},
|
|
639
|
-
|
|
640
|
-
|
|
753
|
+
]]);
|
|
754
|
+
}
|
|
641
755
|
class IntervalCollectionIterator {
|
|
642
756
|
constructor(collection, iteratesForward = true, start, end) {
|
|
643
757
|
this.results = [];
|
|
@@ -659,26 +773,35 @@ class IntervalCollectionIterator {
|
|
|
659
773
|
}
|
|
660
774
|
exports.IntervalCollectionIterator = IntervalCollectionIterator;
|
|
661
775
|
class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
776
|
+
/** @internal */
|
|
662
777
|
constructor(helpers, requiresClient, emitter, serializedIntervals) {
|
|
663
778
|
super();
|
|
664
779
|
this.helpers = helpers;
|
|
665
780
|
this.requiresClient = requiresClient;
|
|
666
781
|
this.emitter = emitter;
|
|
667
|
-
this.
|
|
782
|
+
this.pendingChangesStart = new Map();
|
|
783
|
+
this.pendingChangesEnd = new Map();
|
|
784
|
+
if (Array.isArray(serializedIntervals)) {
|
|
785
|
+
this.savedSerializedIntervals = serializedIntervals;
|
|
786
|
+
}
|
|
787
|
+
else {
|
|
788
|
+
this.savedSerializedIntervals =
|
|
789
|
+
serializedIntervals.intervals.map((i) => decompressInterval(i, serializedIntervals.label));
|
|
790
|
+
}
|
|
668
791
|
}
|
|
669
792
|
get attached() {
|
|
670
793
|
return !!this.localCollection;
|
|
671
794
|
}
|
|
672
795
|
attachGraph(client, label) {
|
|
673
796
|
if (this.attached) {
|
|
674
|
-
throw new
|
|
797
|
+
throw new telemetry_utils_1.LoggingError("Only supports one Sequence attach");
|
|
675
798
|
}
|
|
676
799
|
if ((client === undefined) && (this.requiresClient)) {
|
|
677
|
-
throw new
|
|
800
|
+
throw new telemetry_utils_1.LoggingError("Client required for this collection");
|
|
678
801
|
}
|
|
679
802
|
// Instantiate the local interval collection based on the saved intervals
|
|
680
803
|
this.client = client;
|
|
681
|
-
this.localCollection = new LocalIntervalCollection(client, label, this.helpers);
|
|
804
|
+
this.localCollection = new LocalIntervalCollection(client, label, this.helpers, (interval) => this.emit("changeInterval", interval, true, undefined));
|
|
682
805
|
if (this.savedSerializedIntervals) {
|
|
683
806
|
for (const serializedInterval of this.savedSerializedIntervals) {
|
|
684
807
|
this.localCollection.ensureSerializedId(serializedInterval);
|
|
@@ -687,9 +810,15 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
687
810
|
}
|
|
688
811
|
this.savedSerializedIntervals = undefined;
|
|
689
812
|
}
|
|
813
|
+
/**
|
|
814
|
+
* Gets the next local sequence number, modifying this client's collab window in doing so.
|
|
815
|
+
*/
|
|
816
|
+
getNextLocalSeq() {
|
|
817
|
+
return ++this.client.getCollabWindow().localSeq;
|
|
818
|
+
}
|
|
690
819
|
getIntervalById(id) {
|
|
691
820
|
if (!this.attached) {
|
|
692
|
-
throw new
|
|
821
|
+
throw new telemetry_utils_1.LoggingError("attach must be called before accessing intervals");
|
|
693
822
|
}
|
|
694
823
|
return this.localCollection.getIntervalById(id);
|
|
695
824
|
}
|
|
@@ -704,10 +833,10 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
704
833
|
add(start, end, intervalType, props) {
|
|
705
834
|
var _a, _b;
|
|
706
835
|
if (!this.attached) {
|
|
707
|
-
throw new
|
|
836
|
+
throw new telemetry_utils_1.LoggingError("attach must be called prior to adding intervals");
|
|
708
837
|
}
|
|
709
838
|
if (intervalType & IntervalType.Transient) {
|
|
710
|
-
throw new
|
|
839
|
+
throw new telemetry_utils_1.LoggingError("Can not add transient intervals");
|
|
711
840
|
}
|
|
712
841
|
const interval = this.localCollection.addInterval(start, end, intervalType, props);
|
|
713
842
|
if (interval) {
|
|
@@ -719,7 +848,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
719
848
|
start,
|
|
720
849
|
};
|
|
721
850
|
// Local ops get submitted to the server. Remote ops have the deserializer run.
|
|
722
|
-
this.emitter.emit("add", undefined, serializedInterval);
|
|
851
|
+
this.emitter.emit("add", undefined, serializedInterval, { localSeq: this.getNextLocalSeq() });
|
|
723
852
|
}
|
|
724
853
|
this.emit("addInterval", interval, true, undefined);
|
|
725
854
|
return interval;
|
|
@@ -730,7 +859,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
730
859
|
if (interval) {
|
|
731
860
|
// Local ops get submitted to the server. Remote ops have the deserializer run.
|
|
732
861
|
if (local) {
|
|
733
|
-
this.emitter.emit("delete", undefined, interval.serialize(this.client));
|
|
862
|
+
this.emitter.emit("delete", undefined, interval.serialize(this.client), { localSeq: this.getNextLocalSeq() });
|
|
734
863
|
}
|
|
735
864
|
else {
|
|
736
865
|
if (this.onDeserialize) {
|
|
@@ -749,40 +878,41 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
749
878
|
}
|
|
750
879
|
changeProperties(id, props) {
|
|
751
880
|
if (!this.attached) {
|
|
752
|
-
throw new
|
|
881
|
+
throw new telemetry_utils_1.LoggingError("Attach must be called before accessing intervals");
|
|
753
882
|
}
|
|
754
883
|
if (typeof (id) !== "string") {
|
|
755
|
-
throw new
|
|
884
|
+
throw new telemetry_utils_1.LoggingError("Change API requires an ID that is a string");
|
|
756
885
|
}
|
|
757
886
|
if (!props) {
|
|
758
|
-
throw new
|
|
887
|
+
throw new telemetry_utils_1.LoggingError("changeProperties should be called with a property set");
|
|
759
888
|
}
|
|
760
889
|
const interval = this.getIntervalById(id);
|
|
761
890
|
if (interval) {
|
|
762
891
|
// Pass Unassigned as the sequence number to indicate that this is a local op that is waiting for an ack.
|
|
763
892
|
const deltaProps = interval.addProperties(props, true, merge_tree_1.UnassignedSequenceNumber);
|
|
764
893
|
const serializedInterval = interval.serialize(this.client);
|
|
765
|
-
// Emit a change op that will only change properties. Add the ID to
|
|
894
|
+
// Emit a change op that will only change properties. Add the ID to
|
|
895
|
+
// the property bag provided by the caller.
|
|
766
896
|
serializedInterval.start = undefined;
|
|
767
897
|
serializedInterval.end = undefined;
|
|
768
898
|
serializedInterval.properties = props;
|
|
769
899
|
serializedInterval.properties[reservedIntervalIdKey] = interval.getIntervalId();
|
|
770
|
-
this.emitter.emit("change", undefined, serializedInterval);
|
|
900
|
+
this.emitter.emit("change", undefined, serializedInterval, { localSeq: this.getNextLocalSeq() });
|
|
771
901
|
this.emit("propertyChanged", interval, deltaProps);
|
|
772
902
|
}
|
|
773
903
|
this.emit("changeInterval", interval, true, undefined);
|
|
774
904
|
}
|
|
775
905
|
change(id, start, end) {
|
|
776
906
|
if (!this.attached) {
|
|
777
|
-
throw new
|
|
907
|
+
throw new telemetry_utils_1.LoggingError("Attach must be called before accessing intervals");
|
|
778
908
|
}
|
|
909
|
+
// Force id to be a string.
|
|
779
910
|
if (typeof (id) !== "string") {
|
|
780
|
-
throw new
|
|
911
|
+
throw new telemetry_utils_1.LoggingError("Change API requires an ID that is a string");
|
|
781
912
|
}
|
|
782
|
-
// Force id to be a string.
|
|
783
913
|
const interval = this.getIntervalById(id);
|
|
784
914
|
if (interval) {
|
|
785
|
-
this.localCollection.changeInterval(interval, start, end);
|
|
915
|
+
const newInterval = this.localCollection.changeInterval(interval, start, end);
|
|
786
916
|
const serializedInterval = interval.serialize(this.client);
|
|
787
917
|
serializedInterval.start = start;
|
|
788
918
|
serializedInterval.end = end;
|
|
@@ -791,23 +921,19 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
791
921
|
{
|
|
792
922
|
[reservedIntervalIdKey]: interval.getIntervalId(),
|
|
793
923
|
};
|
|
794
|
-
this.emitter.emit("change", undefined, serializedInterval);
|
|
924
|
+
this.emitter.emit("change", undefined, serializedInterval, { localSeq: this.getNextLocalSeq() });
|
|
795
925
|
this.addPendingChange(id, serializedInterval);
|
|
926
|
+
this.emit("changeInterval", newInterval, true, undefined);
|
|
927
|
+
return newInterval;
|
|
796
928
|
}
|
|
797
|
-
|
|
798
|
-
return
|
|
929
|
+
// No interval to change
|
|
930
|
+
return undefined;
|
|
799
931
|
}
|
|
800
932
|
addPendingChange(id, serializedInterval) {
|
|
801
933
|
if (serializedInterval.start !== undefined) {
|
|
802
|
-
if (!this.pendingChangesStart) {
|
|
803
|
-
this.pendingChangesStart = new Map();
|
|
804
|
-
}
|
|
805
934
|
this.addPendingChangeHelper(id, this.pendingChangesStart, serializedInterval);
|
|
806
935
|
}
|
|
807
936
|
if (serializedInterval.end !== undefined) {
|
|
808
|
-
if (!this.pendingChangesEnd) {
|
|
809
|
-
this.pendingChangesEnd = new Map();
|
|
810
|
-
}
|
|
811
937
|
this.addPendingChangeHelper(id, this.pendingChangesEnd, serializedInterval);
|
|
812
938
|
}
|
|
813
939
|
}
|
|
@@ -820,8 +946,9 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
820
946
|
entries.push(serializedInterval);
|
|
821
947
|
}
|
|
822
948
|
removePendingChange(serializedInterval) {
|
|
949
|
+
var _a;
|
|
823
950
|
// Change ops always have an ID.
|
|
824
|
-
const id = serializedInterval.properties[reservedIntervalIdKey];
|
|
951
|
+
const id = (_a = serializedInterval.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
|
|
825
952
|
if (serializedInterval.start !== undefined) {
|
|
826
953
|
this.removePendingChangeHelper(id, this.pendingChangesStart, serializedInterval);
|
|
827
954
|
}
|
|
@@ -830,26 +957,24 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
830
957
|
}
|
|
831
958
|
}
|
|
832
959
|
removePendingChangeHelper(id, pendingChanges, serializedInterval) {
|
|
833
|
-
const entries = pendingChanges
|
|
960
|
+
const entries = pendingChanges.get(id);
|
|
834
961
|
if (entries) {
|
|
835
962
|
const pendingChange = entries.shift();
|
|
836
963
|
if (entries.length === 0) {
|
|
837
964
|
pendingChanges.delete(id);
|
|
838
965
|
}
|
|
839
|
-
if (pendingChange.start !== serializedInterval.start ||
|
|
840
|
-
pendingChange.end !== serializedInterval.end) {
|
|
841
|
-
throw new
|
|
966
|
+
if ((pendingChange === null || pendingChange === void 0 ? void 0 : pendingChange.start) !== serializedInterval.start ||
|
|
967
|
+
(pendingChange === null || pendingChange === void 0 ? void 0 : pendingChange.end) !== serializedInterval.end) {
|
|
968
|
+
throw new telemetry_utils_1.LoggingError("Mismatch in pending changes");
|
|
842
969
|
}
|
|
843
970
|
}
|
|
844
971
|
}
|
|
845
972
|
hasPendingChangeStart(id) {
|
|
846
|
-
|
|
847
|
-
const entries = (_a = this.pendingChangesStart) === null || _a === void 0 ? void 0 : _a.get(id);
|
|
973
|
+
const entries = this.pendingChangesStart.get(id);
|
|
848
974
|
return entries && entries.length !== 0;
|
|
849
975
|
}
|
|
850
976
|
hasPendingChangeEnd(id) {
|
|
851
|
-
|
|
852
|
-
const entries = (_a = this.pendingChangesEnd) === null || _a === void 0 ? void 0 : _a.get(id);
|
|
977
|
+
const entries = this.pendingChangesEnd.get(id);
|
|
853
978
|
return entries && entries.length !== 0;
|
|
854
979
|
}
|
|
855
980
|
/** @deprecated - use ackChange */
|
|
@@ -858,22 +983,21 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
858
983
|
}
|
|
859
984
|
/** @internal */
|
|
860
985
|
ackChange(serializedInterval, local, op) {
|
|
861
|
-
var _a, _b;
|
|
986
|
+
var _a, _b, _c, _d;
|
|
862
987
|
if (!this.attached) {
|
|
863
|
-
throw new
|
|
988
|
+
throw new telemetry_utils_1.LoggingError("Attach must be called before accessing intervals");
|
|
864
989
|
}
|
|
865
990
|
let interval;
|
|
866
991
|
if (local) {
|
|
867
992
|
// This is an ack from the server. Remove the pending change.
|
|
868
993
|
this.removePendingChange(serializedInterval);
|
|
869
|
-
const id = serializedInterval.properties[reservedIntervalIdKey];
|
|
870
|
-
// Could store the interval in the localOpMetadata to avoid the getIntervalById call
|
|
994
|
+
const id = (_a = serializedInterval.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
|
|
871
995
|
interval = this.getIntervalById(id);
|
|
872
996
|
if (interval) {
|
|
873
997
|
// Let the propertyManager prune its pending change-properties set.
|
|
874
|
-
(
|
|
998
|
+
(_b = interval.propertyManager) === null || _b === void 0 ? void 0 : _b.ackPendingProperties({
|
|
875
999
|
type: merge_tree_1.MergeTreeDeltaType.ANNOTATE,
|
|
876
|
-
props: serializedInterval.properties,
|
|
1000
|
+
props: (_c = serializedInterval.properties) !== null && _c !== void 0 ? _c : {},
|
|
877
1001
|
});
|
|
878
1002
|
this.ackInterval(interval, op);
|
|
879
1003
|
}
|
|
@@ -884,7 +1008,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
884
1008
|
// Note that the ID is in the property bag only to allow us to find the interval.
|
|
885
1009
|
// This API cannot change the ID, and writing to the ID property will result in an exception. So we
|
|
886
1010
|
// strip it out of the properties here.
|
|
887
|
-
const
|
|
1011
|
+
const _e = serializedInterval.properties, _f = reservedIntervalIdKey, id = _e[_f], newProps = __rest(_e, [typeof _f === "symbol" ? _f : _f + ""]);
|
|
888
1012
|
interval = this.getIntervalById(id);
|
|
889
1013
|
if (interval) {
|
|
890
1014
|
let start;
|
|
@@ -899,7 +1023,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
899
1023
|
if (start !== undefined || end !== undefined) {
|
|
900
1024
|
// If changeInterval gives us a new interval, work with that one. Otherwise keep working with
|
|
901
1025
|
// the one we originally found in the tree.
|
|
902
|
-
interval = (
|
|
1026
|
+
interval = (_d = this.localCollection.changeInterval(interval, start, end, op)) !== null && _d !== void 0 ? _d : interval;
|
|
903
1027
|
}
|
|
904
1028
|
const deltaProps = interval.addProperties(newProps, true, op.sequenceNumber);
|
|
905
1029
|
if (this.onDeserialize) {
|
|
@@ -914,7 +1038,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
914
1038
|
}
|
|
915
1039
|
addConflictResolver(conflictResolver) {
|
|
916
1040
|
if (!this.attached) {
|
|
917
|
-
throw new
|
|
1041
|
+
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|
|
918
1042
|
}
|
|
919
1043
|
this.localCollection.addConflictResolver(conflictResolver);
|
|
920
1044
|
}
|
|
@@ -927,13 +1051,38 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
927
1051
|
this.onDeserialize = onDeserialize;
|
|
928
1052
|
// Trigger the async prepare work across all values in the collection
|
|
929
1053
|
this.localCollection.map((interval) => {
|
|
930
|
-
|
|
1054
|
+
onDeserialize(interval);
|
|
931
1055
|
});
|
|
932
1056
|
}
|
|
1057
|
+
/** @internal */
|
|
1058
|
+
rebaseLocalInterval(opName, serializedInterval, localSeq) {
|
|
1059
|
+
var _a, _b;
|
|
1060
|
+
if (!this.attached) {
|
|
1061
|
+
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|
|
1062
|
+
}
|
|
1063
|
+
const { start, end, intervalType, properties, sequenceNumber } = serializedInterval;
|
|
1064
|
+
const startRebased = start === undefined ? undefined :
|
|
1065
|
+
this.client.rebasePosition(start, sequenceNumber, localSeq);
|
|
1066
|
+
const endRebased = end === undefined ? undefined :
|
|
1067
|
+
this.client.rebasePosition(end, sequenceNumber, localSeq);
|
|
1068
|
+
const intervalId = properties === null || properties === void 0 ? void 0 : properties[reservedIntervalIdKey];
|
|
1069
|
+
const rebased = {
|
|
1070
|
+
start: startRebased,
|
|
1071
|
+
end: endRebased,
|
|
1072
|
+
intervalType,
|
|
1073
|
+
sequenceNumber: (_b = (_a = this.client) === null || _a === void 0 ? void 0 : _a.getCurrentSeq()) !== null && _b !== void 0 ? _b : 0,
|
|
1074
|
+
properties,
|
|
1075
|
+
};
|
|
1076
|
+
if (opName === "change" && (this.hasPendingChangeStart(intervalId) || this.hasPendingChangeEnd(intervalId))) {
|
|
1077
|
+
this.removePendingChange(serializedInterval);
|
|
1078
|
+
this.addPendingChange(intervalId, rebased);
|
|
1079
|
+
}
|
|
1080
|
+
return rebased;
|
|
1081
|
+
}
|
|
933
1082
|
getSlideToSegment(lref) {
|
|
934
1083
|
const segoff = { segment: lref.segment, offset: lref.offset };
|
|
935
1084
|
const newSegoff = this.client.getSlideToSegment(segoff);
|
|
936
|
-
const value = (segoff === newSegoff) ? undefined : newSegoff;
|
|
1085
|
+
const value = (segoff.segment === newSegoff.segment && segoff.offset === newSegoff.offset) ? undefined : newSegoff;
|
|
937
1086
|
return value;
|
|
938
1087
|
}
|
|
939
1088
|
setSlideOnRemove(lref) {
|
|
@@ -947,25 +1096,43 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
947
1096
|
if (!(interval instanceof SequenceInterval)) {
|
|
948
1097
|
return;
|
|
949
1098
|
}
|
|
950
|
-
if (!(0, merge_tree_1.refTypeIncludesFlag)(interval.start, merge_tree_1.ReferenceType.StayOnRemove)
|
|
1099
|
+
if (!(0, merge_tree_1.refTypeIncludesFlag)(interval.start, merge_tree_1.ReferenceType.StayOnRemove) &&
|
|
1100
|
+
!(0, merge_tree_1.refTypeIncludesFlag)(interval.end, merge_tree_1.ReferenceType.StayOnRemove)) {
|
|
951
1101
|
return;
|
|
952
1102
|
}
|
|
953
|
-
(0, common_utils_1.assert)((0, merge_tree_1.refTypeIncludesFlag)(interval.end, merge_tree_1.ReferenceType.StayOnRemove), 0x2f7 /* start and end must both be StayOnRemove */);
|
|
954
1103
|
const newStart = this.getSlideToSegment(interval.start);
|
|
955
1104
|
const newEnd = this.getSlideToSegment(interval.end);
|
|
956
|
-
|
|
957
|
-
this.
|
|
958
|
-
|
|
1105
|
+
const id = interval.properties[reservedIntervalIdKey];
|
|
1106
|
+
const hasPendingStartChange = this.hasPendingChangeStart(id);
|
|
1107
|
+
const hasPendingEndChange = this.hasPendingChangeEnd(id);
|
|
1108
|
+
if (!hasPendingStartChange) {
|
|
1109
|
+
this.setSlideOnRemove(interval.start);
|
|
1110
|
+
}
|
|
1111
|
+
if (!hasPendingEndChange) {
|
|
1112
|
+
this.setSlideOnRemove(interval.end);
|
|
1113
|
+
}
|
|
1114
|
+
const needsStartUpdate = newStart !== undefined && !hasPendingStartChange;
|
|
1115
|
+
const needsEndUpdate = newEnd !== undefined && !hasPendingEndChange;
|
|
1116
|
+
if (needsStartUpdate || needsEndUpdate) {
|
|
1117
|
+
// In this case, where we change the start or end of an interval,
|
|
1118
|
+
// it is necessary to remove and re-add the interval listeners.
|
|
1119
|
+
// This ensures that the correct listeners are added to the ReferencePosition.
|
|
959
1120
|
this.localCollection.removeExistingInterval(interval);
|
|
960
|
-
if (
|
|
1121
|
+
if (needsStartUpdate) {
|
|
961
1122
|
const props = interval.start.properties;
|
|
1123
|
+
this.client.removeLocalReferencePosition(interval.start);
|
|
962
1124
|
interval.start = createPositionReferenceFromSegoff(this.client, newStart, interval.start.refType, op);
|
|
963
|
-
|
|
1125
|
+
if (props) {
|
|
1126
|
+
interval.start.addProperties(props);
|
|
1127
|
+
}
|
|
964
1128
|
}
|
|
965
|
-
if (
|
|
1129
|
+
if (needsEndUpdate) {
|
|
966
1130
|
const props = interval.end.properties;
|
|
1131
|
+
this.client.removeLocalReferencePosition(interval.end);
|
|
967
1132
|
interval.end = createPositionReferenceFromSegoff(this.client, newEnd, interval.end.refType, op);
|
|
968
|
-
|
|
1133
|
+
if (props) {
|
|
1134
|
+
interval.end.addProperties(props);
|
|
1135
|
+
}
|
|
969
1136
|
}
|
|
970
1137
|
this.localCollection.add(interval);
|
|
971
1138
|
}
|
|
@@ -976,9 +1143,9 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
976
1143
|
}
|
|
977
1144
|
/** @internal */
|
|
978
1145
|
ackAdd(serializedInterval, local, op) {
|
|
1146
|
+
var _a;
|
|
979
1147
|
if (local) {
|
|
980
|
-
const id = serializedInterval.properties[reservedIntervalIdKey];
|
|
981
|
-
// Could store the interval in the localOpMetadata to avoid the getIntervalById call
|
|
1148
|
+
const id = (_a = serializedInterval.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
|
|
982
1149
|
const localInterval = this.getIntervalById(id);
|
|
983
1150
|
if (localInterval) {
|
|
984
1151
|
this.ackInterval(localInterval, op);
|
|
@@ -986,7 +1153,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
986
1153
|
return;
|
|
987
1154
|
}
|
|
988
1155
|
if (!this.attached) {
|
|
989
|
-
throw new
|
|
1156
|
+
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|
|
990
1157
|
}
|
|
991
1158
|
this.localCollection.ensureSerializedId(serializedInterval);
|
|
992
1159
|
const interval = this.localCollection.addInterval(serializedInterval.start, serializedInterval.end, serializedInterval.intervalType, serializedInterval.properties, op);
|
|
@@ -1011,17 +1178,20 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1011
1178
|
return;
|
|
1012
1179
|
}
|
|
1013
1180
|
if (!this.attached) {
|
|
1014
|
-
throw new
|
|
1181
|
+
throw new telemetry_utils_1.LoggingError("attach must be called prior to deleting intervals");
|
|
1015
1182
|
}
|
|
1016
|
-
this.localCollection.ensureSerializedId(serializedInterval);
|
|
1017
|
-
const interval = this.localCollection.getIntervalById(
|
|
1183
|
+
const id = this.localCollection.ensureSerializedId(serializedInterval);
|
|
1184
|
+
const interval = this.localCollection.getIntervalById(id);
|
|
1018
1185
|
if (interval) {
|
|
1019
1186
|
this.deleteExistingInterval(interval, local, op);
|
|
1020
1187
|
}
|
|
1021
1188
|
}
|
|
1189
|
+
/**
|
|
1190
|
+
* @internal
|
|
1191
|
+
*/
|
|
1022
1192
|
serializeInternal() {
|
|
1023
1193
|
if (!this.attached) {
|
|
1024
|
-
throw new
|
|
1194
|
+
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|
|
1025
1195
|
}
|
|
1026
1196
|
return this.localCollection.serialize();
|
|
1027
1197
|
}
|
|
@@ -1053,25 +1223,25 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1053
1223
|
}
|
|
1054
1224
|
findOverlappingIntervals(startPosition, endPosition) {
|
|
1055
1225
|
if (!this.attached) {
|
|
1056
|
-
throw new
|
|
1226
|
+
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|
|
1057
1227
|
}
|
|
1058
1228
|
return this.localCollection.findOverlappingIntervals(startPosition, endPosition);
|
|
1059
1229
|
}
|
|
1060
1230
|
map(fn) {
|
|
1061
1231
|
if (!this.attached) {
|
|
1062
|
-
throw new
|
|
1232
|
+
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|
|
1063
1233
|
}
|
|
1064
1234
|
this.localCollection.map(fn);
|
|
1065
1235
|
}
|
|
1066
1236
|
previousInterval(pos) {
|
|
1067
1237
|
if (!this.attached) {
|
|
1068
|
-
throw new
|
|
1238
|
+
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|
|
1069
1239
|
}
|
|
1070
1240
|
return this.localCollection.previousInterval(pos);
|
|
1071
1241
|
}
|
|
1072
1242
|
nextInterval(pos) {
|
|
1073
1243
|
if (!this.attached) {
|
|
1074
|
-
throw new
|
|
1244
|
+
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|
|
1075
1245
|
}
|
|
1076
1246
|
return this.localCollection.nextInterval(pos);
|
|
1077
1247
|
}
|