From 9341b2eba9807f4b95bccdc61f85afed8ec8f834 Mon Sep 17 00:00:00 2001 From: Tony Murphy Date: Mon, 9 Jun 2025 11:26:06 -0700 Subject: [PATCH 1/5] Deprecate unnecessary and internal APIs in `ISequenceIntervalCollection` and related interval types. --- .changeset/deep-geckos-listen.md | 14 ++++++++++++++ .../api-report/sequence.legacy.alpha.api.md | 12 ++++++++---- packages/dds/sequence/src/intervalCollection.ts | 3 +++ .../dds/sequence/src/intervals/intervalUtils.ts | 8 +++++++- .../dds/sequence/src/intervals/sequenceInterval.ts | 4 ++++ 5 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 .changeset/deep-geckos-listen.md diff --git a/.changeset/deep-geckos-listen.md b/.changeset/deep-geckos-listen.md new file mode 100644 index 000000000000..1a62954c4127 --- /dev/null +++ b/.changeset/deep-geckos-listen.md @@ -0,0 +1,14 @@ +--- +"@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` +- `ISerializableInterval.serialize` +- `SequenceInterval.clone` +- `SequenceInterval.modify` + +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. diff --git a/packages/dds/sequence/api-report/sequence.legacy.alpha.api.md b/packages/dds/sequence/api-report/sequence.legacy.alpha.api.md index f2b239a0789b..a0a0e0f1d29c 100644 --- a/packages/dds/sequence/api-report/sequence.legacy.alpha.api.md +++ b/packages/dds/sequence/api-report/sequence.legacy.alpha.api.md @@ -32,11 +32,12 @@ 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; @@ -128,7 +129,7 @@ export interface ISequenceIntervalCollection extends TypedEventEmitter void, afterPositionChange: () => void): void; - // (undocumented) + // @deprecated (undocumented) clone(): SequenceInterval; compare(b: SequenceInterval): number; compareEnd(b: SequenceInterval): number; @@ -313,11 +315,13 @@ export interface SequenceInterval extends ISerializableInterval { readonly endSide: Side; // (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; + // @deprecated removePositionChangeListeners(): void; // (undocumented) readonly start: LocalReferencePosition; diff --git a/packages/dds/sequence/src/intervalCollection.ts b/packages/dds/sequence/src/intervalCollection.ts index 03a01f0a9323..5221c632fd4e 100644 --- a/packages/dds/sequence/src/intervalCollection.ts +++ b/packages/dds/sequence/src/intervalCollection.ts @@ -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. diff --git a/packages/dds/sequence/src/intervals/intervalUtils.ts b/packages/dds/sequence/src/intervals/intervalUtils.ts index 53a00c8f1839..070625690062 100644 --- a/packages/dds/sequence/src/intervals/intervalUtils.ts +++ b/packages/dds/sequence/src/intervals/intervalUtils.ts @@ -21,6 +21,8 @@ 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 */ clone(): IInterval; /** @@ -45,6 +47,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, @@ -157,7 +161,9 @@ 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; /** diff --git a/packages/dds/sequence/src/intervals/sequenceInterval.ts b/packages/dds/sequence/src/intervals/sequenceInterval.ts index da82d401b0a4..fb09833fc5bf 100644 --- a/packages/dds/sequence/src/intervals/sequenceInterval.ts +++ b/packages/dds/sequence/src/intervals/sequenceInterval.ts @@ -142,6 +142,7 @@ export interface SequenceInterval extends ISerializableInterval { /** * @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; /** @@ -166,6 +167,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, @@ -189,6 +191,7 @@ export interface SequenceInterval extends ISerializableInterval { /** * 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, @@ -197,6 +200,7 @@ 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; From 19b30e6e5c110e154f6dcbaa4b1e22d7f33ba776 Mon Sep 17 00:00:00 2001 From: Tony Murphy Date: Mon, 9 Jun 2025 12:11:35 -0700 Subject: [PATCH 2/5] gen docs --- .../api-report/fluid-framework.legacy.alpha.api.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/framework/fluid-framework/api-report/fluid-framework.legacy.alpha.api.md b/packages/framework/fluid-framework/api-report/fluid-framework.legacy.alpha.api.md index 48818d6435c5..d6ced7b31898 100644 --- a/packages/framework/fluid-framework/api-report/fluid-framework.legacy.alpha.api.md +++ b/packages/framework/fluid-framework/api-report/fluid-framework.legacy.alpha.api.md @@ -425,11 +425,12 @@ export interface IFluidLoadable extends IProvideFluidLoadable { // @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; @@ -571,7 +572,7 @@ export interface ISequenceIntervalCollection extends TypedEventEmitter void, afterPositionChange: () => void): void; - // (undocumented) + // @deprecated (undocumented) clone(): SequenceInterval; compare(b: SequenceInterval): number; compareEnd(b: SequenceInterval): number; @@ -1042,11 +1044,13 @@ export interface SequenceInterval extends ISerializableInterval { readonly endSide: Side; // (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; + // @deprecated removePositionChangeListeners(): void; // (undocumented) readonly start: LocalReferencePosition; From 59e16d9e6a1017d0329cdb17fce2d6c3057751dd Mon Sep 17 00:00:00 2001 From: Tony Murphy Date: Mon, 9 Jun 2025 13:12:39 -0700 Subject: [PATCH 3/5] improve changeset --- .changeset/deep-geckos-listen.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.changeset/deep-geckos-listen.md b/.changeset/deep-geckos-listen.md index 1a62954c4127..c3769b9d2118 100644 --- a/.changeset/deep-geckos-listen.md +++ b/.changeset/deep-geckos-listen.md @@ -10,5 +10,8 @@ The following APIs are now deprecated and will be removed in a future release: - `ISerializableInterval.serialize` - `SequenceInterval.clone` - `SequenceInterval.modify` +- `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. From 818af9d44674f09684d44fc41646c449ac7f6e43 Mon Sep 17 00:00:00 2001 From: Tony Murphy Date: Mon, 9 Jun 2025 14:56:21 -0700 Subject: [PATCH 4/5] clean up to help removal --- .changeset/deep-geckos-listen.md | 5 +++- .../api-report/sequence.legacy.alpha.api.md | 6 ++++- .../overlappingIntervalsIndex.ts | 26 +++++++++++-------- .../sequence/src/intervals/intervalUtils.ts | 5 ++++ .../src/intervals/sequenceInterval.ts | 18 +++++++++++-- .../fluid-framework.legacy.alpha.api.md | 6 ++++- 6 files changed, 50 insertions(+), 16 deletions(-) diff --git a/.changeset/deep-geckos-listen.md b/.changeset/deep-geckos-listen.md index c3769b9d2118..8ceac9df2452 100644 --- a/.changeset/deep-geckos-listen.md +++ b/.changeset/deep-geckos-listen.md @@ -7,9 +7,12 @@ Deprecate unnecessary and internal APIs in `ISequenceIntervalCollection` and rel The following APIs are now deprecated and will be removed in a future release: - `IInterval.clone` - `IInterval.modify` -- `ISerializableInterval.serialize` +- `IInterval.union` +- `ISerializableInterval` - `SequenceInterval.clone` - `SequenceInterval.modify` +- `SequenceInterval.union` +- `SequenceInterval.serialize` - `SequenceInterval.addPositionChangeListeners` - `SequenceInterval.removePositionChangeListeners` diff --git a/packages/dds/sequence/api-report/sequence.legacy.alpha.api.md b/packages/dds/sequence/api-report/sequence.legacy.alpha.api.md index a0a0e0f1d29c..a8284810b113 100644 --- a/packages/dds/sequence/api-report/sequence.legacy.alpha.api.md +++ b/packages/dds/sequence/api-report/sequence.legacy.alpha.api.md @@ -41,6 +41,7 @@ export interface IInterval { 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; } @@ -176,7 +177,7 @@ 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; @@ -313,6 +314,7 @@ export interface SequenceInterval extends ISerializableInterval { readonly end: LocalReferencePosition; // (undocumented) readonly endSide: Side; + getIntervalId(): string; // (undocumented) readonly intervalType: IntervalType; // @deprecated @@ -321,6 +323,7 @@ export interface SequenceInterval extends ISerializableInterval { overlaps(b: SequenceInterval): boolean; // (undocumented) overlapsPos(bstart: number, bend: number): boolean; + properties: PropertySet; // @deprecated removePositionChangeListeners(): void; // (undocumented) @@ -329,6 +332,7 @@ export interface SequenceInterval extends ISerializableInterval { readonly startSide: Side; // (undocumented) readonly stickiness: IntervalStickiness; + // @deprecated union(b: SequenceInterval): SequenceInterval; } diff --git a/packages/dds/sequence/src/intervalIndex/overlappingIntervalsIndex.ts b/packages/dds/sequence/src/intervalIndex/overlappingIntervalsIndex.ts index 7e782c87cc1c..d3998af88115 100644 --- a/packages/dds/sequence/src/intervalIndex/overlappingIntervalsIndex.ts +++ b/packages/dds/sequence/src/intervalIndex/overlappingIntervalsIndex.ts @@ -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"; @@ -40,7 +44,7 @@ export interface ISequenceOverlappingIntervalsIndex extends SequenceIntervalInde } export class OverlappingIntervalsIndex implements ISequenceOverlappingIntervalsIndex { - protected readonly intervalTree = new IntervalTree(); + protected readonly intervalTree = new IntervalTree(); protected readonly client: Client; constructor(client: Client) { @@ -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 { @@ -77,7 +81,7 @@ export class OverlappingIntervalsIndex implements ISequenceOverlappingIntervalsI }); } } else { - const transientInterval: SequenceInterval = createTransientInterval( + const transientInterval: SequenceIntervalClass = createTransientInterval( start ?? "start", end ?? "end", this.client, @@ -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); } @@ -104,15 +108,15 @@ export class OverlappingIntervalsIndex implements ISequenceOverlappingIntervalsI // this start position. const compareFn = end === undefined - ? (node: IntervalNode) => { + ? (node: IntervalNode) => { return transientInterval.compareStart(node.key); } - : (node: IntervalNode) => { + : (node: IntervalNode) => { return transientInterval.compare(node.key); }; const continueLeftFn = (cmpResult: number) => cmpResult <= 0; const continueRightFn = (cmpResult: number) => cmpResult >= 0; - const actionFn = (node: IntervalNode) => { + const actionFn = (node: IntervalNode) => { results.push(node.key); }; @@ -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); } } diff --git a/packages/dds/sequence/src/intervals/intervalUtils.ts b/packages/dds/sequence/src/intervals/intervalUtils.ts index 070625690062..e6a6613f323e 100644 --- a/packages/dds/sequence/src/intervals/intervalUtils.ts +++ b/packages/dds/sequence/src/intervals/intervalUtils.ts @@ -23,6 +23,7 @@ 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; /** @@ -67,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; } @@ -156,6 +159,8 @@ 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. */ diff --git a/packages/dds/sequence/src/intervals/sequenceInterval.ts b/packages/dds/sequence/src/intervals/sequenceInterval.ts index fb09833fc5bf..22f1522e59ce 100644 --- a/packages/dds/sequence/src/intervals/sequenceInterval.ts +++ b/packages/dds/sequence/src/intervals/sequenceInterval.ts @@ -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, @@ -128,6 +129,7 @@ export function getSerializedProperties( * @alpha * @legacy */ +// eslint-disable-next-line import/no-deprecated export interface SequenceInterval extends ISerializableInterval { readonly start: LocalReferencePosition; /** @@ -140,6 +142,9 @@ 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 @@ -186,6 +191,7 @@ 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; @@ -208,9 +214,17 @@ export interface SequenceInterval extends ISerializableInterval { * @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; @@ -442,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); diff --git a/packages/framework/fluid-framework/api-report/fluid-framework.legacy.alpha.api.md b/packages/framework/fluid-framework/api-report/fluid-framework.legacy.alpha.api.md index d6ced7b31898..20b54a48b102 100644 --- a/packages/framework/fluid-framework/api-report/fluid-framework.legacy.alpha.api.md +++ b/packages/framework/fluid-framework/api-report/fluid-framework.legacy.alpha.api.md @@ -434,6 +434,7 @@ export interface IInterval { 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; } @@ -612,7 +613,7 @@ export interface ISequenceIntervalCollectionEvents extends IEvent { (event: "changed", listener: (interval: SequenceInterval, propertyDeltas: PropertySet, previousInterval: SequenceInterval | undefined, local: boolean, slide: boolean) => void): void; } -// @alpha @legacy (undocumented) +// @alpha @deprecated @legacy (undocumented) export interface ISerializableInterval extends IInterval { getIntervalId(): string; properties: PropertySet; @@ -1042,6 +1043,7 @@ export interface SequenceInterval extends ISerializableInterval { readonly end: LocalReferencePosition; // (undocumented) readonly endSide: Side; + getIntervalId(): string; // (undocumented) readonly intervalType: IntervalType; // @deprecated @@ -1050,6 +1052,7 @@ export interface SequenceInterval extends ISerializableInterval { overlaps(b: SequenceInterval): boolean; // (undocumented) overlapsPos(bstart: number, bend: number): boolean; + properties: PropertySet; // @deprecated removePositionChangeListeners(): void; // (undocumented) @@ -1058,6 +1061,7 @@ export interface SequenceInterval extends ISerializableInterval { readonly startSide: Side; // (undocumented) readonly stickiness: IntervalStickiness; + // @deprecated union(b: SequenceInterval): SequenceInterval; } From 2bf3c3ddd4323947634eb7dd9db06a5bb2de4a4b Mon Sep 17 00:00:00 2001 From: Tony Murphy Date: Tue, 10 Jun 2025 09:41:08 -0700 Subject: [PATCH 5/5] Update .changeset/deep-geckos-listen.md Co-authored-by: jzaffiro <110866475+jzaffiro@users.noreply.github.com> --- .changeset/deep-geckos-listen.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/deep-geckos-listen.md b/.changeset/deep-geckos-listen.md index 8ceac9df2452..08596fd9b7c2 100644 --- a/.changeset/deep-geckos-listen.md +++ b/.changeset/deep-geckos-listen.md @@ -2,7 +2,7 @@ "@fluidframework/sequence": minor "__section": deprecation --- -Deprecate unnecessary and internal APIs in `ISequenceIntervalCollection` and related interval types. +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`