Skip to content

Commit 633221e

Browse files
committed
- Changed all usages of FluidClientVersion to MinimumVersionForCollab.
- Converted FluidClientVersion to a const object with MinimumVersionForCollab values. - Blocked out `selectFeatureFlags` in treeFactory.ts.
1 parent 1607c4f commit 633221e

File tree

12 files changed

+83
-57
lines changed

12 files changed

+83
-57
lines changed

.changeset/warm-windows-cross.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
"@fluidframework/tree": minor
3+
"__section": tree
4+
---
5+
MinimumVersionForCollab is now used in place of FluidClientVersion
6+
7+
FluidClientVersion is no longer used as the declaration type for versions in APIs/codecs (e.g., `oldestCompatibleClient`).
8+
The `oldestCompatibleClient` is still specified at the Shared Tree API level rather than by the Container,
9+
though this will change someday.

packages/dds/tree/api-report/tree.alpha.api.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export function cloneWithReplacements(root: unknown, rootKey: string, replacer:
9797

9898
// @alpha @input
9999
export interface CodecWriteOptions extends ICodecOptions {
100-
readonly oldestCompatibleClient: FluidClientVersion;
100+
readonly oldestCompatibleClient: MinimumVersionForCollab;
101101
}
102102

103103
// @public
@@ -169,7 +169,7 @@ export function evaluateLazySchema<T extends TreeNodeSchema>(value: LazyItem<T>)
169169
type ExtractItemType<Item extends LazyItem> = Item extends () => infer Result ? Result : Item;
170170

171171
// @alpha
172-
export function extractPersistedSchema(schema: ImplicitAnnotatedFieldSchema, oldestCompatibleClient: FluidClientVersion, includeStaged: (upgrade: SchemaUpgrade) => boolean): JsonCompatible;
172+
export function extractPersistedSchema(schema: ImplicitAnnotatedFieldSchema, oldestCompatibleClient: MinimumVersionForCollab, includeStaged: (upgrade: SchemaUpgrade) => boolean): JsonCompatible;
173173

174174
// @alpha @system
175175
export type FactoryContent = IFluidHandle | string | number | boolean | null | Iterable<readonly [string, InsertableContent]> | readonly InsertableContent[] | FactoryContentObject;
@@ -257,11 +257,11 @@ type FlexList<Item = unknown> = readonly LazyItem<Item>[];
257257
type FlexListToUnion<TList extends FlexList> = ExtractItemType<TList[number]>;
258258

259259
// @alpha
260-
export enum FluidClientVersion {
261-
EnableUnstableFeatures,
262-
v2_0 = 2,
263-
v2_52 = 2.052
264-
}
260+
export const FluidClientVersion: {
261+
v2_0: "2.0.0-defaults";
262+
v2_52: MinimumVersionForCollab;
263+
EnableUnstableFeatures: MinimumVersionForCollab;
264+
};
265265

266266
// @beta @input
267267
export interface ForestOptions {

packages/dds/tree/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@
178178
"@tylerbu/sorted-btree-es6": "^1.8.0",
179179
"@types/ungap__structured-clone": "^1.2.0",
180180
"@ungap/structured-clone": "^1.2.0",
181+
"semver-ts": "^1.0.3",
181182
"uuid": "^11.1.0"
182183
},
183184
"devDependencies": {

packages/dds/tree/src/codec/codec.ts

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import type { Static, TAnySchema, TSchema } from "@sinclair/typebox";
1111
import type { ChangeEncodingContext } from "../core/index.js";
1212
import type { JsonCompatibleReadOnly } from "../util/index.js";
1313
import { noopValidator } from "./noopValidator.js";
14+
import type { MinimumVersionForCollab } from "@fluidframework/runtime-definitions/internal";
15+
import { pkgVersion } from "../packageVersion.js";
16+
import { defaultMinVersionForCollab } from "@fluidframework/runtime-utils/internal";
1417

1518
/**
1619
* Translates decoded data to encoded data.
@@ -145,7 +148,7 @@ export interface CodecWriteOptions extends ICodecOptions {
145148
* Note that versions older than this should not result in data corruption if they access the data:
146149
* the data's format should be versioned and if they can't handle the format they should error.
147150
*/
148-
readonly oldestCompatibleClient: FluidClientVersion;
151+
readonly oldestCompatibleClient: MinimumVersionForCollab;
149152
}
150153

151154
/**
@@ -414,16 +417,6 @@ export function withSchemaValidation<
414417
* For example, document if there is an encoding efficiency improvement of oping into that version or newer.
415418
* Versions with no notable impact can be omitted.
416419
*
417-
* These use numeric values for easy threshold comparisons.
418-
* Without zero padding, version 2.10 is treated as 2.1, which is numerically less than 2.2.
419-
* Adding leading zeros to the minor version ensures correct comparisons.
420-
* For example, version 2.20.0 is encoded as 2.020, and version 2.2.0 is encoded as 2.002.
421-
* For example FF 2.20.0 is encoded as 2.020 and FF 2.2.0 is encoded as 2.002.
422-
*
423-
* Three digits was selected as that will likely be enough, while two digits could easily be too few.
424-
* If three digits ends up being too few, minor releases of 1000 and higher
425-
* could still be handled using something like 2.999_00001 without having to change the lower releases.
426-
*
427420
* This scheme assumes a single version will always be enough to communicate compatibility.
428421
* For this to work, compatibility has to be strictly increasing.
429422
* If this is violated (for example a subset of incompatible features from 3.x that are not in 3.0 are back ported to 2.x),
@@ -435,7 +428,7 @@ export function withSchemaValidation<
435428
* For example, if needed, would adding more leading zeros to the minor version break things.
436429
* @alpha
437430
*/
438-
export enum FluidClientVersion {
431+
export const FluidClientVersion = {
439432
/**
440433
* Fluid Framework Client 1.4 and newer.
441434
* @remarks
@@ -445,8 +438,10 @@ export enum FluidClientVersion {
445438
*/
446439
// v1_4 = 1.004,
447440

448-
/** Fluid Framework Client 2.0 and newer. */
449-
v2_0 = 2.0,
441+
/**
442+
* Fluid Framework Client 2.0 and newer.
443+
*/
444+
v2_0: defaultMinVersionForCollab,
450445

451446
/** Fluid Framework Client 2.1 and newer. */
452447
// If we think we might want to start allowing opting into something that landed in 2.1 (without opting into something newer),
@@ -457,19 +452,21 @@ export enum FluidClientVersion {
457452
/** Fluid Framework Client 2.52 and newer. */
458453
// New formats introduced in 2.52:
459454
// - DetachedFieldIndex FormatV2
460-
v2_52 = 2.052,
455+
v2_52: "2.52.0" as MinimumVersionForCollab,
461456

462457
/**
463458
* Enable unreleased and unfinished features.
464459
* @remarks
460+
* pkgVersion will always be the latest version, therefore the version that enables all features.
461+
*
465462
* Using this value can result in documents which can not be opened in future versions of the framework.
466463
* It can also result in data corruption by enabling unfinished features which may not handle all cases correctly.
467464
*
468465
* This can be used with specific APIs when the caller has knowledge of what specific features those APIs will be opted into with it.
469466
* This is useful for testing features before they are released, but should not be used in production code.
470467
*/
471-
EnableUnstableFeatures = Number.POSITIVE_INFINITY,
472-
}
468+
EnableUnstableFeatures: pkgVersion as MinimumVersionForCollab,
469+
};
473470

474471
/**
475472
* An up to date version which includes all the important stable features.
@@ -480,4 +477,4 @@ export enum FluidClientVersion {
480477
* Update as needed.
481478
* TODO: Consider using packageVersion.ts to keep this current.
482479
*/
483-
export const currentVersion: FluidClientVersion = FluidClientVersion.v2_0;
480+
export const currentVersion: MinimumVersionForCollab = FluidClientVersion.v2_0;

packages/dds/tree/src/codec/versioned/codec.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@ import {
1414
type IJsonCodec,
1515
withSchemaValidation,
1616
type FormatVersion,
17-
type FluidClientVersion,
1817
type CodecWriteOptions,
1918
} from "../codec.js";
2019

2120
import { Versioned } from "./format.js";
2221
import { pkgVersion } from "../../packageVersion.js";
22+
import type { MinimumVersionForCollab } from "@fluidframework/runtime-definitions/internal";
2323

2424
export function makeVersionedCodec<
2525
TDecoded,
@@ -115,11 +115,13 @@ export class ClientVersionDispatchingCodecBuilder<TDecoded, TContext> {
115115
*/
116116
private readonly family: ICodecFamily<TDecoded, TContext>,
117117
/**
118-
* A function which maps a {@link FluidClientVersion} to a version number for the codec family which is supported by that version.
118+
* A function which maps a {@link MinimumVersionForCollab} to a version number for the codec family which is supported by that version.
119119
* This can (and typically does) pick the newest version of the codec which is known to be compatible with the client version so that
120120
* any improvements in newer versions of the codec can be used when allowed.
121121
*/
122-
private readonly versionMapping: (oldestCompatibleClient: FluidClientVersion) => number,
122+
private readonly versionMapping: (
123+
oldestCompatibleClient: MinimumVersionForCollab,
124+
) => number,
123125
) {}
124126

125127
public build(

packages/dds/tree/src/feature-libraries/chunked-forest/codec/codecs.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { assert, unreachableCase } from "@fluidframework/core-utils/internal";
77
import type { IIdCompressor, SessionId } from "@fluidframework/id-compressor";
88

99
import {
10-
type FluidClientVersion,
1110
type ICodecOptions,
1211
type IJsonCodec,
1312
makeVersionedValidatedCodec,
@@ -36,6 +35,7 @@ import type { FieldBatch } from "./fieldBatch.js";
3635
import { EncodedFieldBatch, validVersions } from "./format.js";
3736
import { schemaCompressedEncode } from "./schemaBasedEncode.js";
3837
import { uncompressedEncode } from "./uncompressedEncode.js";
38+
import type { MinimumVersionForCollab } from "@fluidframework/runtime-definitions/internal";
3939

4040
/**
4141
* Reference ID for a chunk that is incrementally encoded.
@@ -124,7 +124,7 @@ export type FieldBatchCodec = IJsonCodec<
124124
* TODO: makeFieldBatchCodec (and makeVersionDispatchingCodec transitively) should bake in this versionToFormat logic and the resulting codec can then support use with FluidClientVersion directly.
125125
*/
126126
export function fluidVersionToFieldBatchCodecWriteVersion(
127-
oldestCompatibleClient: FluidClientVersion,
127+
oldestCompatibleClient: MinimumVersionForCollab,
128128
): number {
129129
// There is currently on only 1 version.
130130
return 1;

packages/dds/tree/src/feature-libraries/schema-index/codec.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import { fail, unreachableCase } from "@fluidframework/core-utils/internal";
77

88
import {
9-
type FluidClientVersion,
109
type ICodecFamily,
1110
type ICodecOptions,
1211
type IJsonCodec,
@@ -28,14 +27,15 @@ import { brand, type JsonCompatible } from "../../util/index.js";
2827

2928
import { Format as FormatV1 } from "./formatV1.js";
3029
import { Format as FormatV2 } from "./formatV2.js";
30+
import type { MinimumVersionForCollab } from "@fluidframework/runtime-definitions/internal";
3131

3232
/**
33-
* Convert a FluidClientVersion to a SchemaVersion.
34-
* @param clientVersion - The FluidClientVersion to convert.
35-
* @returns The SchemaVersion that corresponds to the provided FluidClientVersion.
33+
* Convert a MinimumVersionForCollab to a SchemaVersion.
34+
* @param clientVersion - The MinimumVersionForCollab to convert.
35+
* @returns The SchemaVersion that corresponds to the provided MinimumVersionForCollab.
3636
*/
3737
export function clientVersionToSchemaVersion(
38-
clientVersion: FluidClientVersion,
38+
clientVersion: MinimumVersionForCollab,
3939
): SchemaVersion {
4040
// Only one version of the schema codec is currently supported.
4141
return SchemaVersion.v1;

packages/dds/tree/src/simple-tree/api/storedSchema.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
* Licensed under the MIT License.
44
*/
55

6-
import type { FluidClientVersion, ICodecOptions } from "../../codec/index.js";
6+
import type { MinimumVersionForCollab } from "@fluidframework/runtime-definitions/internal";
7+
import type { ICodecOptions } from "../../codec/index.js";
78
import { SchemaVersion } from "../../core/index.js";
89
import { encodeTreeSchema, makeSchemaCodec } from "../../feature-libraries/index.js";
910
import {
@@ -58,7 +59,7 @@ import type { SchemaCompatibilityStatus } from "./tree.js";
5859
*/
5960
export function extractPersistedSchema(
6061
schema: ImplicitAnnotatedFieldSchema,
61-
oldestCompatibleClient: FluidClientVersion,
62+
oldestCompatibleClient: MinimumVersionForCollab,
6263
includeStaged: (upgrade: SchemaUpgrade) => boolean,
6364
): JsonCompatible {
6465
const stored = toStoredSchema(schema, { includeStaged });

packages/dds/tree/src/test/codec/versioned/codec.spec.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,14 @@
55

66
import { strict as assert } from "node:assert";
77

8-
import {
9-
type FluidClientVersion,
10-
type ICodecFamily,
11-
type IJsonCodec,
12-
makeCodecFamily,
13-
} from "../../../codec/index.js";
8+
import { type ICodecFamily, type IJsonCodec, makeCodecFamily } from "../../../codec/index.js";
149
import { typeboxValidator } from "../../../external-utilities/index.js";
1510
// eslint-disable-next-line import/no-internal-modules
1611
import { ClientVersionDispatchingCodecBuilder } from "../../../codec/versioned/codec.js";
1712
import { validateUsageError } from "../../utils.js";
1813
import { pkgVersion } from "../../../packageVersion.js";
14+
import { gt } from "semver-ts";
15+
import type { MinimumVersionForCollab } from "@fluidframework/runtime-definitions/internal";
1916

2017
describe("versioned Codecs", () => {
2118
describe("ClientVersionDispatchingCodecBuilder", () => {
@@ -42,16 +39,17 @@ describe("versioned Codecs", () => {
4239
]);
4340
const builder = new ClientVersionDispatchingCodecBuilder(
4441
family,
45-
(oldestCompatibleClient: FluidClientVersion) => (oldestCompatibleClient > 5 ? 2 : 1),
42+
(oldestCompatibleClient: MinimumVersionForCollab) =>
43+
gt(oldestCompatibleClient, "5.0.0") ? 2 : 1,
4644
);
4745

4846
it("round trip", () => {
4947
const codec1 = builder.build({
50-
oldestCompatibleClient: 2 as FluidClientVersion,
48+
oldestCompatibleClient: "2.0.0" as MinimumVersionForCollab,
5149
jsonValidator: typeboxValidator,
5250
});
5351
const codec2 = builder.build({
54-
oldestCompatibleClient: 6 as FluidClientVersion,
52+
oldestCompatibleClient: "6.0.0" as MinimumVersionForCollab,
5553
jsonValidator: typeboxValidator,
5654
});
5755
const v1 = codec1.encode(42);

packages/dds/tree/src/treeFactory.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { SharedTreeFactoryType, SharedTreeAttributes } from "./sharedTreeAttribu
2727
import type { ITree } from "./simple-tree/index.js";
2828
import { Breakable } from "./util/index.js";
2929
import { FluidClientVersion } from "./codec/index.js";
30+
import type { MinimumVersionForCollab } from "@fluidframework/runtime-definitions/internal";
3031

3132
/**
3233
* {@link ITreePrivate} extended with ISharedObject.
@@ -35,6 +36,14 @@ import { FluidClientVersion } from "./codec/index.js";
3536
*/
3637
export interface ISharedTree extends ISharedObject, ITreePrivate {}
3738

39+
function selectFeatureFlags(
40+
optionsOverride: SharedTreeOptionsInternal,
41+
minVersionForCollab: MinimumVersionForCollab,
42+
): SharedTreeOptionsInternal {
43+
// Passthrough for now. Someday this will alter feature flags and return a copy with the changes.
44+
return optionsOverride;
45+
}
46+
3847
/**
3948
* Creates a factory for shared tree kernels with the given options.
4049
* @remarks
@@ -48,10 +57,16 @@ function treeKernelFactory(
4857
if (args.idCompressor === undefined) {
4958
throw new UsageError("IdCompressor must be enabled to use SharedTree");
5059
}
51-
const adjustedOptions = { ...options };
52-
// TODO: get default from runtime once something like runtime.oldestCompatibleClient exists.
53-
// Using default of 2.0 since that is the oldest version that supports SharedTree.
54-
adjustedOptions.oldestCompatibleClient ??= FluidClientVersion.v2_0;
60+
61+
const adjustedOptions = {
62+
...selectFeatureFlags(
63+
options,
64+
// TODO: get default from runtime once something like runtime.oldestCompatibleClient exists.
65+
// Using default of 2.0 since that is the oldest version that supports SharedTree.
66+
options.oldestCompatibleClient ?? FluidClientVersion.v2_0,
67+
),
68+
};
69+
5570
return new SharedTreeKernel(
5671
new Breakable("SharedTree"),
5772
args.sharedObject,

0 commit comments

Comments
 (0)