Skip to content

Interval Collections: Deprecate unnecessary and internal APIs #24792

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .changeset/deep-geckos-listen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
"@fluidframework/sequence": minor
"__section": deprecation
---
Deprecate unnecessary and internal APIs in `ISequenceIntervalCollection` and related interval types

The following APIs are now deprecated and will be removed in a future release:
- `IInterval.clone`
- `IInterval.modify`
- `IInterval.union`
- `ISerializableInterval`
- `SequenceInterval.clone`
- `SequenceInterval.modify`
- `SequenceInterval.union`
- `SequenceInterval.serialize`
- `SequenceInterval.addPositionChangeListeners`
- `SequenceInterval.removePositionChangeListeners`


These APIs were never intended for public use. There is no migration path, and any usage is strongly discouraged, as it may result in severe errors or data corruption. Please remove any dependencies on these APIs as soon as possible.
18 changes: 13 additions & 5 deletions packages/dds/sequence/api-report/sequence.legacy.alpha.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,16 @@ export function discardSharedStringRevertibles(sharedString: ISharedString, reve

// @alpha @legacy
export interface IInterval {
// (undocumented)
// @deprecated (undocumented)
clone(): IInterval;
compare(b: IInterval): number;
compareEnd(b: IInterval): number;
compareStart(b: IInterval): number;
// @deprecated
modify(label: string, start: SequencePlace | undefined, end: SequencePlace | undefined, op?: ISequencedDocumentMessage, localSeq?: number, useNewSlidingBehavior?: boolean): IInterval | undefined;
// (undocumented)
overlaps(b: IInterval): boolean;
// @deprecated
union(b: IInterval): IInterval;
}

Expand Down Expand Up @@ -128,7 +130,7 @@ export interface ISequenceIntervalCollection extends TypedEventEmitter<ISequence
end: SequencePlace;
props?: PropertySet;
}): SequenceInterval;
// (undocumented)
// @deprecated (undocumented)
attachDeserializer(onDeserialize: DeserializeCallback): void;
// (undocumented)
readonly attached: boolean;
Expand Down Expand Up @@ -175,11 +177,11 @@ export interface ISequenceOverlappingIntervalsIndex extends SequenceIntervalInde
gatherIterationResults(results: SequenceInterval[], iteratesForward: boolean, start?: SequencePlace, end?: SequencePlace): void;
}

// @alpha @legacy (undocumented)
// @alpha @deprecated @legacy (undocumented)
export interface ISerializableInterval extends IInterval {
getIntervalId(): string;
properties: PropertySet;
// (undocumented)
// @deprecated (undocumented)
serialize(): ISerializedInterval;
}

Expand Down Expand Up @@ -302,29 +304,35 @@ export interface SequenceEvent<TOperation extends MergeTreeDeltaOperationTypes =

// @alpha @legacy
export interface SequenceInterval extends ISerializableInterval {
// @deprecated
addPositionChangeListeners(beforePositionChange: () => void, afterPositionChange: () => void): void;
// (undocumented)
// @deprecated (undocumented)
clone(): SequenceInterval;
compare(b: SequenceInterval): number;
compareEnd(b: SequenceInterval): number;
compareStart(b: SequenceInterval): number;
readonly end: LocalReferencePosition;
// (undocumented)
readonly endSide: Side;
getIntervalId(): string;
// (undocumented)
readonly intervalType: IntervalType;
// @deprecated
modify(label: string, start: SequencePlace | undefined, end: SequencePlace | undefined, op?: ISequencedDocumentMessage, localSeq?: number, useNewSlidingBehavior?: boolean): SequenceInterval | undefined;
// (undocumented)
overlaps(b: SequenceInterval): boolean;
// (undocumented)
overlapsPos(bstart: number, bend: number): boolean;
properties: PropertySet;
// @deprecated
removePositionChangeListeners(): void;
// (undocumented)
readonly start: LocalReferencePosition;
// (undocumented)
readonly startSide: Side;
// (undocumented)
readonly stickiness: IntervalStickiness;
// @deprecated
union(b: SequenceInterval): SequenceInterval;
}

Expand Down
3 changes: 3 additions & 0 deletions packages/dds/sequence/src/intervalCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,9 @@ export interface ISequenceIntervalCollection
{ start, end, props }: { start?: SequencePlace; end?: SequencePlace; props?: PropertySet },
): SequenceInterval | undefined;

