From b355165484935be32bb129cdcc46532dcd196882 Mon Sep 17 00:00:00 2001 From: Tyler Butler Date: Tue, 27 May 2025 10:15:04 -0700 Subject: [PATCH 1/5] build(client): Update changesets for clarity and concision --- .changeset/afraid-rice-feel.md | 4 ++-- .changeset/gentle-eggs-heal.md | 4 ++-- .changeset/old-bees-itch.md | 2 +- .changeset/public-houses-add.md | 4 +++- .changeset/public-snakes-fetch.md | 2 +- .changeset/tabaxi-fellas-inspire.md | 2 +- .changeset/tough-parts-kick.md | 5 +++-- .changeset/tricky-shrimps-hunt.md | 14 +++++++++++++- 8 files changed, 26 insertions(+), 11 deletions(-) diff --git a/.changeset/afraid-rice-feel.md b/.changeset/afraid-rice-feel.md index 63ca8bc3ad60..e30f21219f3f 100644 --- a/.changeset/afraid-rice-feel.md +++ b/.changeset/afraid-rice-feel.md @@ -6,7 +6,7 @@ TreeAlpha.create now accepts unhydrated nodes [TreeAlpha.create](https://fluidframework.com/docs/api/fluid-framework/treealpha-interface#create-methodsignature) now accepts [unhydrated](https://fluidframework.com/docs/api/fluid-framework/unhydrated-typealias) nodes. -`TreeAlpha.create`'s documentation has been fixed to indicate support instead of being self contradictory about it. +`TreeAlpha.create`'s documentation has been updated to clarify that this is supported. Additionally `TreeAlpha.create` no longer throws a "Tree does not conform to schema" error when given a tree omitting an identifier. -Instead the identifier behaves like it would for other ways to build unhydrated nodes: remaining unreadable until hydrated. +Instead, the identifier behaves like it would for other ways to build unhydrated nodes: remaining unreadable until hydrated. diff --git a/.changeset/gentle-eggs-heal.md b/.changeset/gentle-eggs-heal.md index f3f3c317f0b1..a5b9dbe507fe 100644 --- a/.changeset/gentle-eggs-heal.md +++ b/.changeset/gentle-eggs-heal.md @@ -2,7 +2,7 @@ "@fluid-experimental/tree-react-api": minor "__section": feature --- -New experimental objectIdNumber API has been added +New experimental objectIdNumber API -A new `objectIdNumber` has been added, which is handy when an identifier is needed which corresponds to an object identity. +A new `objectIdNumber` has been added, which is useful you need an identifier which corresponds to an object identity. For example: when specifying a React "key" that corresponds to a `TreeNode`. diff --git a/.changeset/old-bees-itch.md b/.changeset/old-bees-itch.md index ad5045dd1778..728948ff0e4d 100644 --- a/.changeset/old-bees-itch.md +++ b/.changeset/old-bees-itch.md @@ -3,7 +3,7 @@ "@fluidframework/tree": minor "__section": tree --- -comparePersistedSchema (alpha) has had its canInitialize parameter removed +The comparePersistedSchema function (alpha) has had its canInitialize parameter removed [comparePersistedSchema](https://fluidframework.com/docs/api/tree/#comparepersistedschema-function) has had its `canInitialize` parameter removed. This parameter was only used to add to the output [SchemaCompatibilityStatus](https://fluidframework.com/docs/api/fluid-framework/schemacompatibilitystatus-interface). diff --git a/.changeset/public-houses-add.md b/.changeset/public-houses-add.md index 71ee6eae7849..99368da7fcd9 100644 --- a/.changeset/public-houses-add.md +++ b/.changeset/public-houses-add.md @@ -4,4 +4,6 @@ --- "getPresence(container: IFluidContainer): Presence" now supported -`getPresence` is now supported and may be used to directly acquire `Presence` instead of using `ExperimentalPresenceManager` in container schema and calling `getPresenceViaDataObject`. (Both of those are now deprecated.) +You can now use the `getPresence` function to directly acquire `Presence`. In previous releases, you were required to +use `ExperimentalPresenceManager` in container schema and calling `getPresenceViaDataObject`, but that is no longer +required. Both `ExperimentalPresenceManager` and `getPresenceViaDataObject` are now deprecated. diff --git a/.changeset/public-snakes-fetch.md b/.changeset/public-snakes-fetch.md index 748e3025c10f..5240268d30b4 100644 --- a/.changeset/public-snakes-fetch.md +++ b/.changeset/public-snakes-fetch.md @@ -6,7 +6,7 @@ TreeNodes now implicitly generate identifiers on access instead of throwing Accessing a defaulted [identifier](https://fluidframework.com/docs/api/fluid-framework/schemafactory-class#identifier-property) on an [Unhydrated](https://fluidframework.com/docs/api/fluid-framework/unhydrated-typealias) `TreeNode` no longer throws a usage error. -Instead a new UUID is allocated for the identifier and returned. +Instead, a new UUID is allocated for the identifier and returned. These UUIDs will be more compressible than random ones, since they all come from a single sequence (starting with a random UUID). They will not be fully compressed like the identifiers generated after hydration that leverage the document's [IIdCompressor](https://fluidframework.com/docs/api/id-compressor/iidcompressor-interface). diff --git a/.changeset/tabaxi-fellas-inspire.md b/.changeset/tabaxi-fellas-inspire.md index b225bc14b8ec..9e48394aca84 100644 --- a/.changeset/tabaxi-fellas-inspire.md +++ b/.changeset/tabaxi-fellas-inspire.md @@ -3,7 +3,7 @@ "@fluidframework/tree": minor "__section": tree --- -TableSchema (alpha) APIs have been added +New TableSchema (alpha) APIs A `TableSchema` utility has been added to Shared Tree for managing dynamic, tabular data. This new `TableSchema` namespace contains APIs for creating column, row, and table [node schema](https://fluidframework.com/docs/api/fluid-framework/treenodeschema-typealias). diff --git a/.changeset/tough-parts-kick.md b/.changeset/tough-parts-kick.md index 3262eb98ee85..19be9103a3ba 100644 --- a/.changeset/tough-parts-kick.md +++ b/.changeset/tough-parts-kick.md @@ -2,6 +2,7 @@ "@fluidframework/tree": minor "__section": feature --- -TreeAlpha.key2 API added +New TreeAlpha.key2 API -The `TreeAlpha.key2` method is meant to eventually replace the public `Tree.key` method. This new method now returns undefined in the case where there is a root node. +The `TreeAlpha.key2` method is meant to eventually replace the public `Tree.key` method. +This new method returns `undefined` in the case where there is a root node. diff --git a/.changeset/tricky-shrimps-hunt.md b/.changeset/tricky-shrimps-hunt.md index ca9bf7989e0c..abcc7a8d07cd 100644 --- a/.changeset/tricky-shrimps-hunt.md +++ b/.changeset/tricky-shrimps-hunt.md @@ -3,9 +3,10 @@ "@fluidframework/tree": minor "__section": feature --- -TreeAlpha identifier APIs for converting, retrieving, and generating identifiers have been added +New TreeAlpha identifier APIs for converting, retrieving, and generating identifiers #### TreeAlpha.identifier + You can retrieve the long identifier with `TreeAlpha.identifier(node)`, where `node` is a `TreeNode`. The long identifier is a stable, compressible UUID generated by the tree. In cases where the node does not yet have an identifier assigned, this will return `undefined`. These cases include: @@ -13,45 +14,56 @@ These cases include: - The node is a non-hydrated node with a user provided identifier. Note that if it is a non-hydrated node without an identifier provided, it will throw an error. #### TreeAlpha.identifier.shorten + You can shorten a long identifier with `TreeAlpha.identifier.shorten(branch, identifier)`, where `branch` is a `TreeBranch`, and `identifier` is a `string`. If the method returns a valid short identifier, this identifier can be passed into `TreeAlpha.identifier.lengthen` to get the original valid long `identifier` back. In the cases where it's not possible to shorten the `identifier`, it will return `undefined`. These cases include: + - A compressible long identifier, but it is unrecognized by the tree that the node belongs to. This can occur if the identifier is not generated from the tree. - An identifier which is not compressible by the tree. This can occur if the node's identifier was a user provided string. #### TreeAlpha.identifier.lengthen + You can lengthen a short identifier with `TreeAlpha.identifier.lengthen(branch, identifier)`, where `branch` is a `TreeBranch`, and `identifier` is a `number`. If the method returns a valid long identifier, this identifier can be passed into `TreeAlpha.identifier.shorten` to get the original `identifier` back. In the cases where it's not possible to lengthen the `identifier`, this method will throw an error. These cases include: + - An unrecognized short identifier. This can occur if the identifier is not generated from the tree. #### TreeAlpha.identifier.getShort + You can retrieve the short identifier from a node with `TreeAlpha.identifier.getShort(node)` where `node` is a `TreeNode`. If it is not possible to retrieve the short identifier, it will return `undefined` ##### Example for a node with valid identifier + ```typescript // This will retrieve the short identifier from the node. const shortIdentifier = TreeAlpha.identifier.getShort(nodeWithValidIdentifier) ``` ##### Examples for when you get undefined + In cases where the node provided does not contain an identifier that is recognized or compressible by the tree that the node belongs to, this method will return undefined. This will occur in the following cases: + - The node is an non-hydrated node with a user provided identifier. Note that if it is an non-hydrated node without an identifier provided, it will throw an error. - The node does not contain an identifier field. - The node contains a compressible long identifier, but it is unrecognized by the tree that the node belongs to. This can occur if the identifier is not generated from the tree. - The node contains an identifier which is not compressible by its id compressor. This can occur if the node's identifier was a user provided string. + ```typescript // This will return undefined const shortIdentifier = TreeAlpha.identifier.getShort(node) ``` #### TreeAlpha.identifier.create + You can create a long identifier from a branch with `TreeAlpha.identifier.create(branch)` where `branch` is a `TreeBranch`. + ```typescript const createdIdentifier = TreeAlpha.identifier.create(branch) ``` From bc1139bed4c792d3d5222e1e21e6480e1eda66ca Mon Sep 17 00:00:00 2001 From: Tyler Butler Date: Tue, 27 May 2025 10:23:23 -0700 Subject: [PATCH 2/5] build(client): Add release notes for 2.41.0 --- RELEASE_NOTES/2.41.0.md | 443 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 443 insertions(+) create mode 100644 RELEASE_NOTES/2.41.0.md diff --git a/RELEASE_NOTES/2.41.0.md b/RELEASE_NOTES/2.41.0.md new file mode 100644 index 000000000000..f734e3ee81e2 --- /dev/null +++ b/RELEASE_NOTES/2.41.0.md @@ -0,0 +1,443 @@ + + +# Fluid Framework v2.41.0 + +## Contents + +- [✨ New Features](#-new-features) + - [New experimental objectIdNumber API (#21115)](#new-experimental-objectidnumber-api-21115) + - [New TreeAlpha.key2 API (#24623)](#new-treealphakey2-api-24623) + - [New TreeAlpha identifier APIs for converting, retrieving, and generating identifiers (#24218)](#new-treealpha-identifier-apis-for-converting-retrieving-and-generating-identifiers-24218) + - ["getPresence(container: IFluidContainer): Presence" now supported (#24399)](#getpresencecontainer-ifluidcontainer-presence-now-supported-24399) +- [🌳 SharedTree DDS Changes](#-sharedtree-dds-changes) + - [The comparePersistedSchema function (alpha) has had its canInitialize parameter removed (#24606)](#the-comparepersistedschema-function-alpha-has-had-its-caninitialize-parameter-removed-24606) + - [TreeAlpha.create now accepts unhydrated nodes (#24629)](#treealphacreate-now-accepts-unhydrated-nodes-24629) + - [New TableSchema (alpha) APIs (#24579)](#new-tableschema-alpha-apis-24579) + - [SharedTrees's FluidClientVersion enum (alpha) has been redesigned (#24638)](#sharedtreess-fluidclientversion-enum-alpha-has-been-redesigned-24638) + - [ForestTypeExpensiveDebug now validates content against schema (#24658)](#foresttypeexpensivedebug-now-validates-content-against-schema-24658) + - [TreeNodes now implicitly generate identifiers on access instead of throwing (#24665)](#treenodes-now-implicitly-generate-identifiers-on-access-instead-of-throwing-24665) + +## ✨ New Features + +### New experimental objectIdNumber API ([#21115](https://github.com/microsoft/FluidFramework/issues/21115)) + +A new `objectIdNumber` has been added, which is useful you need an identifier which corresponds to an object identity. For example: when specifying a React "key" that corresponds to a `TreeNode`. + +#### Change details + +Commit: [`df2f139`](https://github.com/microsoft/FluidFramework/commit/df2f139be8e8145d5eea313814cd6d35018cacee) + +Affected packages: + +- @fluid-experimental/tree-react-api + +[⬆️ Table of contents](#contents) + +### New TreeAlpha.key2 API ([#24623](https://github.com/microsoft/FluidFramework/issues/24623)) + +The `TreeAlpha.key2` method is meant to eventually replace the public `Tree.key` method. This new method returns `undefined` in the case where there is a root node. + +#### Change details + +Commit: [`0ddd6b0`](https://github.com/microsoft/FluidFramework/commit/0ddd6b030bf21ef2f315b84e428954ecfe951728) + +Affected packages: + +- @fluidframework/tree + +[⬆️ Table of contents](#contents) + +### New TreeAlpha identifier APIs for converting, retrieving, and generating identifiers ([#24218](https://github.com/microsoft/FluidFramework/issues/24218)) + +#### TreeAlpha.identifier + +You can retrieve the long identifier with `TreeAlpha.identifier(node)`, where `node` is a `TreeNode`. The long identifier is a stable, compressible UUID generated by the tree. In cases where the node does not yet have an identifier assigned, this will return `undefined`. These cases include: + +- The node does not contain an identifier field. +- The node is a non-hydrated node with a user provided identifier. Note that if it is a non-hydrated node without an identifier provided, it will throw an error. + +#### TreeAlpha.identifier.shorten + +You can shorten a long identifier with `TreeAlpha.identifier.shorten(branch, identifier)`, where `branch` is a `TreeBranch`, and `identifier` is a `string`. If the method returns a valid short identifier, this identifier can be passed into `TreeAlpha.identifier.lengthen` to get the original valid long `identifier` back. In the cases where it's not possible to shorten the `identifier`, it will return `undefined`. These cases include: + +- A compressible long identifier, but it is unrecognized by the tree that the node belongs to. This can occur if the identifier is not generated from the tree. +- An identifier which is not compressible by the tree. This can occur if the node's identifier was a user provided string. + +#### TreeAlpha.identifier.lengthen + +You can lengthen a short identifier with `TreeAlpha.identifier.lengthen(branch, identifier)`, where `branch` is a `TreeBranch`, and `identifier` is a `number`. If the method returns a valid long identifier, this identifier can be passed into `TreeAlpha.identifier.shorten` to get the original `identifier` back. In the cases where it's not possible to lengthen the `identifier`, this method will throw an error. These cases include: + +- An unrecognized short identifier. This can occur if the identifier is not generated from the tree. + +#### TreeAlpha.identifier.getShort + +You can retrieve the short identifier from a node with `TreeAlpha.identifier.getShort(node)` where `node` is a `TreeNode`. If it is not possible to retrieve the short identifier, it will return `undefined` + +##### Example for a node with valid identifier + +```typescript +// This will retrieve the short identifier from the node. +const shortIdentifier = TreeAlpha.identifier.getShort(nodeWithValidIdentifier); +``` + +##### Examples for when you get undefined + +In cases where the node provided does not contain an identifier that is recognized or compressible by the tree that the node belongs to, this method will return undefined. This will occur in the following cases: + +- The node is an non-hydrated node with a user provided identifier. Note that if it is an non-hydrated node without an identifier provided, it will throw an error. +- The node does not contain an identifier field. +- The node contains a compressible long identifier, but it is unrecognized by the tree that the node belongs to. This can occur if the identifier is not generated from the tree. +- The node contains an identifier which is not compressible by its id compressor. This can occur if the node's identifier was a user provided string. + +```typescript +// This will return undefined +const shortIdentifier = TreeAlpha.identifier.getShort(node); +``` + +#### TreeAlpha.identifier.create + +You can create a long identifier from a branch with `TreeAlpha.identifier.create(branch)` where `branch` is a `TreeBranch`. + +```typescript +const createdIdentifier = TreeAlpha.identifier.create(branch); +``` + +#### Change details + +Commit: [`e5b2882`](https://github.com/microsoft/FluidFramework/commit/e5b28821323566112096f05805281b8d5321077d) + +Affected packages: + +- fluid-framework +- @fluidframework/tree + +[⬆️ Table of contents](#contents) + +### "getPresence(container: IFluidContainer): Presence" now supported ([#24399](https://github.com/microsoft/FluidFramework/issues/24399)) + +You can now use the `getPresence` function to directly acquire `Presence`. In previous releases, you were required to use `ExperimentalPresenceManager` in container schema and calling `getPresenceViaDataObject`, but that is no longer required. Both `ExperimentalPresenceManager` and `getPresenceViaDataObject` are now deprecated. + +#### Change details + +Commit: [`5c6824a`](https://github.com/microsoft/FluidFramework/commit/5c6824a48da7dad6cb5911e6b1af02dfaf6382e1) + +Affected packages: + +- @fluidframework/presence + +[⬆️ Table of contents](#contents) + +## 🌳 SharedTree DDS Changes + +### The comparePersistedSchema function (alpha) has had its canInitialize parameter removed ([#24606](https://github.com/microsoft/FluidFramework/issues/24606)) + +[comparePersistedSchema](https://fluidframework.com/docs/api/tree/#comparepersistedschema-function) has had its `canInitialize` parameter removed. This parameter was only used to add to the output [SchemaCompatibilityStatus](https://fluidframework.com/docs/api/fluid-framework/schemacompatibilitystatus-interface). If a full `SchemaCompatibilityStatus` is still desired, the `canInitialize` value can be added to the result: + +```typescript +// old +const result = comparePersistedSchema(a, b, canInitialize); +// new +const result = { ...comparePersistedSchema(a, b), canInitialize }; +``` + +#### Change details + +Commit: [`d083a17`](https://github.com/microsoft/FluidFramework/commit/d083a1780a1db74a922cbfb451d23ab932c0eb32) + +Affected packages: + +- fluid-framework +- @fluidframework/tree + +[⬆️ Table of contents](#contents) + +### TreeAlpha.create now accepts unhydrated nodes ([#24629](https://github.com/microsoft/FluidFramework/issues/24629)) + +[TreeAlpha.create](https://fluidframework.com/docs/api/fluid-framework/treealpha-interface#create-methodsignature) now accepts [unhydrated](https://fluidframework.com/docs/api/fluid-framework/unhydrated-typealias) nodes. `TreeAlpha.create`'s documentation has been updated to clarify that this is supported. + +Additionally `TreeAlpha.create` no longer throws a "Tree does not conform to schema" error when given a tree omitting an identifier. Instead, the identifier behaves like it would for other ways to build unhydrated nodes: remaining unreadable until hydrated. + +#### Change details + +Commit: [`e63af87`](https://github.com/microsoft/FluidFramework/commit/e63af87aeb7ece1ff0969027904c3b18f122d2d1) + +Affected packages: + +- @fluidframework/tree +- fluid-framework + +[⬆️ Table of contents](#contents) + +### New TableSchema (alpha) APIs ([#24579](https://github.com/microsoft/FluidFramework/issues/24579)) + +A `TableSchema` utility has been added to Shared Tree for managing dynamic, tabular data. This new `TableSchema` namespace contains APIs for creating column, row, and table [node schema](https://fluidframework.com/docs/api/fluid-framework/treenodeschema-typealias). + +Note: these APIs require the use of [SchemaFactoryAlpha](https://fluidframework.com/docs/api/fluid-framework/schemafactoryalpha-class). + +> \[!WARNING] +> +> These APIs are in preview and are subject to change. Until these APIs have stabilized, it is not recommended to use them in production code. There may be breaking changes to these APIs and their underlying data format. Using these APIs in production code may result in data loss or corruption. + +#### Creating a table + +You can craft a table schema with `TableSchema.table`. This includes providing a schema for the cells that will appear in the table: + +```typescript +class MyTable extends TableSchema.table({ + schemaFactory, + cell: schemaFactory.string, +}) {} + +const table = new MyTable({ + columns: [{ id: "column-0" }], + rows: [{ id: "row-0", cells: { "column-0": "Hello world!" } }], +}); +``` + +#### Creating a table with custom column and row schema + +To associate additional data with your rows or columns, generate custom row and column schema using `TableSchema.column` and `TableSchema.row`. These schema can then be provided to `TableSchema.table`: + +```typescript +class MyColumn extends TableSchema.column({ + schemaFactory, + cell: Cell, + props: schemaFactory.object("TableColumnProps", { + label: schemaFactory.string, + }), +}) {} + +class MyRow extends TableSchema.row({ + schemaFactory, + cell: Cell, +}) {} + +class MyTable extends TableSchema.table({ + schemaFactory, + cell: Cell, + column: MyColumn, + row: MyRow, +}) {} + +const table = new MyTable({ + columns: [ + new MyColumn({ props: { label: "Entry" } }), + new MyColumn({ props: { label: "Date" } }), + new MyColumn({ props: { label: "Amount" } }), + ], + rows: [], +}); +``` + +#### Interacting with the table + +Table trees created using `TableSchema` offer various APIs to make working with tabular data easy. These include: + +- Insertion and removal of columns, rows, and cells. +- Cell access by column/row. + +```typescript +// Create an empty table +const table = MyTable.empty(); + +const column0 = new MyColumn({ + props: { label: "Column 0" }, +}); + +// Append a column to the end of the table. +table.insertColumn({ + column: column0, +}); + +const rows = [new MyRow({ cells: {} }), new MyRow({ cells: {} })]; + +// Insert rows at the beginning of the table. +table.insertRows({ + index: 0, + rows, +}); + +// Set cell at row 0, column 0. +table.setCell({ + key: { + column: column0, + row: rows[0], + }, + cell: "Hello", +}); + +// Set cell at row 1, column 0. +table.setCell({ + key: { + column: column0, + row: rows[1], + }, + cell: "World", +}); + +// Remove the first row. +// Note: this will also remove the row's cell. +table.removeRow(rows[0]); + +// Remove the column. +// Note: this will *not* remove the remaining cell under this column. +table.removeColumn(column0); +``` + +#### Listening for changes + +Listening for changes to table trees behaves just like it would for any other nodes in a Shared Tree (see [here](https://fluidframework.com/docs/data-structures/tree/events) for more details). + +The most straightforward option is to listen for any changes to the table node and its descendants. For example: + +```typescript +class Cell extends schemaFactory.object("TableCell", { + value: schemaFactory.string, +}) {} + +class Table extends TableSchema.table({ + schemaFactory, + cell: Cell, +}) {} + +const table = new Table({ + columns: [{ id: "column-0" }], + rows: [{ id: "row-0", cells: {} }], +}); + +// Listen for any changes to the table and its children. +// The "treeChanged" event will fire when the `table` node or any of its descendants change. +Tree.on(table, "treeChanged", () => { + // Respond to the change. +}); +``` + +If you need more granular eventing to meet your performance needs, that is possible as well. For example, if you wish to know when the table's list of rows changes, you could do the following: + +```typescript +class Cell extends schemaFactory.object("TableCell", { + value: schemaFactory.string, +}) {} + +class Table extends TableSchema.table({ + schemaFactory, + cell: Cell, +}) {} + +const table = new Table({ + columns: [{ id: "column-0" }], + rows: [{ id: "row-0", cells: {} }], +}); + +// Listen for any changes to the list of rows. +// The "nodeChanged" event will fire only when the `rows` node itself changes (i.e., its own properties change). +// In this case, the event will fire when a row is added or removed, or the order of the list is changed. +// But it won't fire when a row's properties change, or when the row's cells change, etc. +Tree.on(table.rows, "nodeChanged", () => { + // Respond to the change. +}); +``` + +#### Limitations + +##### Orphaned cells + +Cells in the table may become "orphaned." That is, it is possible to enter a state where one or more rows contain cells with no corresponding column. To reduce the likelihood of this, you can manually remove corresponding cells when removing columns. + +For example: + +```typescript +// Remove column1 and all of its cells. +// The "transaction" method will ensure that all changes are applied atomically. +Tree.runTransaction(table, () => { + // Remove column1 + table.removeColumn(column1); + + // Remove the cell at column1 for each row. + for (const row of table.rows) { + table.removeCell({ + column: column1, + row, + }); + } +}); +``` + +> \[!WARNING] +> +> Note that even with the above precaution, it is possible to enter such an orphaned cell state via the merging of edits. For example: one client might add a row while another concurrently removes a column, orphaning the cell where the column and row intersected. + +#### Change details + +Commit: [`e565f68`](https://github.com/microsoft/FluidFramework/commit/e565f6838b31d3e777da942c806606575123f6d6) + +Affected packages: + +- fluid-framework +- @fluidframework/tree + +[⬆️ Table of contents](#contents) + +### SharedTrees's FluidClientVersion enum (alpha) has been redesigned ([#24638](https://github.com/microsoft/FluidFramework/issues/24638)) + +Users of [FluidClientVersion](https://fluidframework.com/docs/api/fluid-framework/fluidclientversion-enum)'s `v2_1`, `v2_2`, and `v2_3` entries should specify `v2_0` instead. This will result in no functional differences since no code currently opts into any additional functionality based on specifying those versions. The new approach avoids listing versions which there is currently no reason to select, and thus these options have been removed. If future work adds support to opt into features which only work starting with some of those versions, they will be re-added at that time. + +#### Change details + +Commit: [`5f3b9d7`](https://github.com/microsoft/FluidFramework/commit/5f3b9d7b7d12307d89cbd4b88f5e2d6e1833680d) + +Affected packages: + +- fluid-framework +- @fluidframework/tree + +[⬆️ Table of contents](#contents) + +### ForestTypeExpensiveDebug now validates content against schema ([#24658](https://github.com/microsoft/FluidFramework/issues/24658)) + +When opting into using [ForestTypeExpensiveDebug](https://fluidframework.com/docs/api/fluid-framework/#foresttypeexpensivedebug-variable) using [configuredSharedTree](https://fluidframework.com/docs/api/fluid-framework/#configuredsharedtree-function), the tree is now checked against the schema on load and after every edit. This should help detect and diagnose document corruption bugs. + +```typescript +const DebugSharedTree = configuredSharedTree({ + jsonValidator: typeboxValidator, + // Now detects corrupted documents which are out of schema. + forest: ForestTypeExpensiveDebug, +}); +``` + +#### Change details + +Commit: [`9d600aa`](https://github.com/microsoft/FluidFramework/commit/9d600aae88b9045392067719638258ea7407c2eb) + +Affected packages: + +- @fluidframework/tree +- fluid-framework + +[⬆️ Table of contents](#contents) + +### TreeNodes now implicitly generate identifiers on access instead of throwing ([#24665](https://github.com/microsoft/FluidFramework/issues/24665)) + +Accessing a defaulted [identifier](https://fluidframework.com/docs/api/fluid-framework/schemafactory-class#identifier-property) on an [Unhydrated](https://fluidframework.com/docs/api/fluid-framework/unhydrated-typealias) `TreeNode` no longer throws a usage error. Instead, a new UUID is allocated for the identifier and returned. These UUIDs will be more compressible than random ones, since they all come from a single sequence (starting with a random UUID). They will not be fully compressed like the identifiers generated after hydration that leverage the document's [IIdCompressor](https://fluidframework.com/docs/api/id-compressor/iidcompressor-interface). + +```typescript +const factory = new SchemaFactory("test"); +class HasIdentifier extends schema.object("A", { id: factory.identifier }) {} +// This used to throw an error: +const id = new HasIdentifier({}).id; +``` + +#### Change details + +Commit: [`cd5976b`](https://github.com/microsoft/FluidFramework/commit/cd5976b959d6b7a5259e3bb9ef816f842724bc6e) + +Affected packages: + +- @fluidframework/tree +- fluid-framework + +[⬆️ Table of contents](#contents) + +### 🛠️ Start Building Today! + +Please continue to engage with us on GitHub [Discussion](https://github.com/microsoft/FluidFramework/discussions) and [Issue](https://github.com/microsoft/FluidFramework/issues) pages as you adopt Fluid Framework! From 37c32da6fd98320827974cd81515e6f96138d585 Mon Sep 17 00:00:00 2001 From: Tyler Butler Date: Tue, 27 May 2025 11:14:28 -0700 Subject: [PATCH 3/5] updates --- RELEASE_NOTES/2.41.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE_NOTES/2.41.0.md b/RELEASE_NOTES/2.41.0.md index f734e3ee81e2..cffa34124f04 100644 --- a/RELEASE_NOTES/2.41.0.md +++ b/RELEASE_NOTES/2.41.0.md @@ -21,7 +21,7 @@ ### New experimental objectIdNumber API ([#21115](https://github.com/microsoft/FluidFramework/issues/21115)) -A new `objectIdNumber` has been added, which is useful you need an identifier which corresponds to an object identity. For example: when specifying a React "key" that corresponds to a `TreeNode`. +A new `objectIdNumber` has been added, which is useful when you need an identifier which corresponds to an object identity. For example: when specifying a React "key" that corresponds to a `TreeNode`. #### Change details From 8cab405ed14c8c9dc7b8ec976e46c78154ae189e Mon Sep 17 00:00:00 2001 From: Tyler Butler Date: Tue, 27 May 2025 12:57:01 -0700 Subject: [PATCH 4/5] changeset --- .changeset/fluffy-donkeys-obey.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/fluffy-donkeys-obey.md b/.changeset/fluffy-donkeys-obey.md index c62a15738723..ae52f6dd864a 100644 --- a/.changeset/fluffy-donkeys-obey.md +++ b/.changeset/fluffy-donkeys-obey.md @@ -4,6 +4,6 @@ --- Presence now available at beta support -Importing via `@fluidframework/presence/beta` is now supported. +[Presence APIs](https://fluidframework.com/docs/build/presence) are now beta and can be imported via `@fluidframework/presence/beta`. -Note: `Notifications` support remains only supported via `/alpha` imports. Cast `Presence` to `PresenceWithNotifications` to access notifications only workspace support. +Note: `Notifications` are only supported via `/alpha` imports. To access notifications-only workspace support, cast `Presence` to `PresenceWithNotifications`. From c99d20a8b46daa845331cda4c9334b7634cc3e16 Mon Sep 17 00:00:00 2001 From: Tyler Butler Date: Tue, 27 May 2025 12:59:23 -0700 Subject: [PATCH 5/5] updates --- .changeset/fluffy-donkeys-obey.md | 3 ++- RELEASE_NOTES/2.41.0.md | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/.changeset/fluffy-donkeys-obey.md b/.changeset/fluffy-donkeys-obey.md index ae52f6dd864a..d3a9eb0f2199 100644 --- a/.changeset/fluffy-donkeys-obey.md +++ b/.changeset/fluffy-donkeys-obey.md @@ -1,8 +1,9 @@ --- "@fluidframework/presence": minor "__section": feature +__highlight: true --- -Presence now available at beta support +Presence APIs promoted to beta [Presence APIs](https://fluidframework.com/docs/build/presence) are now beta and can be imported via `@fluidframework/presence/beta`. diff --git a/RELEASE_NOTES/2.41.0.md b/RELEASE_NOTES/2.41.0.md index cffa34124f04..e4ad5cff10b5 100644 --- a/RELEASE_NOTES/2.41.0.md +++ b/RELEASE_NOTES/2.41.0.md @@ -5,6 +5,7 @@ ## Contents - [✨ New Features](#-new-features) + - [Presence APIs promoted to beta (#24710)](#presence-apis-promoted-to-beta-24710) - [New experimental objectIdNumber API (#21115)](#new-experimental-objectidnumber-api-21115) - [New TreeAlpha.key2 API (#24623)](#new-treealphakey2-api-24623) - [New TreeAlpha identifier APIs for converting, retrieving, and generating identifiers (#24218)](#new-treealpha-identifier-apis-for-converting-retrieving-and-generating-identifiers-24218) @@ -19,6 +20,22 @@ ## ✨ New Features +### Presence APIs promoted to beta ([#24710](https://github.com/microsoft/FluidFramework/issues/24710)) + +[Presence APIs](https://fluidframework.com/docs/build/presence) are now beta and can be imported via `@fluidframework/presence/beta`. + +Note: `Notifications` are only supported via `/alpha` imports. To access notifications-only workspace support, cast `Presence` to `PresenceWithNotifications`. + +#### Change details + +Commit: [`6fce410`](https://github.com/microsoft/FluidFramework/commit/6fce4100ca8a3fce8cf69f0ac25d709a3a64d13e) + +Affected packages: + +- @fluidframework/presence + +[⬆️ Table of contents](#contents) + ### New experimental objectIdNumber API ([#21115](https://github.com/microsoft/FluidFramework/issues/21115)) A new `objectIdNumber` has been added, which is useful when you need an identifier which corresponds to an object identity. For example: when specifying a React "key" that corresponds to a `TreeNode`.