Skip to content

Releases: microsoft/FluidFramework

Fluid Framework v2.72.0 (minor)

11 Nov 02:20
06083ca

Choose a tag to compare

Contents

✨ New Features

Expose staged, types, stagedRecursive and typesRecursive on SchemaFactoryBeta (#25779)

These APIs were previously only available on SchemaFactoryAlpha, but are now available on SchemaFactoryBeta.

Change details

Commit: 75d7f11

Affected packages:

  • @fluidframework/tree

⬆️ Table of contents

🌳 SharedTree DDS Changes

formatVersion removed from the options passed to configuredSharedTree (#25752)

Note: this change may break users of alpha APIs. See below for details.

SharedTreeOptions (which is passed to configuredSharedTree) no longer includes a formatVersion: SharedTreeFormatVersion[keyof SharedTreeFormatVersion] field. The concept of SharedTreeFormatVersion has been removed altogether. Instead, users are expected to leverage the already existing minVersionForCollab field.

For migration purposes, the mapping from SharedTreeFormatVersion to minVersionForCollab is as follows:

  • SharedTreeFormatVersion.v1: no supported equivalent
  • SharedTreeFormatVersion.v2: no supported equivalent
  • SharedTreeFormatVersion.v3: minVersionForCollab: FluidClientVersion.v2_0
  • SharedTreeFormatVersion.v5: minVersionForCollab: FluidClientVersion.v2_43
  • SharedTreeFormatVersion.vSharedBranches: minVersionForCollab: FluidClientVersion.v2_43 + SharedTreeOptions.enableSharedBranches

The values for which there is no supported equivalent minVersionForCollab were never given official support. Contact the Fluid Framework team if you need help migrating away from them.

Change details

Commit: df53390

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Legacy API Changes

Added a new Fluid error type layerIncompatibilityError (#25784)

A new Fluid error type layerIncompatibilityError is added to FluidErrorTypesAlpha as @legacy @Alpha. This will be moved to FluidErrorTypes as @legacy @beta in a future legacy breaking release. It will also be added to ContainerErrorTypes since it extends FluidErrorTypes.

Change details

Commit: 01d568b

Affected packages:

  • @fluidframework/core-interfaces
  • @fluidframework/container-definitions

⬆️ Table of contents

🛠️ Start Building Today!

Please continue to engage with us on GitHub Discussion and Issue pages as you adopt Fluid Framework!

Fluid Framework v2.71.0 (minor)

03 Nov 21:41
a5456fd

Choose a tag to compare

Contents

✨ New Features

delete keyword support for ObjectNodes (#25738)

Added support for using the delete keyword to remove content under optional fields for ObjectNodes.

// This is now equivalent to node.foo = undefined
delete node.foo;

Change details

Commit: 31dca54

Affected packages:

  • @fluidframework/tree

⬆️ Table of contents

🌳 SharedTree DDS Changes

Add IndependentTree API (#25785)

New IndependentTreeAlpha and IndependentTreeBeta APIs provide similar utility to the existing alpha IndependentView API, except providing access to the ViewableTree.

This allows for multiple views (in sequence, not concurrently) to be created to test things like schema upgrades and incompatible view schema much more easily (see example below). For IndependentTreeAlpha, this also provides access to exportVerbose and exportSimpleSchema from ITreeAlpha.

An example of how to use createIndependentTreeBeta to create multiple views to test a schema upgrade:

const tree = createIndependentTreeBeta();

const stagedConfig = new TreeViewConfiguration({
  schema: SchemaFactoryAlpha.types([
    SchemaFactory.number,
    SchemaFactoryAlpha.staged(SchemaFactory.string),
  ]),
});
const afterConfig = new TreeViewConfigurationAlpha({
  schema: [SchemaFactory.number, SchemaFactory.string],
});

// Initialize tree
{
  const view = tree.viewWith(stagedConfig);
  view.initialize(1);
  view.dispose();
}

// Do schema upgrade
{
  const view = tree.viewWith(afterConfig);
  view.upgradeSchema();
  view.root = "A";
  view.dispose();
}

// Can still view tree with staged schema
{
  const view = tree.viewWith(stagedConfig);
  assert.equal(view.root, "A");
  view.dispose();
}

Change details

Commit: 21c4245

Affected packages:

  • fluid-framework
  • @fluidframework/tree

⬆️ Table of contents

🛠️ Start Building Today!

Please continue to engage with us on GitHub Discussion and Issue pages as you adopt Fluid Framework!

Fluid Framework v2.70.0 (minor)

28 Oct 21:13
151d310

Choose a tag to compare

Contents

🚨 Breaking Changes

Deprecated properties have been removed from IRuntimeStorageService and IContainerStorageService (#25708)

The following deprecated properties have been removed from IRuntimeStorageService:

  • createBlob
  • dispose
  • disposed
  • downloadSummary
  • getSnapshot
  • getSnapshotTree
  • getVersions
  • policies
  • uploadSummaryWithContext

The following deprecated properties have been removed from IContainerStorageService:

  • dispose
  • disposed
  • downloadSummary

Please see this Github issue for more details.

Change details

Commit: 82c936e

Affected packages:

  • @fluidframework/container-definitions
  • @fluidframework/runtime-definitions

⬆️ Table of contents

getSnapshotTree is now required in IChannelStorageService (#25707)

The getSnapshotTree property was added as optional to IChannelStorageService in version 2.51.0. It is now a required property. See this github issue for more details.

Change details

Commit: d1c4c0a

Affected packages:

  • @fluidframework/datastore-definitions
  • @fluidframework/test-runtime-utils

⬆️ Table of contents

Deprecated property processCore has been removed from SharedObject (#25749)

The deprecated property processCore has been removed from SharedObject.

Please see this github issue for more details.

Change details

Commit: a33a2e3

Affected packages:

  • @fluidframework/ordered-collection
  • @fluidframework/register-collection
  • @fluidframework/shared-object-base

⬆️ Table of contents

Remove submitMessage from FluidDataStoreRuntime and MockFluidDataStoreRuntime (#25755)

As needed, access submitMessage via IFluidDataStoreContext/IFluidParentContext. See #24406 for details.

Change details

Commit: 88860f3

Affected packages:

  • @fluidframework/datastore
  • @fluidframework/test-runtime-utils

⬆️ Table of contents

✨ New Features

Promote core devtools APIs from alpha to beta (#25695)

The primary devtools APIs may now be imported from /beta. This includes:

  • initializeDevtools - Initialize the devtools singleton
  • tryGetFluidDevtools - Get the existing devtools instance if initialized
  • IFluidDevtools - Main devtools interface for registering containers
  • ContainerDevtoolsProps - Properties for registering containers with devtools

For example:

import {
  initializeDevtools,
  tryGetFluidDevtools,
  type IFluidDevtools,
  type ContainerDevtoolsProps,
} from "@fluidframework/devtools-core/beta";

// Initialize devtools
const devtools = initializeDevtools();

// Register a container
devtools.registerContainerDevtools({
  containerKey: "my-container",
  container: myContainer,
});

Change details

Commit: 7c8e203

Affected packages:

  • @fluidframework/devtools-core

⬆️ Table of contents

Added Tree.ensureSchema (#25740)

This helper function allows content to be tagged with a schema type before being inserted into the tree. This allows content that would otherwise be ambiguous to be well-defined, without having to wrap it in a node constructor.

Example:

const sf = new SchemaFactory("example");
class Dog extends sf.object("Dog", { name: sf.string() }) {}
class Cat extends sf.object("Cat", { name: sf.string() }) {}
class Root extends sf.object("Root", { pet: [Dog, Cat] }) {}
// ...
const pet = { name: "Max" };
view.root.pet = pet; // Error: `pet` is ambiguous - is it a Dog or a Cat?
view.root.pet = new Dog(pet); // This works, but has the overhead of creating a Dog node before the insertion actually happens.
TreeAlpha.ensureSchema(Dog, pet); // Instead, this tags the `pet` object as a Dog...
view.root.pet = pet; // So now there is no error for a normal insertion - it's a Dog.

This function works by leveraging the new schemaSymbol, which is also available for use. See its documentation for more information.

Change details

Commit: 8213407

Affected packages:

  • @fluidframework/tree

⬆️ Table of contents

A minimal set of branching APIs has been promoted to beta. (#25744)

The following APIs have been promoted to beta in @fluidframework/tree:

  • TreeBranch.fork()
  • TreeBranch.merge()
  • TreeBranch.rebaseOnto()
  • TreeBranch.dispose()
  • TreeView.fork()

These APIs enable applications to implement basic local branching flows.

Change details

Commit: 32cc2c7

Affected packages:

  • fluid-framework
  • @fluidframework/tree
  • @fluidframework/tree-agent

⬆️ Table of contents

Improved join scalability (#25371)

Protocol for attendees joining has been updated to more efficiently accommodate a larger number of attendees, including when few-to-none have write access.

Change details

Commit: 98dadd3

Affected packages:

  • @fluidframework/presence

⬆️ Table of contents

🌳 SharedTree DDS Changes

Update TableSchema APIs (alpha) to accept SchemaFactoryBeta in addition to SchemaFactoryAlpha ([#25613](https://github.com/microso...

Read more

Fluid Framework v2.63.0 (minor)

14 Oct 18:23
4b609d4

Choose a tag to compare

Contents

🌳 SharedTree DDS Changes

Add FluidSerializableAsTree domain for representing trees of serializable data (alpha) (#25604)

Like JsonAsTree, but also supports Fluid Handles.

Change details

Commit: 46e6dce

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Promote Record node types and factories to beta (#25606)

Record tree node schema may now be declared using SchemaFactoryBeta in addition to SchemaFactoryAlpha.

Change details

Commit: 2e2de30

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Add TreeBeta.create (#25623)

Adds TreeBeta.create, which is a more stable version of the existing TreeAlpha.create. The only difference is the new TreeBeta.create does not support the @alpha UnsafeUnknownSchema option.

Change details

Commit: 376c2d1

Affected packages:

  • fluid-framework
  • @fluidframework/tree

⬆️ Table of contents

Alpha APIs for annotated allowed types have been refactored (#25595)

Staged allowed types must now be run through SchemaFactoryAlpha.types to convert them into an AllowedTypes. This change also means that it is now possible to use the produced AllowedTypesFull in non-alpha APIs since it implements AllowedTypes.

Reading data out of ImplicitAllowedTypes should now be done via normalizeAllowedTypes which now returns a AllowedTypesFull providing access to all the data in a friendly format.

Change details

Commit: c6ba37e

Affected packages:

  • fluid-framework
  • @fluidframework/tree

⬆️ Table of contents

Promote importConcise and exportConcise to beta (#25629)

importConcise and exportConcise were previously available via TreeAlpha. They may now also be accessed via TreeBeta.

Note that the beta form of importConcise does not support UnsafeUnknownSchema.

Change details

Commit: b5d4602

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Stabilize allowUnknownOptionalFields to beta (#25638)

When constructing object node schema with SchemaFactoryBeta.object or SchemaFactoryBeta.objectRecursive you can now provide the allowUnknownOptionalFields option as well as other metadata which were previously only available in SchemaFactoryAlpha.objectAlpha and SchemaFactoryAlpha.objectRecursive.

Additionally the alpha interface SchemaFactoryObjectOptions has been renamed to ObjectSchemaOptionsAlpha to better align with the other related types.

Change details

Commit: b7222d1

Affected packages:

  • fluid-framework
  • @fluidframework/tree

⬆️ Table of contents

Add SchemaFactoryAlpha.typesRecursive and SchemaFactoryAlpha.stagedRecursive (#25199)

With these new APIs, it is now possible to stage changes to recursive types.

Change details

Commit: 931e986

Affected packages:

  • fluid-framework
  • @fluidframework/tree

⬆️ Table of contents

MinimumVersionForCollab is now used in place of tree's alpha FluidClientVersion (#25402)

FluidClientVersion: No longer used as the type for Fluid Client versions in APIs/codecs (for example, oldestCompatibleClient). Additionally, FluidClientVersion is now a const object with members that declare specific MinimumVersionForCollab versions. These are intended to be used with APIs that require a version (such as TreeAlpha.exportCompressed).

CodecWriteOptions and SharedTreeOptions: oldestCompatibleClient has been replaced by minVersionForCollab. See migration guide below.

TreeAlpha.exportCompressed: The options parameter previously had oldestCompatibleClient and now has minVersionForCollab. Migrating requires a rename. Existing FluidClientVersion.* values are now MinimumClientVersions.

Migrating

If an application is calling loadContainerRuntime directly and previously specified the minimum client version when initializing Shared Tree like:

    const factory = configuredSharedTree({ ..., oldestCompatibleClient: FluidClientVersion.v2_52 });

Then the new implementation depends on how the application initializes Fluid.

Applications using AzureClient/OdspClient

If an application is using the declarative model (for example, AzureClient/OdspClient), it should continue to call configuredSharedTree but specify minVersionForCollab instead:

    const factory = configuredSharedTree({ ..., minVersionForCollab: "2.52.0" });
Applications calling loadContainerRuntime

If an application is initializing the ContainerRuntime directly, it should now specify the minVersionForCollab there:

    const runtime = await loadContainerRuntime({ ..., minVersionForCollab: "2.52.0" });

Change details

Commit: 7f59e31

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

🛠️ Start Building Today!

Please continue to engage with us on GitHub Discussion and Issue pages as you adopt Fluid Framework!

Fluid Framework v2.62.0 (minor)

30 Sep 19:41
37cf630

Choose a tag to compare

Contents

🚨 Breaking Changes

The exports of @fluid-experimental/tree-react-api have been moved to the new @fluidframework/react package and placed under its /alpha exports (#25542)

@fluid-experimental/tree-react-api has been adjusted to align with Fluid Framework's API Support Levels. It has been renamed to @fluidframework/react and all existing APIs are now available under @fluidframework/react/alpha.

Since this package was under @fluid-experimental, previously it implicitly made no guarantees. Now all the APIs are @alpha, which also amounts to making no guarantees but makes it possible to promote APIs to @beta in the future to offer some stability.

To accommodate this change, all users of this package will need to adjust:

  • Package dependencies from "@fluid-experimental/tree-react-api" to "@fluidframework/react".
  • Imports from "@fluid-experimental/tree-react-api" to "@fluidframework/react/alpha".

Change details

Commit: b388c7b

Affected packages:

  • @fluid-experimental/tree-react-api
  • @fluidframework/react

⬆️ Table of contents

🌳 SharedTree DDS Changes

Added APIs for tracking observations of SharedTree content for automatic invalidation (#25459)

TreeAlpha.trackObservations and TreeAlpha.trackObservationsOnce have been added. These provide a way to run some operation which reads content from TreeNodes, then run a call back when anything observed by that operation changes.

This functionality has also been exposed in the form of React hooks and React higher order components via the @fluid-experimental/tree-react-api package. It is now possible to use these utilities to implement React applications which pass TreeNodes in their props and get all necessary invalidation from tree changes handled automatically. The recommended pattern for doing this is to use treeDataObject or TreeViewComponent at the root, then withTreeObservations or withMemoizedTreeObservations for any sub-components which read from TreeNodes. Alternatively more localized changes can be made by using PropNode to type erase TreeNodes passed in props, then use one of the usePropTreeNode or usePropTreeRecord hooks to read from them.

These APIs work with both hydrated and un-hydrated TreeNodes.

React Support

Here is a simple example of a React components which has an invalidation bug due to reading a mutable field from a TreeNode that was provided in a prop:

const builder = new SchemaFactory("example");
class Item extends builder.object("Item", { text: SchemaFactory.string }) {}
const ItemComponentBug = ({ item }: { item: Item }): JSX.Element => (
	<span>{item.text}</span> // Reading `text`, a mutable value from a React prop, causes an invalidation bug.
);

This bug can now easily be fixed using withTreeObservations or withMemoizedTreeObservations:

const ItemComponent = withTreeObservations(
	({ item }: { item: Item }): JSX.Element => <span>{item.text}</span>,
);

For components which take in TreeNodes, but merely forward them and do not read their properties, they can use PropTreeNode as shown:

const ItemParentComponent = ({ item }: { item: PropTreeNode<Item> }): JSX.Element => (
	<ItemComponent item={item} />
);

If such a component reads from the TreeNode, it gets a compile error instead of an invalidation bug. In this case the invalidation bug would be that if item.text is modified, the component would not re-render.

const InvalidItemParentComponent = ({
	item,
}: { item: PropTreeNode<Item> }): JSX.Element => (
	// @ts-expect-error PropTreeNode turns this invalidation bug into a compile error
	<span>{item.text}</span>
);

To provide access to TreeNode content in only part of a component the usePropTreeNode or usePropTreeRecord hooks can be used.

TreeAlpha.trackObservationsOnce Examples

Here is a rather minimal example of how TreeAlpha.trackObservationsOnce can be used:

cachedFoo ??= TreeAlpha.trackObservationsOnce(
  () => {
    cachedFoo = undefined;
  },
  () => nodeA.someChild.bar + nodeB.someChild.baz,
).result;

That is equivalent to doing the following:

if (cachedFoo === undefined) {
  cachedFoo = nodeA.someChild.bar + nodeB.someChild.baz;
  const invalidate = (): void => {
    cachedFoo = undefined;
    for (const u of unsubscribe) {
      u();
    }
  };
  const unsubscribe: (() => void)[] = [
    TreeBeta.on(nodeA, "nodeChanged", (data) => {
      if (data.changedProperties.has("someChild")) {
        invalidate();
      }
    }),
    TreeBeta.on(nodeB, "nodeChanged", (data) => {
      if (data.changedProperties.has("someChild")) {
        invalidate();
      }
    }),
    TreeBeta.on(nodeA.someChild, "nodeChanged", (data) => {
      if (data.changedProperties.has("bar")) {
        invalidate();
      }
    }),
    TreeBeta.on(nodeB.someChild, "nodeChanged", (data) => {
      if (data.changedProperties.has("baz")) {
        invalidate();
      }
    }),
  ];
}

Here is more complete example showing how to use TreeAlpha.trackObservationsOnce invalidate a property derived from its tree fields.

const factory = new SchemaFactory("com.example");
class Vector extends factory.object("Vector", {
  x: SchemaFactory.number,
  y: SchemaFactory.number,
}) {
  #length: number | undefined = undefined;
  public length(): number {
    if (this.#length === undefined) {
      const result = TreeAlpha.trackObservationsOnce(
        () => {
          this.#length = undefined;
        },
        () => Math.hypot(this.x, this.y),
      );
      this.#length = result.result;
    }
    return this.#length;
  }
}
const vec = new Vector({ x: 3, y: 4 });
assert.equal(vec.length(), 5);
vec.x = 0;
assert.equal(vec.length(), 4);

Change details

Commit: 21d45d5

Affected packages:

  • fluid-framework
  • @fluidframework/tree
  • @fluid-experimental/tree-react-api
  • @fluidframework/react

⬆️ Table of contents

Remove JsonValidator (#25381)

The @alpha API JsonValidator has been removed: its replacement FormatValidator must now be used.

As part of this:

  • typeboxValidator has been replaced with FormatValidatorBasic.
  • noopValidator has been replaced with FormatValidatorNoOp.

Change details

Commit: 64a9b88

Affected packages:

  • fluid-framework
  • @fluidframework/tree

⬆️ Table of contents

Add configuredSharedTreeBeta (#25531)

A limited subset of the options from the existing @alpha configuredSharedTree API have been stabilized to @beta in the form of configuredSharedTreeBeta.

import {
  configuredSharedTreeBeta,
  ForestTypeExpensiveDebug,
} from "fluid-framework/beta";
const SharedTree = configuredSharedTreeBeta({
  forest: ForestTypeExpensiveDebug,
});

Change details

Commit: 1e2d48f

Affected packages:

  • fluid-framework
  • @fluidframework/tree

⬆️ Table of contents

⚠️ Deprecations

asTreeViewAlpha has been deprecated in favor of asAlpha. ([#25512](#255...

Read more

Fluid Framework v2.61.0 (minor)

23 Sep 02:45
b34a58a

Choose a tag to compare

Contents

✨ New Features

minVersionForCollab is now available on IFluidDataStoreContext (#25130)

minVersionForCollab is now passed down from the ContainerRuntime to the Datastore layer where it is made available for SharedObject construction. DDSes may optionally consume this value and use it to determine which sets of feature flags should be enabled.

Public type changes

  • @fluidframework/datastore: FluidDataStoreRuntime - Exposes minVersionForCollab.
  • @fluidframework/runtime-definitions: IFluidDataStoreContext - Exposes optional member minVersionForCollab. See FluidDataStoreContext for an example implementation.
  • @fluidframework/test-runtime-utils: MockFluidDataStoreContext, MockFluidDataStoreRuntime - Exposes minVersionForCollab either via a getter or as a readonly field.

Note that the new implementations are optional fields and in some cases accept undefined. This is needed for layer compatibility, and in a future release these members will no longer be optional.

Change details

Commit: 2566772

Affected packages:

  • @fluidframework/datastore
  • @fluidframework/runtime-definitions
  • @fluidframework/test-runtime-utils

⬆️ Table of contents

⚠️ Deprecations

Deprecate submitMessage on FluidDataStoreRuntime and MockFluidDataStoreRuntime (#25332)

As needed, access submitMessage via IFluidDataStoreContext/IFluidParentContext. See #24406 for details.

Change details

Commit: 687378a

Affected packages:

  • @fluidframework/datastore
  • @fluidframework/test-runtime-utils

⬆️ Table of contents

Legacy API Changes

Wrapped errors preserved as cause property (#25485)

IFluidErrorBase (internal basis for FluidFramework client errors) declares cause property matching ES2022 lib (whether targeted or not). When an error is wrapped, cause will be set to the originating error (which may or may not itself be an Error).

Change details

Commit: c69d56d

Affected packages:

  • @fluidframework/telemetry-utils

⬆️ Table of contents

🛠️ Start Building Today!

Please continue to engage with us on GitHub Discussion and Issue pages as you adopt Fluid Framework!

Fluid Framework v2.60.0 (minor)

02 Sep 20:30
8817a0b

Choose a tag to compare

Contents

🚨 Breaking Changes

Remove unnecessary and internal APIs in ISequenceIntervalCollection and related interval types (#25244)

The following APIs are now removed:

  • 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.

Change details

Commit: 15d476e

Affected packages:

  • fluid-framework
  • @fluidframework/sequence

⬆️ Table of contents

🌳 SharedTree DDS Changes

Single-node insertion/removal APIs have been removed from TableSchema (alpha) (#25233)

There is a significant performance benefit to inserting / removing rows / columns in batches. To help encourage more performant usage patterns, single-node insertion and removal APIs have been removed. The APIs that operate on batches should be used instead.

Specifically:

  • insertColumn
    • Use insertColumns instead
  • insertRow
    • Use insertRows instead
  • removeColumn
    • Use removeColumns instead
  • removeRow
    • Use removeRows instead

Change details

Commit: 99281d2

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Range-based row/column removal methods have been added to TableSchema APIs (alpha) (#25235)

Adds range-based overloads to removeColumns and removeRows for removing contiguous ranges of rows and columns.

The removeAllColumns and removeAllRows methods have been removed, as they can be trivially implemented in terms of the new methods.

Change details

Commit: c803393

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Replace "TreeEncodingOptions.useStoredKeys" with "keys" and "KeyEncodingOptions" (#25263)

The alpha API TreeEncodingOptions has had its useStoredKeys boolean replaced with keys that takes a KeyEncodingOptions allowing for three options instead of the previous two. With the new API, it is now possible to control, for APIs which support it (like TreeAlpha.exportVerbose), if unknown optional fields will be included when exporting data using stored keys.

Additionally, the relevant options interfaces have been marked as @input, indicating that more options may be added as optional parameters in the future, and that should be considered non-breaking.

Change details

Commit: b65f2a8

Affected packages:

  • fluid-framework
  • @fluidframework/tree

⬆️ Table of contents

Hoist runTransaction method from TreeViewAlpha to TreeBranch (#25280)

Transactions are not view-schema-dependent, so it isn't necessary for them to be exclusive to the view type. runTransaction is now available on TreeBranch (alpha). TreeViewAlpha extends TreeBranch, so this change strictly makes the API more accessible.

Change details

Commit: a66b3b7

Affected packages:

  • fluid-framework
  • @fluidframework/tree

⬆️ Table of contents

SchemaFactoryAlpha.recordRecursive now supports metadata (#25289)

SchemaFactoryAlpha.recordRecursive now support metadata like SchemaFactoryAlpha.recordAlpha and the other TreeNodeSchema creation methods on SchemaFactoryAlpha (except for SchemaFactoryAlpha.record which does not support metadata).

Change details

Commit: 8324170

Affected packages:

  • fluid-framework
  • @fluidframework/tree

⬆️ Table of contents

FormatValidator added to replace JsonValidator (#25311)

The existing @alpha type JsonValidator has a new type-erased alternative, FormatValidator, which is planned to be stabilized to @beta in the future. It replaces JsonValidator in ICodecOptions. Existing code using ICodecOptions should migrate to use FormatValidator, but this is not required for adopting this release as JsonValidator is still supported.

Change details

Commit: 9db6e08

Affected packages:

  • fluid-framework
  • @fluidframework/tree

⬆️ Table of contents

Add SchemaFactoryBeta (#25313)

SchemaFactoryBeta is added to provide a place to partially stabilize APIs from SchemaFactoryAlpha. Initially just one APIs is added as @beta: scopedFactory. Users of the existing @alpha scopedFactory API on SchemaFactoryAlpha will need to update to use scopedFactoryAlpha if they require the returned factory to be a SchemaFactoryAlpha instance.

Change details

Commit: dca2361

Affected packages:

  • fluid-framework
  • @fluidframework/tree

⬆️ Table of contents

🛠️ Start Building Today!

Please continue to engage with us on GitHub Discussion and Issue pages as you adopt Fluid Framework!

Fluid Framework v2.53.1 (patch)

25 Aug 21:09
a33ba13

Choose a tag to compare

What's Changed

  • fix(directory): Fix SharedDirectory.forEach() (#25299) #25301
  • Bump client patch version to 2.53.1 and update type tests #25254

Full Changelog: client_v2.53.0...client_v2.53.1

Fluid Framework v2.53.0 (minor)

18 Aug 20:00
4177e97

Choose a tag to compare

Contents

✨ New Features

Adds staged allowed types to SchemaFactoryAlpha (#25116)

This adds the staged API to SchemaFactoryAlpha. Staged allowed types can be used for schema evolution to add members to an AllowedTypes while supporting cross version collaboration.

Staged allowed types are allowed types that can be upgraded by schema upgrades. Before being upgraded, any attempt to insert or move a node to a location which requires its type to be upgraded to be valid will throw an error.

To add a new member to an AllowedTypes, add the type wrapped by staged. For example, migrating an array which previously supported only numbers to support both numbers and strings would start by deploying a version of the app using staged:

class TestArray extends schemaFactoryAlpha.arrayAlpha("TestArray", [
  SchemaFactoryAlpha.number,
  SchemaFactoryAlpha.staged(SchemaFactoryAlpha.string),
]) {}

Once enough clients have this code update, it is safe to allow writing strings to the array. To allow writing strings to the array, a code change must be made to remove the staged annotation:

class TestArray extends schemaFactoryAlpha.arrayAlpha("TestArray", [
  schemaFactoryAlpha.number,
  schemaFactoryAlpha.string,
]) {}

Then when opening old documents upgradeSchema is used to upgrade the stored schema:

view.upgradeSchema();

The @alpha API extractPersistedSchema now takes the schema as an ImplicitAnnotatedFieldSchema and an additional parameter to filter which staged upgrades it includes.

Below is a full example of how the schema migration process works. This can also be found in the tests.

// Schema A: only number allowed
const schemaA = SchemaFactoryAlpha.optional([SchemaFactoryAlpha.number]);

// Schema B: number or string (string is staged)
const schemaB = SchemaFactoryAlpha.optional([
  SchemaFactoryAlpha.number,
  SchemaFactoryAlpha.staged(SchemaFactoryAlpha.string),
]);

// Schema C: number or string, both fully allowed
const schemaC = SchemaFactoryAlpha.optional([
  SchemaFactoryAlpha.number,
  SchemaFactoryAlpha.string,
]);

// Initialize with schema A.
const configA = new TreeViewConfiguration({
  schema: schemaA,
});
const viewA = treeA.viewWith(configA);
viewA.initialize(5);

// Since we are running all the different versions of the app in the same process making changes synchronously,
// an explicit flush is needed to make them available to each other.
synchronizeTrees();

assert.deepEqual(viewA.root, 5);

// View the same document with a second tree using schema B.
const configB = new TreeViewConfiguration({
  schema: schemaB,
});
const viewB = treeB.viewWith(configB);
// B cannot write strings to the root.
assert.throws(() => (viewB.root = "test"));

// View the same document with a third tree using schema C.
const configC = new TreeViewConfiguration({
  schema: schemaC,
});
const viewC = treeC.viewWith(configC);
// Upgrade to schema C
viewC.upgradeSchema();
// Use the newly enabled schema.
viewC.root = "test";

synchronizeTrees();

// View A is now incompatible with the stored schema:
assert.equal(viewA.compatibility.canView, false);

// View B can still read the document, and now sees the string root which relies on the staged schema.
assert.deepEqual(viewB.root, "test");

Change details

Commit: 59baf03

Affected packages:

  • fluid-framework
  • @fluidframework/tree

⬆️ Table of contents

StateFactory.latestMap now accepts a validator parameter (#25172)

The StateFactory.latestMap API now accepts a validator argument. The validator is a function that will be called at runtime to verify that the data is valid. This is especially useful when changing the schema of presence data.

See the presence documentation for more details.

Change details

Commit: cac39eb

Affected packages:

  • @fluidframework/presence

⬆️ Table of contents

🌳 SharedTree DDS Changes

TableSchema's "removeColumn" API now removes corresponding cells (alpha) (#25213)

Previously, the removeColumn API on Table nodes derived from TableSchema (alpha) only removed the Column node from the list of columns tracked by the table. To also remove the corresponding cells from the table (which are stored on the Row nodes), the user was required to write a custom transaction that removed the column and cells.

The motivation for this design was due to performance concerns with transactions. Those concerns are still relevant, but the data leak risk of dropping columns without removing corresponding cells seems a greater risk, and we have plans to address the performance issues with transactions.

Change details

Commit: b665ba8

Affected packages:

  • fluid-framework
  • @fluidframework/tree

⬆️ Table of contents

Export TreeNode not only as a type (#25226)

TreeNode can now be used as a runtime object. This enables checking if an object is a TreeNode with instanceof. TreeNode has customized instanceof support so it can detect TreeNode instances, even if they hide their prototype like POJO mode nodes do.

Change details

Commit: eefb952

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

🐛 Bug Fixes

Allow edits in arrays to be concurrent to dependent edits of transactions with violated constraints (#25191)

Before this release, making concurrent edits to an array could lead to assertion error 0x8a2 being thrown if the following conditions were met:

  • Some edit e1 was a transaction with a constraint that turned out to be violated by edits concurrent to (and sequenced before) e1
  • Some edit e2 was dependent on e1 (from before the violation of its constraint)
  • Some edit e3 was concurrent to and sequenced after both e1 and e2
  • e3 was either concurrent to or the revert of some other edit e0 that predated e1, e2, and e3.
  • e0 and e2 made edits to the same gap (that is, in the same space between nodes) in the sequence/array.

After this release, these scenarios will work as expected (that is, no assertion error thrown).

Change details

Commit: ef64bae

Affected packages:

  • @fluidframework/tree
  • fluid-framework

[⬆️ Table ...

Read more

Fluid Framework v2.52.0 (minor)

04 Aug 20:52
5fa574a

Choose a tag to compare

Contents

🌳 SharedTree DDS Changes

Change and clarify limitations related to alpha features allowUnknownOptionalFields and importVerbose (#25074)

allowUnknownOptionalFields currently has some limitations. To mitigate some bugs, importVerbose has dropped support for unknown optional fields. Previously importVerbose would tolerate some unknown optional fields, but could not validate they comply with the document stored schema. This could cause some crashes, and likely document corruption. This support has been removed: now trying to create nodes containing unknown optional fields via importVerbose will throw a UsageError. There is no longer a way to create and insert nodes which contain subtrees for which there is no schema.

Ideally exportVerbose and importVerbose could be used to round trip data while optionally preserving unknown optional fields, but this is currently not working and thus not supported.

If exporting using useStoredKeys, the unknown optional fields will be preserved but may not be able to be imported. If exporting not using useStoredKeys, unknown optional fields will be omitted.

Change details

Commit: 62dc0b0

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Fix independentInitializedView when used with ForestTypeExpensiveDebug (#25083)

Previously, when using independentInitializedView with ForestTypeExpensiveDebug and the root schema was not an optional field, an error was thrown about the tree being out of schema. This has been fixed.

Change details

Commit: 2570b65

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Allow attaching a SharedTree to an already attached container (#25102)

Before this release, attaching a SharedTree instance to an already attached container would fail with assert code 0x88f if that instance needed to include data about removed nodes in its attach summary. (This is the case when nodes are removed before attaching and there is a local branch that forks from a commit that made such a removal or from an earlier commit. This is also the case when retaining Revertible objects for those commits).

After this release, the behavior depends on the CodecWriteOptions.oldestCompatibleClient value:

  • For values < FluidClientVersion.v2_52, the behavior is the same.
  • For values >= FluidClientVersion.v2_52, the attach will succeed, but use a newer storage format.

Applications should take care to saturate their clients with FF version 2.52 (or greater) before using a CodecWriteOptions.oldestCompatibleClient that is equal to or greater than FluidClientVersion.v2_52. Failure to do so may lead clients with CodecWriteOptions.oldestCompatibleClient equal to or greater than FluidClientVersion.v2_52 to attach SharedTree instances using a storage format that is not supported by FF versions before 2.52. This means that application versions using FF versions before 2.52 will be unable to open documents where such an operation has happened.

Change details

Commit: 3e03f94

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Support unknown optional fields in TreeBeta.clone, TreeAlpha.exportConcise and TreeAlpha.exportVerbose (#25106)

Trees with unknown optional fields are now supported in TreeBeta.clone, TreeBeta.exportConcise and TreeBeta.exportVerbose.

Previously, attempts to clone or export such nodes could error in some cases, but should now work robustly.

Change details

Commit: e3a126f

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

⚠️ Deprecations

Moved MinimumVersionForCollab to @fluidframework/runtime-definitions (#25059)

MinimumVersionForCollab has been moved from @fluidframework/container-runtime to @fluidframework/runtime-definitions. The export in @fluidframework/container-runtime is now deprecated and will be removed in a future version. Consumers should import it from @fluidframework/runtime-definitions going forward.

Change details

Commit: 4a7b370

Affected packages:

  • @fluidframework/container-runtime
  • @fluidframework/runtime-utils

⬆️ Table of contents

Legacy API Changes

Introduced new interface "IRuntimeStorageService" to replace "IDocumentStorageService" between Runtime and DataStore layers (#25057)

Added an interface IRuntimeStorageService which will replace IDocumentStorageService in the DataStore layer. This is exposed by the Runtime layer to the DataStore layer. This new interface will only contain properties that are needed and used by the DataStore layer.

The following properties from IRuntimeStorageService are deprecated as they are not needed by the DataStore layer. These be removed in a future release:

  • disposed
  • dispose
  • policies
  • getSnapshotTree
  • getSnapshot
  • getVersions
  • createBlob
  • uploadSummaryWithContext
  • downloadSummary

Change details

Commit: 92012de

Affected packages:

  • @fluidframework/runtime-...
Read more