/**
* @deprecated This api is not meant or necessary for external consumption and will be removed in subsequent release
*/
attachDeserializer(onDeserialize: DeserializeCallback): void;
/**
* @returns an iterator over all intervals in this collection.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import {
} from "@fluidframework/merge-tree/internal";

import { IntervalNode, IntervalTree } from "../intervalTree.js";
import { SequenceInterval, createTransientInterval } from "../intervals/index.js";
import {
SequenceInterval,
SequenceIntervalClass,
createTransientInterval,
} from "../intervals/index.js";
import { ISharedString } from "../sharedString.js";

import { type SequenceIntervalIndex } from "./intervalIndex.js";
Expand Down Expand Up @@ -40,7 +44,7 @@ export interface ISequenceOverlappingIntervalsIndex extends SequenceIntervalInde
}

export class OverlappingIntervalsIndex implements ISequenceOverlappingIntervalsIndex {
protected readonly intervalTree = new IntervalTree<SequenceInterval>();
protected readonly intervalTree = new IntervalTree<SequenceIntervalClass>();
protected readonly client: Client;

constructor(client: Client) {
Expand Down Expand Up @@ -68,7 +72,7 @@ export class OverlappingIntervalsIndex implements ISequenceOverlappingIntervalsI
if (start === undefined && end === undefined) {
// No start/end provided. Gather the whole tree in the specified order.
if (iteratesForward) {
this.intervalTree.map((interval: SequenceInterval) => {
this.intervalTree.map((interval: SequenceIntervalClass) => {
results.push(interval);
});
} else {
Expand All @@ -77,7 +81,7 @@ export class OverlappingIntervalsIndex implements ISequenceOverlappingIntervalsI
});
}
} else {
const transientInterval: SequenceInterval = createTransientInterval(
const transientInterval: SequenceIntervalClass = createTransientInterval(
start ?? "start",
end ?? "end",
this.client,
Expand All @@ -87,13 +91,13 @@ export class OverlappingIntervalsIndex implements ISequenceOverlappingIntervalsI
// Only end position provided. Since the tree is not sorted by end position,
// walk the whole tree in the specified order, gathering intervals that match the end.
if (iteratesForward) {
this.intervalTree.map((interval: SequenceInterval) => {
this.intervalTree.map((interval: SequenceIntervalClass) => {
if (transientInterval.compareEnd(interval) === 0) {
results.push(interval);
}
});
} else {
this.intervalTree.mapBackward((interval: SequenceInterval) => {
this.intervalTree.mapBackward((interval: SequenceIntervalClass) => {
if (transientInterval.compareEnd(interval) === 0) {
results.push(interval);
}
Expand All @@ -104,15 +108,15 @@ export class OverlappingIntervalsIndex implements ISequenceOverlappingIntervalsI
// this start position.
const compareFn =
end === undefined
? (node: IntervalNode<SequenceInterval>) => {
? (node: IntervalNode<SequenceIntervalClass>) => {
return transientInterval.compareStart(node.key);
}
: (node: IntervalNode<SequenceInterval>) => {
: (node: IntervalNode<SequenceIntervalClass>) => {
return transientInterval.compare(node.key);
};
const continueLeftFn = (cmpResult: number) => cmpResult <= 0;
const continueRightFn = (cmpResult: number) => cmpResult >= 0;
const actionFn = (node: IntervalNode<SequenceInterval>) => {
const actionFn = (node: IntervalNode<SequenceIntervalClass>) => {
results.push(node.key);
};

Expand Down Expand Up @@ -157,11 +161,11 @@ export class OverlappingIntervalsIndex implements ISequenceOverlappingIntervalsI
return overlappingIntervalNodes.map((node) => node.key);
}

public remove(interval: SequenceInterval) {
public remove(interval: SequenceIntervalClass) {
this.intervalTree.removeExisting(interval);
}

public add(interval: SequenceInterval) {
public add(interval: SequenceIntervalClass) {
this.intervalTree.put(interval);
}
}
Expand Down
13 changes: 12 additions & 1 deletion packages/dds/sequence/src/intervals/intervalUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import {
export interface IInterval {
/**
* @returns a new interval object with identical semantics.
*
* @deprecated This api is not meant or necessary for external consumption and will be removed in subsequent release
* @privateRemarks Move to ISerializableInterval after deprecation period
*/
clone(): IInterval;
/**
Expand All @@ -45,6 +48,8 @@ export interface IInterval {
compareEnd(b: IInterval): number;
/**
* Modifies one or more of the endpoints of this interval, returning a new interval representing the result.
*
* @deprecated This api is not meant or necessary for external consumption and will be removed in subsequent release
*/
modify(
label: string,
Expand All @@ -63,6 +68,8 @@ export interface IInterval {
* Unions this interval with `b`, returning a new interval.
* The union operates as a convex hull, i.e. if the two intervals are disjoint, the return value includes
* intermediate values between the two intervals.
* @deprecated This api is not meant or necessary for external consumption and will be removed in subsequent release
* @privateRemarks Move to ISerializableInterval after deprecation period
*/
union(b: IInterval): IInterval;
}
Expand Down Expand Up @@ -152,12 +159,16 @@ export interface ISerializedInterval {
/**
* @legacy
* @alpha
* @deprecated This api is not meant or necessary for external consumption and will be removed in subsequent release
* @privateRemarks Remove from external exports, and replace usages of IInterval with this interface after deprecation period
*/
export interface ISerializableInterval extends IInterval {
/** Serializable bag of properties associated with the interval. */
properties: PropertySet;

/***/
/**
* @deprecated This api is not meant or necessary for external consumption and will be removed in subsequent release
*/
serialize(): ISerializedInterval;

/**
Expand Down
22 changes: 20 additions & 2 deletions packages/dds/sequence/src/intervals/sequenceInterval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { v4 as uuid } from "uuid";
import { computeStickinessFromSide } from "../intervalCollection.js";

import {
// eslint-disable-next-line import/no-deprecated
ISerializableInterval,
ISerializedInterval,
IntervalStickiness,
Expand Down Expand Up @@ -128,6 +129,7 @@ export function getSerializedProperties(
* @alpha
* @legacy
*/
// eslint-disable-next-line import/no-deprecated
export interface SequenceInterval extends ISerializableInterval {
readonly start: LocalReferencePosition;
/**
Expand All @@ -140,8 +142,12 @@ export interface SequenceInterval extends ISerializableInterval {
readonly endSide: Side;
readonly stickiness: IntervalStickiness;

/** Serializable bag of properties associated with the interval. */
properties: PropertySet;

/**
* @returns a new interval object with identical semantics.
* @deprecated This api is not meant or necessary for external consumption and will be removed in subsequent release
*/
clone(): SequenceInterval;
/**
Expand All @@ -166,6 +172,7 @@ export interface SequenceInterval extends ISerializableInterval {
compareEnd(b: SequenceInterval): number;
/**
* Modifies one or more of the endpoints of this interval, returning a new interval representing the result.
* @deprecated This api is not meant or necessary for external consumption and will be removed in subsequent release
*/
modify(
label: string,
Expand All @@ -184,11 +191,13 @@ export interface SequenceInterval extends ISerializableInterval {
* Unions this interval with `b`, returning a new interval.
* The union operates as a convex hull, i.e. if the two intervals are disjoint, the return value includes
* intermediate values between the two intervals.
* @deprecated This api is not meant or necessary for external consumption and will be removed in subsequent release
*/
union(b: SequenceInterval): SequenceInterval;

/**
* Subscribes to position change events on this interval if there are no current listeners.
* @deprecated This api is not meant or necessary for external consumption and will be removed in subsequent release
*/
addPositionChangeListeners(
beforePositionChange: () => void,
Expand All @@ -197,16 +206,25 @@ export interface SequenceInterval extends ISerializableInterval {

/**
* Removes the currently subscribed position change listeners.
* @deprecated This api is not meant or necessary for external consumption and will be removed in subsequent release
*/
removePositionChangeListeners(): void;

/**
* @returns whether this interval overlaps two numerical positions.
*/
overlapsPos(bstart: number, bend: number): boolean;

/**
* Gets the id associated with this interval.
* When the interval is used as part of an interval collection, this id can be used to modify or remove the
* interval.
*/
getIntervalId(): string;
}

export class SequenceIntervalClass implements SequenceInterval {
// eslint-disable-next-line import/no-deprecated
export class SequenceIntervalClass implements SequenceInterval, ISerializableInterval {
readonly #props: {
propertyManager?: PropertiesManager;
properties: PropertySet;
Expand Down Expand Up @@ -438,7 +456,7 @@ export class SequenceIntervalClass implements SequenceInterval {
/**
* {@inheritDoc IInterval.union}
*/
public union(b: SequenceInterval) {
public union(b: SequenceIntervalClass) {
const newStart = minReferencePosition(this.start, b.start);
const newEnd = maxReferencePosition(this.end, b.end);

Expand Down
Loading
Loading