@fluidframework/tree 2.112.0 → 2.113.0-411909
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/api-report/tree.alpha.api.md +23 -2
- package/dist/entrypoints/alpha.d.ts +1 -1
- package/dist/entrypoints/alpha.d.ts.map +1 -1
- package/dist/entrypoints/alpha.js +3 -2
- package/dist/entrypoints/alpha.js.map +1 -1
- package/dist/feature-libraries/default-schema/defaultFieldKinds.js +1 -1
- package/dist/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
- package/dist/feature-libraries/modular-schema/fieldChangeHandler.d.ts +39 -7
- package/dist/feature-libraries/modular-schema/fieldChangeHandler.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/fieldChangeHandler.js +22 -2
- package/dist/feature-libraries/modular-schema/fieldChangeHandler.js.map +1 -1
- package/dist/feature-libraries/modular-schema/genericFieldKind.js +1 -1
- package/dist/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
- package/dist/feature-libraries/modular-schema/index.d.ts +1 -1
- package/dist/feature-libraries/modular-schema/index.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/index.js +2 -1
- package/dist/feature-libraries/modular-schema/index.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFamily.js +8 -1
- package/dist/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
- package/dist/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
- package/dist/feature-libraries/optional-field/optionalField.js +26 -3
- package/dist/feature-libraries/optional-field/optionalField.js.map +1 -1
- package/dist/feature-libraries/sequence-field/filterEdits.d.ts +12 -0
- package/dist/feature-libraries/sequence-field/filterEdits.d.ts.map +1 -0
- package/dist/feature-libraries/sequence-field/filterEdits.js +111 -0
- package/dist/feature-libraries/sequence-field/filterEdits.js.map +1 -0
- package/dist/feature-libraries/sequence-field/markQueue.d.ts +8 -3
- package/dist/feature-libraries/sequence-field/markQueue.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/markQueue.js +22 -8
- package/dist/feature-libraries/sequence-field/markQueue.js.map +1 -1
- package/dist/feature-libraries/sequence-field/moveEffectTable.d.ts +1 -1
- package/dist/feature-libraries/sequence-field/moveEffectTable.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/moveEffectTable.js +2 -6
- package/dist/feature-libraries/sequence-field/moveEffectTable.js.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldChangeRebaser.d.ts +7 -6
- package/dist/feature-libraries/sequence-field/sequenceFieldChangeRebaser.d.ts.map +1 -1
- package/dist/feature-libraries/sequence-field/sequenceFieldChangeRebaser.js +2 -4
- package/dist/feature-libraries/sequence-field/sequenceFieldChangeRebaser.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.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/shared-tree/schematizingTreeView.d.ts +8 -0
- package/dist/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/dist/shared-tree/schematizingTreeView.js +25 -13
- package/dist/shared-tree/schematizingTreeView.js.map +1 -1
- package/dist/simple-tree/api/configuration.d.ts +32 -2
- package/dist/simple-tree/api/configuration.d.ts.map +1 -1
- package/dist/simple-tree/api/configuration.js +3 -1
- package/dist/simple-tree/api/configuration.js.map +1 -1
- package/dist/simple-tree/api/index.d.ts +1 -1
- package/dist/simple-tree/api/index.d.ts.map +1 -1
- package/dist/simple-tree/api/index.js.map +1 -1
- package/dist/simple-tree/api/schemaCompatibilityTester.d.ts +7 -4
- package/dist/simple-tree/api/schemaCompatibilityTester.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaCompatibilityTester.js +7 -5
- package/dist/simple-tree/api/schemaCompatibilityTester.js.map +1 -1
- package/dist/simple-tree/api/tree.d.ts +58 -1
- package/dist/simple-tree/api/tree.d.ts.map +1 -1
- package/dist/simple-tree/api/tree.js.map +1 -1
- package/dist/simple-tree/core/index.d.ts +1 -1
- package/dist/simple-tree/core/index.d.ts.map +1 -1
- package/dist/simple-tree/core/index.js +2 -1
- package/dist/simple-tree/core/index.js.map +1 -1
- package/dist/simple-tree/core/toStored.d.ts +72 -6
- package/dist/simple-tree/core/toStored.d.ts.map +1 -1
- package/dist/simple-tree/core/toStored.js +25 -1
- package/dist/simple-tree/core/toStored.js.map +1 -1
- package/dist/simple-tree/index.d.ts +3 -3
- package/dist/simple-tree/index.d.ts.map +1 -1
- package/dist/simple-tree/index.js +4 -5
- package/dist/simple-tree/index.js.map +1 -1
- package/dist/simple-tree/prepareForInsertion.d.ts.map +1 -1
- package/dist/simple-tree/prepareForInsertion.js +9 -0
- package/dist/simple-tree/prepareForInsertion.js.map +1 -1
- package/dist/simple-tree/toStoredSchema.d.ts +11 -27
- package/dist/simple-tree/toStoredSchema.d.ts.map +1 -1
- package/dist/simple-tree/toStoredSchema.js +25 -33
- package/dist/simple-tree/toStoredSchema.js.map +1 -1
- package/docs/main/runtime-schema-upgrade.md +208 -0
- package/lib/entrypoints/alpha.d.ts +1 -1
- package/lib/entrypoints/alpha.d.ts.map +1 -1
- package/lib/entrypoints/alpha.js +1 -1
- package/lib/entrypoints/alpha.js.map +1 -1
- package/lib/feature-libraries/default-schema/defaultFieldKinds.js +1 -1
- package/lib/feature-libraries/default-schema/defaultFieldKinds.js.map +1 -1
- package/lib/feature-libraries/modular-schema/fieldChangeHandler.d.ts +39 -7
- package/lib/feature-libraries/modular-schema/fieldChangeHandler.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/fieldChangeHandler.js +21 -1
- package/lib/feature-libraries/modular-schema/fieldChangeHandler.js.map +1 -1
- package/lib/feature-libraries/modular-schema/genericFieldKind.js +1 -1
- package/lib/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
- package/lib/feature-libraries/modular-schema/index.d.ts +1 -1
- package/lib/feature-libraries/modular-schema/index.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/index.js +1 -1
- package/lib/feature-libraries/modular-schema/index.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFamily.js +9 -2
- package/lib/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
- package/lib/feature-libraries/optional-field/optionalField.d.ts.map +1 -1
- package/lib/feature-libraries/optional-field/optionalField.js +27 -4
- package/lib/feature-libraries/optional-field/optionalField.js.map +1 -1
- package/lib/feature-libraries/sequence-field/filterEdits.d.ts +12 -0
- package/lib/feature-libraries/sequence-field/filterEdits.d.ts.map +1 -0
- package/lib/feature-libraries/sequence-field/filterEdits.js +107 -0
- package/lib/feature-libraries/sequence-field/filterEdits.js.map +1 -0
- package/lib/feature-libraries/sequence-field/markQueue.d.ts +8 -3
- package/lib/feature-libraries/sequence-field/markQueue.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/markQueue.js +22 -9
- package/lib/feature-libraries/sequence-field/markQueue.js.map +1 -1
- package/lib/feature-libraries/sequence-field/moveEffectTable.d.ts +1 -1
- package/lib/feature-libraries/sequence-field/moveEffectTable.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/moveEffectTable.js +2 -6
- package/lib/feature-libraries/sequence-field/moveEffectTable.js.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldChangeRebaser.d.ts +7 -6
- package/lib/feature-libraries/sequence-field/sequenceFieldChangeRebaser.d.ts.map +1 -1
- package/lib/feature-libraries/sequence-field/sequenceFieldChangeRebaser.js +2 -4
- package/lib/feature-libraries/sequence-field/sequenceFieldChangeRebaser.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.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/shared-tree/schematizingTreeView.d.ts +8 -0
- package/lib/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/lib/shared-tree/schematizingTreeView.js +26 -14
- package/lib/shared-tree/schematizingTreeView.js.map +1 -1
- package/lib/simple-tree/api/configuration.d.ts +32 -2
- package/lib/simple-tree/api/configuration.d.ts.map +1 -1
- package/lib/simple-tree/api/configuration.js +4 -2
- package/lib/simple-tree/api/configuration.js.map +1 -1
- package/lib/simple-tree/api/index.d.ts +1 -1
- package/lib/simple-tree/api/index.d.ts.map +1 -1
- package/lib/simple-tree/api/index.js.map +1 -1
- package/lib/simple-tree/api/schemaCompatibilityTester.d.ts +7 -4
- package/lib/simple-tree/api/schemaCompatibilityTester.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaCompatibilityTester.js +7 -5
- package/lib/simple-tree/api/schemaCompatibilityTester.js.map +1 -1
- package/lib/simple-tree/api/tree.d.ts +58 -1
- package/lib/simple-tree/api/tree.d.ts.map +1 -1
- package/lib/simple-tree/api/tree.js.map +1 -1
- package/lib/simple-tree/core/index.d.ts +1 -1
- package/lib/simple-tree/core/index.d.ts.map +1 -1
- package/lib/simple-tree/core/index.js +1 -1
- package/lib/simple-tree/core/index.js.map +1 -1
- package/lib/simple-tree/core/toStored.d.ts +72 -6
- package/lib/simple-tree/core/toStored.d.ts.map +1 -1
- package/lib/simple-tree/core/toStored.js +24 -0
- package/lib/simple-tree/core/toStored.js.map +1 -1
- package/lib/simple-tree/index.d.ts +3 -3
- package/lib/simple-tree/index.d.ts.map +1 -1
- package/lib/simple-tree/index.js +2 -2
- package/lib/simple-tree/index.js.map +1 -1
- package/lib/simple-tree/prepareForInsertion.d.ts.map +1 -1
- package/lib/simple-tree/prepareForInsertion.js +9 -0
- package/lib/simple-tree/prepareForInsertion.js.map +1 -1
- package/lib/simple-tree/toStoredSchema.d.ts +11 -27
- package/lib/simple-tree/toStoredSchema.d.ts.map +1 -1
- package/lib/simple-tree/toStoredSchema.js +24 -33
- package/lib/simple-tree/toStoredSchema.js.map +1 -1
- package/package.json +21 -21
- package/src/entrypoints/alpha.ts +3 -0
- package/src/feature-libraries/default-schema/defaultFieldKinds.ts +1 -1
- package/src/feature-libraries/modular-schema/fieldChangeHandler.ts +51 -7
- package/src/feature-libraries/modular-schema/genericFieldKind.ts +1 -1
- package/src/feature-libraries/modular-schema/index.ts +4 -2
- package/src/feature-libraries/modular-schema/modularChangeFamily.ts +16 -1
- package/src/feature-libraries/optional-field/optionalField.ts +43 -3
- package/src/feature-libraries/sequence-field/filterEdits.ts +143 -0
- package/src/feature-libraries/sequence-field/markQueue.ts +28 -11
- package/src/feature-libraries/sequence-field/moveEffectTable.ts +2 -7
- package/src/feature-libraries/sequence-field/sequenceFieldChangeRebaser.ts +3 -5
- package/src/index.ts +3 -0
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/schematizingTreeView.ts +42 -20
- package/src/simple-tree/api/configuration.ts +40 -2
- package/src/simple-tree/api/index.ts +1 -0
- package/src/simple-tree/api/schemaCompatibilityTester.ts +8 -4
- package/src/simple-tree/api/tree.ts +58 -1
- package/src/simple-tree/core/index.ts +2 -1
- package/src/simple-tree/core/toStored.ts +95 -8
- package/src/simple-tree/index.ts +3 -2
- package/src/simple-tree/prepareForInsertion.ts +12 -0
- package/src/simple-tree/toStoredSchema.ts +44 -39
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import type { ICodecFamily, JsonCodecPart } from "../../codec/index.js";
|
|
7
7
|
import type {
|
|
8
|
+
ChangeAtomId,
|
|
8
9
|
ChangeEncodingContext,
|
|
9
10
|
DeltaDetachedNodeChanges,
|
|
10
11
|
DeltaDetachedNodeId,
|
|
@@ -16,7 +17,7 @@ import type {
|
|
|
16
17
|
RevisionTag,
|
|
17
18
|
RevisionTagSchema,
|
|
18
19
|
} from "../../core/index.js";
|
|
19
|
-
import type { IdAllocator, Invariant } from "../../util/index.js";
|
|
20
|
+
import type { IdAllocator, Invariant, RangeQueryResult } from "../../util/index.js";
|
|
20
21
|
|
|
21
22
|
import type { CrossFieldManager } from "./crossFieldQueries.js";
|
|
22
23
|
import type { EncodedNodeChangeset } from "./modularChangeFormatV1.js";
|
|
@@ -167,10 +168,53 @@ export interface FieldChangeRebaser<TChangeset> {
|
|
|
167
168
|
replaceRevisions(change: TChangeset, replacer: RevisionReplacer): TChangeset;
|
|
168
169
|
|
|
169
170
|
/**
|
|
170
|
-
* Returns a copy of the given changeset with
|
|
171
|
-
*
|
|
171
|
+
* Returns a copy of the given changeset with edits removed as specified.
|
|
172
|
+
* @param change - The change to filter edits from
|
|
173
|
+
* @param filterDetach - This should be called for each range of detaches in the changeset,
|
|
174
|
+
* and the detach should be preserved, removed, or converted to a non-move detach as specified.
|
|
175
|
+
* If the returned result does not cover the entire detach range, the remainder should be queried again.
|
|
176
|
+
* @param filterDetach - This should be called for each range of attaches in the changeset,
|
|
177
|
+
* and the attach should be preserved, removed, or converted to a non-move attach as specified.
|
|
178
|
+
* If the returned result does not cover the entire detach range, the remainder should be queried again.
|
|
179
|
+
* @param preserveOtherEdits - Whether edits other than attaches and detaches (e.g. root renames),
|
|
180
|
+
* should be preserved or removed.
|
|
172
181
|
*/
|
|
173
|
-
|
|
182
|
+
filterEdits(
|
|
183
|
+
change: TChangeset,
|
|
184
|
+
options: {
|
|
185
|
+
filterDetach: EditFilterFunc;
|
|
186
|
+
filterAttach: EditFilterFunc;
|
|
187
|
+
preserveOtherEdits: boolean;
|
|
188
|
+
},
|
|
189
|
+
): TChangeset;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export type EditFilterFunc = (
|
|
193
|
+
id: ChangeAtomId,
|
|
194
|
+
count: number,
|
|
195
|
+
endpoint?: ChangeAtomId,
|
|
196
|
+
) => RangeQueryResult<EditFilterStatus>;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Used to describe what should be done with a particular attach or detach during `filterEdits`.
|
|
200
|
+
*/
|
|
201
|
+
export enum EditFilterStatus {
|
|
202
|
+
/**
|
|
203
|
+
* The edit should be removed from the filtered changeset.
|
|
204
|
+
*/
|
|
205
|
+
Remove,
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* The edit should be preserved in the filtered changeset.
|
|
209
|
+
*/
|
|
210
|
+
Preserve,
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* This should only be used for an attach or detach which is part of a move.
|
|
214
|
+
* The edit should be preserved, but should be adjusted, if necessary,
|
|
215
|
+
* to reflect that the other endpoint of the move has been filtered out.
|
|
216
|
+
*/
|
|
217
|
+
PreserveWithoutMove,
|
|
174
218
|
}
|
|
175
219
|
|
|
176
220
|
/**
|
|
@@ -181,13 +225,13 @@ export function referenceFreeFieldChangeRebaser<TChangeset>(data: {
|
|
|
181
225
|
compose: (change1: TChangeset, change2: TChangeset) => TChangeset;
|
|
182
226
|
invert: (change: TChangeset) => TChangeset;
|
|
183
227
|
rebase: (change: TChangeset, over: TChangeset) => TChangeset;
|
|
184
|
-
|
|
228
|
+
filterEdits: FieldChangeRebaser<TChangeset>["filterEdits"];
|
|
185
229
|
}): FieldChangeRebaser<TChangeset> {
|
|
186
230
|
return isolatedFieldChangeRebaser({
|
|
187
231
|
compose: (change1, change2, _composeChild, _genId) => data.compose(change1, change2),
|
|
188
232
|
invert: (change, _invertChild, _genId) => data.invert(change),
|
|
189
233
|
rebase: (change, over, _rebaseChild, _genId) => data.rebase(change, over),
|
|
190
|
-
|
|
234
|
+
filterEdits: (change, options) => data.filterEdits(change, options),
|
|
191
235
|
});
|
|
192
236
|
}
|
|
193
237
|
|
|
@@ -195,7 +239,7 @@ export function isolatedFieldChangeRebaser<TChangeset>(data: {
|
|
|
195
239
|
compose: FieldChangeRebaser<TChangeset>["compose"];
|
|
196
240
|
invert: FieldChangeRebaser<TChangeset>["invert"];
|
|
197
241
|
rebase: FieldChangeRebaser<TChangeset>["rebase"];
|
|
198
|
-
|
|
242
|
+
filterEdits: FieldChangeRebaser<TChangeset>["filterEdits"];
|
|
199
243
|
}): FieldChangeRebaser<TChangeset> {
|
|
200
244
|
return {
|
|
201
245
|
...data,
|
|
@@ -40,7 +40,7 @@ export const genericChangeHandler: FieldChangeHandler<GenericChangeset> = {
|
|
|
40
40
|
rebase: rebaseGenericChange,
|
|
41
41
|
prune: pruneGenericChange,
|
|
42
42
|
replaceRevisions,
|
|
43
|
-
|
|
43
|
+
filterEdits: (change: GenericChangeset): GenericChangeset => change,
|
|
44
44
|
},
|
|
45
45
|
codecsFactory: makeGenericChangeCodec,
|
|
46
46
|
editor: {
|
|
@@ -29,10 +29,14 @@ export {
|
|
|
29
29
|
export { EncodedModularChangesetV2 } from "./modularChangeFormatV2.js";
|
|
30
30
|
export { FlexFieldKind, type FullSchemaPolicy } from "./fieldKind.js";
|
|
31
31
|
export {
|
|
32
|
+
type EditFilterFunc,
|
|
33
|
+
EditFilterStatus,
|
|
32
34
|
type FieldChangeHandler,
|
|
33
35
|
type FieldChangeDelta,
|
|
36
|
+
type FieldChangeEncodingContext,
|
|
34
37
|
type FieldChangeRebaser,
|
|
35
38
|
type FieldEditor,
|
|
39
|
+
type NestedChangesIndices,
|
|
36
40
|
type NodeChangeComposer,
|
|
37
41
|
type NodeChangeInverter,
|
|
38
42
|
type NodeChangeRebaser,
|
|
@@ -42,8 +46,6 @@ export {
|
|
|
42
46
|
type RelevantRemovedRootsFromChild,
|
|
43
47
|
type ToDelta,
|
|
44
48
|
NodeAttachState,
|
|
45
|
-
type FieldChangeEncodingContext,
|
|
46
|
-
type NestedChangesIndices,
|
|
47
49
|
} from "./fieldChangeHandler.js";
|
|
48
50
|
export type {
|
|
49
51
|
CrossFieldKey,
|
|
@@ -82,6 +82,7 @@ import {
|
|
|
82
82
|
setInCrossFieldMap,
|
|
83
83
|
} from "./crossFieldQueries.js";
|
|
84
84
|
import {
|
|
85
|
+
EditFilterStatus,
|
|
85
86
|
type FieldChangeHandler,
|
|
86
87
|
NodeAttachState,
|
|
87
88
|
type RebaseRevisionMetadata,
|
|
@@ -1739,11 +1740,25 @@ export class ModularChangeFamily
|
|
|
1739
1740
|
const handler = getChangeHandler(this.fieldKinds, change.fieldKind);
|
|
1740
1741
|
return {
|
|
1741
1742
|
fieldKind: change.fieldKind,
|
|
1742
|
-
change: brand(
|
|
1743
|
+
change: brand(
|
|
1744
|
+
handler.rebaser.filterEdits(change.change, {
|
|
1745
|
+
filterDetach: removeAllEditsFilter,
|
|
1746
|
+
filterAttach: removeAllEditsFilter,
|
|
1747
|
+
preserveOtherEdits: false,
|
|
1748
|
+
}),
|
|
1749
|
+
),
|
|
1743
1750
|
};
|
|
1744
1751
|
}
|
|
1745
1752
|
}
|
|
1746
1753
|
|
|
1754
|
+
function removeAllEditsFilter(
|
|
1755
|
+
_id: ChangeAtomId,
|
|
1756
|
+
count: number,
|
|
1757
|
+
_endpointId?: ChangeAtomId,
|
|
1758
|
+
): RangeQueryResult<EditFilterStatus> {
|
|
1759
|
+
return { value: EditFilterStatus.Remove, length: count };
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1747
1762
|
function replaceCrossFieldKeyTableRevisions(
|
|
1748
1763
|
table: CrossFieldKeyTable,
|
|
1749
1764
|
replacer: RevisionReplacer,
|
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
requiredIdentifier,
|
|
36
36
|
} from "../fieldKindIdentifiers.js";
|
|
37
37
|
import {
|
|
38
|
+
EditFilterStatus,
|
|
38
39
|
type FieldChangeHandler,
|
|
39
40
|
type FieldChangeRebaser,
|
|
40
41
|
type FieldEditor,
|
|
@@ -48,6 +49,7 @@ import {
|
|
|
48
49
|
type NestedChangesIndices,
|
|
49
50
|
type FieldChangeDelta,
|
|
50
51
|
FlexFieldKind,
|
|
52
|
+
type EditFilterFunc,
|
|
51
53
|
} from "../modular-schema/index.js";
|
|
52
54
|
|
|
53
55
|
import type {
|
|
@@ -466,9 +468,7 @@ export const optionalChangeRebaser: FieldChangeRebaser<OptionalChangeset> = {
|
|
|
466
468
|
return updated;
|
|
467
469
|
},
|
|
468
470
|
|
|
469
|
-
|
|
470
|
-
return { childChanges: change.childChanges, moves: [] };
|
|
471
|
-
},
|
|
471
|
+
filterEdits,
|
|
472
472
|
};
|
|
473
473
|
|
|
474
474
|
function replaceReplaceRevisions(
|
|
@@ -814,3 +814,43 @@ export const optional: Optional = new FlexFieldKind(
|
|
|
814
814
|
]),
|
|
815
815
|
},
|
|
816
816
|
);
|
|
817
|
+
|
|
818
|
+
function filterEdits(
|
|
819
|
+
change: OptionalChangeset,
|
|
820
|
+
options: {
|
|
821
|
+
filterDetach: EditFilterFunc;
|
|
822
|
+
filterAttach: EditFilterFunc;
|
|
823
|
+
preserveOtherEdits: boolean;
|
|
824
|
+
},
|
|
825
|
+
): OptionalChangeset {
|
|
826
|
+
const filtered: Mutable<OptionalChangeset> = { ...change };
|
|
827
|
+
if (filtered.valueReplace !== undefined) {
|
|
828
|
+
if (isReplaceEffectful(filtered.valueReplace)) {
|
|
829
|
+
const detachId = getEffectfulDst(filtered.valueReplace);
|
|
830
|
+
const detachResult =
|
|
831
|
+
detachId === undefined ? undefined : options.filterDetach(detachId, 1).value;
|
|
832
|
+
|
|
833
|
+
const attachId = filtered.valueReplace.src;
|
|
834
|
+
const attachResult =
|
|
835
|
+
attachId === undefined ? undefined : options.filterAttach(attachId, 1).value;
|
|
836
|
+
|
|
837
|
+
if (detachResult === EditFilterStatus.Remove) {
|
|
838
|
+
assert(
|
|
839
|
+
attachId === undefined || attachResult === EditFilterStatus.Remove,
|
|
840
|
+
"Cannot remove detach without also removing attach",
|
|
841
|
+
);
|
|
842
|
+
|
|
843
|
+
delete filtered.valueReplace;
|
|
844
|
+
} else if (attachResult === EditFilterStatus.Remove) {
|
|
845
|
+
delete filtered.valueReplace.src;
|
|
846
|
+
}
|
|
847
|
+
} else if (!options.preserveOtherEdits) {
|
|
848
|
+
delete filtered.valueReplace;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
if (!options.preserveOtherEdits) {
|
|
853
|
+
filtered.moves = [];
|
|
854
|
+
}
|
|
855
|
+
return filtered;
|
|
856
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ChangeAtomId } from "../../core/index.js";
|
|
7
|
+
import type { RangeQueryResult } from "../../util/index.js";
|
|
8
|
+
import { EditFilterStatus, type EditFilterFunc } from "../modular-schema/index.js";
|
|
9
|
+
import { MarkListFactory } from "./markListFactory.js";
|
|
10
|
+
import { NoopMarkType, type Changeset, type Mark } from "./types.js";
|
|
11
|
+
import { getDetachedNodeId, getDetachOutputCellId, omitMarkEffect } from "./utils.js";
|
|
12
|
+
import { MarkQueueBase } from "./markQueue.js";
|
|
13
|
+
import { unreachableCase } from "@fluidframework/core-utils/internal";
|
|
14
|
+
|
|
15
|
+
export function filterEdits(
|
|
16
|
+
change: Changeset,
|
|
17
|
+
options: {
|
|
18
|
+
filterDetach: EditFilterFunc;
|
|
19
|
+
filterAttach: EditFilterFunc;
|
|
20
|
+
preserveOtherEdits: boolean;
|
|
21
|
+
},
|
|
22
|
+
): Changeset {
|
|
23
|
+
const factory = new MarkListFactory();
|
|
24
|
+
const queue = new MarkQueueBase(change);
|
|
25
|
+
for (let mark = queue.peek(); mark !== undefined; mark = queue.peek()) {
|
|
26
|
+
const filtered = filterMark(
|
|
27
|
+
mark,
|
|
28
|
+
options.filterDetach,
|
|
29
|
+
options.filterAttach,
|
|
30
|
+
options.preserveOtherEdits,
|
|
31
|
+
);
|
|
32
|
+
factory.push(filtered);
|
|
33
|
+
queue.dequeueUpTo(filtered.count);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return factory.list;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function filterMark(
|
|
40
|
+
mark: Mark,
|
|
41
|
+
filterDetach: (
|
|
42
|
+
id: ChangeAtomId,
|
|
43
|
+
count: number,
|
|
44
|
+
endpoint?: ChangeAtomId,
|
|
45
|
+
) => RangeQueryResult<EditFilterStatus>,
|
|
46
|
+
filterAttach: (
|
|
47
|
+
id: ChangeAtomId,
|
|
48
|
+
count: number,
|
|
49
|
+
endpoint?: ChangeAtomId,
|
|
50
|
+
) => RangeQueryResult<EditFilterStatus>,
|
|
51
|
+
preserveOtherEdits: boolean,
|
|
52
|
+
): Mark {
|
|
53
|
+
const type = mark.type;
|
|
54
|
+
switch (type) {
|
|
55
|
+
case "Insert":
|
|
56
|
+
case "MoveIn": {
|
|
57
|
+
if (mark.cellId === undefined) {
|
|
58
|
+
return preserveOtherEdits ? mark : omitMarkEffect(mark);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const endpoint = mark.type === "MoveIn" ? mark.finalEndpoint : undefined;
|
|
62
|
+
const result = filterAttach(mark.cellId, mark.count, endpoint);
|
|
63
|
+
|
|
64
|
+
let filtered: Mark;
|
|
65
|
+
switch (result.value) {
|
|
66
|
+
case EditFilterStatus.Preserve: {
|
|
67
|
+
filtered = mark;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
case EditFilterStatus.PreserveWithoutMove: {
|
|
71
|
+
// KLUDGE: PreserveWithoutMove requires us to return a mark which attaches the node
|
|
72
|
+
// using the detach ID of the move (the endpoint ID).
|
|
73
|
+
// Insert marks use the cell ID as the attach ID, so we must change the cell ID here.
|
|
74
|
+
// This could be a problem if there were references to the old cell ID outside this changeset,
|
|
75
|
+
// but PreserveWithoutMove is only used for transaction minimization, where that is not a problem.
|
|
76
|
+
const newCellId = endpoint ?? { revision: mark.revision, localId: mark.id };
|
|
77
|
+
filtered = {
|
|
78
|
+
type: "Insert",
|
|
79
|
+
count: result.length,
|
|
80
|
+
cellId: newCellId,
|
|
81
|
+
revision: mark.revision,
|
|
82
|
+
id: mark.id,
|
|
83
|
+
};
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
case EditFilterStatus.Remove: {
|
|
87
|
+
filtered = omitMarkEffect(mark);
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
default: {
|
|
91
|
+
unreachableCase(result.value);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return { ...filtered, count: result.length };
|
|
96
|
+
}
|
|
97
|
+
case "Remove":
|
|
98
|
+
case "MoveOut": {
|
|
99
|
+
const detachId = getDetachedNodeId(mark);
|
|
100
|
+
const endpoint = mark.type === "MoveOut" ? mark.finalEndpoint : undefined;
|
|
101
|
+
const result = filterDetach(detachId, mark.count, endpoint);
|
|
102
|
+
|
|
103
|
+
let filtered: Mark;
|
|
104
|
+
switch (result.value) {
|
|
105
|
+
case EditFilterStatus.Preserve: {
|
|
106
|
+
filtered = mark;
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
case EditFilterStatus.PreserveWithoutMove: {
|
|
110
|
+
const outputCellId = getDetachOutputCellId(mark);
|
|
111
|
+
filtered = {
|
|
112
|
+
type: "Remove",
|
|
113
|
+
count: mark.count,
|
|
114
|
+
revision: outputCellId.revision,
|
|
115
|
+
id: outputCellId.localId,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
if (mark.changes !== undefined) {
|
|
119
|
+
filtered.changes = mark.changes;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
case EditFilterStatus.Remove: {
|
|
125
|
+
filtered = omitMarkEffect(mark);
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
default: {
|
|
129
|
+
unreachableCase(result.value);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return { ...filtered, count: result.length };
|
|
133
|
+
}
|
|
134
|
+
case NoopMarkType:
|
|
135
|
+
case "Rename":
|
|
136
|
+
case "AttachAndDetach": {
|
|
137
|
+
return preserveOtherEdits ? mark : omitMarkEffect(mark);
|
|
138
|
+
}
|
|
139
|
+
default: {
|
|
140
|
+
unreachableCase(type);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -3,20 +3,17 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { assert
|
|
6
|
+
import { assert } from "@fluidframework/core-utils/internal";
|
|
7
7
|
|
|
8
|
-
import { type MoveEffectTable
|
|
8
|
+
import { getFirstMoveEffectLength, type MoveEffectTable } from "./moveEffectTable.js";
|
|
9
9
|
import type { Mark } from "./types.js";
|
|
10
10
|
import { splitMark } from "./utils.js";
|
|
11
11
|
|
|
12
|
-
export class
|
|
12
|
+
export class MarkQueueBase {
|
|
13
13
|
private readonly stack: Mark[] = [];
|
|
14
14
|
private index = 0;
|
|
15
15
|
|
|
16
|
-
public constructor(
|
|
17
|
-
private readonly list: readonly Mark[],
|
|
18
|
-
private readonly moveEffects: MoveEffectTable,
|
|
19
|
-
) {
|
|
16
|
+
public constructor(private readonly list: readonly Mark[]) {
|
|
20
17
|
this.list = list;
|
|
21
18
|
}
|
|
22
19
|
|
|
@@ -36,11 +33,14 @@ export class MarkQueue {
|
|
|
36
33
|
return undefined;
|
|
37
34
|
}
|
|
38
35
|
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
36
|
+
const splitLength = this.getLengthForSplit(mark);
|
|
37
|
+
if (splitLength < mark.count) {
|
|
38
|
+
const [part1, part2] = splitMark(mark, splitLength);
|
|
39
|
+
this.stack.push(part2);
|
|
40
|
+
return part1;
|
|
42
41
|
}
|
|
43
|
-
|
|
42
|
+
|
|
43
|
+
return mark;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
/**
|
|
@@ -66,4 +66,21 @@ export class MarkQueue {
|
|
|
66
66
|
}
|
|
67
67
|
return mark;
|
|
68
68
|
}
|
|
69
|
+
|
|
70
|
+
protected getLengthForSplit(mark: Mark): number {
|
|
71
|
+
return mark.count;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export class MarkQueue extends MarkQueueBase {
|
|
76
|
+
public constructor(
|
|
77
|
+
list: readonly Mark[],
|
|
78
|
+
private readonly moveEffects: MoveEffectTable,
|
|
79
|
+
) {
|
|
80
|
+
super(list);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
protected override getLengthForSplit(mark: Mark): number {
|
|
84
|
+
return getFirstMoveEffectLength(mark, mark.count, this.moveEffects);
|
|
85
|
+
}
|
|
69
86
|
}
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
|
|
16
16
|
import type { MoveMarkEffect } from "./helperTypes.js";
|
|
17
17
|
import type { CellMark, Detach, Mark, MarkEffect, MoveId, MoveIn, MoveOut } from "./types.js";
|
|
18
|
-
import { isAttachAndDetachEffect,
|
|
18
|
+
import { isAttachAndDetachEffect, splitMarkEffect } from "./utils.js";
|
|
19
19
|
|
|
20
20
|
export type MoveEffectTable = CrossFieldManager<MoveEffect>;
|
|
21
21
|
|
|
@@ -168,12 +168,7 @@ function adjustMoveEffectBasis(effect: MoveEffectWithBasis, newBasis: MoveId): M
|
|
|
168
168
|
return adjusted;
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
export function
|
|
172
|
-
const length = getFirstMoveEffectLength(mark, mark.count, effects);
|
|
173
|
-
return length < mark.count ? splitMark(mark, length) : [mark];
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function getFirstMoveEffectLength(
|
|
171
|
+
export function getFirstMoveEffectLength(
|
|
177
172
|
markEffect: MarkEffect,
|
|
178
173
|
count: number,
|
|
179
174
|
effects: MoveEffectTable,
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
import type { FieldChangeRebaser } from "../modular-schema/index.js";
|
|
7
7
|
|
|
8
8
|
import { compose } from "./compose.js";
|
|
9
|
+
import { filterEdits } from "./filterEdits.js";
|
|
9
10
|
import { invert } from "./invert.js";
|
|
10
11
|
import { prune } from "./prune.js";
|
|
11
12
|
import { rebase } from "./rebase.js";
|
|
12
13
|
import { replaceRevisions } from "./replaceRevisions.js";
|
|
13
14
|
import type { Changeset } from "./types.js";
|
|
14
|
-
import { omitMarkEffect } from "./utils.js";
|
|
15
15
|
|
|
16
16
|
export type SequenceChangeRebaser = FieldChangeRebaser<Changeset>;
|
|
17
17
|
|
|
@@ -21,7 +21,5 @@ export const sequenceFieldChangeRebaser = {
|
|
|
21
21
|
rebase,
|
|
22
22
|
prune,
|
|
23
23
|
replaceRevisions,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
},
|
|
27
|
-
};
|
|
24
|
+
filterEdits,
|
|
25
|
+
} as const;
|
package/src/index.ts
CHANGED
|
@@ -99,6 +99,7 @@ export {
|
|
|
99
99
|
type TreeNodeSchema,
|
|
100
100
|
TreeViewConfiguration,
|
|
101
101
|
type ITreeViewConfiguration,
|
|
102
|
+
type ITreeViewConfigurationAlpha,
|
|
102
103
|
type ITreeConfigurationOptions,
|
|
103
104
|
type TreeView,
|
|
104
105
|
type TreeViewEvents,
|
|
@@ -334,6 +335,8 @@ export {
|
|
|
334
335
|
type ErasedNode,
|
|
335
336
|
type ErasedSchemaSubclassable,
|
|
336
337
|
type SnapshotSchemaCompatibilityOptions,
|
|
338
|
+
StagedSchemaUpgradePolicy,
|
|
339
|
+
type StagedSchemaUpgradePolicyFactory,
|
|
337
340
|
type ArrayPlaceAnchor,
|
|
338
341
|
createArrayInsertionAnchor,
|
|
339
342
|
type WithValue,
|
package/src/packageVersion.ts
CHANGED
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
type FlexTreeUnknownUnboxed,
|
|
24
24
|
FieldKinds,
|
|
25
25
|
type FlexTreeRequiredField,
|
|
26
|
+
allowsRepoSuperset,
|
|
26
27
|
} from "../feature-libraries/index.js";
|
|
27
28
|
import {
|
|
28
29
|
type ImplicitFieldSchema,
|
|
@@ -34,6 +35,7 @@ import {
|
|
|
34
35
|
normalizeFieldSchema,
|
|
35
36
|
checkSchemaCompatibility,
|
|
36
37
|
type InsertableContent,
|
|
38
|
+
type StagedSchemaUpgradePolicy,
|
|
37
39
|
type TreeViewConfiguration,
|
|
38
40
|
type TreeViewAlpha,
|
|
39
41
|
type InsertableField,
|
|
@@ -99,7 +101,14 @@ export class SchematizingSimpleTreeView<
|
|
|
99
101
|
IEmitter<TreeViewEvents & TreeBranchEvents> &
|
|
100
102
|
HasListeners<TreeViewEvents & TreeBranchEvents> = createEmitter();
|
|
101
103
|
|
|
104
|
+
/**
|
|
105
|
+
* The schema for this view, captured at construction time for compatibility checking.
|
|
106
|
+
*/
|
|
102
107
|
private readonly viewSchema: TreeSchema;
|
|
108
|
+
/**
|
|
109
|
+
* Stored-schema generation policy from the view configuration, frozen at construction time.
|
|
110
|
+
*/
|
|
111
|
+
private readonly stagedUpgradePolicy: StagedSchemaUpgradePolicy;
|
|
103
112
|
|
|
104
113
|
/**
|
|
105
114
|
* Events to unregister upon flex-tree view disposal.
|
|
@@ -142,8 +151,17 @@ export class SchematizingSimpleTreeView<
|
|
|
142
151
|
|
|
143
152
|
this.rootFieldSchema = normalizeFieldSchema(config.schema);
|
|
144
153
|
|
|
145
|
-
const
|
|
154
|
+
const stagedUpgradePolicy =
|
|
155
|
+
config instanceof TreeViewConfigurationAlpha ? config.stagedUpgradePolicy : undefined;
|
|
156
|
+
const configAlpha = new TreeViewConfigurationAlpha({
|
|
157
|
+
schema: config.schema,
|
|
158
|
+
enableSchemaValidation: config.enableSchemaValidation,
|
|
159
|
+
preventAmbiguity: config.preventAmbiguity,
|
|
160
|
+
stagedUpgradePolicy,
|
|
161
|
+
});
|
|
162
|
+
this.stagedUpgradePolicy = configAlpha.stagedUpgradePolicy;
|
|
146
163
|
|
|
164
|
+
// Store viewSchema directly from the configuration (TreeViewConfigurationAlpha implements TreeSchema)
|
|
147
165
|
this.viewSchema = configAlpha;
|
|
148
166
|
// This must be initialized before `update` can be called.
|
|
149
167
|
this.currentCompatibility = {
|
|
@@ -189,7 +207,7 @@ export class SchematizingSimpleTreeView<
|
|
|
189
207
|
}
|
|
190
208
|
|
|
191
209
|
this.runSchemaEdit(() => {
|
|
192
|
-
const schema = toInitialSchema(this.config.schema);
|
|
210
|
+
const schema = toInitialSchema(this.config.schema, this.stagedUpgradePolicy);
|
|
193
211
|
// This has to be the contextless version, since when "initialize" is called (right after this),
|
|
194
212
|
// it will do a schema change which would dispose of the current context (see inside `update`).
|
|
195
213
|
// Thus using the current context (if any) would hydrate nodes then
|
|
@@ -247,19 +265,18 @@ export class SchematizingSimpleTreeView<
|
|
|
247
265
|
public upgradeSchema(): void {
|
|
248
266
|
this.ensureUndisposed();
|
|
249
267
|
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if (!compatibility.canUpgrade) {
|
|
268
|
+
const newSchema = toUpgradeSchema(this.viewSchema.root, this.stagedUpgradePolicy);
|
|
269
|
+
const storedSchema = this.checkout.storedSchema.clone();
|
|
270
|
+
if (!allowsRepoSuperset(defaultSchemaPolicy, storedSchema, newSchema)) {
|
|
257
271
|
throw new UsageError(
|
|
258
|
-
"Existing stored schema cannot be upgraded (see TreeView.compatibility.canUpgrade).",
|
|
272
|
+
"Existing stored schema cannot be upgraded to the requested schema (see TreeView.compatibility.canUpgrade).",
|
|
259
273
|
);
|
|
260
274
|
}
|
|
275
|
+
if (allowsRepoSuperset(defaultSchemaPolicy, newSchema, storedSchema)) {
|
|
276
|
+
// No-op
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
261
279
|
|
|
262
|
-
const newSchema = toUpgradeSchema(this.viewSchema.root);
|
|
263
280
|
this.runSchemaEdit(() => this.checkout.updateSchema(newSchema));
|
|
264
281
|
}
|
|
265
282
|
|
|
@@ -348,15 +365,8 @@ export class SchematizingSimpleTreeView<
|
|
|
348
365
|
private update(): void {
|
|
349
366
|
this.disposeFlexView();
|
|
350
367
|
|
|
351
|
-
const compatibility =
|
|
352
|
-
|
|
353
|
-
this.checkout.storedSchema,
|
|
354
|
-
);
|
|
355
|
-
|
|
356
|
-
this.currentCompatibility = {
|
|
357
|
-
...compatibility,
|
|
358
|
-
canInitialize: canInitialize(this.checkout),
|
|
359
|
-
};
|
|
368
|
+
const compatibility = this.computeCompatibility();
|
|
369
|
+
this.currentCompatibility = compatibility;
|
|
360
370
|
|
|
361
371
|
const anchors = this.checkout.forest.anchors;
|
|
362
372
|
const slots = anchors.slots;
|
|
@@ -427,6 +437,18 @@ export class SchematizingSimpleTreeView<
|
|
|
427
437
|
}
|
|
428
438
|
}
|
|
429
439
|
|
|
440
|
+
private computeCompatibility(): SchemaCompatibilityStatus {
|
|
441
|
+
const compatibility = checkSchemaCompatibility(
|
|
442
|
+
this.viewSchema,
|
|
443
|
+
this.checkout.storedSchema,
|
|
444
|
+
this.stagedUpgradePolicy,
|
|
445
|
+
);
|
|
446
|
+
return {
|
|
447
|
+
...compatibility,
|
|
448
|
+
canInitialize: canInitialize(this.checkout),
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
|
|
430
452
|
private runSchemaEdit(edit: () => void): void {
|
|
431
453
|
this.midUpgrade = true;
|
|
432
454
|
try {
|