@fluidframework/sequence 2.0.0-internal.4.2.1 → 2.0.0-internal.4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/defaultMap.d.ts +3 -2
- package/dist/defaultMap.d.ts.map +1 -1
- package/dist/defaultMap.js +4 -3
- package/dist/defaultMap.js.map +1 -1
- package/dist/defaultMapInterfaces.d.ts +12 -1
- package/dist/defaultMapInterfaces.d.ts.map +1 -1
- package/dist/defaultMapInterfaces.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/intervalCollection.d.ts +199 -46
- package/dist/intervalCollection.d.ts.map +1 -1
- package/dist/intervalCollection.js +164 -78
- package/dist/intervalCollection.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/revertibles.d.ts +104 -0
- package/dist/revertibles.d.ts.map +1 -0
- package/dist/revertibles.js +374 -0
- package/dist/revertibles.js.map +1 -0
- package/dist/sequence.d.ts +2 -2
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +3 -3
- 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/lib/defaultMap.d.ts +3 -2
- package/lib/defaultMap.d.ts.map +1 -1
- package/lib/defaultMap.js +4 -3
- package/lib/defaultMap.js.map +1 -1
- package/lib/defaultMapInterfaces.d.ts +12 -1
- package/lib/defaultMapInterfaces.d.ts.map +1 -1
- package/lib/defaultMapInterfaces.js.map +1 -1
- package/lib/index.d.ts +3 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/intervalCollection.d.ts +199 -46
- package/lib/intervalCollection.d.ts.map +1 -1
- package/lib/intervalCollection.js +164 -78
- package/lib/intervalCollection.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/revertibles.d.ts +104 -0
- package/lib/revertibles.d.ts.map +1 -0
- package/lib/revertibles.js +364 -0
- package/lib/revertibles.js.map +1 -0
- package/lib/sequence.d.ts +2 -2
- package/lib/sequence.d.ts.map +1 -1
- package/lib/sequence.js +3 -3
- 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/package.json +38 -14
- package/src/defaultMap.ts +4 -1
- package/src/defaultMapInterfaces.ts +13 -1
- package/src/index.ts +16 -1
- package/src/intervalCollection.ts +370 -57
- package/src/packageVersion.ts +1 -1
- package/src/revertibles.ts +572 -0
- package/src/sequence.ts +12 -3
- package/src/sharedIntervalCollection.ts +3 -2
- package/.vscode/launch.json +0 -16
|
@@ -15,7 +15,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
15
15
|
return t;
|
|
16
16
|
};
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.intervalLocatorFromEndpoint = exports.IntervalCollection = exports.IntervalCollectionIterator = exports.makeOpsMap = exports.IntervalCollectionValueType = exports.SequenceIntervalCollectionValueType = exports.compareSequenceIntervalEnds = exports.LocalIntervalCollection = exports.createIntervalIndex = exports.createSequenceInterval = exports.SequenceInterval = exports.Interval = exports.IntervalType = void 0;
|
|
18
|
+
exports.intervalLocatorFromEndpoint = exports.IntervalCollection = exports.IntervalCollectionIterator = exports.makeOpsMap = exports.IntervalCollectionValueType = exports.SequenceIntervalCollectionValueType = exports.compareSequenceIntervalEnds = exports.LocalIntervalCollection = exports.createIntervalIndex = exports.createSequenceInterval = exports.SequenceInterval = exports.Interval = exports.IntervalStickiness = exports.IntervalType = exports.IntervalOpType = void 0;
|
|
19
19
|
/* eslint-disable no-bitwise */
|
|
20
20
|
const common_utils_1 = require("@fluidframework/common-utils");
|
|
21
21
|
const container_utils_1 = require("@fluidframework/container-utils");
|
|
@@ -24,6 +24,17 @@ const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
|
|
|
24
24
|
const uuid_1 = require("uuid");
|
|
25
25
|
const intervalTree_1 = require("./intervalTree");
|
|
26
26
|
const reservedIntervalIdKey = "intervalId";
|
|
27
|
+
/**
|
|
28
|
+
* Values are used in persisted formats (ops) and revertibles.
|
|
29
|
+
* @alpha
|
|
30
|
+
*/
|
|
31
|
+
exports.IntervalOpType = {
|
|
32
|
+
ADD: "add",
|
|
33
|
+
DELETE: "delete",
|
|
34
|
+
CHANGE: "change",
|
|
35
|
+
PROPERTY_CHANGED: "propertyChanged",
|
|
36
|
+
POSITION_REMOVE: "positionRemove",
|
|
37
|
+
};
|
|
27
38
|
var IntervalType;
|
|
28
39
|
(function (IntervalType) {
|
|
29
40
|
IntervalType[IntervalType["Simple"] = 0] = "Simple";
|
|
@@ -52,6 +63,7 @@ function decompressInterval(interval, label) {
|
|
|
52
63
|
sequenceNumber: interval[2],
|
|
53
64
|
intervalType: interval[3],
|
|
54
65
|
properties: Object.assign(Object.assign({}, interval[4]), { [merge_tree_1.reservedRangeLabelsKey]: [label] }),
|
|
66
|
+
stickiness: interval[5],
|
|
55
67
|
};
|
|
56
68
|
}
|
|
57
69
|
/**
|
|
@@ -60,14 +72,57 @@ function decompressInterval(interval, label) {
|
|
|
60
72
|
*/
|
|
61
73
|
function compressInterval(interval) {
|
|
62
74
|
const { start, end, sequenceNumber, intervalType, properties } = interval;
|
|
63
|
-
|
|
75
|
+
const base = [
|
|
64
76
|
start,
|
|
65
77
|
end,
|
|
66
78
|
sequenceNumber,
|
|
67
79
|
intervalType,
|
|
68
80
|
Object.assign(Object.assign({}, properties), { [merge_tree_1.reservedRangeLabelsKey]: undefined }),
|
|
69
81
|
];
|
|
82
|
+
if (interval.stickiness !== undefined && interval.stickiness !== exports.IntervalStickiness.END) {
|
|
83
|
+
base.push(interval.stickiness);
|
|
84
|
+
}
|
|
85
|
+
return base;
|
|
86
|
+
}
|
|
87
|
+
function startReferenceSlidingPreference(stickiness) {
|
|
88
|
+
// if any start stickiness, prefer sliding backwards
|
|
89
|
+
return (stickiness & exports.IntervalStickiness.START) !== 0
|
|
90
|
+
? merge_tree_1.SlidingPreference.BACKWARD
|
|
91
|
+
: merge_tree_1.SlidingPreference.FORWARD;
|
|
92
|
+
}
|
|
93
|
+
function endReferenceSlidingPreference(stickiness) {
|
|
94
|
+
// if any end stickiness, prefer sliding forwards
|
|
95
|
+
return (stickiness & exports.IntervalStickiness.END) !== 0
|
|
96
|
+
? merge_tree_1.SlidingPreference.FORWARD
|
|
97
|
+
: merge_tree_1.SlidingPreference.BACKWARD;
|
|
70
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Determines how an interval should expand when segments are inserted adjacent
|
|
101
|
+
* to the range it spans
|
|
102
|
+
*
|
|
103
|
+
* Note that interval stickiness is currently an experimental feature and must
|
|
104
|
+
* be explicitly enabled with the `intervalStickinessEnabled` flag
|
|
105
|
+
*/
|
|
106
|
+
exports.IntervalStickiness = {
|
|
107
|
+
/**
|
|
108
|
+
* Interval does not expand to include adjacent segments
|
|
109
|
+
*/
|
|
110
|
+
NONE: 0b00,
|
|
111
|
+
/**
|
|
112
|
+
* Interval expands to include segments inserted adjacent to the start
|
|
113
|
+
*/
|
|
114
|
+
START: 0b01,
|
|
115
|
+
/**
|
|
116
|
+
* Interval expands to include segments inserted adjacent to the end
|
|
117
|
+
*
|
|
118
|
+
* This is the default stickiness
|
|
119
|
+
*/
|
|
120
|
+
END: 0b10,
|
|
121
|
+
/**
|
|
122
|
+
* Interval expands to include all segments inserted adjacent to it
|
|
123
|
+
*/
|
|
124
|
+
FULL: 0b11,
|
|
125
|
+
};
|
|
71
126
|
/**
|
|
72
127
|
* Serializable interval whose endpoints are plain-old numbers.
|
|
73
128
|
*/
|
|
@@ -258,11 +313,12 @@ class SequenceInterval {
|
|
|
258
313
|
* End endpoint of this interval.
|
|
259
314
|
* @remarks - This endpoint can be resolved into a character position using the SharedString it's a part of.
|
|
260
315
|
*/
|
|
261
|
-
end, intervalType, props) {
|
|
316
|
+
end, intervalType, props, stickiness = exports.IntervalStickiness.END) {
|
|
262
317
|
this.client = client;
|
|
263
318
|
this.start = start;
|
|
264
319
|
this.end = end;
|
|
265
320
|
this.intervalType = intervalType;
|
|
321
|
+
this.stickiness = stickiness;
|
|
266
322
|
this.propertyManager = new merge_tree_1.PropertiesManager();
|
|
267
323
|
this.properties = {};
|
|
268
324
|
if (props) {
|
|
@@ -314,13 +370,16 @@ class SequenceInterval {
|
|
|
314
370
|
if (this.properties) {
|
|
315
371
|
serializedInterval.properties = this.properties;
|
|
316
372
|
}
|
|
373
|
+
if (this.stickiness !== exports.IntervalStickiness.END) {
|
|
374
|
+
serializedInterval.stickiness = this.stickiness;
|
|
375
|
+
}
|
|
317
376
|
return serializedInterval;
|
|
318
377
|
}
|
|
319
378
|
/**
|
|
320
379
|
* {@inheritDoc IInterval.clone}
|
|
321
380
|
*/
|
|
322
381
|
clone() {
|
|
323
|
-
return new SequenceInterval(this.client, this.start, this.end, this.intervalType, this.properties);
|
|
382
|
+
return new SequenceInterval(this.client, this.start, this.end, this.intervalType, this.properties, this.stickiness);
|
|
324
383
|
}
|
|
325
384
|
/**
|
|
326
385
|
* {@inheritDoc IInterval.compare}
|
|
@@ -404,7 +463,7 @@ class SequenceInterval {
|
|
|
404
463
|
* {@inheritDoc IInterval.modify}
|
|
405
464
|
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
406
465
|
*/
|
|
407
|
-
modify(label, start, end, op, localSeq) {
|
|
466
|
+
modify(label, start, end, op, localSeq, stickiness = exports.IntervalStickiness.END) {
|
|
408
467
|
const getRefType = (baseType) => {
|
|
409
468
|
let refType = baseType;
|
|
410
469
|
if (op === undefined) {
|
|
@@ -415,14 +474,14 @@ class SequenceInterval {
|
|
|
415
474
|
};
|
|
416
475
|
let startRef = this.start;
|
|
417
476
|
if (start !== undefined) {
|
|
418
|
-
startRef = createPositionReference(this.client, start, getRefType(this.start.refType), op, undefined, localSeq);
|
|
477
|
+
startRef = createPositionReference(this.client, start, getRefType(this.start.refType), op, undefined, localSeq, startReferenceSlidingPreference(stickiness));
|
|
419
478
|
if (this.start.properties) {
|
|
420
479
|
startRef.addProperties(this.start.properties);
|
|
421
480
|
}
|
|
422
481
|
}
|
|
423
482
|
let endRef = this.end;
|
|
424
483
|
if (end !== undefined) {
|
|
425
|
-
endRef = createPositionReference(this.client, end, getRefType(this.end.refType), op, undefined, localSeq);
|
|
484
|
+
endRef = createPositionReference(this.client, end, getRefType(this.end.refType), op, undefined, localSeq, endReferenceSlidingPreference(stickiness));
|
|
426
485
|
if (this.end.properties) {
|
|
427
486
|
endRef.addProperties(this.end.properties);
|
|
428
487
|
}
|
|
@@ -444,9 +503,9 @@ class SequenceInterval {
|
|
|
444
503
|
}
|
|
445
504
|
}
|
|
446
505
|
exports.SequenceInterval = SequenceInterval;
|
|
447
|
-
function createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot) {
|
|
506
|
+
function createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot, slidingPreference) {
|
|
448
507
|
if (segoff.segment) {
|
|
449
|
-
const ref = client.createLocalReferencePosition(segoff.segment, segoff.offset, refType, undefined);
|
|
508
|
+
const ref = client.createLocalReferencePosition(segoff.segment, segoff.offset, refType, undefined, slidingPreference);
|
|
450
509
|
return ref;
|
|
451
510
|
}
|
|
452
511
|
// Creating references on detached segments is allowed for:
|
|
@@ -462,7 +521,7 @@ function createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq
|
|
|
462
521
|
}
|
|
463
522
|
return (0, merge_tree_1.createDetachedLocalReferencePosition)(refType);
|
|
464
523
|
}
|
|
465
|
-
function createPositionReference(client, pos, refType, op, fromSnapshot, localSeq) {
|
|
524
|
+
function createPositionReference(client, pos, refType, op, fromSnapshot, localSeq, slidingPreference) {
|
|
466
525
|
let segoff;
|
|
467
526
|
if (op) {
|
|
468
527
|
(0, common_utils_1.assert)((refType & merge_tree_1.ReferenceType.SlideOnRemove) !== 0, 0x2f5 /* op create references must be SlideOnRemove */);
|
|
@@ -476,9 +535,9 @@ function createPositionReference(client, pos, refType, op, fromSnapshot, localSe
|
|
|
476
535
|
(0, common_utils_1.assert)((refType & merge_tree_1.ReferenceType.SlideOnRemove) === 0 || !!fromSnapshot, 0x2f6 /* SlideOnRemove references must be op created */);
|
|
477
536
|
segoff = client.getContainingSegment(pos, undefined, localSeq);
|
|
478
537
|
}
|
|
479
|
-
return createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot);
|
|
538
|
+
return createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot, slidingPreference);
|
|
480
539
|
}
|
|
481
|
-
function createSequenceInterval(label, start, end, client, intervalType, op, fromSnapshot) {
|
|
540
|
+
function createSequenceInterval(label, start, end, client, intervalType, op, fromSnapshot, stickiness = exports.IntervalStickiness.END) {
|
|
482
541
|
let beginRefType = merge_tree_1.ReferenceType.RangeBegin;
|
|
483
542
|
let endRefType = merge_tree_1.ReferenceType.RangeEnd;
|
|
484
543
|
if (intervalType === IntervalType.Transient) {
|
|
@@ -502,14 +561,14 @@ function createSequenceInterval(label, start, end, client, intervalType, op, fro
|
|
|
502
561
|
endRefType |= merge_tree_1.ReferenceType.StayOnRemove;
|
|
503
562
|
}
|
|
504
563
|
}
|
|
505
|
-
const startLref = createPositionReference(client, start, beginRefType, op, fromSnapshot);
|
|
506
|
-
const endLref = createPositionReference(client, end, endRefType, op, fromSnapshot);
|
|
564
|
+
const startLref = createPositionReference(client, start, beginRefType, op, fromSnapshot, undefined, startReferenceSlidingPreference(stickiness));
|
|
565
|
+
const endLref = createPositionReference(client, end, endRefType, op, fromSnapshot, undefined, endReferenceSlidingPreference(stickiness));
|
|
507
566
|
const rangeProp = {
|
|
508
567
|
[merge_tree_1.reservedRangeLabelsKey]: [label],
|
|
509
568
|
};
|
|
510
569
|
startLref.addProperties(rangeProp);
|
|
511
570
|
endLref.addProperties(rangeProp);
|
|
512
|
-
const ival = new SequenceInterval(client, startLref, endLref, intervalType, rangeProp);
|
|
571
|
+
const ival = new SequenceInterval(client, startLref, endLref, intervalType, rangeProp, stickiness);
|
|
513
572
|
return ival;
|
|
514
573
|
}
|
|
515
574
|
exports.createSequenceInterval = createSequenceInterval;
|
|
@@ -680,11 +739,11 @@ class LocalIntervalCollection {
|
|
|
680
739
|
this.overlappingIntervalsIndex = new OverlappingIntervalsIndex(client, helpers);
|
|
681
740
|
this.idIntervalIndex = new IdIntervalIndex();
|
|
682
741
|
this.endIntervalIndex = new EndpointIndex(client, helpers);
|
|
683
|
-
this.indexes = [
|
|
742
|
+
this.indexes = new Set([
|
|
684
743
|
this.overlappingIntervalsIndex,
|
|
685
744
|
this.idIntervalIndex,
|
|
686
745
|
this.endIntervalIndex,
|
|
687
|
-
];
|
|
746
|
+
]);
|
|
688
747
|
}
|
|
689
748
|
createLegacyId(start, end) {
|
|
690
749
|
// Create a non-unique ID based on start and end to be used on intervals that come from legacy clients
|
|
@@ -724,17 +783,23 @@ class LocalIntervalCollection {
|
|
|
724
783
|
index.remove(interval);
|
|
725
784
|
}
|
|
726
785
|
}
|
|
786
|
+
appendIndex(index) {
|
|
787
|
+
this.indexes.add(index);
|
|
788
|
+
}
|
|
789
|
+
removeIndex(index) {
|
|
790
|
+
return this.indexes.delete(index);
|
|
791
|
+
}
|
|
727
792
|
removeExistingInterval(interval) {
|
|
728
793
|
this.removeIntervalFromIndexes(interval);
|
|
729
794
|
this.removeIntervalListeners(interval);
|
|
730
795
|
}
|
|
731
|
-
createInterval(start, end, intervalType, op) {
|
|
732
|
-
return this.helpers.create(this.label, start, end, this.client, intervalType, op);
|
|
796
|
+
createInterval(start, end, intervalType, op, stickiness = exports.IntervalStickiness.END) {
|
|
797
|
+
return this.helpers.create(this.label, start, end, this.client, intervalType, op, undefined, stickiness);
|
|
733
798
|
}
|
|
734
|
-
addInterval(start, end, intervalType, props, op) {
|
|
799
|
+
addInterval(start, end, intervalType, props, op, stickiness = exports.IntervalStickiness.END) {
|
|
735
800
|
var _a;
|
|
736
801
|
var _b;
|
|
737
|
-
const interval = this.createInterval(start, end, intervalType, op);
|
|
802
|
+
const interval = this.createInterval(start, end, intervalType, op, stickiness);
|
|
738
803
|
if (interval) {
|
|
739
804
|
if (!interval.properties) {
|
|
740
805
|
interval.properties = (0, merge_tree_1.createMap)();
|
|
@@ -787,7 +852,7 @@ class LocalIntervalCollection {
|
|
|
787
852
|
// either, so this must be special-cased.
|
|
788
853
|
return ref;
|
|
789
854
|
}
|
|
790
|
-
return this.client.createLocalReferencePosition(segment, ref.getOffset(), merge_tree_1.ReferenceType.Transient, ref.properties);
|
|
855
|
+
return this.client.createLocalReferencePosition(segment, ref.getOffset(), merge_tree_1.ReferenceType.Transient, ref.properties, ref.slidingPreference);
|
|
791
856
|
};
|
|
792
857
|
if (interval instanceof SequenceInterval) {
|
|
793
858
|
let previousInterval;
|
|
@@ -824,12 +889,12 @@ LocalIntervalCollection.legacyIdPrefix = "legacy";
|
|
|
824
889
|
const compareSequenceIntervalEnds = (a, b) => (0, merge_tree_1.compareReferencePositions)(a.end, b.end);
|
|
825
890
|
exports.compareSequenceIntervalEnds = compareSequenceIntervalEnds;
|
|
826
891
|
class SequenceIntervalCollectionFactory {
|
|
827
|
-
load(emitter, raw = []) {
|
|
892
|
+
load(emitter, raw = [], options) {
|
|
828
893
|
const helpers = {
|
|
829
894
|
compareEnds: exports.compareSequenceIntervalEnds,
|
|
830
895
|
create: createSequenceInterval,
|
|
831
896
|
};
|
|
832
|
-
return new IntervalCollection(helpers, true, emitter, raw);
|
|
897
|
+
return new IntervalCollection(helpers, true, emitter, raw, options);
|
|
833
898
|
}
|
|
834
899
|
store(value) {
|
|
835
900
|
return value.serializeInternal();
|
|
@@ -851,7 +916,7 @@ SequenceIntervalCollectionValueType.Name = "sharedStringIntervalCollection";
|
|
|
851
916
|
SequenceIntervalCollectionValueType._factory = new SequenceIntervalCollectionFactory();
|
|
852
917
|
SequenceIntervalCollectionValueType._ops = makeOpsMap();
|
|
853
918
|
const compareIntervalEnds = (a, b) => a.end - b.end;
|
|
854
|
-
function createInterval(label, start, end, client) {
|
|
919
|
+
function createInterval(label, start, end, client, intervalType, op, fromSnapshot) {
|
|
855
920
|
const rangeProp = {};
|
|
856
921
|
if (label && label.length > 0) {
|
|
857
922
|
rangeProp[merge_tree_1.reservedRangeLabelsKey] = [label];
|
|
@@ -859,12 +924,12 @@ function createInterval(label, start, end, client) {
|
|
|
859
924
|
return new Interval(start, end, rangeProp);
|
|
860
925
|
}
|
|
861
926
|
class IntervalCollectionFactory {
|
|
862
|
-
load(emitter, raw = []) {
|
|
927
|
+
load(emitter, raw = [], options) {
|
|
863
928
|
const helpers = {
|
|
864
929
|
compareEnds: compareIntervalEnds,
|
|
865
930
|
create: createInterval,
|
|
866
931
|
};
|
|
867
|
-
const collection = new IntervalCollection(helpers, false, emitter, raw);
|
|
932
|
+
const collection = new IntervalCollection(helpers, false, emitter, raw, options);
|
|
868
933
|
collection.attachGraph(undefined, "");
|
|
869
934
|
return collection;
|
|
870
935
|
}
|
|
@@ -896,7 +961,7 @@ function makeOpsMap() {
|
|
|
896
961
|
};
|
|
897
962
|
return new Map([
|
|
898
963
|
[
|
|
899
|
-
|
|
964
|
+
exports.IntervalOpType.ADD,
|
|
900
965
|
{
|
|
901
966
|
process: (collection, params, local, op, localOpMetadata) => {
|
|
902
967
|
// if params is undefined, the interval was deleted during
|
|
@@ -911,7 +976,7 @@ function makeOpsMap() {
|
|
|
911
976
|
},
|
|
912
977
|
],
|
|
913
978
|
[
|
|
914
|
-
|
|
979
|
+
exports.IntervalOpType.DELETE,
|
|
915
980
|
{
|
|
916
981
|
process: (collection, params, local, op) => {
|
|
917
982
|
(0, common_utils_1.assert)(op !== undefined, 0x3fc /* op should exist here */);
|
|
@@ -924,7 +989,7 @@ function makeOpsMap() {
|
|
|
924
989
|
},
|
|
925
990
|
],
|
|
926
991
|
[
|
|
927
|
-
|
|
992
|
+
exports.IntervalOpType.CHANGE,
|
|
928
993
|
{
|
|
929
994
|
process: (collection, params, local, op, localOpMetadata) => {
|
|
930
995
|
// if params is undefined, the interval was deleted during
|
|
@@ -941,6 +1006,10 @@ function makeOpsMap() {
|
|
|
941
1006
|
]);
|
|
942
1007
|
}
|
|
943
1008
|
exports.makeOpsMap = makeOpsMap;
|
|
1009
|
+
/**
|
|
1010
|
+
* @deprecated - Public export will be removed. Use an appropriate iterator creation method on
|
|
1011
|
+
* {@link IIntervalCollection} to iterate intervals instead.
|
|
1012
|
+
*/
|
|
944
1013
|
class IntervalCollectionIterator {
|
|
945
1014
|
constructor(collection, iteratesForward = true, start, end) {
|
|
946
1015
|
this.results = [];
|
|
@@ -962,19 +1031,16 @@ class IntervalCollectionIterator {
|
|
|
962
1031
|
}
|
|
963
1032
|
exports.IntervalCollectionIterator = IntervalCollectionIterator;
|
|
964
1033
|
/**
|
|
965
|
-
*
|
|
966
|
-
* This class is not a DDS in its own right, but emits events on mutating operations such that it's possible to
|
|
967
|
-
* integrate into a DDS.
|
|
968
|
-
* This aligns with its usage in `SharedSegmentSequence`, which allows associating intervals to positions in the
|
|
969
|
-
* sequence DDS which are broadcast to all other clients in an eventually consistent fashion.
|
|
1034
|
+
* @deprecated - Use {@link IIntervalCollection} instead.
|
|
970
1035
|
*/
|
|
971
1036
|
class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
972
1037
|
/** @internal */
|
|
973
|
-
constructor(helpers, requiresClient, emitter, serializedIntervals) {
|
|
1038
|
+
constructor(helpers, requiresClient, emitter, serializedIntervals, options = {}) {
|
|
974
1039
|
super();
|
|
975
1040
|
this.helpers = helpers;
|
|
976
1041
|
this.requiresClient = requiresClient;
|
|
977
1042
|
this.emitter = emitter;
|
|
1043
|
+
this.options = options;
|
|
978
1044
|
this.localSeqToSerializedInterval = new Map();
|
|
979
1045
|
this.localSeqToRebasedInterval = new Map();
|
|
980
1046
|
this.pendingChangesStart = new Map();
|
|
@@ -986,6 +1052,36 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
986
1052
|
get attached() {
|
|
987
1053
|
return !!this.localCollection;
|
|
988
1054
|
}
|
|
1055
|
+
/**
|
|
1056
|
+
* {@inheritdoc IIntervalCollection.attachIndex}
|
|
1057
|
+
*/
|
|
1058
|
+
attachIndex(index) {
|
|
1059
|
+
var _a;
|
|
1060
|
+
if (!this.attached) {
|
|
1061
|
+
throw new telemetry_utils_1.LoggingError("The local interval collection must exist");
|
|
1062
|
+
}
|
|
1063
|
+
for (const interval of this) {
|
|
1064
|
+
index.add(interval);
|
|
1065
|
+
}
|
|
1066
|
+
(_a = this.localCollection) === null || _a === void 0 ? void 0 : _a.appendIndex(index);
|
|
1067
|
+
}
|
|
1068
|
+
/**
|
|
1069
|
+
* {@inheritdoc IIntervalCollection.detachIndex}
|
|
1070
|
+
*/
|
|
1071
|
+
detachIndex(index) {
|
|
1072
|
+
var _a;
|
|
1073
|
+
if (!this.attached) {
|
|
1074
|
+
throw new telemetry_utils_1.LoggingError("The local interval collection must exist");
|
|
1075
|
+
}
|
|
1076
|
+
// Avoid removing intervals if the index does not exist
|
|
1077
|
+
if (!((_a = this.localCollection) === null || _a === void 0 ? void 0 : _a.removeIndex(index))) {
|
|
1078
|
+
return false;
|
|
1079
|
+
}
|
|
1080
|
+
for (const interval of this) {
|
|
1081
|
+
index.remove(interval);
|
|
1082
|
+
}
|
|
1083
|
+
return true;
|
|
1084
|
+
}
|
|
989
1085
|
rebasePositionWithSegmentSlide(pos, seqNumberFrom, localSeq) {
|
|
990
1086
|
var _a;
|
|
991
1087
|
if (!this.client) {
|
|
@@ -1041,8 +1137,8 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1041
1137
|
if (this.savedSerializedIntervals) {
|
|
1042
1138
|
for (const serializedInterval of this.savedSerializedIntervals) {
|
|
1043
1139
|
this.localCollection.ensureSerializedId(serializedInterval);
|
|
1044
|
-
const { start, end, intervalType, properties } = serializedInterval;
|
|
1045
|
-
const interval = this.helpers.create(label, start, end, client, intervalType, undefined, true);
|
|
1140
|
+
const { start, end, intervalType, properties, stickiness } = serializedInterval;
|
|
1141
|
+
const interval = this.helpers.create(label, start, end, client, intervalType, undefined, true, stickiness);
|
|
1046
1142
|
if (properties) {
|
|
1047
1143
|
interval.addProperties(properties);
|
|
1048
1144
|
}
|
|
@@ -1080,8 +1176,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1080
1176
|
}
|
|
1081
1177
|
}
|
|
1082
1178
|
/**
|
|
1083
|
-
* @
|
|
1084
|
-
* If no interval in the collection has this `id`, returns `undefined`.
|
|
1179
|
+
* {@inheritdoc IIntervalCollection.getIntervalById}
|
|
1085
1180
|
*/
|
|
1086
1181
|
getIntervalById(id) {
|
|
1087
1182
|
if (!this.localCollection) {
|
|
@@ -1090,16 +1185,9 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1090
1185
|
return this.localCollection.idIntervalIndex.getIntervalById(id);
|
|
1091
1186
|
}
|
|
1092
1187
|
/**
|
|
1093
|
-
*
|
|
1094
|
-
* @param start - interval start position (inclusive)
|
|
1095
|
-
* @param end - interval end position (exclusive)
|
|
1096
|
-
* @param intervalType - type of the interval. All intervals are SlideOnRemove. Intervals may not be Transient.
|
|
1097
|
-
* @param props - properties of the interval
|
|
1098
|
-
* @returns - the created interval
|
|
1099
|
-
* @remarks - See documentation on {@link SequenceInterval} for comments on interval endpoint semantics: there are subtleties
|
|
1100
|
-
* with how the current half-open behavior is represented.
|
|
1188
|
+
* {@inheritdoc IIntervalCollection.add}
|
|
1101
1189
|
*/
|
|
1102
|
-
add(start, end, intervalType, props) {
|
|
1190
|
+
add(start, end, intervalType, props, stickiness = exports.IntervalStickiness.END) {
|
|
1103
1191
|
var _a, _b;
|
|
1104
1192
|
if (!this.localCollection) {
|
|
1105
1193
|
throw new telemetry_utils_1.LoggingError("attach must be called prior to adding intervals");
|
|
@@ -1107,7 +1195,10 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1107
1195
|
if (intervalType & IntervalType.Transient) {
|
|
1108
1196
|
throw new telemetry_utils_1.LoggingError("Can not add transient intervals");
|
|
1109
1197
|
}
|
|
1110
|
-
|
|
1198
|
+
if (stickiness !== exports.IntervalStickiness.END && !this.options.intervalStickinessEnabled) {
|
|
1199
|
+
throw new container_utils_1.UsageError("attempted to set interval stickiness without enabling `intervalStickinessEnabled` feature flag");
|
|
1200
|
+
}
|
|
1201
|
+
const interval = this.localCollection.addInterval(start, end, intervalType, props, undefined, stickiness);
|
|
1111
1202
|
if (interval) {
|
|
1112
1203
|
const serializedInterval = {
|
|
1113
1204
|
end,
|
|
@@ -1115,6 +1206,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1115
1206
|
properties: interval.properties,
|
|
1116
1207
|
sequenceNumber: (_b = (_a = this.client) === null || _a === void 0 ? void 0 : _a.getCurrentSeq()) !== null && _b !== void 0 ? _b : 0,
|
|
1117
1208
|
start,
|
|
1209
|
+
stickiness,
|
|
1118
1210
|
};
|
|
1119
1211
|
const localSeq = this.getNextLocalSeq();
|
|
1120
1212
|
this.localSeqToSerializedInterval.set(localSeq, serializedInterval);
|
|
@@ -1146,9 +1238,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1146
1238
|
this.emit("deleteInterval", interval, local, op);
|
|
1147
1239
|
}
|
|
1148
1240
|
/**
|
|
1149
|
-
*
|
|
1150
|
-
* @param id - Id of the interval to remove
|
|
1151
|
-
* @returns the removed interval
|
|
1241
|
+
* {@inheritdoc IIntervalCollection.removeIntervalById}
|
|
1152
1242
|
*/
|
|
1153
1243
|
removeIntervalById(id) {
|
|
1154
1244
|
if (!this.localCollection) {
|
|
@@ -1161,10 +1251,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1161
1251
|
return interval;
|
|
1162
1252
|
}
|
|
1163
1253
|
/**
|
|
1164
|
-
*
|
|
1165
|
-
* @param id - Id of the interval whose properties should be changed
|
|
1166
|
-
* @param props - Property set to apply to the interval. Shallow merging is used between any existing properties
|
|
1167
|
-
* and `prop`, i.e. the interval will end up with a property object equivalent to `{ ...oldProps, ...props }`.
|
|
1254
|
+
* {@inheritdoc IIntervalCollection.changeProperties}
|
|
1168
1255
|
*/
|
|
1169
1256
|
changeProperties(id, props) {
|
|
1170
1257
|
if (!this.attached) {
|
|
@@ -1194,11 +1281,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1194
1281
|
}
|
|
1195
1282
|
}
|
|
1196
1283
|
/**
|
|
1197
|
-
*
|
|
1198
|
-
* @param id - Id of the interval to change
|
|
1199
|
-
* @param start - New start value, if defined. `undefined` signifies this endpoint should be left unchanged.
|
|
1200
|
-
* @param end - New end value, if defined. `undefined` signifies this endpoint should be left unchanged.
|
|
1201
|
-
* @returns the interval that was changed, if it existed in the collection.
|
|
1284
|
+
* {@inheritdoc IIntervalCollection.change}
|
|
1202
1285
|
*/
|
|
1203
1286
|
change(id, start, end) {
|
|
1204
1287
|
if (!this.localCollection) {
|
|
@@ -1353,6 +1436,9 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1353
1436
|
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|
|
1354
1437
|
}
|
|
1355
1438
|
}
|
|
1439
|
+
/**
|
|
1440
|
+
* {@inheritdoc IIntervalCollection.attachDeserializer}
|
|
1441
|
+
*/
|
|
1356
1442
|
attachDeserializer(onDeserialize) {
|
|
1357
1443
|
// If no deserializer is specified can skip all processing work
|
|
1358
1444
|
if (!onDeserialize) {
|
|
@@ -1473,7 +1559,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1473
1559
|
}
|
|
1474
1560
|
if (needsStartUpdate) {
|
|
1475
1561
|
const props = interval.start.properties;
|
|
1476
|
-
interval.start = createPositionReferenceFromSegoff(this.client, newStart, interval.start.refType, op);
|
|
1562
|
+
interval.start = createPositionReferenceFromSegoff(this.client, newStart, interval.start.refType, op, startReferenceSlidingPreference(interval.stickiness));
|
|
1477
1563
|
if (props) {
|
|
1478
1564
|
interval.start.addProperties(props);
|
|
1479
1565
|
}
|
|
@@ -1485,7 +1571,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1485
1571
|
}
|
|
1486
1572
|
if (needsEndUpdate) {
|
|
1487
1573
|
const props = interval.end.properties;
|
|
1488
|
-
interval.end = createPositionReferenceFromSegoff(this.client, newEnd, interval.end.refType, op);
|
|
1574
|
+
interval.end = createPositionReferenceFromSegoff(this.client, newEnd, interval.end.refType, op, endReferenceSlidingPreference(interval.stickiness));
|
|
1489
1575
|
if (props) {
|
|
1490
1576
|
interval.end.addProperties(props);
|
|
1491
1577
|
}
|
|
@@ -1516,7 +1602,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1516
1602
|
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|
|
1517
1603
|
}
|
|
1518
1604
|
this.localCollection.ensureSerializedId(serializedInterval);
|
|
1519
|
-
const interval = this.localCollection.addInterval(serializedInterval.start, serializedInterval.end, serializedInterval.intervalType, serializedInterval.properties, op);
|
|
1605
|
+
const interval = this.localCollection.addInterval(serializedInterval.start, serializedInterval.end, serializedInterval.intervalType, serializedInterval.properties, op, serializedInterval.stickiness);
|
|
1520
1606
|
if (interval) {
|
|
1521
1607
|
if (this.onDeserialize) {
|
|
1522
1608
|
this.onDeserialize(interval);
|
|
@@ -1559,40 +1645,35 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1559
1645
|
return iterator;
|
|
1560
1646
|
}
|
|
1561
1647
|
/**
|
|
1562
|
-
* @
|
|
1648
|
+
* {@inheritdoc IIntervalCollection.CreateForwardIteratorWithStartPosition}
|
|
1563
1649
|
*/
|
|
1564
1650
|
CreateForwardIteratorWithStartPosition(startPosition) {
|
|
1565
1651
|
const iterator = new IntervalCollectionIterator(this, true, startPosition);
|
|
1566
1652
|
return iterator;
|
|
1567
1653
|
}
|
|
1568
1654
|
/**
|
|
1569
|
-
* @
|
|
1655
|
+
* {@inheritdoc IIntervalCollection.CreateBackwardIteratorWithStartPosition}
|
|
1570
1656
|
*/
|
|
1571
1657
|
CreateBackwardIteratorWithStartPosition(startPosition) {
|
|
1572
1658
|
const iterator = new IntervalCollectionIterator(this, false, startPosition);
|
|
1573
1659
|
return iterator;
|
|
1574
1660
|
}
|
|
1575
1661
|
/**
|
|
1576
|
-
* @
|
|
1662
|
+
* {@inheritdoc IIntervalCollection.CreateForwardIteratorWithEndPosition}
|
|
1577
1663
|
*/
|
|
1578
1664
|
CreateForwardIteratorWithEndPosition(endPosition) {
|
|
1579
1665
|
const iterator = new IntervalCollectionIterator(this, true, undefined, endPosition);
|
|
1580
1666
|
return iterator;
|
|
1581
1667
|
}
|
|
1582
1668
|
/**
|
|
1583
|
-
* @
|
|
1669
|
+
* {@inheritdoc IIntervalCollection.CreateBackwardIteratorWithEndPosition}
|
|
1584
1670
|
*/
|
|
1585
1671
|
CreateBackwardIteratorWithEndPosition(endPosition) {
|
|
1586
1672
|
const iterator = new IntervalCollectionIterator(this, false, undefined, endPosition);
|
|
1587
1673
|
return iterator;
|
|
1588
1674
|
}
|
|
1589
1675
|
/**
|
|
1590
|
-
*
|
|
1591
|
-
* @param results - Array to gather the results into. In lieu of a return value, this array will be populated with
|
|
1592
|
-
* intervals matching the query upon edit.
|
|
1593
|
-
* @param iteratesForward - whether or not iteration should be in the forward direction
|
|
1594
|
-
* @param start - If provided, only match intervals whose start point is equal to `start`.
|
|
1595
|
-
* @param end - If provided, only match intervals whose end point is equal to `end`.
|
|
1676
|
+
* {@inheritdoc IIntervalCollection.gatherIterationResults}
|
|
1596
1677
|
*/
|
|
1597
1678
|
gatherIterationResults(results, iteratesForward, start, end) {
|
|
1598
1679
|
if (!this.localCollection) {
|
|
@@ -1601,8 +1682,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1601
1682
|
this.localCollection.overlappingIntervalsIndex.gatherIterationResults(results, iteratesForward, start, end);
|
|
1602
1683
|
}
|
|
1603
1684
|
/**
|
|
1604
|
-
* @
|
|
1605
|
-
* `[startPosition, endPosition]`.
|
|
1685
|
+
* {@inheritdoc IIntervalCollection.findOverlappingIntervals}
|
|
1606
1686
|
*/
|
|
1607
1687
|
findOverlappingIntervals(startPosition, endPosition) {
|
|
1608
1688
|
if (!this.localCollection) {
|
|
@@ -1611,7 +1691,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1611
1691
|
return this.localCollection.overlappingIntervalsIndex.findOverlappingIntervals(startPosition, endPosition);
|
|
1612
1692
|
}
|
|
1613
1693
|
/**
|
|
1614
|
-
*
|
|
1694
|
+
* {@inheritdoc IIntervalCollection.map}
|
|
1615
1695
|
*/
|
|
1616
1696
|
map(fn) {
|
|
1617
1697
|
if (!this.localCollection) {
|
|
@@ -1621,12 +1701,18 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
|
|
|
1621
1701
|
fn(interval);
|
|
1622
1702
|
}
|
|
1623
1703
|
}
|
|
1704
|
+
/**
|
|
1705
|
+
* {@inheritdoc IIntervalCollection.previousInterval}
|
|
1706
|
+
*/
|
|
1624
1707
|
previousInterval(pos) {
|
|
1625
1708
|
if (!this.localCollection) {
|
|
1626
1709
|
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|
|
1627
1710
|
}
|
|
1628
1711
|
return this.localCollection.endIntervalIndex.previousInterval(pos);
|
|
1629
1712
|
}
|
|
1713
|
+
/**
|
|
1714
|
+
* {@inheritdoc IIntervalCollection.nextInterval}
|
|
1715
|
+
*/
|
|
1630
1716
|
nextInterval(pos) {
|
|
1631
1717
|
if (!this.localCollection) {
|
|
1632
1718
|
throw new telemetry_utils_1.LoggingError("attachSequence must be called");
|