Skip to content

Fluid Framework v3.10.0 (minor)

Choose a tag to compare

@github-actions github-actions released this 03 Nov 23:03
· 9 commits to main since this release
acfde92

Contents

✨ New Features

Configure public schema factories with reusable object defaults (#28604)

SchemaFactory now accepts an options object with the scope and an objectOptions property bag through the public API. The property bag provides reusable defaults for object and objectRecursive, including the public allowUnknownOptionalFields option. Options passed directly to an object schema override factory defaults through a shallow merge.

import { SchemaFactory } from "fluid-framework";

const sf = new SchemaFactory({
  scope: "com.example",
  objectOptions: {
    allowUnknownOptionalFields: true,
  },
});

class Person extends sf.object("Person", { name: sf.string }) {}

// Override the default for one schema.
class StrictPerson extends sf.object(
  "StrictPerson",
  { name: sf.string },
  { allowUnknownOptionalFields: false },
) {}

You can read and extend factory settings without changing the original factory:

  • settings provides the factory's options without its scope.
  • scopedFactory creates a child factory by merging provided object-option properties with the current settings, without changing the original factory.
const extended = sf.scopedFactory("strict", {
  objectOptions: {
    allowUnknownOptionalFields: false,
  },
});

Passing {} or { objectOptions: {} } preserves inherited settings. Metadata and persisted metadata, when supported, are replaced as whole objects when provided; they are not deep-merged. To start without inherited settings, construct a new factory with the desired scope.

The beta and alpha schema factories support their corresponding tier-specific options.

Change details

Commit: 1642d66

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

🌳 SharedTree DDS Changes

Add an alpha API to check if a node has content in unknown optional fields (#28529)

Object nodes whose schema sets allowUnknownOptionalFields can contain optional fields that are not in the view schema. The content of these fields is not available through the node's properties.

The new TreeAlpha.hasUnknownChildren API returns true if a node has content in at least one unknown optional field. To read that content, use TreeAlpha.exportVerbose with KeyEncodingOptions.allStoredKeys.

const sf = new SchemaFactoryBeta("com.example");
class Person extends sf.object(
  "Person",
  { name: sf.string },
  { allowUnknownOptionalFields: true },
) {}

// ...

// A newer version of the application added a `nickname` field.
if (TreeAlpha.hasUnknownChildren(person)) {
  const content = TreeAlpha.exportVerbose(person, {
    keys: KeyEncodingOptions.allStoredKeys,
  });
  // { type: "com.example.Person", fields: { name: "Alice", nickname: "Ali" } }
}

Change details

Commit: 6571145

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Reduce navigation overhead for SharedTree reads and edits (#28554)

SharedTree reads, edits, and parent/key queries have lower overhead, including in deeply nested trees. No application code or stored document format changes are required.

Performance measurements

Benchmarks on trees nested ten levels deep measure improvements with both the reference (default) forest and the optimized forest. Times are microseconds per benchmark iteration.

Forest Workload Before After Less elapsed time
Reference (default) Object and array reads 5.349 1.626 69.6%
Reference (default) Edits 138.518 115.525 16.6%
Reference (default) Parent/key queries 13.577 0.728 94.6%
Optimized Object and array reads 3.610 1.593 55.9%
Optimized Edits 112.610 97.693 13.2%
Optimized Parent/key queries 7.011 0.635 90.9%

Results are means from two fresh processes per version, run serially in balanced order on Linux x64 with Node.js 22.22.3 and production emulation enabled. These are workload-specific results on a shared host, not whole-application speedups. Edit measurements are noisier, with relative margins of error up to approximately 20%, so treat those differences with caution.

Change details

Commit: 53f3c89

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Remove deprecated TreeBranch and TreeBranchAlpha type aliases (#28284)

The deprecated TreeBranch and TreeBranchAlpha compatibility aliases have been removed. Use UntypedTreeView and UntypedTreeViewAlpha instead.

// Before
import type { TreeBranch } from "fluid-framework/beta";
import type { TreeBranchAlpha } from "fluid-framework/alpha";

// After
import type { UntypedTreeView } from "fluid-framework/beta";
import type { UntypedTreeViewAlpha } from "fluid-framework/alpha";

Change details

Commit: 326214d

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Preserve alpha capabilities when configuring SharedTree kinds (#28583)

configuredSharedTreeAlpha now returns SharedObjectKindAlpha, matching the capabilities exposed by SharedTreeAlpha. This exposes the type and adapt members needed to use configured kinds as registry keys. Existing uses of the returned SharedObjectKind remain supported, and runtime behavior is unchanged.

Change details

Commit: 742ef2f

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Preserve array and map node types when accessing alpha APIs (#28579)

Calling asAlpha on an array or map node now preserves its read and insertion types, customized subclass members, and schema identity. The additional alpha methods use the node's existing read and insertion types, so valid content remains accepted and invalid content remains rejected.

Omit the type arguments to preserve the complete node type automatically. If you already specify the allowed types explicitly, that call remains supported, but it does not preserve customized members in the returned type. Specify the node type as the second type argument to preserve those members too.

import { asAlpha, SchemaFactory } from "fluid-framework/alpha";

const sf = new SchemaFactory("example");
class Numbers extends sf.array("Numbers", sf.number) {
  public label = "numbers";
}
const numbers = new Numbers([1, 2]);

// Recommended: infer the element type and preserve the custom label property.
const inferred = asAlpha(numbers);
inferred.unshift(0);
inferred.label; // string

// An explicit allowed-types argument still supports numeric array operations.
const explicit = asAlpha<typeof sf.number>(numbers);
explicit.unshift(3);

// Also specify the node type to preserve the custom label property.
const explicitNode = asAlpha<typeof sf.number, Numbers>(numbers);
explicitNode.label; // string

The same type-argument guidance applies to map nodes. The conversion still returns the original node without changing runtime behavior.

Change details

Commit: 1c8dc49

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Track annotations across array and formatted text edits (#27621)

You can now track ranges with application-defined data, such as review comments, through edits to arrays and formatted text. The new alpha APIs ExtrinsicLocations.createArraySchema and FormattedText.createSchemaWithRanges provide this capability. Both expose ranges and their associated data through a ranges property.

These APIs are early @alpha features and are not yet production-ready. Configure SharedTree with minVersionForCollab of at least 2.80.0. In this early @alpha version, concurrent changes anywhere in the document can reject a content or range edit rather than merge it: this version is intended for API experimentation and feedback, not production use.

Arrays

Use ExtrinsicLocations to create an array schema with tracked ranges. Edit content through transactOnContent to maintain ranges across insertions, removals, and moves. You can use synchronous nested runTransaction calls inside its callback. If a nested transaction rolls back content edits, the range endpoints are restored before that transaction call returns.

import {
  ExtrinsicLocations,
  SchemaFactoryBeta,
} from "@fluidframework/tree/alpha";

const sf = new SchemaFactoryBeta("com.example.review");
class Document extends ExtrinsicLocations.createArraySchema({
  schemaFactory: sf,
  rangeDataSchema: sf.string,
  contentSchema: sf.string,
}) {}

const document = Document.create(["Plan", "Build", "Ship"]);
const comment = document.ranges.trackRange(
  "comment",
  { start: 1, end: 3 },
  "Check these steps",
);
document.transactOnContent((content) => content.insertAt(0, "Design"));
document.content.slice(comment.start.index, comment.end.index); // ["Build", "Ship"]

Formatted text

Use FormattedText.createSchemaWithRanges for text whose existing editing methods maintain ranges automatically. It accepts named options for the schema factory, formatting, additional atom schemas, default formatting, and range data schema.

Formatted text implementations now reserve the ranges property name, including schemas created with the existing FormattedText.createSchema Alpha API. If your subclass defines this property, rename it to avoid a collision with the implementation. Assignments to this property can now throw a TypeError, even though the existing factory's return type does not prevent the collision.

import {
  FormattedText,
  SchemaFactoryBeta,
  TreeViewConfiguration,
  createIndependentTreeAlpha,
} from "@fluidframework/tree/alpha";

const sf = new SchemaFactoryBeta("com.example.annotatedText");
class Format extends sf.object("Format", { bold: sf.boolean }) {}
class Comment extends sf.object("Comment", { message: sf.string }) {}
class Text extends FormattedText.createSchemaWithRanges({
  schemaFactory: sf,
  formatSchema: Format,
  extraAtoms: [],
  defaultFormatInsertable: { bold: false },
  rangeDataSchema: Comment,
}) {}

const view = createIndependentTreeAlpha({
  minVersionForCollab: "2.80.0",
}).viewWith(new TreeViewConfiguration({ schema: Text }));
view.initialize(Text.fromString("Hello world"));
const text = view.root;
const comment = text.ranges.trackRange(
  "comment",
  { start: 6, end: 11 },
  { message: "Review this word" },
);
text.insertAt(0, "Say: ");
const { start, end } = comment; // start.index === 11, end.index === 16
text.getString(start.index, end.index); // "world"

Existing formatted text can be upgraded to support ranges without rewriting its content. See the FormattedText namespace documentation for details.

Change details

Commit: 93bacfe

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Fix nodeChanged events for changes to unknown optional fields (#28577)

When another client changed an unknown optional field of an object node, subscribing to nodeChanged on that node caused an error to be thrown when the change was applied. This also affected TreeAlpha.trackObservations, TreeAlpha.trackObservationsOnce, and React components using observation tracking from @fluidframework/react, such as useTreeObservations and withTreeObservations.

Now nodeChanged is emitted for these changes. Unknown optional fields have no property, so they are not included in changedProperties. Instead, the new changedUnknownProperties property of the event data lists their stored keys. If only unknown optional fields changed, changedProperties is empty.

TreeBeta.on(
  node,
  "nodeChanged",
  ({ changedProperties, changedUnknownProperties }) => {
    // changedProperties: property keys of known fields that changed.
    // changedUnknownProperties: stored keys of unknown optional fields that changed, or undefined if none changed.
  },
);

Observation tracking is invalidated when an unknown optional field changes if the tracked code observed it, for example by calling TreeAlpha.hasUnknownChildren.

Change details

Commit: 7a49a6e

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Applications can configure the policy for tolerating unknown optional fields through the public API (#28603)

SchemaFactory.object and SchemaFactory.objectRecursive now accept the allowUnknownOptionalFields option through the public API. The option defaults to true.

This option controls how an object node's view schema handles optional fields that are declared in the document's stored schema but not in the view schema:

  • Set allowUnknownOptionalFields to true to let an older application version continue to view and edit a document after a newer version adds new optional fields to the object schema, provided the schemas are otherwise compatible. The older version cannot access those fields through its view. Copying nodes by reading their fields or spreading them into new nodes can drop data in the unknown fields.
  • Set allowUnknownOptionalFields to false to prevent viewing documents whose stored schema declares additional optional fields for that object. After a newer application version adds an optional field to the object schema, older versions with this policy cannot view the document until their view schemas include that field.
import { SchemaFactory } from "@fluidframework/tree";

const factory = new SchemaFactory("com.example");

class Person extends factory.object(
  "Person",
  { name: factory.string },
  // Reject documents with additional optional fields on Person.
  { allowUnknownOptionalFields: false },
) {}

The beta ObjectSchemaOptions type is renamed to ObjectSchemaOptionsBeta. If you reference the beta type directly, update those references to the new name.

Change details

Commit: 5e94cbf

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Add an alpha API to get the schema of unknown fields (#28563)

The new TreeContextAlpha.unknownFieldSchemas property maps each object node schema that has unknown fields to the schema of those fields, keyed by stored key. The value updates when the document's stored schema changes: listen to the view's schemaChanged event to know when to read it again. It is available on TreeViewAlpha and on the context of any hydrated node. It is undefined for unhydrated nodes, which have no view schema.

To read the content of these fields, use TreeAlpha.exportVerbose with KeyEncodingOptions.allStoredKeys.

Example

Version 1 of an application defines a Person with a name field, and allows unknown optional fields. allowUnknownOptionalFields will be enabled by default in the 3.10 release.

const sf = new SchemaFactoryBeta("com.example");
class Person extends sf.object(
  "Person",
  { name: sf.string },
  { allowUnknownOptionalFields: true },
) {}

Version 2 of the application adds an optional nickname field:

class Person extends sf.object(
  "Person",
  { name: sf.string, nickname: sf.optional(sf.string) },
  { allowUnknownOptionalFields: true },
) {}

Version 1 can still open a document after version 2 upgrades its schema, but the nickname field is unknown to it. Version 1 can use unknownFieldSchemas to find the schema of that field, then use exportVerbose to read its content:

// In version 1 of the application:
const fieldSchemas = TreeAlpha.context(person).unknownFieldSchemas?.get(Person);
// Map { "nickname" => { kind: FieldKind.Optional, simpleAllowedTypes: Map { "com.fluidframework.leaf.string" => ... }, ... } }

const content = TreeAlpha.exportVerbose(person, {
  keys: KeyEncodingOptions.allStoredKeys,
});
// { type: "com.example.Person", fields: { name: "Ali", nickname: "Al" } }

Change details

Commit: 35adb67

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

Object schemas support unknown optional fields by default (#28606)

Object schemas created by SchemaFactory, SchemaFactoryBeta, and SchemaFactoryAlpha now allow unknown optional fields by default universally. This makes older application versions forward-compatible with documents whose stored schema has added optional fields, without requiring every object schema to specify allowUnknownOptionalFields: true.

Applications that require an exact match between the object view schema and stored schema can retain the previous behavior by explicitly setting allowUnknownOptionalFields: false. The allowUnknownOptionalFields option is available on the public SchemaFactory.object API:

const schemaFactory = new SchemaFactory("com.example");

class StrictPerson extends schemaFactory.object(
  "Person",
  {
    name: schemaFactory.string,
  },
  {
    allowUnknownOptionalFields: false,
  },
) {}

Applications can also set allowUnknownOptionalFields: false once on the public SchemaFactory to preserve the previous default for all object schemas created by that factory. Set the factory's objectOptions property bag when constructing it:

const factory = new SchemaFactory({
  scope: "com.example",
  objectOptions: {
    allowUnknownOptionalFields: false,
  },
});

Individual schemas can still override this factory default.

Behavior to review

Code that reads only known properties does not observe unknown fields. As a result, application implementations of cloning, equality, serialization, or object reconstruction may omit unknown data even though SharedTree preserves it internally. Spreading a node into a new object also includes only the known view-schema properties. Review any code that round-trips a node by reading its known properties and constructing a replacement, since such code may silently discard unknown fields.

For example, an older client may define Person with only a name field:

class Person extends schemaFactory.object("Person", {
  name: schemaFactory.string,
}) {}

After a newer client adds an optional nickname field, the older client can still read the document, but this custom clone loses the unknown field:

function clonePerson(person: Person): Person {
  return new Person({ name: person.name });
}

Calling clonePerson omits nickname because the older view does not expose that property, even though SharedTree preserved it on the original node.

Use TreeBeta.clone to clone a hydrated tree, which will preserve unknown fields and the source document's schema context. When exporting, TreeAlpha.exportVerbose preserves unknown fields only when configured to use all stored keys.

const exported = TreeAlpha.exportVerbose(person, {
  keys: KeyEncodingOptions.allStoredKeys,
});

Using KeyEncodingOptions.knownStoredKeys or KeyEncodingOptions.usePropertyKeys omits unknown optional fields. Unhydrated nodes created using constructors or insertable content have no source document schema from which unknown fields could be interpreted. TreeAlpha.importVerbose currently rejects unexpected fields, including when the target schema allows unknown optional fields. Support for preserving these fields through import and export should be added in follow-up work.

Applications whose code depends on enumerating every field, reconstructs nodes from their known properties, or requires schema equality rather than forward compatibility should set allowUnknownOptionalFields: false on the affected object schemas:

class StrictPerson extends schemaFactory.object(
  "Person",
  {
    name: schemaFactory.string,
  },
  {
    allowUnknownOptionalFields: false,
  },
) {}

Schema compatibility snapshots

Applications using snapshotSchemaCompatibility with object schemas from any schema factory will see snapshot-test failures because the serialized view schema changes from allowUnknownOptionalFields: false to allowUnknownOptionalFields: true. Review the affected schemas, retain historical snapshots unchanged, and generate a current-version snapshot to record the new forward-compatible behavior. Alternatively, explicitly set allowUnknownOptionalFields: false to retain the previous behavior and avoid a new snapshot.

For example, if the snapshot directory contains 3.9.0.json, leave that file unchanged and regenerate snapshots so a new 3.10.0.json records allowUnknownOptionalFields: true:

schema-compatibility-snapshots/
├── 3.9.0.json  # Retained with allowUnknownOptionalFields: false
└── 3.10.0.json # Added with allowUnknownOptionalFields: true

If the schema must remain strict instead, opt out before rerunning the snapshot test:

class StrictPerson extends schemaFactory.object(
  "Person",
  {
    name: schemaFactory.string,
  },
  {
    allowUnknownOptionalFields: false,
  },
) {}

Snapshot failures identify schemas whose compatibility contract changed, but do not verify that application cloning, equality, serialization, or reconstruction code safely handles unknown fields.

Compatibility snapshot files are now written with a trailing newline so regenerating them does not create formatting-only diffs.

Change details

Commit: 5a4b8c2

Affected packages:

  • fluid-framework
  • @fluidframework/tree

⬆️ Table of contents

🐛 Bug Fixes

Fix SharedTree history length tracking during trimming (#28522)

Reading branch history no longer causes a commit-count assertion when rebasing a branch triggers history trimming. Branch lengths are now directly computed and cached on the branch itself rather than relying on event listening, which is subject to timing issues and interleaving. Reading a branch's history length after the branch is disposed now throws an error.

Change details

Commit: 77e3f67

Affected packages:

  • @fluidframework/tree
  • fluid-framework

⬆️ Table of contents

⚠️ Deprecations

Deprecate shared object implementation classes (#28533)

SharedObject and SharedObjectCore from @fluidframework/shared-object-base are deprecated. These classes will become internal in release 3.20.0. Use existing distributed data structures instead of custom subclasses. For types that do not need implementation details, use ISharedObject instead:

import type { ISharedObject } from "@fluidframework/shared-object-base/legacy";

function getSharedObjectId(sharedObject: ISharedObject): string {
  return sharedObject.id;
}

See issue #26284 for details.

Change details

Commit: e68833f

Affected packages:

  • @fluidframework/shared-object-base

⬆️ Table of contents

Deprecate summarizer implementation APIs (#28599)

Direct summarizer control, detailed summarizer results, and summary collection APIs from @fluidframework/container-runtime are deprecated. These APIs expose implementation details and are intended to become internal. The following APIs are deprecated:

  • Direct control: ISummarizer, ISummarizeOptions, IOnDemandSummarizeOptions, and ISummarizeResults.
  • Enqueue support: IEnqueueSummarizeOptions and EnqueueSummarizeResult.
  • Result stages: SummarizeResultPart, SubmitSummaryResult, IBaseSummarizeResult, IGenerateSummaryTreeResult, IUploadSummaryResult, ISubmitSummaryOpResult, SubmitSummaryFailureData, and SummaryStage.
  • Result metadata and acknowledgements: IRetriableFailureError, IGeneratedSummaryStats, IBroadcastSummaryResult, IAckSummaryResult, and INackSummaryResult.
  • Collection and message wrappers: SummaryCollection, ISummary, IAckedSummary, ISummaryOpMessage, ISummaryAckMessage, and ISummaryNackMessage.
  • Collection watchers and events: IClientSummaryWatcher, ISummaryCollectionOpEvents, OpActionEventName, and OpActionEventListener.

For application-requested summaries, use loadAndSummarize from @fluidframework/container-loader/legacy. This is the recommended migration API for most customers:

import { loadAndSummarize } from "@fluidframework/container-loader/legacy";

// props supplies the loader services and request.
const { version, referenceSequenceNumber } = await loadAndSummarize(props);

loadAndSummarize manages loading and disposing the summarizer container and requests an on-demand summary without requiring the application to manage summarizer implementation details. It waits for service acknowledgement and returns the acknowledged snapshot version and the reference sequence number of its summary proposal. Use version with LoaderHeader.version on drivers that support loading snapshot versions. The API rejects on failure. Enqueueing, collection watching, and detailed stage promises are implementation-level controls that are intentionally not exposed by this API.

The older loadSummarizerContainerAndMakeSummary API is intended for specialized integrations that do not provide service acknowledgement ops. Most customers should use loadAndSummarize instead. The older API's success requires submission and broadcast, and its proposal handle is not guaranteed to identify an acknowledged snapshot version.

SummaryTreeBuilder and convertToSummaryTreeWithStats from @fluidframework/runtime-utils are also deprecated as implementation utilities intended to become internal. There is no supported replacement for these tree-building and conversion utilities. The loader API is not a replacement for building summary trees.

This change preserves existing exports, signatures, and behavior. Internal implementations in the Fluid Framework repository can continue using these APIs. No internalization version or date is specified.

Change details

Commit: d44fce6

Affected packages:

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

⬆️ Table of contents

Legacy API Changes

On-demand summarization API is now beta (#28546)

loadSummarizerContainerAndMakeSummary is promoted from @alpha to @beta, together with ILoadSummarizerContainerProps, LoadSummarizerSummaryResult, OnDemandSummaryResults, and SummaryStage. These APIs can now be imported from @fluidframework/container-loader/legacy.

Change details

Commit: 2a411f3

Affected packages:

  • @fluidframework/container-loader

⬆️ Table of contents

Add oldestSupportedClient across runtime layers (#28537)

Runtime and data store contexts now expose the required oldestSupportedClient property beside minVersionForCollab. Consumers can use context.oldestSupportedClient directly instead of context.minVersionForCollab. The runtime retains its internal fallback for older contexts that expose only minVersionForCollab, so mixed-version packages remain supported.

IFluidParentContext.minVersionForCollab is deprecated in 3.10.0 and will be removed in a future release. Use IFluidParentContext.oldestSupportedClient instead.

const oldestSupportedClient = context.oldestSupportedClient;

The on-disk schema and telemetry property names do not change. See the migration issue for more details.

Change details

Commit: 9fc4c21

Affected packages:

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

⬆️ Table of contents

On-demand summaries can return an acknowledged snapshot version (#28613)

loadAndSummarize creates a summary and waits for service acknowledgement. It returns an AcknowledgedSummary with required version and referenceSequenceNumber fields, and rejects on error. Use version with LoaderHeader.version to load the acknowledged snapshot. The reference sequence number comes from the matching summary proposal and identifies the document state captured by the summary.

import { LoaderHeader } from "@fluidframework/container-definitions/legacy";
import {
  loadExistingContainer,
  loadAndSummarize,
} from "@fluidframework/container-loader/legacy";

// props supplies the loader services and request.
const { version, referenceSequenceNumber } = await loadAndSummarize(props);
const container = await loadExistingContainer({
  ...props,
  request: {
    ...props.request,
    headers: { ...props.request.headers, [LoaderHeader.version]: version },
  },
});
// Use container, then dispose it when finished.

loadAndSummarize rejects if summarization cannot recover from NACK, timeout, or premature container termination. The runtime handles summary-stage retries. The loader retries every failed attempt once with a fresh container, regardless of error retryability. A fresh load can succeed if a transient condition has resolved, but recovery is not guaranteed. Both returned values identify the successful attempt. The summarizer container is disposed before the promise settles.

loadSummarizerContainerAndMakeSummary returns summaryResults.summaryInfo.handle, which identifies the broadcast summary proposal. It is not guaranteed to identify an acknowledged snapshot that can be loaded with LoaderHeader.version. Use the version returned by loadAndSummarize when an acknowledged snapshot version is required.

Change details

Commit: 5f18a5c

Affected packages:

  • @fluidframework/container-loader

⬆️ Table of contents

Remove the deprecated beta assert API (#28624)

The deprecated assert API is removed from @fluidframework/core-utils. No replacement API is offered. Use an assertion utility appropriate for your application or throw an Error directly.

See the removal tracking issue for context.

Change details

Commit: 950732d

Affected packages:

  • @fluidframework/core-utils

⬆️ Table of contents

Use the register collection interface instead of its implementation class (#28558)

To keep applications independent of implementation details, the package no longer exports ConsensusRegisterCollectionClass. As a result, applications can no longer construct or subclass that class directly.

For instance annotations, use IConsensusRegisterCollection or the ConsensusRegisterCollection type alias. To create a collection, use the existing ConsensusRegisterCollection creation value instead of the implementation constructor, as shown below.

import {
  ConsensusRegisterCollection,
  type IConsensusRegisterCollection,
} from "@fluidframework/register-collection/legacy";

const registers: IConsensusRegisterCollection<string> =
  ConsensusRegisterCollection.create(runtime);
const factory = ConsensusRegisterCollection.getFactory();

These replacements leave collection interfaces, events, factories, handles, and persisted data formats unchanged. For the removal plan and existing deprecation, see issue #26691.

Change details

Commit: 9ccc415

Affected packages:

  • @fluidframework/register-collection

⬆️ Table of contents

🛠️ Start Building Today!

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