fluid-framework 2.23.0 → 2.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1311 -1158
- package/api-extractor/api-extractor.current.json +0 -3
- package/api-report/fluid-framework.alpha.api.md +264 -100
- package/api-report/fluid-framework.beta.api.md +83 -58
- package/api-report/fluid-framework.legacy.alpha.api.md +141 -61
- package/api-report/fluid-framework.legacy.public.api.md +83 -58
- package/api-report/fluid-framework.public.api.md +83 -58
- package/dist/alpha.d.ts +33 -1
- package/dist/beta.d.ts +5 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -9
- package/dist/index.js.map +1 -1
- package/dist/legacy.d.ts +8 -1
- package/dist/public.d.ts +5 -1
- package/lib/alpha.d.ts +33 -1
- package/lib/beta.d.ts +5 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/legacy.d.ts +8 -1
- package/lib/public.d.ts +5 -1
- package/lib/tsdoc-metadata.json +1 -1
- package/package.json +13 -15
- package/src/index.ts +5 -0
- package/prettier.config.cjs +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,1534 +1,1687 @@
|
|
|
1
1
|
# fluid-framework
|
|
2
2
|
|
|
3
|
-
## 2.
|
|
3
|
+
## 2.31.0
|
|
4
4
|
|
|
5
5
|
### Minor Changes
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
SharedTree sometimes composes several sequential changes into a single change.
|
|
10
|
-
It does so whenever a transaction is created and when processing inbound changes.
|
|
11
|
-
|
|
12
|
-
Version 2.23.0 makes this composition process asymptotically faster.
|
|
13
|
-
For example, creating a transaction that performs 1000 edits on a single array now takes 170ms instead of 1.5s (an 89% improvement).
|
|
7
|
+
- Better type errors for invalid recursive schema ([#24080](https://github.com/microsoft/FluidFramework/pull/24080)) [8ae8d2cb05](https://github.com/microsoft/FluidFramework/commit/8ae8d2cb05f7ce765f1d1997135e72a1ea1e00fb)
|
|
14
8
|
|
|
15
|
-
|
|
9
|
+
Constraints have been added to `*Recursive` [`SchemaFactory`](https://fluidframework.com/docs/api/fluid-framework/schemafactory-class) methods to ensure correct use without relying on [`ValidateRecursiveSchema`](https://fluidframework.com/docs/api/fluid-framework/validaterecursiveschema-typealias) as much.
|
|
16
10
|
|
|
17
|
-
-
|
|
11
|
+
- Improved type checking for recursive object schema Fields ([#24113](https://github.com/microsoft/FluidFramework/pull/24113)) [5b656f5cb0](https://github.com/microsoft/FluidFramework/commit/5b656f5cb0707c149aa4537017f71052f10467ee)
|
|
18
12
|
|
|
19
|
-
|
|
20
|
-
processing a batch of changes.
|
|
13
|
+
Most ways to provide incorrectly typed data for fields of [recursive object schema](https://fluidframework.com/docs/api/fluid-framework/schemafactory-class#objectrecursive-method) now produce simpler type errors without relying on [ValidateRecursiveSchema](https://fluidframework.com/docs/api/fluid-framework/validaterecursiveschema-typealias).
|
|
21
14
|
|
|
22
|
-
|
|
23
|
-
[#23908](https://github.com/microsoft/FluidFramework/pull/23908) for more details.
|
|
15
|
+
As a side effect of this work, some schema which violated the documented allowed patterns specified by [SchemaFactory](https://fluidframework.com/docs/api/fluid-framework/schemafactory-class#schemafactory-remarks) but used to work (as long as they were not package exported) no longer compile.
|
|
24
16
|
|
|
25
|
-
|
|
17
|
+
The specific case known to break is when:
|
|
26
18
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
1. An Object node schema is co-recursive with an Array node schema.
|
|
20
|
+
2. The Array does not declare a named subclass.
|
|
21
|
+
3. The schema reference from the Object to the Array is not using the [lazy syntax](https://fluidframework.com/docs/api/fluid-framework/lazyitem-typealias).
|
|
30
22
|
|
|
31
|
-
|
|
23
|
+
For example:
|
|
32
24
|
|
|
33
|
-
|
|
25
|
+
```typescript
|
|
26
|
+
class Foo extends sf.objectRecursive("Foo", {
|
|
27
|
+
fooList: sf.arrayRecursive("FooList", [() => Foo]), // Bad
|
|
28
|
+
}) {}
|
|
29
|
+
{
|
|
30
|
+
type _check = ValidateRecursiveSchema<typeof Foo>;
|
|
31
|
+
}
|
|
32
|
+
```
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
Such a schema is disallowed according to the documentation. See the
|
|
35
|
+
["recursive schema must explicitly declare a named class"](<(https://fluidframework.com/docs/api/fluid-framework/schemafactory-class#schemafactory-remarks)>) remarks.
|
|
36
|
+
This restriction is necessary to avoid [generated `.d.ts` files replacing recursive references with `any`](https://github.com/microsoft/TypeScript/issues/55832).
|
|
37
|
+
Fixing this code is now also necessary to avoid a compile error.
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
```typescript
|
|
40
|
+
// Fixed
|
|
41
|
+
class FooList extends sf.arrayRecursive("FooList", [() => Foo]) {}
|
|
42
|
+
{
|
|
43
|
+
type _check = ValidateRecursiveSchema<typeof FooList>;
|
|
44
|
+
}
|
|
45
|
+
class Foo extends sf.objectRecursive("Foo", {
|
|
46
|
+
fooList: FooList,
|
|
47
|
+
}) {}
|
|
48
|
+
{
|
|
49
|
+
type _check = ValidateRecursiveSchema<typeof Foo>;
|
|
50
|
+
}
|
|
51
|
+
```
|
|
40
52
|
|
|
41
|
-
|
|
42
|
-
One place where it was easy to accidentally violate this rule and get hard-to-debug results was [`Tree.is`](https://fluidframework.com/docs/data-structures/tree/nodes#treeis).
|
|
43
|
-
This has been mitigated by adding a check in `Tree.is` which detects this mistake (which used to result in `false` being returned) and instead throws a `UsageError` explaining the situation.
|
|
44
|
-
The error will look something like:
|
|
53
|
+
This change will also result in much nicer IntelliSense and type errors while fixing the typing if the schema is exported.
|
|
45
54
|
|
|
46
|
-
|
|
55
|
+
There are still several cases which compile but violate this policy regarding recursive schema and can cause issues when exporting schema;
|
|
56
|
+
these should be migrated to the above pattern as well.
|
|
57
|
+
It is still valid to use non-recursive structurally named array and map schema inline; this change does not impact them.
|
|
47
58
|
|
|
48
|
-
|
|
59
|
+
- Performance enhancements in SharedTree branch-related ops processing ([#24093](https://github.com/microsoft/FluidFramework/pull/24093)) [47b275bcf2](https://github.com/microsoft/FluidFramework/commit/47b275bcf2dd79696387f7c8f3e876d03b2813f8)
|
|
49
60
|
|
|
50
|
-
|
|
61
|
+
SharedTree leverages the "op bunching" feature where contiguous ops in a grouped batch are bunched and processed together
|
|
62
|
+
to asymptotically improve the performance of processing ops.
|
|
63
|
+
This performance enhancement focuses on the scenario where there are one or more commits in the trunk and one or more peer
|
|
64
|
+
commits are received in a bunch. With 1 trunk commits and 10 peer commits, the performance increases by 57%; with 100
|
|
65
|
+
trunk commits and 100 peer commits, the performance increases by 97%.
|
|
51
66
|
|
|
52
|
-
|
|
67
|
+
Some example scenarios where the performance will be improved:
|
|
53
68
|
|
|
54
|
-
-
|
|
69
|
+
- A client makes some local changes and another client simultaneously makes a large number of changes in a single JavaScript turn.
|
|
70
|
+
For example, a client is typing into a canvas while another client pastes a large amount of content into a table.
|
|
71
|
+
- A client makes a local branch with some changes and rebases it into the trunk. For example, an AI agent makes changes
|
|
72
|
+
on a local branch which are accepted by a user resulting in the AI's branch being merged into the trunk.
|
|
55
73
|
|
|
56
|
-
|
|
57
|
-
This may result in newer JavaScript language features being used.
|
|
58
|
-
This does not change TypeScript types, nor the JavaScript libraries being used.
|
|
59
|
-
We only support users which support ES2022, so updating to target ES2021 should not break any supported use-case.
|
|
60
|
-
Any users which do not have at least ES2021 language feature support may need to transpile out some additional cases after this change.
|
|
74
|
+
- `TreeAlpha.exportConcise` now supports `undefined` ([#24187](https://github.com/microsoft/FluidFramework/pull/24187)) [958b9fd8b9](https://github.com/microsoft/FluidFramework/commit/958b9fd8b9a2bd43558fe2a94dc55f8f51d47ea8)
|
|
61
75
|
|
|
62
|
-
|
|
63
|
-
|
|
76
|
+
There is a new overload for `TreeAlpha.exportConcise` which makes exporting optional fields easier.
|
|
77
|
+
This overload allows `undefined` and returns `undefined` in this case.
|
|
64
78
|
|
|
65
|
-
-
|
|
79
|
+
- Improvements to typing of object node schema ([#24143](https://github.com/microsoft/FluidFramework/pull/24143)) [02ecf8dfb2](https://github.com/microsoft/FluidFramework/commit/02ecf8dfb238dc4d1c88610cec34d7895802d28c)
|
|
66
80
|
|
|
67
|
-
|
|
81
|
+
Several tweaks to the typing of object node schema have been made to allow exposing an `@alpha` `ObjectNodeSchema` type.
|
|
68
82
|
|
|
69
|
-
|
|
83
|
+
[SchemaFactoryAlpha](https://fluidframework.com/docs/api/fluid-framework/schemafactoryalpha-class)'s `object` and `objectRecursive` now return schema which are compatible with the new `ObjectNodeSchema` type.
|
|
84
|
+
This new `ObjectNodeSchema` type exposes a `fields: ReadonlyMap<string, FieldSchemaAlpha & SimpleObjectFieldSchema>` property which provides an easy way to get information about the object's fields.
|
|
70
85
|
|
|
71
|
-
|
|
86
|
+
Additionally an alpha `ObjectNodeSchema` object is added to enable support for `schema instanceof ObjectNodeSchema` to safely narrow `TreeNodeSchema` to this new type.
|
|
72
87
|
|
|
73
|
-
|
|
88
|
+
In support of this work, several typing details were fixed including:
|
|
74
89
|
|
|
75
|
-
|
|
90
|
+
- `info` field of `[typeSchemaSymbol]` type brand on recursive object schema was specified to match non-recursive variants.
|
|
91
|
+
- Type of field metadata was correctly plumbed through `optionalReclusive` and `requiredRecursive`.
|
|
92
|
+
- When fields object provided to [SchemaFactory.object](https://fluidframework.com/docs/api/fluid-framework/schemafactory-class#object-method) is typed as `RestrictiveStringRecord<ImplicitFieldSchema>` the resulting [TreeObjectNode](https://fluidframework.com/docs/api/fluid-framework/treeobjectnode-typealias) no longer gets a `Record<string, TreeNode | TreeLeafValue>` signature which could incorrectly conflict with custom members added to the object. Instead `{}` is used to provide no information about felids on the type when the schema provides no information about them. Additionally this case is explicitly made non-constructable: the constructor takes in `never` instead of a `Record<string,never>` which could be erroneously satisfied with an empty object due to how TypeScript assignability rules consider records to have all allowed fields, but also allow objects missing those fields to be assigned to them.
|
|
76
93
|
|
|
77
|
-
|
|
94
|
+
Lastly, `metadata` on the various schema types has been made required instead of optional.
|
|
95
|
+
This does not impact the APIs for constructing schema: when `undefined` is provided the schema now defaults to `{}` instead of `undefined`.
|
|
96
|
+
This reduces the number of cases code reading metadata from schema has to handle.
|
|
78
97
|
|
|
79
|
-
## 2.
|
|
98
|
+
## 2.30.0
|
|
80
99
|
|
|
81
100
|
### Minor Changes
|
|
82
101
|
|
|
83
|
-
-
|
|
102
|
+
- New SchemaFactoryAlpha.scopedFactory method ([#23987](https://github.com/microsoft/FluidFramework/pull/23987)) [cddd5139c3](https://github.com/microsoft/FluidFramework/commit/cddd5139c3e070ef26db55331528435a99c0a1b1)
|
|
84
103
|
|
|
85
|
-
|
|
86
|
-
|
|
104
|
+
The [`SchemaFactoryAlpha.scopedFactory`](https://fluidframework.com/docs/api/fluid-framework/schemafactoryalpha-class)
|
|
105
|
+
method has been added, providing an easy way to create a new `SchemaFactory` with a nested scope string.
|
|
87
106
|
|
|
88
|
-
|
|
107
|
+
- TreeBranchEvents now exposes the rootChanged event ([#24014](https://github.com/microsoft/FluidFramework/pull/24014)) [702a08af83](https://github.com/microsoft/FluidFramework/commit/702a08af83206c21e1016ca47051052fa8554aa5)
|
|
89
108
|
|
|
90
|
-
|
|
91
|
-
const schemaFactory = new SchemaFactoryAlpha(...);
|
|
92
|
-
class Point extends schemaFactory.object("Point", {
|
|
93
|
-
x: schemaFactory.required(schemaFactory.number),
|
|
94
|
-
y: schemaFactory.required(schemaFactory.number),
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
metadata: {
|
|
98
|
-
description: "A point in 2D space",
|
|
99
|
-
},
|
|
100
|
-
}) {}
|
|
109
|
+
`TreeBranchEvents` now includes the `rootChanged` event from `TreeViewEvents`.
|
|
101
110
|
|
|
102
|
-
|
|
111
|
+
- Alpha APIs for replacing handles in export formats have been redesigned ([#24061](https://github.com/microsoft/FluidFramework/pull/24061)) [34b319cae7](https://github.com/microsoft/FluidFramework/commit/34b319cae7a78db5530dc898689e2eb846f1419f)
|
|
103
112
|
|
|
104
|
-
|
|
105
|
-
|
|
113
|
+
The various import and export [`VerboseTree`](https://fluidframework.com/docs/api/fluid-framework/verbosetree-typealias) and [`ConciseTree`](https://fluidframework.com/docs/api/fluid-framework/concisetree-typealias) APIs no longer include `valueConverter` options.
|
|
114
|
+
Instead the resulting tree can be further processed to do any desired replacements.
|
|
115
|
+
The following `@alpha` APIs have been added to assist with this:
|
|
106
116
|
|
|
107
|
-
|
|
108
|
-
|
|
117
|
+
1. `cloneWithReplacements`
|
|
118
|
+
2. `replaceHandles`
|
|
119
|
+
3. `replaceConciseTreeHandles`
|
|
120
|
+
4. `replaceVerboseTreeHandles`
|
|
109
121
|
|
|
110
|
-
|
|
122
|
+
- Rules regarding how and when lazy schema references are resolved have been clarified ([#24030](https://github.com/microsoft/FluidFramework/pull/24030)) [23f32794db](https://github.com/microsoft/FluidFramework/commit/23f32794dbd3672dcc18e2a9ba2f16f4bf1241f0)
|
|
111
123
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
- (new) `mapAlpha` - Variant of `map` that accepts an options parameter which supports `metadata`
|
|
124
|
+
A lazy schema reference is a [LazyItem](https://fluidframework.com/docs/api/fluid-framework/lazyitem-typealias) referencing a [TreeNodeSchema](https://fluidframework.com/docs/api/fluid-framework/treenodeschema-typealias).
|
|
125
|
+
They typically look like `() => MySchema` and are used when a [forward reference](https://en.wikipedia.org/wiki/Forward_declaration#Forward_reference) from one schema to another is required (including but not limited to recursive and co-recursive schema).
|
|
115
126
|
|
|
116
|
-
|
|
127
|
+
[TreeViewConfiguration](https://fluidframework.com/docs/api/fluid-framework/treeviewconfiguration-class#_constructor_-constructor) now documents its significance with respect to lazy schema references.
|
|
128
|
+
Additionally some implicit assumptions like no modifications of [AllowedTypes](https://fluidframework.com/docs/api/fluid-framework/allowedtypes-typealias)
|
|
129
|
+
after resolving of lazy schema references have been enforced (such modifications would previously cause undefined behavior in the future, and now an error is thrown when trying to modify them).
|
|
117
130
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
131
|
+
`evaluateLazySchema` has been added as an `@alpha` API that is now consistently used by all internal code when evaluating lazy schema references.
|
|
132
|
+
This ensures consistent behavior and error reporting, but also adds caching.
|
|
133
|
+
Therefore it is now supported for applications to have lazy schema references which compute the schema when invoked,
|
|
134
|
+
without having to implement their own caching as long as those applications use `evaluateLazySchema` anytime they need to evaluate a lazy schema reference.
|
|
121
135
|
|
|
122
|
-
|
|
136
|
+
## 2.23.0
|
|
123
137
|
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Whether or not nodes of this type should be ignored by search.
|
|
127
|
-
* @defaultValue `false`
|
|
128
|
-
*/
|
|
129
|
-
searchIgnore?: boolean;
|
|
130
|
-
}
|
|
138
|
+
### Minor Changes
|
|
131
139
|
|
|
132
|
-
|
|
133
|
-
class Point extends schemaFactory.object("Point", {
|
|
134
|
-
x: schemaFactory.required(schemaFactory.number),
|
|
135
|
-
y: schemaFactory.required(schemaFactory.number),
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
metadata: {
|
|
139
|
-
description: "A point in 2D space",
|
|
140
|
-
custom: {
|
|
141
|
-
searchIgnore: true,
|
|
142
|
-
},
|
|
143
|
-
}
|
|
144
|
-
}) {}
|
|
145
|
-
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
Search can then be implemented to look for the appropriate metadata, and leverage it to omit the unwanted position data from search.
|
|
149
|
-
|
|
150
|
-
#### Potential for breaking existing code
|
|
151
|
-
|
|
152
|
-
These changes add the new property "metadata" to the base type from which all node schema derive.
|
|
153
|
-
If you have existing node schema subclasses that include a property of this name, there is a chance for potential conflict here that could be breaking.
|
|
154
|
-
If you encounter issues here, consider renaming your property or leveraging the new metadata support.
|
|
155
|
-
|
|
156
|
-
- New alpha APIs for schema evolution ([#23362](https://github.com/microsoft/FluidFramework/pull/23362)) [2406e00efe](https://github.com/microsoft/FluidFramework/commit/2406e00efed282be58a9e09cb3478c9a9d170ef0)
|
|
157
|
-
|
|
158
|
-
There are now `@alpha` APIs for schema evolution which support adding optional fields to object node types without a staged rollout.
|
|
159
|
-
|
|
160
|
-
SharedTree has many safety checks in place to ensure applications understand the format of documents they must support.
|
|
161
|
-
One of these checks verifies that the view schema (defined in application's code) aligns with the document schema (determined by the document data at rest).
|
|
162
|
-
This helps to ensure that clients running incompatible versions of the application's code don't collaborate at the same time on some document, which could cause data loss or disrupt application invariants.
|
|
163
|
-
One general solution application authors can perform is to stage the rollout of a feature which changes document schema into multiple phases:
|
|
164
|
-
|
|
165
|
-
1. Release an application version which understands documents written with the new format but doesn't attempt to upgrade any documents
|
|
166
|
-
2. Wait for this application version to saturate in the app's ecosystem
|
|
167
|
-
3. Release an application version which upgrades documents to start leveraging the new format.
|
|
168
|
-
|
|
169
|
-
However, this process can be cumbersome for application authors: for many types of changes, an app author doesn't particularly care if older application code collaborates with newer code, as the only downside is that the older application version might not present a fully faithful experience.
|
|
170
|
-
As an example, consider an application which renders circles on a canvas (similar to what is presented [here](https://github.com/microsoft/FluidFramework/blob/main/packages/dds/tree/docs/user-facing/schema-evolution.md)).
|
|
171
|
-
The application author might anticipate adding support to render the circle with various different other properties (border style, border width, background color, varying radius, etc.).
|
|
172
|
-
Therefore, they should declare their schema using `SchemaFactoryObjectOptions.allowUnknownOptionalFields` like so:
|
|
173
|
-
|
|
174
|
-
```typescript
|
|
175
|
-
import { SchemaFactoryAlpha } from "@fluidframework/tree/alpha";
|
|
176
|
-
// "Old" application code/schema
|
|
177
|
-
const factory = new SchemaFactoryAlpha("Geometry");
|
|
178
|
-
class Circle extends factory.object(
|
|
179
|
-
"Circle",
|
|
180
|
-
{
|
|
181
|
-
x: factory.number,
|
|
182
|
-
y: factory.number,
|
|
183
|
-
},
|
|
184
|
-
{ allowUnknownOptionalFields: true },
|
|
185
|
-
) {}
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
Later, they add some of these features to their application:
|
|
189
|
-
|
|
190
|
-
```typescript
|
|
191
|
-
import { SchemaFactoryAlpha } from "@fluidframework/tree/alpha";
|
|
192
|
-
// "New" application code/schema
|
|
193
|
-
const factory = new SchemaFactoryAlpha("Geometry");
|
|
194
|
-
class Circle extends factory.object(
|
|
195
|
-
"Circle",
|
|
196
|
-
{
|
|
197
|
-
x: factory.number,
|
|
198
|
-
y: factory.number,
|
|
199
|
-
// Note that radius and color must both be declared as optional fields since this application must
|
|
200
|
-
// support opening up existing documents that didn't have this information.
|
|
201
|
-
radius: factory.optional(factory.number),
|
|
202
|
-
color: factory.optional(factory.string), // ex: #00FF00
|
|
203
|
-
},
|
|
204
|
-
{ allowUnknownOptionalFields: true },
|
|
205
|
-
) {}
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
When they go to deploy this newer version of the application, they could opt to start upgrading documents as soon as the newer code is rolled out, and the older code would still be able to open up (and collaborate on) documents using the newer schema version.
|
|
209
|
-
Note that it's only important that the old _application code_ elected to allow opening documents with unknown optional fields.
|
|
210
|
-
This policy is not persisted into documents in any form, so applications are free to modify it at any point.
|
|
211
|
-
|
|
212
|
-
For specific API details, see documentation on `SchemaFactoryObjectOptions.allowUnknownOptionalFields`.
|
|
213
|
-
For a more thorough discussion of this topic, see [Schema Evolvability](https://github.com/microsoft/FluidFramework/tree/main/packages/dds/tree#schema-evolvability) in the SharedTree README.
|
|
140
|
+
- Creating large transactions and processing inbound changes is now faster ([#23929](https://github.com/microsoft/FluidFramework/pull/23929)) [35847b5ffe0](https://github.com/microsoft/FluidFramework/commit/35847b5ffe09d94cef42b74ab59e37c4bd6d8c2d)
|
|
214
141
|
|
|
215
|
-
|
|
142
|
+
SharedTree sometimes composes several sequential changes into a single change.
|
|
143
|
+
It does so whenever a transaction is created and when processing inbound changes.
|
|
216
144
|
|
|
217
|
-
|
|
145
|
+
Version 2.23.0 makes this composition process asymptotically faster.
|
|
146
|
+
For example, creating a transaction that performs 1000 edits on a single array now takes 170ms instead of 1.5s (an 89% improvement).
|
|
218
147
|
|
|
219
|
-
|
|
148
|
+
See [Change #23902](https://github.com/microsoft/FluidFramework/pull/23902) for more details.
|
|
220
149
|
|
|
221
|
-
|
|
150
|
+
- Faster processing of events for large transactions ([#23939](https://github.com/microsoft/FluidFramework/pull/23939)) [2a1e7e0617f](https://github.com/microsoft/FluidFramework/commit/2a1e7e0617f618f82134c0bba269119ed980aadc)
|
|
222
151
|
|
|
223
|
-
|
|
152
|
+
In versions prior to 2.23.0, event processing time could scale quadratically (`O(N^2)`) with the change count when
|
|
153
|
+
processing a batch of changes.
|
|
224
154
|
|
|
225
|
-
|
|
155
|
+
This performance characteristic has been corrected. See change
|
|
156
|
+
[#23908](https://github.com/microsoft/FluidFramework/pull/23908) for more details.
|
|
226
157
|
|
|
227
|
-
-
|
|
158
|
+
- Op bunching performance enhancements ([#23732](https://github.com/microsoft/FluidFramework/pull/23732)) [a98b04fc9e0](https://github.com/microsoft/FluidFramework/commit/a98b04fc9e000971bdfa8135251a7dc3e189502c)
|
|
228
159
|
|
|
229
|
-
|
|
230
|
-
|
|
160
|
+
`SharedTree` now takes advantage of a new feature called "op bunching" where contiguous ops in a grouped batch are
|
|
161
|
+
bunched and processed together. This improves the performance of processing ops asymptotically; as
|
|
162
|
+
the number of local ops and incoming ops increase, the processing time will reduce.
|
|
231
163
|
|
|
232
|
-
|
|
233
|
-
class A extends schemaFactory.object("A", {}) {}
|
|
234
|
-
const a = new A({ thisDoesNotExist: 5 }); // This now errors.
|
|
235
|
-
```
|
|
164
|
+
For example, with 10 local ops + 10 incoming ops, the performance increases by 70%; with 100 local ops + 100 incoming ops, the performance increases by 94%.
|
|
236
165
|
|
|
237
|
-
|
|
166
|
+
This will help improve performance in the following scenarios:
|
|
238
167
|
|
|
239
|
-
|
|
168
|
+
- A client makes a large number of changes in a single JS turn. For example, copy pasting large data like a table.
|
|
169
|
+
- A client has a large number of local changes. For example, slow clients whose changes are slow to ack or clients with
|
|
170
|
+
a local branch with large number of changes.
|
|
240
171
|
|
|
241
|
-
|
|
242
|
-
Depending on the schema, the user specifies which field to key the node on.
|
|
172
|
+
- Invalid schema base classes in Tree.is now throw an error instead of returning false ([#23938](https://github.com/microsoft/FluidFramework/pull/23938)) [00995654070](https://github.com/microsoft/FluidFramework/commit/00995654070a4e13b57b2562ff4a5935aba70a2f)
|
|
243
173
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
return typeof key === "string";
|
|
249
|
-
}
|
|
174
|
+
As documented in [`TreeNodeSchemaClass`](https://fluidframework.com/docs/api/fluid-framework/treenodeschemaclass-typealias#treenodeschemaclass-remarks), there are specific rules around sub-classing schema, mainly that only a single most derived class can be used.
|
|
175
|
+
One place where it was easy to accidentally violate this rule and get hard-to-debug results was [`Tree.is`](https://fluidframework.com/docs/data-structures/tree/nodes#treeis).
|
|
176
|
+
This has been mitigated by adding a check in `Tree.is` which detects this mistake (which used to result in `false` being returned) and instead throws a `UsageError` explaining the situation.
|
|
177
|
+
The error will look something like:
|
|
250
178
|
|
|
251
|
-
|
|
252
|
-
view,
|
|
253
|
-
new Map([
|
|
254
|
-
[IndexableParent, parentKey],
|
|
255
|
-
[IndexableChild, childKey],
|
|
256
|
-
]),
|
|
257
|
-
(nodes) => nodes[0],
|
|
258
|
-
isStringKey,
|
|
259
|
-
[IndexableParent, IndexableChild],
|
|
260
|
-
);
|
|
261
|
-
```
|
|
179
|
+
> Two schema classes were used (CustomObjectNode and Derived) which derived from the same SchemaFactory generated class ("com.example.Test"). This is invalid.
|
|
262
180
|
|
|
263
|
-
|
|
181
|
+
For applications wanting to test if a given `TreeNode` is an instance of some schema base class, this can be done using `instanceof` which includes base classes when doing the check.
|
|
264
182
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
```typescript
|
|
268
|
-
const identifierIndex = createIdentifierIndex(view);
|
|
269
|
-
const node = identifierIndex.get("node12345");
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
## 2.10.0
|
|
183
|
+
## 2.22.0
|
|
273
184
|
|
|
274
185
|
### Minor Changes
|
|
275
186
|
|
|
276
|
-
-
|
|
187
|
+
- Target ES2021 ([#23307](https://github.com/microsoft/FluidFramework/pull/23307)) [36ed18289b](https://github.com/microsoft/FluidFramework/commit/36ed18289bd9b076a996dc48965a9ef12a95bda6)
|
|
277
188
|
|
|
278
|
-
|
|
189
|
+
The TypeScript build for Fluid Framework packages has been updated to target ES2021 instead of ES2020.
|
|
190
|
+
This may result in newer JavaScript language features being used.
|
|
191
|
+
This does not change TypeScript types, nor the JavaScript libraries being used.
|
|
192
|
+
We only support users which support ES2022, so updating to target ES2021 should not break any supported use-case.
|
|
193
|
+
Any users which do not have at least ES2021 language feature support may need to transpile out some additional cases after this change.
|
|
279
194
|
|
|
280
|
-
|
|
195
|
+
This should result in slightly reduced bundle size and slightly improved performance for users not transpiling these features out.
|
|
196
|
+
No major impact is expected.
|
|
281
197
|
|
|
282
|
-
|
|
283
|
-
- MergeNode
|
|
284
|
-
- ObliterateInfo
|
|
285
|
-
- PropertiesManager
|
|
286
|
-
- PropertiesRollback
|
|
287
|
-
- SegmentGroup
|
|
288
|
-
- SegmentGroupCollection
|
|
198
|
+
- Add `leaves` and statics to `SchemaFactory`. ([#23787](https://github.com/microsoft/FluidFramework/pull/23787)) [efa90f6274](https://github.com/microsoft/FluidFramework/commit/efa90f6274152cadb55329b7bbf6a6cd8e299847)
|
|
289
199
|
|
|
290
|
-
|
|
200
|
+
`SchemaFactory` now has a `leaves` member that is an array of all leaf schema.
|
|
291
201
|
|
|
292
|
-
|
|
202
|
+
`SchemaFactory` now has static members to access leaf schema and create field schema.
|
|
293
203
|
|
|
294
|
-
|
|
295
|
-
- ack
|
|
204
|
+
## 2.21.0
|
|
296
205
|
|
|
297
|
-
|
|
206
|
+
Dependency updates only.
|
|
298
207
|
|
|
299
|
-
|
|
300
|
-
- segmentGroups
|
|
208
|
+
## 2.20.0
|
|
301
209
|
|
|
302
|
-
|
|
303
|
-
[Fluid Framework v2.2.0](https://github.com/microsoft/FluidFramework/blob/main/RELEASE_NOTES/2.2.0.md)
|
|
210
|
+
Dependency updates only.
|
|
304
211
|
|
|
305
|
-
|
|
212
|
+
## 2.13.0
|
|
306
213
|
|
|
307
|
-
|
|
214
|
+
### Minor Changes
|
|
308
215
|
|
|
309
|
-
|
|
310
|
-
Part of this improvement was fixing the `.schema` property to be a tuple over each of the schema where it was previously a tuple of a single combined schema due to a bug.
|
|
216
|
+
- Metadata can be associated with Node Schema ([#23321](https://github.com/microsoft/FluidFramework/pull/23321)) [58619c3c4e](https://github.com/microsoft/FluidFramework/commit/58619c3c4ee55ca1497a117321ae0b364e6084e6)
|
|
311
217
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
This mainly matters when matching all cases like the switch statement below:
|
|
218
|
+
Users of TreeView can now specify metadata when creating Node Schema, via `SchemaFactoryAlpha`.
|
|
219
|
+
This metadata may include system-understood properties like `description`.
|
|
315
220
|
|
|
316
|
-
|
|
317
|
-
const Mode = enumFromStrings(schema, ["Fun", "Bonus"]);
|
|
318
|
-
type Mode = TreeNodeFromImplicitAllowedTypes<typeof Mode.schema>;
|
|
319
|
-
const node = new Mode.Bonus() as Mode;
|
|
221
|
+
Example:
|
|
320
222
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
}
|
|
333
|
-
```
|
|
223
|
+
```typescript
|
|
224
|
+
const schemaFactory = new SchemaFactoryAlpha(...);
|
|
225
|
+
class Point extends schemaFactory.object("Point", {
|
|
226
|
+
x: schemaFactory.required(schemaFactory.number),
|
|
227
|
+
y: schemaFactory.required(schemaFactory.number),
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
metadata: {
|
|
231
|
+
description: "A point in 2D space",
|
|
232
|
+
},
|
|
233
|
+
}) {}
|
|
334
234
|
|
|
335
|
-
|
|
235
|
+
```
|
|
336
236
|
|
|
337
|
-
|
|
338
|
-
|
|
237
|
+
Functionality like the experimental conversion of Tree Schema to [JSON Schema](https://json-schema.org/) ([getJsonSchema](https://github.com/microsoft/FluidFramework/releases/tag/client_v2.4.0#user-content-metadata-can-now-be-associated-with-field-schema-22564)) leverages such system-understood metadata to generate useful information.
|
|
238
|
+
In the case of the `description` property, it is mapped directly to the `description` property supported by JSON Schema.
|
|
339
239
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
function deregisterViaOff(view: TreeView<MySchema>): {
|
|
343
|
-
const listener = () => { /* ... */ };
|
|
344
|
-
view.events.on("commitApplied", listener); // Register
|
|
345
|
-
view.events.off("commitApplied", listener); // Deregister
|
|
346
|
-
}
|
|
240
|
+
Custom, user-defined properties can also be specified.
|
|
241
|
+
These properties will not be used by the system by default, but can be used to associate common application-specific properties with Node Schema.
|
|
347
242
|
|
|
348
|
-
|
|
349
|
-
function deregisterViaCallback(view: TreeView<MySchema>): {
|
|
350
|
-
const off = view.events.on("commitApplied", () => { /* ... */ }); // Register
|
|
351
|
-
off(); // Deregister
|
|
352
|
-
}
|
|
353
|
-
```
|
|
243
|
+
#### `SchemaFactoryAlpha` Updates
|
|
354
244
|
|
|
355
|
-
-
|
|
245
|
+
- `object` and `objectRecursive`, `arrayRecursive`, and `mapRecursive` now support `metadata` in their `options` parameter.
|
|
246
|
+
- (new) `arrayAlpha` - Variant of `array` that accepts an options parameter which supports `metadata`
|
|
247
|
+
- (new) `mapAlpha` - Variant of `map` that accepts an options parameter which supports `metadata`
|
|
356
248
|
|
|
357
|
-
|
|
358
|
-
Now all maps nodes can constructed from objects:
|
|
249
|
+
#### Example
|
|
359
250
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
type _check = ValidateRecursiveSchema<typeof MapRecursive>;
|
|
364
|
-
}
|
|
365
|
-
// New:
|
|
366
|
-
const fromObject = new MapRecursive({ x: new MapRecursive() });
|
|
367
|
-
// Existing:
|
|
368
|
-
const fromIterator = new MapRecursive([["x", new MapRecursive()]]);
|
|
369
|
-
const fromMap = new MapRecursive(new Map([["x", new MapRecursive()]]));
|
|
370
|
-
const fromNothing = new MapRecursive();
|
|
371
|
-
const fromUndefined = new MapRecursive(undefined);
|
|
372
|
-
```
|
|
251
|
+
An application is implementing search functionality.
|
|
252
|
+
By default, the app author wishes for all app content to be potentially indexable by search, unless otherwise specified.
|
|
253
|
+
They can leverage schema metadata to decorate types of nodes that should be ignored by search, and leverage that information when walking the tree during a search.
|
|
373
254
|
|
|
374
|
-
|
|
255
|
+
```typescript
|
|
375
256
|
|
|
376
|
-
|
|
257
|
+
interface AppMetadata {
|
|
258
|
+
/**
|
|
259
|
+
* Whether or not nodes of this type should be ignored by search.
|
|
260
|
+
* @defaultValue `false`
|
|
261
|
+
*/
|
|
262
|
+
searchIgnore?: boolean;
|
|
263
|
+
}
|
|
377
264
|
|
|
378
|
-
|
|
265
|
+
const schemaFactory = new SchemaFactoryAlpha(...);
|
|
266
|
+
class Point extends schemaFactory.object("Point", {
|
|
267
|
+
x: schemaFactory.required(schemaFactory.number),
|
|
268
|
+
y: schemaFactory.required(schemaFactory.number),
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
metadata: {
|
|
272
|
+
description: "A point in 2D space",
|
|
273
|
+
custom: {
|
|
274
|
+
searchIgnore: true,
|
|
275
|
+
},
|
|
276
|
+
}
|
|
277
|
+
}) {}
|
|
379
278
|
|
|
380
|
-
|
|
279
|
+
```
|
|
381
280
|
|
|
382
|
-
|
|
383
|
-
- **Consistent Property Changes**: The feature ensures that property changes are consistent, managing both local and remote changes effectively. This is essential for collaborative rich text editing where multiple users may be making adjustments simultaneously.
|
|
384
|
-
- **Rich Text Formatting**: Adjustments can be used to modify text properties such as font size, indentation, or other formatting attributes dynamically based on user actions.
|
|
281
|
+
Search can then be implemented to look for the appropriate metadata, and leverage it to omit the unwanted position data from search.
|
|
385
282
|
|
|
386
|
-
|
|
283
|
+
#### Potential for breaking existing code
|
|
387
284
|
|
|
388
|
-
|
|
285
|
+
These changes add the new property "metadata" to the base type from which all node schema derive.
|
|
286
|
+
If you have existing node schema subclasses that include a property of this name, there is a chance for potential conflict here that could be breaking.
|
|
287
|
+
If you encounter issues here, consider renaming your property or leveraging the new metadata support.
|
|
389
288
|
|
|
390
|
-
|
|
289
|
+
- New alpha APIs for schema evolution ([#23362](https://github.com/microsoft/FluidFramework/pull/23362)) [2406e00efe](https://github.com/microsoft/FluidFramework/commit/2406e00efed282be58a9e09cb3478c9a9d170ef0)
|
|
391
290
|
|
|
392
|
-
|
|
393
|
-
sharedString.annotateAdjustRange(start, end, {
|
|
394
|
-
key: { value: 5, min: 0, max: 10 },
|
|
395
|
-
});
|
|
396
|
-
```
|
|
291
|
+
There are now `@alpha` APIs for schema evolution which support adding optional fields to object node types without a staged rollout.
|
|
397
292
|
|
|
398
|
-
|
|
293
|
+
SharedTree has many safety checks in place to ensure applications understand the format of documents they must support.
|
|
294
|
+
One of these checks verifies that the view schema (defined in application's code) aligns with the document schema (determined by the document data at rest).
|
|
295
|
+
This helps to ensure that clients running incompatible versions of the application's code don't collaborate at the same time on some document, which could cause data loss or disrupt application invariants.
|
|
296
|
+
One general solution application authors can perform is to stage the rollout of a feature which changes document schema into multiple phases:
|
|
399
297
|
|
|
400
|
-
|
|
298
|
+
1. Release an application version which understands documents written with the new format but doesn't attempt to upgrade any documents
|
|
299
|
+
2. Wait for this application version to saturate in the app's ecosystem
|
|
300
|
+
3. Release an application version which upgrades documents to start leveraging the new format.
|
|
401
301
|
|
|
402
|
-
|
|
302
|
+
However, this process can be cumbersome for application authors: for many types of changes, an app author doesn't particularly care if older application code collaborates with newer code, as the only downside is that the older application version might not present a fully faithful experience.
|
|
303
|
+
As an example, consider an application which renders circles on a canvas (similar to what is presented [here](https://github.com/microsoft/FluidFramework/blob/main/packages/dds/tree/docs/user-facing/schema-evolution.md)).
|
|
304
|
+
The application author might anticipate adding support to render the circle with various different other properties (border style, border width, background color, varying radius, etc.).
|
|
305
|
+
Therefore, they should declare their schema using `SchemaFactoryObjectOptions.allowUnknownOptionalFields` like so:
|
|
403
306
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
307
|
+
```typescript
|
|
308
|
+
import { SchemaFactoryAlpha } from "@fluidframework/tree/alpha";
|
|
309
|
+
// "Old" application code/schema
|
|
310
|
+
const factory = new SchemaFactoryAlpha("Geometry");
|
|
311
|
+
class Circle extends factory.object(
|
|
312
|
+
"Circle",
|
|
313
|
+
{
|
|
314
|
+
x: factory.number,
|
|
315
|
+
y: factory.number,
|
|
316
|
+
},
|
|
317
|
+
{ allowUnknownOptionalFields: true },
|
|
318
|
+
) {}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Later, they add some of these features to their application:
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
import { SchemaFactoryAlpha } from "@fluidframework/tree/alpha";
|
|
325
|
+
// "New" application code/schema
|
|
326
|
+
const factory = new SchemaFactoryAlpha("Geometry");
|
|
327
|
+
class Circle extends factory.object(
|
|
328
|
+
"Circle",
|
|
329
|
+
{
|
|
330
|
+
x: factory.number,
|
|
331
|
+
y: factory.number,
|
|
332
|
+
// Note that radius and color must both be declared as optional fields since this application must
|
|
333
|
+
// support opening up existing documents that didn't have this information.
|
|
334
|
+
radius: factory.optional(factory.number),
|
|
335
|
+
color: factory.optional(factory.string), // ex: #00FF00
|
|
336
|
+
},
|
|
337
|
+
{ allowUnknownOptionalFields: true },
|
|
338
|
+
) {}
|
|
339
|
+
```
|
|
409
340
|
|
|
410
|
-
|
|
341
|
+
When they go to deploy this newer version of the application, they could opt to start upgrading documents as soon as the newer code is rolled out, and the older code would still be able to open up (and collaborate on) documents using the newer schema version.
|
|
342
|
+
Note that it's only important that the old _application code_ elected to allow opening documents with unknown optional fields.
|
|
343
|
+
This policy is not persisted into documents in any form, so applications are free to modify it at any point.
|
|
411
344
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
- SequenceDeltaEvent
|
|
415
|
-
- SequenceMaintenanceEvent
|
|
345
|
+
For specific API details, see documentation on `SchemaFactoryObjectOptions.allowUnknownOptionalFields`.
|
|
346
|
+
For a more thorough discussion of this topic, see [Schema Evolvability](https://github.com/microsoft/FluidFramework/tree/main/packages/dds/tree#schema-evolvability) in the SharedTree README.
|
|
416
347
|
|
|
417
|
-
|
|
418
|
-
[Several MergeTree Client Legacy APIs are now deprecated](https://github.com/microsoft/FluidFramework/blob/main/RELEASE_NOTES/2.4.0.md#several-mergetree-client-legacy-apis-are-now-deprecated-22629)
|
|
348
|
+
## 2.12.0
|
|
419
349
|
|
|
420
|
-
|
|
350
|
+
Dependency updates only.
|
|
351
|
+
|
|
352
|
+
## 2.11.0
|
|
421
353
|
|
|
422
354
|
### Minor Changes
|
|
423
355
|
|
|
424
|
-
-
|
|
356
|
+
- Revertible objects can now be cloned using `RevertibleAlpha.clone()` ([#23044](https://github.com/microsoft/FluidFramework/pull/23044)) [5abfa015af](https://github.com/microsoft/FluidFramework/commit/5abfa015aff9d639d82830f3ad828324d5680bd7)
|
|
425
357
|
|
|
426
|
-
|
|
427
|
-
These include import and export APIs for `VerboseTree`, `ConciseTree` and compressed tree formats.
|
|
358
|
+
The `DisposableRevertible` interface has been replaced with `RevertibleAlpha`. The new `RevertibleAlpha` interface extends `Revertible` and includes a `clone(branch: TreeBranch)` method to facilitate cloning a Revertible to a specified target branch. The source branch where the `RevertibleAlpha` was created must share revision logs with the target branch where the `RevertibleAlpha` is being cloned. If this condition is not met, the operation will throw an error.
|
|
428
359
|
|
|
429
|
-
|
|
360
|
+
- Providing unused properties in object literals for building empty ObjectNodes no longer compiles ([#23162](https://github.com/microsoft/FluidFramework/pull/23162)) [dc3c30019e](https://github.com/microsoft/FluidFramework/commit/dc3c30019ef869b27b9468bff59f10434d3c5c68)
|
|
430
361
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
`independentView` has also been added, which is similar but handles the case of creating a new view without an existing schema or tree.
|
|
362
|
+
ObjectNodes with no fields will now emit a compiler error if constructed from an object literal with fields.
|
|
363
|
+
This matches the behavior of non-empty ObjectNodes which already gave errors when unexpected properties were provided.
|
|
434
364
|
|
|
435
|
-
|
|
365
|
+
```typescript
|
|
366
|
+
class A extends schemaFactory.object("A", {}) {}
|
|
367
|
+
const a = new A({ thisDoesNotExist: 5 }); // This now errors.
|
|
368
|
+
```
|
|
436
369
|
|
|
437
|
-
|
|
438
|
-
2. Importing and exporting data from a SharedTree to and from other services or storage locations (such as locally saved files).
|
|
439
|
-
3. Testing various scenarios without relying on a service.
|
|
440
|
-
4. Using SharedTree libraries for just the schema system and encode/decode support.
|
|
370
|
+
- ✨ New! Alpha APIs for indexing ([#22491](https://github.com/microsoft/FluidFramework/pull/22491)) [cd95357ba8](https://github.com/microsoft/FluidFramework/commit/cd95357ba8f8cea6615f4fb0e9a62743770dce83)
|
|
441
371
|
|
|
442
|
-
|
|
372
|
+
SharedTree now supports indexing via two new APIs, `createSimpleTreeIndex` and `createIdentifierIndex`.
|
|
443
373
|
|
|
444
|
-
|
|
374
|
+
`createSimpleTreeIndex` is used to create a `SimpleTreeIndex` which indexes nodes based on their schema.
|
|
375
|
+
Depending on the schema, the user specifies which field to key the node on.
|
|
445
376
|
|
|
446
|
-
|
|
447
|
-
> tsc
|
|
377
|
+
The following example indexes `IndexableParent`s and `IndexableChild`s and returns the first node of a particular key:
|
|
448
378
|
|
|
449
|
-
|
|
379
|
+
```typescript
|
|
380
|
+
function isStringKey(key: TreeIndexKey): key is string {
|
|
381
|
+
return typeof key === "string";
|
|
382
|
+
}
|
|
450
383
|
|
|
451
|
-
|
|
452
|
-
|
|
384
|
+
const index = createSimpleTreeIndex(
|
|
385
|
+
view,
|
|
386
|
+
new Map([
|
|
387
|
+
[IndexableParent, parentKey],
|
|
388
|
+
[IndexableChild, childKey],
|
|
389
|
+
]),
|
|
390
|
+
(nodes) => nodes[0],
|
|
391
|
+
isStringKey,
|
|
392
|
+
[IndexableParent, IndexableChild],
|
|
393
|
+
);
|
|
394
|
+
```
|
|
453
395
|
|
|
454
|
-
|
|
455
|
-
Try `npm i --save-dev @types/ungap__structured-clone` if it exists or add a new declaration (.d.ts) file containing `declare module '@ungap/structured-clone';`
|
|
396
|
+
`createIdentifierIndex` is used to create an `IdentifierIndex` which provides an efficient way to retrieve nodes using the node identifier.
|
|
456
397
|
|
|
457
|
-
|
|
458
|
-
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
459
|
-
```
|
|
398
|
+
Example:
|
|
460
399
|
|
|
461
|
-
|
|
462
|
-
|
|
400
|
+
```typescript
|
|
401
|
+
const identifierIndex = createIdentifierIndex(view);
|
|
402
|
+
const node = identifierIndex.get("node12345");
|
|
403
|
+
```
|
|
463
404
|
|
|
464
|
-
|
|
405
|
+
## 2.10.0
|
|
465
406
|
|
|
466
|
-
|
|
407
|
+
### Minor Changes
|
|
467
408
|
|
|
468
|
-
-
|
|
409
|
+
- Unsupported merge-tree types and related exposed internals have been removed ([#22696](https://github.com/microsoft/FluidFramework/pull/22696)) [7a032533a6](https://github.com/microsoft/FluidFramework/commit/7a032533a6ee6a6f76fe154ef65dfa33f87e5a7b)
|
|
469
410
|
|
|
470
|
-
|
|
471
|
-
This replaces the use of `typedObjectValues` which has been removed.
|
|
411
|
+
As part of ongoing improvements, several internal types and related APIs have been removed. These types are unnecessary for any supported scenarios and could lead to errors if used. Since directly using these types would likely result in errors, these changes are not likely to impact any Fluid Framework consumers.
|
|
472
412
|
|
|
473
|
-
|
|
413
|
+
Removed types:
|
|
474
414
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
415
|
+
- IMergeTreeTextHelper
|
|
416
|
+
- MergeNode
|
|
417
|
+
- ObliterateInfo
|
|
418
|
+
- PropertiesManager
|
|
419
|
+
- PropertiesRollback
|
|
420
|
+
- SegmentGroup
|
|
421
|
+
- SegmentGroupCollection
|
|
481
422
|
|
|
482
|
-
|
|
423
|
+
In addition to removing the above types, they are no longer exposed through the following interfaces and their implementations: `ISegment`, `ReferencePosition`, and `ISerializableInterval`.
|
|
483
424
|
|
|
484
|
-
|
|
485
|
-
type Mode = NodeFromSchema<(typeof Mode)[keyof typeof Mode]>; // This no longer works
|
|
486
|
-
class Parent extends schemaFactory.object("Parent", { mode: typedObjectValues(Mode) }) {} // This no longer works
|
|
487
|
-
```
|
|
425
|
+
Removed functions:
|
|
488
426
|
|
|
489
|
-
-
|
|
427
|
+
- addProperties
|
|
428
|
+
- ack
|
|
490
429
|
|
|
491
|
-
|
|
492
|
-
This change further narrows this to `TreeNode`.
|
|
430
|
+
Removed properties:
|
|
493
431
|
|
|
494
|
-
|
|
432
|
+
- propertyManager
|
|
433
|
+
- segmentGroups
|
|
495
434
|
|
|
496
|
-
|
|
435
|
+
The initial deprecations of the now changed or removed types were announced in Fluid Framework v2.2.0:
|
|
436
|
+
[Fluid Framework v2.2.0](https://github.com/microsoft/FluidFramework/blob/main/RELEASE_NOTES/2.2.0.md)
|
|
497
437
|
|
|
498
|
-
|
|
438
|
+
- Fix typing bug in `adaptEnum` and `enumFromStrings` ([#23077](https://github.com/microsoft/FluidFramework/pull/23077)) [cfb68388cb](https://github.com/microsoft/FluidFramework/commit/cfb68388cb6b88a0ef670633b3afa46a82c99972)
|
|
499
439
|
|
|
500
|
-
|
|
440
|
+
When using the return value from [`adaptEnum`](https://fluidframework.com/docs/api/v2/tree#adaptenum-function) as a function, passing in a value who's type is a union no longer produced an incorrectly typed return value. This has been fixed.
|
|
501
441
|
|
|
502
|
-
|
|
503
|
-
|
|
442
|
+
Additionally [`enumFromStrings`](https://fluidframework.com/docs/api/v2/tree#enumfromstrings-function) has improved the typing of its schema, ensuring the returned object's members have sufficiently specific types.
|
|
443
|
+
Part of this improvement was fixing the `.schema` property to be a tuple over each of the schema where it was previously a tuple of a single combined schema due to a bug.
|
|
504
444
|
|
|
505
|
-
|
|
506
|
-
|
|
445
|
+
One side-effect of these fixes is that narrowing of the `value` field of a node typed from the `.schema` behaves slightly different, such that the node type is now a union instead of it being a single type with a `.value` that is a union.
|
|
446
|
+
This means that narrowing based on `.value` property narrows which node type you have, not just the value property.
|
|
447
|
+
This mainly matters when matching all cases like the switch statement below:
|
|
507
448
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
449
|
+
```typescript
|
|
450
|
+
const Mode = enumFromStrings(schema, ["Fun", "Bonus"]);
|
|
451
|
+
type Mode = TreeNodeFromImplicitAllowedTypes<typeof Mode.schema>;
|
|
452
|
+
const node = new Mode.Bonus() as Mode;
|
|
512
453
|
|
|
513
|
-
|
|
514
|
-
|
|
454
|
+
switch (node.value) {
|
|
455
|
+
case "Fun": {
|
|
456
|
+
assert.fail();
|
|
457
|
+
}
|
|
458
|
+
case "Bonus": {
|
|
459
|
+
// This one runs
|
|
460
|
+
break;
|
|
461
|
+
}
|
|
462
|
+
default:
|
|
463
|
+
// Before this change, "node.value" was never here, now "node" is never.
|
|
464
|
+
unreachableCase(node);
|
|
465
|
+
}
|
|
466
|
+
```
|
|
515
467
|
|
|
516
|
-
|
|
517
|
-
const _fromIterable: Schema = new Schema([]);
|
|
518
|
-
const _fromObject: Schema = new Schema({});
|
|
468
|
+
- SharedTree event listeners that implement `Listenable` now allow deregistration of event listeners via an `off()` function. ([#23046](https://github.com/microsoft/FluidFramework/pull/23046)) [c59225db03](https://github.com/microsoft/FluidFramework/commit/c59225db033a516ee20e459ae31567d97ce8776c)
|
|
519
469
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
const _fromNothing: Schema = new Schema();
|
|
523
|
-
```
|
|
470
|
+
The ability to deregister events via a callback returned by `on()` remains the same.
|
|
471
|
+
Both strategies will remain supported and consumers of SharedTree events may choose which method of deregistration they prefer in a given instance.
|
|
524
472
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
473
|
+
```typescript
|
|
474
|
+
// The new behavior
|
|
475
|
+
function deregisterViaOff(view: TreeView<MySchema>): {
|
|
476
|
+
const listener = () => { /* ... */ };
|
|
477
|
+
view.events.on("commitApplied", listener); // Register
|
|
478
|
+
view.events.off("commitApplied", listener); // Deregister
|
|
479
|
+
}
|
|
528
480
|
|
|
529
|
-
|
|
530
|
-
|
|
481
|
+
// The existing behavior (still supported)
|
|
482
|
+
function deregisterViaCallback(view: TreeView<MySchema>): {
|
|
483
|
+
const off = view.events.on("commitApplied", () => { /* ... */ }); // Register
|
|
484
|
+
off(); // Deregister
|
|
485
|
+
}
|
|
486
|
+
```
|
|
531
487
|
|
|
532
|
-
|
|
533
|
-
const _fromUndefined: Schema = Schema.create(undefined);
|
|
534
|
-
const _fromNothing: Schema = Schema.create();
|
|
535
|
-
```
|
|
488
|
+
- Allow constructing recursive maps from objects ([#23070](https://github.com/microsoft/FluidFramework/pull/23070)) [0185a08c6f](https://github.com/microsoft/FluidFramework/commit/0185a08c6f8bf6e922a6467f11da049503c4d215)
|
|
536
489
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
type Schema = NodeFromSchema<typeof Schema>;
|
|
540
|
-
// Existing support
|
|
541
|
-
const _fromIterable: Schema = Schema.create([]);
|
|
542
|
-
const _fromObject: Schema = Schema.create({});
|
|
490
|
+
Previously only non-recursive maps could be constructed from objects.
|
|
491
|
+
Now all maps nodes can constructed from objects:
|
|
543
492
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
493
|
+
```typescript
|
|
494
|
+
class MapRecursive extends sf.mapRecursive("Map", [() => MapRecursive]) {}
|
|
495
|
+
{
|
|
496
|
+
type _check = ValidateRecursiveSchema<typeof MapRecursive>;
|
|
497
|
+
}
|
|
498
|
+
// New:
|
|
499
|
+
const fromObject = new MapRecursive({ x: new MapRecursive() });
|
|
500
|
+
// Existing:
|
|
501
|
+
const fromIterator = new MapRecursive([["x", new MapRecursive()]]);
|
|
502
|
+
const fromMap = new MapRecursive(new Map([["x", new MapRecursive()]]));
|
|
503
|
+
const fromNothing = new MapRecursive();
|
|
504
|
+
const fromUndefined = new MapRecursive(undefined);
|
|
505
|
+
```
|
|
548
506
|
|
|
549
|
-
-
|
|
507
|
+
- SharedString DDS annotateAdjustRange ([#22751](https://github.com/microsoft/FluidFramework/pull/22751)) [d54b9dde14](https://github.com/microsoft/FluidFramework/commit/d54b9dde14e9e0e5eb7999db8ebf6da98fdfb526)
|
|
550
508
|
|
|
551
|
-
|
|
552
|
-
Due to limitations of the TypeScript language, there was no practical way to prevent less descriptive types, like `TreeNodeSchema` or `ImplicitFieldSchema`, from being used where the type of a specific schema was intended.
|
|
553
|
-
Code which does this will encounter several issues with tree APIs, and this change fixes some of those issues.
|
|
554
|
-
This change mainly fixes that `NodeFromSchema<TreeNodeSchema>` used to return `unknown` and now returns `TreeNode | TreeLeafValue`.
|
|
509
|
+
This update introduces a new feature to the `SharedString` DDS, allowing for the adjustment of properties over a specified range. The `annotateAdjustRange` method enables users to apply adjustments to properties within a given range, providing more flexibility and control over property modifications.
|
|
555
510
|
|
|
556
|
-
|
|
557
|
-
Unfortunately, there are other typing bugs which complicate the situation, causing APIs for inserting data into the tree to also behave poorly when given non-specific types like `TreeNodeSchema`.
|
|
558
|
-
These APIs include cases like `TreeView.initialize`.
|
|
511
|
+
An adjustment is a modification applied to a property value within a specified range. Adjustments can be used to increment or decrement property values dynamically. They are particularly useful in scenarios where property values need to be updated based on user interactions or other events. For example, in a rich text editor, adjustments can be used for modifying indentation levels or font sizes, where multiple users could apply differing numerical adjustments.
|
|
559
512
|
|
|
560
|
-
|
|
561
|
-
With the typing being partly fixed, some unsafe inputs are still allowed when trying to initialize such a view, but some are now prevented.
|
|
513
|
+
### Key Features and Use Cases:
|
|
562
514
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
515
|
+
- **Adjustments with Constraints**: Adjustments can include optional minimum and maximum constraints to ensure the final value falls within specified bounds. This is particularly useful for maintaining consistent formatting in rich text editors.
|
|
516
|
+
- **Consistent Property Changes**: The feature ensures that property changes are consistent, managing both local and remote changes effectively. This is essential for collaborative rich text editing where multiple users may be making adjustments simultaneously.
|
|
517
|
+
- **Rich Text Formatting**: Adjustments can be used to modify text properties such as font size, indentation, or other formatting attributes dynamically based on user actions.
|
|
566
518
|
|
|
567
|
-
|
|
519
|
+
### Configuration and Compatibility Requirements:
|
|
568
520
|
|
|
569
|
-
|
|
570
|
-
import { TinyliciousClient } from "@fluidframework/tinylicious-client";
|
|
571
|
-
import {
|
|
572
|
-
SchemaFactory,
|
|
573
|
-
SharedTree,
|
|
574
|
-
TreeViewConfiguration,
|
|
575
|
-
type TreeNodeSchema,
|
|
576
|
-
} from "fluid-framework";
|
|
577
|
-
|
|
578
|
-
// Create a ITree instance
|
|
579
|
-
const tinyliciousClient = new TinyliciousClient();
|
|
580
|
-
const { container } = await tinyliciousClient.createContainer({ initialObjects: {} }, "2");
|
|
581
|
-
const tree = await container.create(SharedTree);
|
|
521
|
+
This feature is only available when the configuration `Fluid.Sequence.mergeTreeEnableAnnotateAdjust` is set to `true`. Additionally, all collaborating clients must have this feature enabled to use it. If any client does not have this feature enabled, it will lead to the client exiting collaboration. A future major version of Fluid will enable this feature by default.
|
|
582
522
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
// Bad: This loses the schema aware type information. `: TreeNodeSchema` should be omitted to preserve strong typing.
|
|
586
|
-
const schema: TreeNodeSchema = schemaFactory.array(schemaFactory.number);
|
|
587
|
-
const config = new TreeViewConfiguration({ schema });
|
|
523
|
+
### Usage Example:
|
|
588
524
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
// Since all assignments are allowed, valid ones still work:
|
|
595
|
-
view.root = [];
|
|
596
|
-
```
|
|
597
|
-
|
|
598
|
-
After this change:
|
|
599
|
-
|
|
600
|
-
```typescript
|
|
601
|
-
// Root is now typed as `TreeNode | TreeLeafValue`, still allowing some invalid assignment operations.
|
|
602
|
-
// In the future this should be prevented as well, since the type of the setter in this case should be `never`.
|
|
603
|
-
view.root = "invalid";
|
|
604
|
-
// This no longer compiles:
|
|
605
|
-
view.root = {};
|
|
606
|
-
// This also no longer compiles despite being valid at runtime:
|
|
607
|
-
view.root = [];
|
|
608
|
-
```
|
|
609
|
-
|
|
610
|
-
For code that wants to continue using an unsafe API, which can result in runtime errors if the data does not follow the schema, a new alternative has been added to address this use-case. A special type `UnsafeUnknownSchema` can now be used to opt into allowing all valid trees to be provided.
|
|
611
|
-
Note that this leaves ensuring the data is in schema up to the user.
|
|
612
|
-
For now these adjusted APIs can be accessed by casting the view to `TreeViewAlpha<UnsafeUnknownSchema>`.
|
|
613
|
-
If stabilized, this option will be added to `TreeView` directly.
|
|
614
|
-
|
|
615
|
-
```typescript
|
|
616
|
-
const viewAlpha = view as TreeViewAlpha<UnsafeUnknownSchema>;
|
|
617
|
-
viewAlpha.initialize([]);
|
|
618
|
-
viewAlpha.root = [];
|
|
619
|
-
```
|
|
620
|
-
|
|
621
|
-
Additionally, this seems to have negatively impacted co-recursive schema which declare a co-recursive array as the first schema in the co-recursive cycle.
|
|
622
|
-
Like the TypeScript language our schema system is built on, we don't guarantee exactly which recursive type will compile, but will do our best to ensure useful recursive schema can be created easily.
|
|
623
|
-
In this case a slight change may be required to some recursive schema to get them to compile again:
|
|
624
|
-
|
|
625
|
-
For example this schema used to compile:
|
|
626
|
-
|
|
627
|
-
```typescript
|
|
628
|
-
class A extends sf.arrayRecursive("A", [() => B]) {}
|
|
629
|
-
{
|
|
630
|
-
type _check = ValidateRecursiveSchema<typeof A>;
|
|
631
|
-
}
|
|
632
|
-
// Used to work, but breaks in this update.
|
|
633
|
-
class B extends sf.object("B", { x: A }) {}
|
|
634
|
-
```
|
|
525
|
+
```typescript
|
|
526
|
+
sharedString.annotateAdjustRange(start, end, {
|
|
527
|
+
key: { value: 5, min: 0, max: 10 },
|
|
528
|
+
});
|
|
529
|
+
```
|
|
635
530
|
|
|
636
|
-
|
|
637
|
-
In our example, it can be fixed as follows:
|
|
531
|
+
- MergeTree `Client` Legacy API Removed ([#22697](https://github.com/microsoft/FluidFramework/pull/22697)) [2aa0b5e794](https://github.com/microsoft/FluidFramework/commit/2aa0b5e7941efe52386782595f96ff847c786fc3)
|
|
638
532
|
|
|
639
|
-
|
|
640
|
-
class A extends sf.arrayRecursive("A", [() => B]) {}
|
|
641
|
-
{
|
|
642
|
-
type _check = ValidateRecursiveSchema<typeof A>;
|
|
643
|
-
}
|
|
644
|
-
// Fixed corecursive type, using "Recursive" method variant to declare schema.
|
|
645
|
-
class B extends sf.objectRecursive("B", { x: A }) {}
|
|
646
|
-
{
|
|
647
|
-
type _check = ValidateRecursiveSchema<typeof B>;
|
|
648
|
-
}
|
|
649
|
-
```
|
|
533
|
+
The `Client` class in the merge-tree package has been removed. Types that directly or indirectly expose the merge-tree `Client` class have also been removed.
|
|
650
534
|
|
|
651
|
-
|
|
535
|
+
The removed types were not meant to be used directly, and direct usage was not supported:
|
|
652
536
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
// Works, for now, but not recommended.
|
|
659
|
-
class A extends sf.array("A", B) {}
|
|
660
|
-
```
|
|
537
|
+
- AttributionPolicy
|
|
538
|
+
- IClientEvents
|
|
539
|
+
- IMergeTreeAttributionOptions
|
|
540
|
+
- SharedSegmentSequence
|
|
541
|
+
- SharedStringClass
|
|
661
542
|
|
|
662
|
-
|
|
543
|
+
Some classes that referenced the `Client` class have been transitioned to interfaces. Direct instantiation of these classes was not supported or necessary for any supported scenario, so the change to an interface should not impact usage. This applies to the following types:
|
|
663
544
|
|
|
664
|
-
|
|
545
|
+
- SequenceInterval
|
|
546
|
+
- SequenceEvent
|
|
547
|
+
- SequenceDeltaEvent
|
|
548
|
+
- SequenceMaintenanceEvent
|
|
665
549
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
class A extends schemaFactory.object("A", {}) {}
|
|
669
|
-
class B extends schemaFactory.array("B", schemaFactory.number) {}
|
|
550
|
+
The initial deprecations of the now changed or removed types were announced in Fluid Framework v2.4.0:
|
|
551
|
+
[Several MergeTree Client Legacy APIs are now deprecated](https://github.com/microsoft/FluidFramework/blob/main/RELEASE_NOTES/2.4.0.md#several-mergetree-client-legacy-apis-are-now-deprecated-22629)
|
|
670
552
|
|
|
671
|
-
|
|
672
|
-
const schema = [A, B];
|
|
553
|
+
## 2.5.0
|
|
673
554
|
|
|
674
|
-
|
|
675
|
-
const view = sharedTree.viewWith(config);
|
|
555
|
+
### Minor Changes
|
|
676
556
|
|
|
677
|
-
|
|
678
|
-
view.root = [];
|
|
679
|
-
```
|
|
557
|
+
- ✨ New! Alpha APIs for tree data import and export ([#22566](https://github.com/microsoft/FluidFramework/pull/22566)) [18a23e8816](https://github.com/microsoft/FluidFramework/commit/18a23e8816467f2ed0c9d6d8637b70d99aa48b7a)
|
|
680
558
|
|
|
681
|
-
|
|
559
|
+
A collection of new `@alpha` APIs for importing and exporting tree content and schema from SharedTrees has been added to `TreeAlpha`.
|
|
560
|
+
These include import and export APIs for `VerboseTree`, `ConciseTree` and compressed tree formats.
|
|
682
561
|
|
|
683
|
-
|
|
684
|
-
const schema: (typeof A | typeof B)[] = [A];
|
|
685
|
-
```
|
|
562
|
+
`TreeAlpha.create` is also added to allow constructing trees with a more general API instead of having to use the schema constructor directly (since that doesn't handle polymorphic roots, or non-schema aware code).
|
|
686
563
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
564
|
+
The function `independentInitializedView` has been added to provide a way to combine data from the existing `extractPersistedSchema` and new `TreeAlpha.exportCompressed` back into a `TreeView` in a way which can support safely importing data which could have been exported with a different schema.
|
|
565
|
+
This allows replicating the schema evolution process for Fluid documents stored in a service, but entirely locally without involving any collaboration services.
|
|
566
|
+
`independentView` has also been added, which is similar but handles the case of creating a new view without an existing schema or tree.
|
|
690
567
|
|
|
691
|
-
|
|
692
|
-
const schema: (typeof A | typeof B)[] = [A, B];
|
|
693
|
-
```
|
|
568
|
+
Together these APIs address several use-cases:
|
|
694
569
|
|
|
695
|
-
|
|
570
|
+
1. Using SharedTree as an in-memory non-collaborative datastore.
|
|
571
|
+
2. Importing and exporting data from a SharedTree to and from other services or storage locations (such as locally saved files).
|
|
572
|
+
3. Testing various scenarios without relying on a service.
|
|
573
|
+
4. Using SharedTree libraries for just the schema system and encode/decode support.
|
|
696
574
|
|
|
697
|
-
|
|
575
|
+
- Compilation no longer fails when building with TypeScript's libCheck option ([#22923](https://github.com/microsoft/FluidFramework/pull/22923)) [a1b4cdd45e](https://github.com/microsoft/FluidFramework/commit/a1b4cdd45ee9812e2598ab8d2854333d26a06eb4)
|
|
698
576
|
|
|
699
|
-
|
|
700
|
-
const schema = [A, B] as const;
|
|
701
|
-
const config = new TreeViewConfiguration({ schema });
|
|
702
|
-
```
|
|
577
|
+
When compiling code using Fluid Framework with TypeScript's `libCheck` (meaning without [skipLibCheck](https://www.typescriptlang.org/tsconfig/#skipLibCheck)), two compile errors can be encountered:
|
|
703
578
|
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
```
|
|
579
|
+
```
|
|
580
|
+
> tsc
|
|
707
581
|
|
|
708
|
-
|
|
709
|
-
Many usages of this API will produce incorrectly typed outputs.
|
|
710
|
-
However, when given `AllowedTypes` arrays which should not contain any unions, but that were accidentally flattened to a single union, it can fix them:
|
|
582
|
+
node_modules/@fluidframework/merge-tree/lib/client.d.ts:124:18 - error TS2368: Type parameter name cannot be 'undefined'.
|
|
711
583
|
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
const schemaBad = [A, B];
|
|
715
|
-
// Fixes the type to be [typeof A, typeof B]
|
|
716
|
-
const schema = unsafeArrayToTuple(schemaBad);
|
|
584
|
+
124 walkSegments<undefined>(handler: ISegmentAction<undefined>, start?: number, end?: number, accum?: undefined, splitRange?: boolean): void;
|
|
585
|
+
~~~~~~~~~
|
|
717
586
|
|
|
718
|
-
|
|
719
|
-
|
|
587
|
+
node_modules/@fluidframework/tree/lib/util/utils.d.ts:5:29 - error TS7016: Could not find a declaration file for module '@ungap/structured-clone'. 'node_modules/@ungap/structured-clone/esm/index.js' implicitly has an 'any' type.
|
|
588
|
+
Try `npm i --save-dev @types/ungap__structured-clone` if it exists or add a new declaration (.d.ts) file containing `declare module '@ungap/structured-clone';`
|
|
720
589
|
|
|
721
|
-
|
|
590
|
+
5 import structuredClone from "@ungap/structured-clone";
|
|
591
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
592
|
+
```
|
|
722
593
|
|
|
723
|
-
|
|
594
|
+
The first error impacts projects using TypeScript 5.5 or greater and either of the `fluid-framework` or `@fluidframework/merge-tree` packages.
|
|
595
|
+
The second error impacts projects using the `noImplicitAny` tsconfig setting and the `fluid-framework` or `@fluidframework/tree` packages.
|
|
724
596
|
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
A new alpha `configuredSharedTree` had been added.
|
|
728
|
-
This allows providing configuration options, primarily for debugging, testing and evaluation of upcoming features.
|
|
729
|
-
The resulting configured `SharedTree` object can then be used in-place of the regular `SharedTree` imported from `fluid-framework`.
|
|
730
|
-
|
|
731
|
-
```typescript
|
|
732
|
-
import {
|
|
733
|
-
ForestType,
|
|
734
|
-
TreeCompressionStrategy,
|
|
735
|
-
configuredSharedTree,
|
|
736
|
-
typeboxValidator,
|
|
737
|
-
} from "@fluid-framework/alpha";
|
|
738
|
-
// Maximum debuggability and validation enabled:
|
|
739
|
-
const SharedTree = configuredSharedTree({
|
|
740
|
-
forest: ForestType.Expensive,
|
|
741
|
-
jsonValidator: typeboxValidator,
|
|
742
|
-
treeEncodeType: TreeCompressionStrategy.Uncompressed,
|
|
743
|
-
});
|
|
744
|
-
// Opts into the under development optimized tree storage planned to be the eventual default implementation:
|
|
745
|
-
const SharedTree = configuredSharedTree({
|
|
746
|
-
forest: ForestType.Optimized,
|
|
747
|
-
});
|
|
748
|
-
```
|
|
749
|
-
|
|
750
|
-
- ✨ New! Alpha API for snapshotting Schema ([#22733](https://github.com/microsoft/FluidFramework/pull/22733)) [920a65f66e](https://github.com/microsoft/FluidFramework/commit/920a65f66e0caad7e1b5e3df1e0afd3475a87c4a)
|
|
751
|
-
|
|
752
|
-
`extractPersistedSchema` can now be used to extra a JSON-compatible representation of the subset of a schema that gets stored in documents.
|
|
753
|
-
This can be used write tests which snapshot an applications schema.
|
|
754
|
-
Such tests can be used to detect schema changes which could would impact document compatibility,
|
|
755
|
-
and can be combined with the new `comparePersistedSchema` to measure what kind of compatibility impact the schema change has.
|
|
756
|
-
|
|
757
|
-
- Fix reading of `null` from unhydrated trees ([#22748](https://github.com/microsoft/FluidFramework/pull/22748)) [6a75bd0616](https://github.com/microsoft/FluidFramework/commit/6a75bd0616ecd315ae0e9458d88ba1c755dfd785)
|
|
758
|
-
|
|
759
|
-
Unhydrated trees containing object nodes with required fields set to `null` used to throw an error.
|
|
760
|
-
This was a bug: `null` is a valid value in tree's whose schema allow it, and this specific case now correctly returns `null` values when appropriate without erroring.
|
|
761
|
-
|
|
762
|
-
- ✨ New! Alpha SharedTree branching APIs ([#22550](https://github.com/microsoft/FluidFramework/pull/22550)) [8f4587c912](https://github.com/microsoft/FluidFramework/commit/8f4587c912f955c405d7bbbc5b42f3ffc3b497d7)
|
|
763
|
-
|
|
764
|
-
Several APIs have been added to allow for creating and coordinating "version-control"-style branches of the SharedTree.
|
|
765
|
-
Use the `getBranch` entry point function to acquire a branch.
|
|
766
|
-
For example:
|
|
767
|
-
|
|
768
|
-
```ts
|
|
769
|
-
function makeEditOnBranch(mainView: TreeView<typeof MySchema>) {
|
|
770
|
-
mainView.root.myData = 3;
|
|
771
|
-
const mainBranch = getBranch(mainView); // This function accepts either a view of a SharedTree (acquired e.g. via `sharedTree.viewWith(...)`) or a `SharedTree` directly.
|
|
772
|
-
const forkBranch = mainBranch.branch(); // This creates a new branch based on the existing branch.
|
|
773
|
-
const forkView = forkBranch.viewWith(new TreeViewConfiguration({ schema: MySchema })); // Acquire a view of the forked branch in order to read or edit its tree.
|
|
774
|
-
forkView.root.myData = 4; // Set the value on the fork branch to be 4. The main branch still has a value of 3.
|
|
775
|
-
mainBranch.merge(forkBranch); // Merging the fork changes into the main branch causes the main branch to have a value of 4.
|
|
776
|
-
|
|
777
|
-
// Note: The main branch (and therefore, also the `forkView`) is automatically disposed by the merge.
|
|
778
|
-
// To prevent this, use `mainBranch.merge(forkBranch, false)`.
|
|
779
|
-
}
|
|
780
|
-
```
|
|
597
|
+
Both errors have been fixed.
|
|
781
598
|
|
|
782
|
-
|
|
783
|
-
commit on the target branch. See [#22644](https://github.com/microsoft/FluidFramework/pull/22644) for more information
|
|
784
|
-
about revertible support in the branching APIs.
|
|
599
|
+
This should allow `libCheck` to be reenabled in any impacted projects.
|
|
785
600
|
|
|
786
|
-
-
|
|
601
|
+
- A `.schema` member has been added to the alpha enum schema APIs ([#22874](https://github.com/microsoft/FluidFramework/pull/22874)) [645b9ed695](https://github.com/microsoft/FluidFramework/commit/645b9ed69540338843ad14f1144ff4d1f80d6f09)
|
|
787
602
|
|
|
788
|
-
|
|
603
|
+
The return value from `@alpha` APIs `enumFromStrings` and `adaptEnum` now has a property named `schema` which can be used to include it in a parent schema.
|
|
604
|
+
This replaces the use of `typedObjectValues` which has been removed.
|
|
789
605
|
|
|
790
|
-
|
|
791
|
-
Fixing this bug appears to be impossible within the current limitation of TypeScript, however this library does not require any case other than `TKey` being exactly `string`.
|
|
606
|
+
Use of these APIs now look like:
|
|
792
607
|
|
|
793
|
-
|
|
608
|
+
```typescript
|
|
609
|
+
const schemaFactory = new SchemaFactory("com.myApp");
|
|
610
|
+
const Mode = enumFromStrings(schemaFactory, ["Fun", "Cool"]);
|
|
611
|
+
type Mode = NodeFromSchema<(typeof Mode.schema)[number]>;
|
|
612
|
+
class Parent extends schemaFactory.object("Parent", { mode: Mode.schema }) {}
|
|
613
|
+
```
|
|
794
614
|
|
|
795
|
-
|
|
796
|
-
See [API Support Levels](https://fluidframework.com/docs/build/releases-and-apitags/#api-support-levels) for more details.
|
|
615
|
+
Previously, the last two lines would have been:
|
|
797
616
|
|
|
798
|
-
|
|
617
|
+
```typescript
|
|
618
|
+
type Mode = NodeFromSchema<(typeof Mode)[keyof typeof Mode]>; // This no longer works
|
|
619
|
+
class Parent extends schemaFactory.object("Parent", {
|
|
620
|
+
mode: typedObjectValues(Mode),
|
|
621
|
+
}) {} // This no longer works
|
|
622
|
+
```
|
|
799
623
|
|
|
800
|
-
|
|
801
|
-
This has been fixed, and can now be used as follows:
|
|
624
|
+
- TreeNodeSchemaClass now specifies its TNode as TreeNode ([#22938](https://github.com/microsoft/FluidFramework/pull/22938)) [b669a6efdb](https://github.com/microsoft/FluidFramework/commit/b669a6efdba685c71897cade4f907304f1a73910)
|
|
802
625
|
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
type MyMap = NodeFromSchema<typeof MyMap>;
|
|
806
|
-
const _fromMap: MyMap = MyMap.create(new MyMap());
|
|
807
|
-
const _fromIterable: MyMap = MyMap.create([]);
|
|
808
|
-
const _fromObject: MyMap = MyMap.create({});
|
|
809
|
-
```
|
|
626
|
+
`TreeNodeSchemaClass`'s `TNode` parameter was formerly `unknown` and has been improved to be the more specific `TreeNode | TreeLeafValue`.
|
|
627
|
+
This change further narrows this to `TreeNode`.
|
|
810
628
|
|
|
811
|
-
|
|
812
|
-
While `TreeNodeSchemaNonClass` is `@system` (See [Fluid Releases and API Support Levels
|
|
813
|
-
](https://fluidframework.com/docs/build/releases-and-apitags/) for details) and thus not intended to be referred to by users of Fluid,
|
|
814
|
-
this change caused the TypeScript compiler to generate references to it in more cases when compiling `d.ts` files.
|
|
815
|
-
Since the TypeScript compiler is unable to generate references to `TreeNodeSchemaNonClass` with how it was nested in `internalTypes.js`,
|
|
816
|
-
this change could break the build of packages exporting types referencing structurally named map and array schema.
|
|
817
|
-
This has been mitigated by moving `TreeNodeSchemaNonClass` out of `internalTypes.js`:
|
|
818
|
-
any code importing `TreeNodeSchemaNonClass` (and thus disregarding the `@system` restriction) can be fixed by importing it from the top level instead of the `internalTypes.js`
|
|
629
|
+
`TreeNodeSchema`, which is more commonly used, still permits `TNode` of `TreeNode | TreeLeafValue`, so this change should have little impact on most code, but in some edge cases it can result in slightly more specific typing.
|
|
819
630
|
|
|
820
|
-
-
|
|
631
|
+
- Array and Map nodes can now be explicitly constructed with undefined or no argument ([#22946](https://github.com/microsoft/FluidFramework/pull/22946)) [176335ce88](https://github.com/microsoft/FluidFramework/commit/176335ce88d005159819c559b445a1655ec429d5)
|
|
821
632
|
|
|
822
|
-
|
|
823
|
-
Several operations on subtrees under arrays have been optimized, including reading of non-leaf nodes for the first time.
|
|
824
|
-
Overall this showed a roughly 5% speed up in a read heavy test application (the BubbleBench example) but gains are expected to vary a lot based on use-case.
|
|
633
|
+
The input parameter to the constructor and `create` methods of Array and Map nodes is now optional. When the optional parameter is omitted, an empty map or array will be created.
|
|
825
634
|
|
|
826
|
-
|
|
635
|
+
#### Examples
|
|
827
636
|
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
thus if these change or stable alternatives are needed, an application can replicate this functionality using these implementations as an example.
|
|
637
|
+
```typescript
|
|
638
|
+
class Schema extends schemaFactory.array("x", schemaFactory.number) {}
|
|
831
639
|
|
|
832
|
-
|
|
640
|
+
// Existing support
|
|
641
|
+
const _fromIterable: Schema = new Schema([]);
|
|
833
642
|
|
|
834
|
-
|
|
643
|
+
// New
|
|
644
|
+
const _fromUndefined: Schema = new Schema(undefined);
|
|
645
|
+
const _fromNothing: Schema = new Schema();
|
|
646
|
+
```
|
|
835
647
|
|
|
836
|
-
|
|
648
|
+
```typescript
|
|
649
|
+
class Schema extends schemaFactory.map("x", schemaFactory.number) {}
|
|
837
650
|
|
|
838
|
-
|
|
651
|
+
// Existing support
|
|
652
|
+
const _fromIterable: Schema = new Schema([]);
|
|
653
|
+
const _fromObject: Schema = new Schema({});
|
|
839
654
|
|
|
840
|
-
|
|
655
|
+
// New
|
|
656
|
+
const _fromUndefined: Schema = new Schema(undefined);
|
|
657
|
+
const _fromNothing: Schema = new Schema();
|
|
658
|
+
```
|
|
841
659
|
|
|
842
|
-
|
|
660
|
+
```typescript
|
|
661
|
+
const Schema = schemaFactory.array(schemaFactory.number);
|
|
662
|
+
type Schema = NodeFromSchema<typeof Schema>;
|
|
843
663
|
|
|
844
|
-
|
|
664
|
+
// Existing support
|
|
665
|
+
const _fromIterable: Schema = Schema.create([]);
|
|
845
666
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
This has been fixed: both validation and node construction now only consider own properties.
|
|
667
|
+
// New
|
|
668
|
+
const _fromUndefined: Schema = Schema.create(undefined);
|
|
669
|
+
const _fromNothing: Schema = Schema.create();
|
|
670
|
+
```
|
|
851
671
|
|
|
852
|
-
|
|
853
|
-
|
|
672
|
+
```typescript
|
|
673
|
+
const Schema = schemaFactory.map(schemaFactory.number);
|
|
674
|
+
type Schema = NodeFromSchema<typeof Schema>;
|
|
675
|
+
// Existing support
|
|
676
|
+
const _fromIterable: Schema = Schema.create([]);
|
|
677
|
+
const _fromObject: Schema = Schema.create({});
|
|
854
678
|
|
|
855
|
-
|
|
679
|
+
// New
|
|
680
|
+
const _fromUndefined: Schema = Schema.create(undefined);
|
|
681
|
+
const _fromNothing: Schema = Schema.create();
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
- Typing has been improved when an exact TypeScript type for a schema is not provided ([#22763](https://github.com/microsoft/FluidFramework/pull/22763)) [05197d6d3f](https://github.com/microsoft/FluidFramework/commit/05197d6d3f0189ecd61fd74ec55f6836e6797249)
|
|
685
|
+
|
|
686
|
+
The Tree APIs are designed to be used in a strongly typed way, with the full TypeScript type for the schema always being provided.
|
|
687
|
+
Due to limitations of the TypeScript language, there was no practical way to prevent less descriptive types, like `TreeNodeSchema` or `ImplicitFieldSchema`, from being used where the type of a specific schema was intended.
|
|
688
|
+
Code which does this will encounter several issues with tree APIs, and this change fixes some of those issues.
|
|
689
|
+
This change mainly fixes that `NodeFromSchema<TreeNodeSchema>` used to return `unknown` and now returns `TreeNode | TreeLeafValue`.
|
|
690
|
+
|
|
691
|
+
This change by itself seems mostly harmless, as it just improves the precision of the typing in this one edge case.
|
|
692
|
+
Unfortunately, there are other typing bugs which complicate the situation, causing APIs for inserting data into the tree to also behave poorly when given non-specific types like `TreeNodeSchema`.
|
|
693
|
+
These APIs include cases like `TreeView.initialize`.
|
|
694
|
+
|
|
695
|
+
This incorrectly allowed some usage like taking a type-erased schema and initial tree pair, creating a view of type `TreeView<ImplicitFieldSchema>`, then initializing it.
|
|
696
|
+
With the typing being partly fixed, some unsafe inputs are still allowed when trying to initialize such a view, but some are now prevented.
|
|
697
|
+
|
|
698
|
+
This use-case of modifying trees in code not that is not strongly typed by the exact schema was not intended to be supported.
|
|
699
|
+
Despite this, it did mostly work in some cases, and has some real use-cases (like tests looping over test data consisting of pairs of schema and initial trees).
|
|
700
|
+
To help mitigate the impact of this change, some experimental `@alpha` APIs have been introduced to help address these previously unsupported but somewhat working use-cases.
|
|
701
|
+
|
|
702
|
+
Before this change:
|
|
703
|
+
|
|
704
|
+
```typescript
|
|
705
|
+
import { TinyliciousClient } from "@fluidframework/tinylicious-client";
|
|
706
|
+
import {
|
|
707
|
+
SchemaFactory,
|
|
708
|
+
SharedTree,
|
|
709
|
+
TreeViewConfiguration,
|
|
710
|
+
type TreeNodeSchema,
|
|
711
|
+
} from "fluid-framework";
|
|
712
|
+
|
|
713
|
+
// Create a ITree instance
|
|
714
|
+
const tinyliciousClient = new TinyliciousClient();
|
|
715
|
+
const { container } = await tinyliciousClient.createContainer(
|
|
716
|
+
{ initialObjects: {} },
|
|
717
|
+
"2",
|
|
718
|
+
);
|
|
719
|
+
const tree = await container.create(SharedTree);
|
|
720
|
+
|
|
721
|
+
const schemaFactory = new SchemaFactory("demo");
|
|
722
|
+
|
|
723
|
+
// Bad: This loses the schema aware type information. `: TreeNodeSchema` should be omitted to preserve strong typing.
|
|
724
|
+
const schema: TreeNodeSchema = schemaFactory.array(schemaFactory.number);
|
|
725
|
+
const config = new TreeViewConfiguration({ schema });
|
|
726
|
+
|
|
727
|
+
// This view is typed as `TreeView<TreeNodeSchema>`, which does not work well since it's missing the actual schema type information.
|
|
728
|
+
const view = tree.viewWith(config);
|
|
729
|
+
// Root is typed as `unknown` allowing invalid assignment operations.
|
|
730
|
+
view.root = "invalid";
|
|
731
|
+
view.root = {};
|
|
732
|
+
// Since all assignments are allowed, valid ones still work:
|
|
733
|
+
view.root = [];
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
After this change:
|
|
737
|
+
|
|
738
|
+
```typescript
|
|
739
|
+
// Root is now typed as `TreeNode | TreeLeafValue`, still allowing some invalid assignment operations.
|
|
740
|
+
// In the future this should be prevented as well, since the type of the setter in this case should be `never`.
|
|
741
|
+
view.root = "invalid";
|
|
742
|
+
// This no longer compiles:
|
|
743
|
+
view.root = {};
|
|
744
|
+
// This also no longer compiles despite being valid at runtime:
|
|
745
|
+
view.root = [];
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
For code that wants to continue using an unsafe API, which can result in runtime errors if the data does not follow the schema, a new alternative has been added to address this use-case. A special type `UnsafeUnknownSchema` can now be used to opt into allowing all valid trees to be provided.
|
|
749
|
+
Note that this leaves ensuring the data is in schema up to the user.
|
|
750
|
+
For now these adjusted APIs can be accessed by casting the view to `TreeViewAlpha<UnsafeUnknownSchema>`.
|
|
751
|
+
If stabilized, this option will be added to `TreeView` directly.
|
|
752
|
+
|
|
753
|
+
```typescript
|
|
754
|
+
const viewAlpha = view as TreeViewAlpha<UnsafeUnknownSchema>;
|
|
755
|
+
viewAlpha.initialize([]);
|
|
756
|
+
viewAlpha.root = [];
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
Additionally, this seems to have negatively impacted co-recursive schema which declare a co-recursive array as the first schema in the co-recursive cycle.
|
|
760
|
+
Like the TypeScript language our schema system is built on, we don't guarantee exactly which recursive type will compile, but will do our best to ensure useful recursive schema can be created easily.
|
|
761
|
+
In this case a slight change may be required to some recursive schema to get them to compile again:
|
|
762
|
+
|
|
763
|
+
For example this schema used to compile:
|
|
764
|
+
|
|
765
|
+
```typescript
|
|
766
|
+
class A extends sf.arrayRecursive("A", [() => B]) {}
|
|
767
|
+
{
|
|
768
|
+
type _check = ValidateRecursiveSchema<typeof A>;
|
|
769
|
+
}
|
|
770
|
+
// Used to work, but breaks in this update.
|
|
771
|
+
class B extends sf.object("B", { x: A }) {}
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
But now you must use the recursive functions like `objectRecursive` for types which are co-recursive with an array in some cases.
|
|
775
|
+
In our example, it can be fixed as follows:
|
|
776
|
+
|
|
777
|
+
```typescript
|
|
778
|
+
class A extends sf.arrayRecursive("A", [() => B]) {}
|
|
779
|
+
{
|
|
780
|
+
type _check = ValidateRecursiveSchema<typeof A>;
|
|
781
|
+
}
|
|
782
|
+
// Fixed corecursive type, using "Recursive" method variant to declare schema.
|
|
783
|
+
class B extends sf.objectRecursive("B", { x: A }) {}
|
|
784
|
+
{
|
|
785
|
+
type _check = ValidateRecursiveSchema<typeof B>;
|
|
786
|
+
}
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
Note: while the following pattern may still compile, we recommend using the previous pattern instead since the one below may break in the future.
|
|
790
|
+
|
|
791
|
+
```typescript
|
|
792
|
+
class B extends sf.objectRecursive("B", { x: [() => A] }) {}
|
|
793
|
+
{
|
|
794
|
+
type _check = ValidateRecursiveSchema<typeof B>;
|
|
795
|
+
}
|
|
796
|
+
// Works, for now, but not recommended.
|
|
797
|
+
class A extends sf.array("A", B) {}
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
- The strictness of input tree types when inexact schemas are provided has been improved ([#22874](https://github.com/microsoft/FluidFramework/pull/22874)) [645b9ed695](https://github.com/microsoft/FluidFramework/commit/645b9ed69540338843ad14f1144ff4d1f80d6f09)
|
|
801
|
+
|
|
802
|
+
Consider the following code where the type of the schema is not exactly specified:
|
|
803
|
+
|
|
804
|
+
```typescript
|
|
805
|
+
const schemaFactory = new SchemaFactory("com.myApp");
|
|
806
|
+
class A extends schemaFactory.object("A", {}) {}
|
|
807
|
+
class B extends schemaFactory.array("B", schemaFactory.number) {}
|
|
808
|
+
|
|
809
|
+
// Gives imprecise type (typeof A | typeof B)[]. The desired precise type here is [typeof A, typeof B].
|
|
810
|
+
const schema = [A, B];
|
|
811
|
+
|
|
812
|
+
const config = new TreeViewConfiguration({ schema });
|
|
813
|
+
const view = sharedTree.viewWith(config);
|
|
814
|
+
|
|
815
|
+
// Does not compile since setter for root is typed `never` due to imprecise schema.
|
|
816
|
+
view.root = [];
|
|
817
|
+
```
|
|
818
|
+
|
|
819
|
+
The assignment of `view.root` is disallowed since a schema with type `(typeof A | typeof B)[]` could be any of:
|
|
820
|
+
|
|
821
|
+
```typescript
|
|
822
|
+
const schema: (typeof A | typeof B)[] = [A];
|
|
823
|
+
```
|
|
824
|
+
|
|
825
|
+
```typescript
|
|
826
|
+
const schema: (typeof A | typeof B)[] = [B];
|
|
827
|
+
```
|
|
828
|
+
|
|
829
|
+
```typescript
|
|
830
|
+
const schema: (typeof A | typeof B)[] = [A, B];
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
The attempted assignment is not compatible with all of these (specifically it is incompatible with the first one) so performing this assignment could make the tree out of schema and is thus disallowed.
|
|
834
|
+
|
|
835
|
+
To avoid this ambiguity and capture the precise type of `[typeof A, typeof B]`, use one of the following patterns:
|
|
836
|
+
|
|
837
|
+
```typescript
|
|
838
|
+
const schema = [A, B] as const;
|
|
839
|
+
const config = new TreeViewConfiguration({ schema });
|
|
840
|
+
```
|
|
841
|
+
|
|
842
|
+
```typescript
|
|
843
|
+
const config = new TreeViewConfiguration({ schema: [A, B] });
|
|
844
|
+
```
|
|
845
|
+
|
|
846
|
+
To help update existing code which accidentally depended on this bug, an `@alpha` API `unsafeArrayToTuple` has been added.
|
|
847
|
+
Many usages of this API will produce incorrectly typed outputs.
|
|
848
|
+
However, when given `AllowedTypes` arrays which should not contain any unions, but that were accidentally flattened to a single union, it can fix them:
|
|
849
|
+
|
|
850
|
+
```typescript
|
|
851
|
+
// Gives imprecise type (typeof A | typeof B)[]
|
|
852
|
+
const schemaBad = [A, B];
|
|
853
|
+
// Fixes the type to be [typeof A, typeof B]
|
|
854
|
+
const schema = unsafeArrayToTuple(schemaBad);
|
|
855
|
+
|
|
856
|
+
const config = new TreeViewConfiguration({ schema });
|
|
857
|
+
```
|
|
856
858
|
|
|
857
|
-
|
|
858
|
-
const factory = new SchemaFactory("example");
|
|
859
|
-
class Point2d extends factory.object("Point2d", {
|
|
860
|
-
x: factory.number,
|
|
861
|
-
y: factory.number,
|
|
862
|
-
}) {}
|
|
859
|
+
## 2.4.0
|
|
863
860
|
|
|
864
|
-
|
|
861
|
+
### Minor Changes
|
|
865
862
|
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
863
|
+
- ✨ New! Alpha API for providing SharedTree configuration options ([#22701](https://github.com/microsoft/FluidFramework/pull/22701)) [40d3648ddf](https://github.com/microsoft/FluidFramework/commit/40d3648ddfb5223ef6daef49a4f5cab1cfa52b71)
|
|
864
|
+
|
|
865
|
+
A new alpha `configuredSharedTree` had been added.
|
|
866
|
+
This allows providing configuration options, primarily for debugging, testing and evaluation of upcoming features.
|
|
867
|
+
The resulting configured `SharedTree` object can then be used in-place of the regular `SharedTree` imported from `fluid-framework`.
|
|
868
|
+
|
|
869
|
+
```typescript
|
|
870
|
+
import {
|
|
871
|
+
ForestType,
|
|
872
|
+
TreeCompressionStrategy,
|
|
873
|
+
configuredSharedTree,
|
|
874
|
+
typeboxValidator,
|
|
875
|
+
} from "@fluid-framework/alpha";
|
|
876
|
+
// Maximum debuggability and validation enabled:
|
|
877
|
+
const SharedTree = configuredSharedTree({
|
|
878
|
+
forest: ForestType.Expensive,
|
|
879
|
+
jsonValidator: typeboxValidator,
|
|
880
|
+
treeEncodeType: TreeCompressionStrategy.Uncompressed,
|
|
881
|
+
});
|
|
882
|
+
// Opts into the under development optimized tree storage planned to be the eventual default implementation:
|
|
883
|
+
const SharedTree = configuredSharedTree({
|
|
884
|
+
forest: ForestType.Optimized,
|
|
885
|
+
});
|
|
886
|
+
```
|
|
887
|
+
|
|
888
|
+
- ✨ New! Alpha API for snapshotting Schema ([#22733](https://github.com/microsoft/FluidFramework/pull/22733)) [920a65f66e](https://github.com/microsoft/FluidFramework/commit/920a65f66e0caad7e1b5e3df1e0afd3475a87c4a)
|
|
889
|
+
|
|
890
|
+
`extractPersistedSchema` can now be used to extra a JSON-compatible representation of the subset of a schema that gets stored in documents.
|
|
891
|
+
This can be used write tests which snapshot an applications schema.
|
|
892
|
+
Such tests can be used to detect schema changes which could would impact document compatibility,
|
|
893
|
+
and can be combined with the new `comparePersistedSchema` to measure what kind of compatibility impact the schema change has.
|
|
894
|
+
|
|
895
|
+
- Fix reading of `null` from unhydrated trees ([#22748](https://github.com/microsoft/FluidFramework/pull/22748)) [6a75bd0616](https://github.com/microsoft/FluidFramework/commit/6a75bd0616ecd315ae0e9458d88ba1c755dfd785)
|
|
896
|
+
|
|
897
|
+
Unhydrated trees containing object nodes with required fields set to `null` used to throw an error.
|
|
898
|
+
This was a bug: `null` is a valid value in tree's whose schema allow it, and this specific case now correctly returns `null` values when appropriate without erroring.
|
|
899
|
+
|
|
900
|
+
- ✨ New! Alpha SharedTree branching APIs ([#22550](https://github.com/microsoft/FluidFramework/pull/22550)) [8f4587c912](https://github.com/microsoft/FluidFramework/commit/8f4587c912f955c405d7bbbc5b42f3ffc3b497d7)
|
|
901
|
+
|
|
902
|
+
Several APIs have been added to allow for creating and coordinating "version-control"-style branches of the SharedTree.
|
|
903
|
+
Use the `getBranch` entry point function to acquire a branch.
|
|
904
|
+
For example:
|
|
905
|
+
|
|
906
|
+
```ts
|
|
907
|
+
function makeEditOnBranch(mainView: TreeView<typeof MySchema>) {
|
|
908
|
+
mainView.root.myData = 3;
|
|
909
|
+
const mainBranch = getBranch(mainView); // This function accepts either a view of a SharedTree (acquired e.g. via `sharedTree.viewWith(...)`) or a `SharedTree` directly.
|
|
910
|
+
const forkBranch = mainBranch.branch(); // This creates a new branch based on the existing branch.
|
|
911
|
+
const forkView = forkBranch.viewWith(
|
|
912
|
+
new TreeViewConfiguration({ schema: MySchema }),
|
|
913
|
+
); // Acquire a view of the forked branch in order to read or edit its tree.
|
|
914
|
+
forkView.root.myData = 4; // Set the value on the fork branch to be 4. The main branch still has a value of 3.
|
|
915
|
+
mainBranch.merge(forkBranch); // Merging the fork changes into the main branch causes the main branch to have a value of 4.
|
|
916
|
+
|
|
917
|
+
// Note: The main branch (and therefore, also the `forkView`) is automatically disposed by the merge.
|
|
918
|
+
// To prevent this, use `mainBranch.merge(forkBranch, false)`.
|
|
919
|
+
}
|
|
920
|
+
```
|
|
921
|
+
|
|
922
|
+
Merging any number of commits into a target branch (via the `TreeBranch.merge` method) generates a revertible for each
|
|
923
|
+
commit on the target branch. See [#22644](https://github.com/microsoft/FluidFramework/pull/22644) for more information
|
|
924
|
+
about revertible support in the branching APIs.
|
|
925
|
+
|
|
926
|
+
- SharedTree's `RestrictiveReadonlyRecord` is deprecated ([#22479](https://github.com/microsoft/FluidFramework/pull/22479)) [8be73d374d](https://github.com/microsoft/FluidFramework/commit/8be73d374de04ff6226c531ba8b562561572640f)
|
|
927
|
+
|
|
928
|
+
`RestrictiveReadonlyRecord` was an attempt to implement a version of TypeScript's built-in `Record<TKey, TValue>` type that would prohibit (instead of leaving unrestricted like Record does) values under keys that do not extend `TKey`.
|
|
929
|
+
|
|
930
|
+
The implementation of `RestrictiveReadonlyRecord` failed to accomplish this except for the edge cases where `TKey` was exactly `string` or exactly `symbol`.
|
|
931
|
+
Fixing this bug appears to be impossible within the current limitation of TypeScript, however this library does not require any case other than `TKey` being exactly `string`.
|
|
932
|
+
|
|
933
|
+
To reduce the risk of users of the tree library using the problematic `RestrictiveReadonlyRecord` type, it has been deprecated and replaced with a more specific type that avoids the bug, `RestrictiveStringRecord<TValue>`.
|
|
934
|
+
|
|
935
|
+
To highlight that this new type is not intended for direct use by users of tree, and instead is just used as part of the typing of its public API, `RestrictiveStringRecord` has been tagged with `@system`.
|
|
936
|
+
See [API Support Levels](https://fluidframework.com/docs/build/releases-and-apitags/#api-support-levels) for more details.
|
|
937
|
+
|
|
938
|
+
- Fix `.create` on structurally named MapNode and ArrayNode schema ([#22522](https://github.com/microsoft/FluidFramework/pull/22522)) [b3f91ae91c](https://github.com/microsoft/FluidFramework/commit/b3f91ae91cb750a6a7696ab5ea17c00895bb6d92)
|
|
939
|
+
|
|
940
|
+
Constructing a structurally named MapNode or ArrayNode schema (using the overload of `SchemaFactory.map` or `SchemaFactory.array` which does not take an explicit name), returned a `TreeNodeSchema` instead of a `TreeNodeSchemaNonClass`, which resulted in the `create` static method not being exposed.
|
|
941
|
+
This has been fixed, and can now be used as follows:
|
|
942
|
+
|
|
943
|
+
```typescript
|
|
944
|
+
const MyMap = schemaFactory.map(schemaFactory.number);
|
|
945
|
+
type MyMap = NodeFromSchema<typeof MyMap>;
|
|
946
|
+
const _fromMap: MyMap = MyMap.create(new MyMap());
|
|
947
|
+
const _fromIterable: MyMap = MyMap.create([]);
|
|
948
|
+
const _fromObject: MyMap = MyMap.create({});
|
|
949
|
+
```
|
|
950
|
+
|
|
951
|
+
This change causes some types to reference `TreeNodeSchemaNonClass` which did not reference it before.
|
|
952
|
+
While `TreeNodeSchemaNonClass` is `@system` (See [Fluid Releases and API Support Levels
|
|
953
|
+
](https://fluidframework.com/docs/build/releases-and-apitags/) for details) and thus not intended to be referred to by users of Fluid,
|
|
954
|
+
this change caused the TypeScript compiler to generate references to it in more cases when compiling `d.ts` files.
|
|
955
|
+
Since the TypeScript compiler is unable to generate references to `TreeNodeSchemaNonClass` with how it was nested in `internalTypes.js`,
|
|
956
|
+
this change could break the build of packages exporting types referencing structurally named map and array schema.
|
|
957
|
+
This has been mitigated by moving `TreeNodeSchemaNonClass` out of `internalTypes.js`:
|
|
958
|
+
any code importing `TreeNodeSchemaNonClass` (and thus disregarding the `@system` restriction) can be fixed by importing it from the top level instead of the `internalTypes.js`
|
|
959
|
+
|
|
960
|
+
- Non-leaf field access has been optimized ([#22717](https://github.com/microsoft/FluidFramework/pull/22717)) [6a2b68103c](https://github.com/microsoft/FluidFramework/commit/6a2b68103cc3ad56a9ac0dfcaaa8546978ec29ac)
|
|
961
|
+
|
|
962
|
+
When reading non-leaf children which have been read previously, they are retrieved from cache faster.
|
|
963
|
+
Several operations on subtrees under arrays have been optimized, including reading of non-leaf nodes for the first time.
|
|
964
|
+
Overall this showed a roughly 5% speed up in a read heavy test application (the BubbleBench example) but gains are expected to vary a lot based on use-case.
|
|
965
|
+
|
|
966
|
+
- ✨ New! Alpha APIs for producing SharedTree schema from enums ([#20035](https://github.com/microsoft/FluidFramework/pull/20035)) [5f9bbe011a](https://github.com/microsoft/FluidFramework/commit/5f9bbe011a18ccac08a70340f6d20e60ce30c4a4)
|
|
967
|
+
|
|
968
|
+
`adaptEnum` and `enumFromStrings` have been added to `@fluidframework/tree/alpha` and `fluid-framework/alpha`.
|
|
969
|
+
These unstable alpha APIs are relatively simple helpers on-top of public APIs (source: [schemaCreationUtilities.ts](https://github.com/microsoft/FluidFramework/blob/main/packages/dds/tree/src/simple-tree/schemaCreationUtilities.ts)):
|
|
970
|
+
thus if these change or stable alternatives are needed, an application can replicate this functionality using these implementations as an example.
|
|
873
971
|
|
|
874
|
-
|
|
875
|
-
which properties of the node changed.
|
|
972
|
+
## 2.3.0
|
|
876
973
|
|
|
877
|
-
|
|
878
|
-
identifiers (or "stored keys") that can be provided through `FieldProps` when defining a schema.
|
|
879
|
-
See the documentation for `FieldProps` for more details about the distinction between "property keys" and "stored keys".
|
|
974
|
+
### Minor Changes
|
|
880
975
|
|
|
881
|
-
|
|
976
|
+
- Add /alpha import path to @fluidframework/tree and fluid-framework packages ([#22483](https://github.com/microsoft/FluidFramework/pull/22483)) [12242cfdb5a](https://github.com/microsoft/FluidFramework/commit/12242cfdb5aa4c342cc62f11cbf1c072840bec44)
|
|
882
977
|
|
|
883
|
-
|
|
978
|
+
`@fluidframework/tree` and `fluid-framework` now have a `/alpha` import path where their `@alpha` APIs are exported.
|
|
884
979
|
|
|
885
|
-
|
|
980
|
+
- Export SharedTree beta APIs from fluid-framework/beta ([#22469](https://github.com/microsoft/FluidFramework/pull/22469)) [c51f55c01a6](https://github.com/microsoft/FluidFramework/commit/c51f55c01a641eb030f872b684e2862e57ad5197)
|
|
886
981
|
|
|
887
|
-
|
|
888
|
-
TreeBeta.on(point, "nodeChanged", (data) => {
|
|
889
|
-
// @ts-expect-error Strong typing for changed properties of object nodes detects incorrect keys:
|
|
890
|
-
if (data.changedProperties.has("z")) {
|
|
891
|
-
// ...
|
|
892
|
-
}
|
|
893
|
-
});
|
|
894
|
-
```
|
|
982
|
+
`fluid-framework/beta` now contains the `@beta` APIs from `@fluidframework/tree/beta`.
|
|
895
983
|
|
|
896
|
-
|
|
897
|
-
This could break existing code using "nodeChanged" in a particularly fragile way.
|
|
984
|
+
- Implicitly constructed object nodes now only consider own properties during validation ([#22453](https://github.com/microsoft/FluidFramework/pull/22453)) [27faa56f5ae](https://github.com/microsoft/FluidFramework/commit/27faa56f5ae334e0b65fdd84c75764645e64f063)
|
|
898
985
|
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
```
|
|
986
|
+
When determining if some given data is compatible with a particular ObjectNode schema, both inherited and own properties were considered.
|
|
987
|
+
However, when constructing the node from this data, only own properties were used.
|
|
988
|
+
This allowed input which provided required values in inherited fields to pass validation.
|
|
989
|
+
When the node was constructed, it would lack these fields, and end up out of schema.
|
|
990
|
+
This has been fixed: both validation and node construction now only consider own properties.
|
|
905
991
|
|
|
906
|
-
|
|
907
|
-
|
|
992
|
+
This may cause some cases which previously exhibited data corruption to now throw a usage error reporting the data is incompatible.
|
|
993
|
+
Such cases may need to copy data from the objects with inherited properties into new objects with own properties before constructing nodes from them.
|
|
908
994
|
|
|
909
|
-
|
|
910
|
-
function f(optional?: number) {
|
|
911
|
-
// ...
|
|
912
|
-
}
|
|
913
|
-
Tree.on(point, "nodeChanged", () => f()); // Safe
|
|
914
|
-
```
|
|
995
|
+
- A `@beta` version of `nodeChanged` which includes the list of properties has been added ([#22229](https://github.com/microsoft/FluidFramework/pull/22229)) [aae34dd9fe1](https://github.com/microsoft/FluidFramework/commit/aae34dd9fe1aa6c153c26035f1486f4d8944c810)
|
|
915
996
|
|
|
916
|
-
|
|
997
|
+
```typescript
|
|
998
|
+
const factory = new SchemaFactory("example");
|
|
999
|
+
class Point2d extends factory.object("Point2d", {
|
|
1000
|
+
x: factory.number,
|
|
1001
|
+
y: factory.number,
|
|
1002
|
+
}) {}
|
|
917
1003
|
|
|
918
|
-
|
|
1004
|
+
const point = new Point2d({ x: 0, y: 0 });
|
|
919
1005
|
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
- There are no scenarios where they need to be used directly.
|
|
926
|
-
- Using them directly will cause eventual consistency problems.
|
|
927
|
-
- Upcoming features will require modifications to these mechanisms.
|
|
928
|
-
|
|
929
|
-
- Compile-time type narrowing based on a TreeNode's NodeKind ([#22222](https://github.com/microsoft/FluidFramework/pull/22222)) [4d3bc876ae](https://github.com/microsoft/FluidFramework/commit/4d3bc876ae32fa3f2568299e29246f6970e48ee0)
|
|
930
|
-
|
|
931
|
-
`TreeNode`'s schema-aware APIs implement `WithType`, which now has a `NodeKind` parameter that can be used to narrow `TreeNode`s based on `NodeKind`.
|
|
932
|
-
|
|
933
|
-
Example:
|
|
934
|
-
|
|
935
|
-
```typescript
|
|
936
|
-
function getKeys(node: TreeNode & WithType<string, NodeKind.Array>): number[];
|
|
937
|
-
function getKeys(node: TreeNode & WithType<string, NodeKind.Map | NodeKind.Object>): string[];
|
|
938
|
-
function getKeys(node: TreeNode): string[] | number[];
|
|
939
|
-
function getKeys(node: TreeNode): string[] | number[] {
|
|
940
|
-
const schema = Tree.schema(node);
|
|
941
|
-
switch (schema.kind) {
|
|
942
|
-
case NodeKind.Array: {
|
|
943
|
-
const arrayNode = node as TreeArrayNode;
|
|
944
|
-
const keys: number[] = [];
|
|
945
|
-
for (let index = 0; index < arrayNode.length; index++) {
|
|
946
|
-
keys.push(index);
|
|
947
|
-
}
|
|
948
|
-
return keys;
|
|
949
|
-
}
|
|
950
|
-
case NodeKind.Map:
|
|
951
|
-
return [...(node as TreeMapNode).keys()];
|
|
952
|
-
case NodeKind.Object:
|
|
953
|
-
return Object.keys(node);
|
|
954
|
-
default:
|
|
955
|
-
throw new Error("Unsupported Kind");
|
|
956
|
-
}
|
|
1006
|
+
TreeBeta.on(point, "nodeChanged", (data) => {
|
|
1007
|
+
const changed: ReadonlySet<"x" | "y"> = data.changedProperties;
|
|
1008
|
+
if (changed.has("x")) {
|
|
1009
|
+
// ...
|
|
957
1010
|
}
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
- ✨ New! `Record`-typed objects can now be used to construct MapNodes ([#22042](https://github.com/microsoft/FluidFramework/pull/22042)) [25deff344b](https://github.com/microsoft/FluidFramework/commit/25deff344b447380486c1efb64ed69177c32ddc5)
|
|
961
|
-
|
|
962
|
-
You can now construct MapNodes from `Record` typed objects, similar to how maps are expressed in JSON.
|
|
963
|
-
|
|
964
|
-
Before this change, an `Iterable<string, Child>` was required, but now an object like `{key1: Child1, key2: Child2}` is allowed.
|
|
965
|
-
|
|
966
|
-
Full example using this new API:
|
|
967
|
-
|
|
968
|
-
```typescript
|
|
969
|
-
class Schema extends schemaFactory.map("ExampleMap", schemaFactory.number) {}
|
|
970
|
-
const fromRecord = new Schema({ x: 5 });
|
|
971
|
-
```
|
|
1011
|
+
});
|
|
1012
|
+
```
|
|
972
1013
|
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
or IFluidHandles (which themselves are not JSON compatible).
|
|
1014
|
+
The payload of the `nodeChanged` event emitted by SharedTree's `TreeBeta` includes a `changedProperties` property that indicates
|
|
1015
|
+
which properties of the node changed.
|
|
976
1016
|
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
1017
|
+
For object nodes, the list of properties uses the property identifiers defined in the schema, and not the persisted
|
|
1018
|
+
identifiers (or "stored keys") that can be provided through `FieldProps` when defining a schema.
|
|
1019
|
+
See the documentation for `FieldProps` for more details about the distinction between "property keys" and "stored keys".
|
|
980
1020
|
|
|
981
|
-
|
|
1021
|
+
For map nodes, every key that was added, removed, or updated by a change to the tree is included in the list of properties.
|
|
982
1022
|
|
|
983
|
-
|
|
1023
|
+
For array nodes, the set of properties will always be undefined: there is currently no API to get details about changes to an array.
|
|
984
1024
|
|
|
985
|
-
|
|
1025
|
+
Object nodes revieve strongly types sets of changed keys, allowing compile time detection of incorrect keys:
|
|
986
1026
|
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
});
|
|
996
|
-
const view = tree.viewWith(config);
|
|
997
|
-
// This is invalid since it is ambiguous which type of node is being constructed.
|
|
998
|
-
// The error thrown above when constructing the TreeViewConfiguration is because of this ambiguous case:
|
|
999
|
-
view.initialize({ length: 5 });
|
|
1000
|
-
```
|
|
1001
|
-
|
|
1002
|
-
See the documentation on `ITreeConfigurationOptions.preventAmbiguity` for a more complete example and more details.
|
|
1003
|
-
|
|
1004
|
-
- `Tree.schema` now returns `TreeNodeSchema` ([#22185](https://github.com/microsoft/FluidFramework/pull/22185)) [bfe8310a94](https://github.com/microsoft/FluidFramework/commit/bfe8310a9406a8658c2fac8827c7114844c32234)
|
|
1005
|
-
|
|
1006
|
-
The typing of `Tree.schema` has changed from:
|
|
1027
|
+
```typescript
|
|
1028
|
+
TreeBeta.on(point, "nodeChanged", (data) => {
|
|
1029
|
+
// @ts-expect-error Strong typing for changed properties of object nodes detects incorrect keys:
|
|
1030
|
+
if (data.changedProperties.has("z")) {
|
|
1031
|
+
// ...
|
|
1032
|
+
}
|
|
1033
|
+
});
|
|
1034
|
+
```
|
|
1007
1035
|
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
```
|
|
1036
|
+
The existing stable "nodeChanged" event's callback now is given a parameter called `unstable` of type `unknown` which is used to indicate that additional data can be provided there.
|
|
1037
|
+
This could break existing code using "nodeChanged" in a particularly fragile way.
|
|
1011
1038
|
|
|
1012
|
-
|
|
1039
|
+
```typescript
|
|
1040
|
+
function f(optional?: number) {
|
|
1041
|
+
// ...
|
|
1042
|
+
}
|
|
1043
|
+
Tree.on(point, "nodeChanged", f); // Bad
|
|
1044
|
+
```
|
|
1013
1045
|
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
```
|
|
1046
|
+
Code like this which is implicitly discarding an optional argument from the function used as the listener will be broken.
|
|
1047
|
+
It can be fixed by using an inline lambda expression:
|
|
1017
1048
|
|
|
1018
|
-
|
|
1049
|
+
```typescript
|
|
1050
|
+
function f(optional?: number) {
|
|
1051
|
+
// ...
|
|
1052
|
+
}
|
|
1053
|
+
Tree.on(point, "nodeChanged", () => f()); // Safe
|
|
1054
|
+
```
|
|
1019
1055
|
|
|
1020
|
-
|
|
1056
|
+
## 2.2.0
|
|
1021
1057
|
|
|
1022
|
-
|
|
1023
|
-
When the type of the input is not known precisely (for example it is a union of node types like `Foo | Bar`, or `TreeNode` or even `TreeNode | TreeLeafValue`), this was fine since schema are covariant over their node type.
|
|
1024
|
-
However when the input was more specific that the schema type, for example the type is simply `0`, this would result in unsound typing, since the create function could actually return values that did not conform with that schema (for example `schema.create(1)` for the number schema typed with `0` would return `1` with type `0`).
|
|
1025
|
-
2. The node type was provided to the incorrect type parameter of TreeNodeSchema.
|
|
1026
|
-
The `TNode` parameter is the third one, not the fourth.
|
|
1027
|
-
The fourth is `TBuild` which sets the input accepted to its create function or constructor.
|
|
1028
|
-
Thus this code accidentally left `TNode` unset (which is good due to the above issue), but invalidly set `TBuild`.
|
|
1029
|
-
`TBuild` is contravariant, so it has the opposite issue that setting `TNode` would have: if your input is simply typed as something general like `TreeNode`, then the returned schema would claim to be able to construct an instance given any `TreeNode`.
|
|
1030
|
-
This is incorrect, and this typing has been removed.
|
|
1058
|
+
### Minor Changes
|
|
1031
1059
|
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1060
|
+
- The PropertyManager class and related functions and properties are deprecated ([#22183](https://github.com/microsoft/FluidFramework/pull/22183)) [cbba69554f](https://github.com/microsoft/FluidFramework/commit/cbba69554fc5026f562f44683a902474fabd6e81)
|
|
1061
|
+
|
|
1062
|
+
The `PropertyManager` class, along with the `propertyManager` properties and `addProperties` functions on segments and intervals, are not intended for external use.
|
|
1063
|
+
These elements will be removed in a future release for the following reasons:
|
|
1064
|
+
|
|
1065
|
+
- There are no scenarios where they need to be used directly.
|
|
1066
|
+
- Using them directly will cause eventual consistency problems.
|
|
1067
|
+
- Upcoming features will require modifications to these mechanisms.
|
|
1068
|
+
|
|
1069
|
+
- Compile-time type narrowing based on a TreeNode's NodeKind ([#22222](https://github.com/microsoft/FluidFramework/pull/22222)) [4d3bc876ae](https://github.com/microsoft/FluidFramework/commit/4d3bc876ae32fa3f2568299e29246f6970e48ee0)
|
|
1070
|
+
|
|
1071
|
+
`TreeNode`'s schema-aware APIs implement `WithType`, which now has a `NodeKind` parameter that can be used to narrow `TreeNode`s based on `NodeKind`.
|
|
1072
|
+
|
|
1073
|
+
Example:
|
|
1074
|
+
|
|
1075
|
+
```typescript
|
|
1076
|
+
function getKeys(node: TreeNode & WithType<string, NodeKind.Array>): number[];
|
|
1077
|
+
function getKeys(
|
|
1078
|
+
node: TreeNode & WithType<string, NodeKind.Map | NodeKind.Object>,
|
|
1079
|
+
): string[];
|
|
1080
|
+
function getKeys(node: TreeNode): string[] | number[];
|
|
1081
|
+
function getKeys(node: TreeNode): string[] | number[] {
|
|
1082
|
+
const schema = Tree.schema(node);
|
|
1083
|
+
switch (schema.kind) {
|
|
1084
|
+
case NodeKind.Array: {
|
|
1085
|
+
const arrayNode = node as TreeArrayNode;
|
|
1086
|
+
const keys: number[] = [];
|
|
1087
|
+
for (let index = 0; index < arrayNode.length; index++) {
|
|
1088
|
+
keys.push(index);
|
|
1089
|
+
}
|
|
1090
|
+
return keys;
|
|
1091
|
+
}
|
|
1092
|
+
case NodeKind.Map:
|
|
1093
|
+
return [...(node as TreeMapNode).keys()];
|
|
1094
|
+
case NodeKind.Object:
|
|
1095
|
+
return Object.keys(node);
|
|
1096
|
+
default:
|
|
1097
|
+
throw new Error("Unsupported Kind");
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
```
|
|
1037
1101
|
|
|
1038
|
-
-
|
|
1102
|
+
- ✨ New! `Record`-typed objects can now be used to construct MapNodes ([#22042](https://github.com/microsoft/FluidFramework/pull/22042)) [25deff344b](https://github.com/microsoft/FluidFramework/commit/25deff344b447380486c1efb64ed69177c32ddc5)
|
|
1039
1103
|
|
|
1040
|
-
|
|
1104
|
+
You can now construct MapNodes from `Record` typed objects, similar to how maps are expressed in JSON.
|
|
1041
1105
|
|
|
1042
|
-
|
|
1043
|
-
|
|
1106
|
+
Before this change, an `Iterable<string, Child>` was required, but now an object like `{key1: Child1, key2: Child2}` is allowed.
|
|
1107
|
+
|
|
1108
|
+
Full example using this new API:
|
|
1109
|
+
|
|
1110
|
+
```typescript
|
|
1111
|
+
class Schema extends schemaFactory.map("ExampleMap", schemaFactory.number) {}
|
|
1112
|
+
const fromRecord = new Schema({ x: 5 });
|
|
1113
|
+
```
|
|
1114
|
+
|
|
1115
|
+
This new feature makes it possible for schemas to construct a tree entirely from JSON-compatible objects using their constructors,
|
|
1116
|
+
as long as they do not require unhydrated nodes to differentiate ambiguous unions,
|
|
1117
|
+
or IFluidHandles (which themselves are not JSON compatible).
|
|
1118
|
+
|
|
1119
|
+
Due to limitations of TypeScript and recursive types,
|
|
1120
|
+
recursive maps do not advertise support for this feature in their typing,
|
|
1121
|
+
but it works at runtime.
|
|
1122
|
+
|
|
1123
|
+
- New SharedTree configuration option: `ITreeConfigurationOptions.preventAmbiguity` ([#22048](https://github.com/microsoft/FluidFramework/pull/22048)) [966906a034](https://github.com/microsoft/FluidFramework/commit/966906a03490daa5a914030b37342abb8267c12d)
|
|
1124
|
+
|
|
1125
|
+
The new `ITreeConfigurationOptions.preventAmbiguity` flag can be set to true to enable checking of some additional rules when constructing the `TreeViewConfiguration`.
|
|
1126
|
+
|
|
1127
|
+
This example shows an ambiguous schema:
|
|
1128
|
+
|
|
1129
|
+
```typescript
|
|
1130
|
+
const schemaFactory = new SchemaFactory("com.example");
|
|
1131
|
+
class Feet extends schemaFactory.object("Feet", {
|
|
1132
|
+
length: schemaFactory.number,
|
|
1133
|
+
}) {}
|
|
1134
|
+
class Meters extends schemaFactory.object("Meters", {
|
|
1135
|
+
length: schemaFactory.number,
|
|
1136
|
+
}) {}
|
|
1137
|
+
const config = new TreeViewConfiguration({
|
|
1138
|
+
// This combination of schema can lead to ambiguous cases, and will error since preventAmbiguity is true.
|
|
1139
|
+
schema: [Feet, Meters],
|
|
1140
|
+
preventAmbiguity: true,
|
|
1141
|
+
});
|
|
1142
|
+
const view = tree.viewWith(config);
|
|
1143
|
+
// This is invalid since it is ambiguous which type of node is being constructed.
|
|
1144
|
+
// The error thrown above when constructing the TreeViewConfiguration is because of this ambiguous case:
|
|
1145
|
+
view.initialize({ length: 5 });
|
|
1146
|
+
```
|
|
1147
|
+
|
|
1148
|
+
See the documentation on `ITreeConfigurationOptions.preventAmbiguity` for a more complete example and more details.
|
|
1149
|
+
|
|
1150
|
+
- `Tree.schema` now returns `TreeNodeSchema` ([#22185](https://github.com/microsoft/FluidFramework/pull/22185)) [bfe8310a94](https://github.com/microsoft/FluidFramework/commit/bfe8310a9406a8658c2fac8827c7114844c32234)
|
|
1151
|
+
|
|
1152
|
+
The typing of `Tree.schema` has changed from:
|
|
1153
|
+
|
|
1154
|
+
```typescript
|
|
1155
|
+
schema<T extends TreeNode | TreeLeafValue>(node: T): TreeNodeSchema<string, NodeKind, unknown, T>;
|
|
1156
|
+
```
|
|
1157
|
+
|
|
1158
|
+
to:
|
|
1159
|
+
|
|
1160
|
+
```typescript
|
|
1161
|
+
schema(node: TreeNode | TreeLeafValue): TreeNodeSchema;
|
|
1162
|
+
```
|
|
1163
|
+
|
|
1164
|
+
The runtime behavior is unaffected: any code which worked and still compiles is fine and does not need changes.
|
|
1165
|
+
|
|
1166
|
+
`Tree.schema` was changed to mitigate two different issues:
|
|
1167
|
+
|
|
1168
|
+
1. It tried to give a more specific type based on the type of the passed in value.
|
|
1169
|
+
When the type of the input is not known precisely (for example it is a union of node types like `Foo | Bar`, or `TreeNode` or even `TreeNode | TreeLeafValue`), this was fine since schema are covariant over their node type.
|
|
1170
|
+
However when the input was more specific that the schema type, for example the type is simply `0`, this would result in unsound typing, since the create function could actually return values that did not conform with that schema (for example `schema.create(1)` for the number schema typed with `0` would return `1` with type `0`).
|
|
1171
|
+
2. The node type was provided to the incorrect type parameter of TreeNodeSchema.
|
|
1172
|
+
The `TNode` parameter is the third one, not the fourth.
|
|
1173
|
+
The fourth is `TBuild` which sets the input accepted to its create function or constructor.
|
|
1174
|
+
Thus this code accidentally left `TNode` unset (which is good due to the above issue), but invalidly set `TBuild`.
|
|
1175
|
+
`TBuild` is contravariant, so it has the opposite issue that setting `TNode` would have: if your input is simply typed as something general like `TreeNode`, then the returned schema would claim to be able to construct an instance given any `TreeNode`.
|
|
1176
|
+
This is incorrect, and this typing has been removed.
|
|
1177
|
+
|
|
1178
|
+
Fortunately it should be rare for code to be impacted by this issue.
|
|
1179
|
+
Any code which manually specified a generic type parameter to `Tree.schema()` will break, as well as code which assigned its result to an overly specifically typed variable.
|
|
1180
|
+
Code which used `typeof` on the returned schema could also break, though there are few use-cases for this so such code is not expected to exist.
|
|
1181
|
+
Currently it's very difficult to invoke the create function or constructor associated with a `TreeNodeSchema` as doing so already requires narrowing to `TreeNodeSchemaClass` or `TreeNodeSchemaNonClass`.
|
|
1182
|
+
It is possible some such code exists which will need to have an explicit cast added because it happened to work with the more specific (but incorrect) constructor input type.
|
|
1183
|
+
|
|
1184
|
+
- Recursive SharedTree schemas using MapNodes no longer produce invalid d.ts files ([#22106](https://github.com/microsoft/FluidFramework/pull/22106)) [554fc5a94e](https://github.com/microsoft/FluidFramework/commit/554fc5a94e57e2d109ea9008b7c64517c58a6b73)
|
|
1185
|
+
|
|
1186
|
+
Consider a recursive SharedTree schema like the following, which follows all our recommended best practices:
|
|
1187
|
+
|
|
1188
|
+
```typescript
|
|
1189
|
+
export class RecursiveMap extends schema.mapRecursive("RM", [
|
|
1190
|
+
() => RecursiveMap,
|
|
1191
|
+
]) {}
|
|
1192
|
+
{
|
|
1193
|
+
type _check = ValidateRecursiveSchema<typeof RecursiveMap>;
|
|
1194
|
+
}
|
|
1195
|
+
```
|
|
1196
|
+
|
|
1197
|
+
This schema would work when used from within its compilation unit, but would generate d.ts that fails to compile when exporting it:
|
|
1198
|
+
|
|
1199
|
+
```typescript
|
|
1200
|
+
declare const RecursiveMap_base: import("@fluidframework/tree").TreeNodeSchemaClass<
|
|
1201
|
+
"com.example.RM",
|
|
1202
|
+
import("@fluidframework/tree").NodeKind.Map,
|
|
1203
|
+
import("@fluidframework/tree").TreeMapNodeUnsafe<
|
|
1204
|
+
readonly [() => typeof RecursiveMap]
|
|
1205
|
+
> &
|
|
1206
|
+
import("@fluidframework/tree").WithType<"com.example.RM">,
|
|
1044
1207
|
{
|
|
1045
|
-
|
|
1046
|
-
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
declare const RecursiveMap_base: import("@fluidframework/tree").TreeNodeSchemaClass<
|
|
1053
|
-
"com.example.RM",
|
|
1054
|
-
import("@fluidframework/tree").NodeKind.Map,
|
|
1055
|
-
import("@fluidframework/tree").TreeMapNodeUnsafe<readonly [() => typeof RecursiveMap]> &
|
|
1056
|
-
import("@fluidframework/tree").WithType<"com.example.RM">,
|
|
1057
|
-
{
|
|
1058
|
-
[Symbol.iterator](): Iterator<[string, RecursiveMap], any, undefined>;
|
|
1059
|
-
},
|
|
1060
|
-
false,
|
|
1061
|
-
readonly [() => typeof RecursiveMap]
|
|
1062
|
-
>;
|
|
1063
|
-
export declare class RecursiveMap extends RecursiveMap_base {}
|
|
1064
|
-
```
|
|
1208
|
+
[Symbol.iterator](): Iterator<[string, RecursiveMap], any, undefined>;
|
|
1209
|
+
},
|
|
1210
|
+
false,
|
|
1211
|
+
readonly [() => typeof RecursiveMap]
|
|
1212
|
+
>;
|
|
1213
|
+
export declare class RecursiveMap extends RecursiveMap_base {}
|
|
1214
|
+
```
|
|
1065
1215
|
|
|
1066
|
-
|
|
1216
|
+
This results in the compile error in TypeScript 5.4.5:
|
|
1067
1217
|
|
|
1068
|
-
|
|
1218
|
+
> error TS2310: Type 'RecursiveMap' recursively references itself as a base type.
|
|
1069
1219
|
|
|
1070
|
-
|
|
1220
|
+
With this change, that error is fixed by modifying the `TreeMapNodeUnsafe` type it references to inline the definition of `ReadonlyMap` instead of using the one from the TypeScript standard library.
|
|
1071
1221
|
|
|
1072
|
-
-
|
|
1222
|
+
- ✨ New! When unambiguous, ArrayNodes can now be constructed from Maps and MapNodes from arrays ([#22036](https://github.com/microsoft/FluidFramework/pull/22036)) [25e74f9f3b](https://github.com/microsoft/FluidFramework/commit/25e74f9f3bed6e6ff041c088813c4cc1ea276b9c)
|
|
1073
1223
|
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1224
|
+
Since the types for ArrayNodes and MapNodes indicate they can be constructed from iterables,
|
|
1225
|
+
it should work, even if those iterables are themselves arrays or maps.
|
|
1226
|
+
To avoid this being a breaking change, a priority system was introduced.
|
|
1227
|
+
ArrayNodes will only be implicitly constructable from JavaScript Map objects in contexts where no MapNodes are allowed.
|
|
1228
|
+
Similarly MapNodes will only be implicitly constructable from JavaScript Array objects in contexts where no ArrayNodes are allowed.
|
|
1079
1229
|
|
|
1080
|
-
|
|
1230
|
+
In practice, the main case in which this is likely to matter is when implicitly constructing a map node. If you provide an array of key value pairs, this now works instead of erroring, as long as no ArrayNode is valid at that location in the tree.
|
|
1081
1231
|
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1232
|
+
```typescript
|
|
1233
|
+
class MyMapNode extends schemaFactory.map("x", schemaFactory.number) {}
|
|
1234
|
+
class Root extends schemaFactory.object("root", { data: MyMapNode }) {}
|
|
1235
|
+
// This now works (before it compiled, but error at runtime):
|
|
1236
|
+
const fromArray = new Root({ data: [["x", 5]] });
|
|
1237
|
+
```
|
|
1088
1238
|
|
|
1089
|
-
|
|
1239
|
+
Prior versions used to have to do:
|
|
1090
1240
|
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1241
|
+
```typescript
|
|
1242
|
+
new Root({ data: new MyMapNode([["x", 5]]) });
|
|
1243
|
+
```
|
|
1094
1244
|
|
|
1095
|
-
|
|
1245
|
+
or:
|
|
1096
1246
|
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1247
|
+
```typescript
|
|
1248
|
+
new Root({ data: new Map([["x", 5]]) });
|
|
1249
|
+
```
|
|
1100
1250
|
|
|
1101
|
-
|
|
1251
|
+
Both of these options still work: strictly more cases are allowed with this change.
|
|
1102
1252
|
|
|
1103
|
-
-
|
|
1253
|
+
- Implicit TreeNode construction improvements ([#21995](https://github.com/microsoft/FluidFramework/pull/21995)) [977f96c1a0](https://github.com/microsoft/FluidFramework/commit/977f96c1a0dd1d5eb0dbcd087d07cb7510d533ea)
|
|
1104
1254
|
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1255
|
+
ArrayNodes and MapNodes could always be explicitly constructed (using `new`) from iterables.
|
|
1256
|
+
The types also allowed using of iterables to implicitly construct array nodes and map nodes,
|
|
1257
|
+
but this did not work at runtime.
|
|
1258
|
+
This has been fixed for all cases except implicitly constructing an ArrayNode form an `Iterable` that is actually a `Map`,
|
|
1259
|
+
and implicitly constructing a MapNode from an `Iterable` that is actually an `Array`.
|
|
1260
|
+
These cases may be fixed in the future, but require additional work to ensure unions of array nodes and map nodes work correctly.
|
|
1111
1261
|
|
|
1112
|
-
|
|
1262
|
+
Additionally MapNodes can now be constructed from `Iterator<readonly [string, content]>` where previously the inner arrays had to be mutable.
|
|
1113
1263
|
|
|
1114
|
-
-
|
|
1264
|
+
- Enforce use of TreeViewConfiguration's constructor ([#22055](https://github.com/microsoft/FluidFramework/pull/22055)) [e8955579f6](https://github.com/microsoft/FluidFramework/commit/e8955579f6d52a6c7e300642088c60d6ed12d7db)
|
|
1115
1265
|
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1266
|
+
`TreeViewConfiguration` is `@sealed`, meaning creating custom implementations of it such as assigning object literals to a `TreeViewConfiguration` or sub-classing it are not supported.
|
|
1267
|
+
This reserved the ability for the Fluid Framework to add members to this class over time, informing users that they must use it in such a way where such changes are non-breaking.
|
|
1268
|
+
However, there was no compiler-based enforcement of this expectation.
|
|
1269
|
+
It was only indicated via documentation and an implicit assumption that when an API takes in a typed defined as a class, that an instance of that class must be used rather than an arbitrary object of a similar shape.
|
|
1120
1270
|
|
|
1121
|
-
|
|
1271
|
+
With this change, the TypeScript compiler will now inform users when they invalidly provide an object literal as a `TreeViewConfiguration`.
|
|
1122
1272
|
|
|
1123
|
-
|
|
1273
|
+
More specifically this causes code like this to produce a compile error:
|
|
1124
1274
|
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1275
|
+
```typescript
|
|
1276
|
+
// Don't do this!
|
|
1277
|
+
const view = tree.viewWith({
|
|
1278
|
+
schema: TestNode,
|
|
1279
|
+
enableSchemaValidation: false,
|
|
1280
|
+
});
|
|
1281
|
+
```
|
|
1129
1282
|
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1283
|
+
The above was never intended to work, and is not a supported use of the `viewWith` since it requires a `TreeViewConfiguration` which is sealed.
|
|
1284
|
+
Any code using the above pattern will break in Fluid Framework 2.2 and above. Such code will need to be updated to the pattern shown below.
|
|
1285
|
+
Any code broken by this change is technically unsupported and only worked due to a gap in the type checking. This is not considered a breaking change.
|
|
1286
|
+
The correct way to get a `TreeViewConfiguration` is by using its constructor:
|
|
1134
1287
|
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1288
|
+
```typescript
|
|
1289
|
+
// This pattern correctly initializes default values and validates input.
|
|
1290
|
+
const view = tree.viewWith(new TreeViewConfiguration({ schema: TestNode }));
|
|
1291
|
+
```
|
|
1139
1292
|
|
|
1140
|
-
|
|
1293
|
+
Skipping the constructor causes the following problems:
|
|
1141
1294
|
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1295
|
+
1. `TreeViewConfiguration` does validation in its constructor, so skipping it also skips the validation which leads to much less friendly error messages for invalid schema.
|
|
1296
|
+
2. Skipping the constructor also discards any default values for options like `enableSchemaValidation`.
|
|
1297
|
+
This means that code written in that style would break if more options were added. Since such changes are planned,
|
|
1298
|
+
it is not practical to support this pattern.
|
|
1146
1299
|
|
|
1147
|
-
-
|
|
1300
|
+
- New `isFluidHandle` type guard to check if an object is an `IFluidHandle` ([#22029](https://github.com/microsoft/FluidFramework/pull/22029)) [7827d1040a](https://github.com/microsoft/FluidFramework/commit/7827d1040a9ebc0bd11388dc31f15370ea9f68d3)
|
|
1148
1301
|
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1302
|
+
The `isFluidHandle` type guard function is now exported and can be used to detect which objects are `IFluidHandle`s.
|
|
1303
|
+
Since `IFluidHandle` often needs special handling (for example when serializing since it's not JSON compatible),
|
|
1304
|
+
having a dedicated detection function for it is useful.
|
|
1305
|
+
Doing this detection was possible previously using the `tree` package's schema system via `Tree.is(value, new SchemaFactory("").handle)`,
|
|
1306
|
+
but can now be done with just `isFluidHandle(value)`.
|
|
1154
1307
|
|
|
1155
|
-
-
|
|
1308
|
+
- Add a function `isRepoSuperset` to determine if changes to a document schema are backward-compatible ([#22045](https://github.com/microsoft/FluidFramework/pull/22045)) [f6fdc95bb3](https://github.com/microsoft/FluidFramework/commit/f6fdc95bb36a892710bc315aae85fd2c75aec975)
|
|
1156
1309
|
|
|
1157
|
-
|
|
1310
|
+
Note: These changes are not customer-facing and make progress toward future plans in Tree's schema evolution space.
|
|
1158
1311
|
|
|
1159
1312
|
## 2.1.0
|
|
1160
1313
|
|
|
1161
1314
|
### Minor Changes
|
|
1162
1315
|
|
|
1163
|
-
-
|
|
1316
|
+
- Detect arrayNode iterator invalidation ([#21760](https://github.com/microsoft/FluidFramework/pull/21760)) [6fd320c385](https://github.com/microsoft/FluidFramework/commit/6fd320c38561e272a1acaf4248f47fc386c650e4)
|
|
1164
1317
|
|
|
1165
|
-
|
|
1318
|
+
When `arrayNode`s are edited concurrently during iteration, an error will be thrown.
|
|
1166
1319
|
|
|
1167
|
-
-
|
|
1320
|
+
- Some SharedDirectory/SharedMap-related APIs have been sealed ([#21836](https://github.com/microsoft/FluidFramework/pull/21836)) [b1d0427eab](https://github.com/microsoft/FluidFramework/commit/b1d0427eab3fcd55588dd80996967133db66f1b8)
|
|
1168
1321
|
|
|
1169
|
-
|
|
1322
|
+
Note that this is a _documentation only change._ There is no runtime or type-level impact.
|
|
1170
1323
|
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1324
|
+
Some top-level APIs within `@fluidframework/map` and `fluid-framework` have been updated to reflect their
|
|
1325
|
+
sealed/readonly nature. That is, they are not to be implemented externally to Fluid Framework and not changed. This was
|
|
1326
|
+
already the case, but the documentation was not clear.
|
|
1174
1327
|
|
|
1175
|
-
|
|
1328
|
+
Updated APIs:
|
|
1176
1329
|
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1330
|
+
- [IDirectory](https://fluidframework.com/docs/api/v2/fluid-framework/idirectory-interface) sealed
|
|
1331
|
+
- [IDirectoryEvents](https://fluidframework.com/docs/api/v2/fluid-framework/idirectoryevents-interface) sealed
|
|
1332
|
+
- [IDirectoryValueChanged](https://fluidframework.com/docs/api/v2/fluid-framework/idirectoryvaluechanged-interface) sealed and path property is readonly
|
|
1333
|
+
- [ISharedDirectory](https://fluidframework.com/docs/api/v2/fluid-framework/ishareddirectory-interface) sealed
|
|
1334
|
+
- [ISharedDirectoryEvents](https://fluidframework.com/docs/api/v2/fluid-framework/ishareddirectoryevents-interface) sealed
|
|
1335
|
+
- [IValueChanged](https://fluidframework.com/docs/api/v2/fluid-framework/ivaluechanged-interface) sealed
|
|
1183
1336
|
|
|
1184
|
-
-
|
|
1337
|
+
- tree: Improved performance for accessing identifiers in shortId API ([#21944](https://github.com/microsoft/FluidFramework/pull/21944)) [6b4cf26d9c](https://github.com/microsoft/FluidFramework/commit/6b4cf26d9cc14c1a36cf07fd7408f1d1227e373a)
|
|
1185
1338
|
|
|
1186
|
-
|
|
1339
|
+
Users should see improved performance when calling the `Tree.shortId` API. Identifier field keys are now cached in the schema for faster access.
|
|
1187
1340
|
|
|
1188
|
-
-
|
|
1341
|
+
- ✨ New! Debug visualizers for TreeNodes in NodeJS and browsers ([#21895](https://github.com/microsoft/FluidFramework/pull/21895)) [0d197fefec](https://github.com/microsoft/FluidFramework/commit/0d197fefec852df2911151217ac1b71cde528a70)
|
|
1189
1342
|
|
|
1190
|
-
|
|
1343
|
+
TreeNodes now have custom debug visualizers to improve the debug experience in NodeJS and in browsers. Note that custom formatters must be enabled in the browser developer tools for that visualizer to be used.
|
|
1191
1344
|
|
|
1192
|
-
-
|
|
1345
|
+
- Using "delete" on tree fields now throws an error instead of not working correctly ([#21609](https://github.com/microsoft/FluidFramework/pull/21609)) [416849b1fd](https://github.com/microsoft/FluidFramework/commit/416849b1fda029870ee1c1742100de4f8dde45b7)
|
|
1193
1346
|
|
|
1194
|
-
|
|
1195
|
-
|
|
1347
|
+
TypeScript allows `delete` on object node optional fields if the `exactOptionalPropertyTypes` tsconfig setting is not
|
|
1348
|
+
enabled. This does not work correctly at runtime and now produces an informative error.
|
|
1196
1349
|
|
|
1197
|
-
-
|
|
1350
|
+
- Improved error reporting ([#21940](https://github.com/microsoft/FluidFramework/pull/21940)) [3b8a366dd1](https://github.com/microsoft/FluidFramework/commit/3b8a366dd15660f9c916832040faf772534c0755)
|
|
1198
1351
|
|
|
1199
|
-
|
|
1200
|
-
|
|
1352
|
+
Several cases of invalid usage patterns for tree APIs have gained improved error reporting, as well as improved documentation on the APIs detailing what usage is supported.
|
|
1353
|
+
These improvements include:
|
|
1201
1354
|
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1355
|
+
- Unsupported usages of schema classes: using more than one schema class derived from a single SchemaFactory generated base class. This used to hit internal asserts, but now has a descriptive user-facing UsageError. Most of this work was done in [9fb3dcf](https://github.com/microsoft/FluidFramework/commit/9fb3dcf491a7f0d66f4abbdc64ab97ccabef4707).
|
|
1356
|
+
- Improved detection of when prior exception may have left SharedTree in an invalid state.
|
|
1357
|
+
These cases now report a UsageError including a reference to the prior exception. This was mainly done in [9fb3dcf](https://github.com/microsoft/FluidFramework/commit/9fb3dcf491a7f0d66f4abbdc64ab97ccabef4707) and [b77d530](https://github.com/microsoft/FluidFramework/commit/b77d530b9252201c40a90d1a2a6315f76f1a4a4b).
|
|
1205
1358
|
|
|
1206
1359
|
## 2.0.0-rc.5.0.0
|
|
1207
1360
|
|
|
1208
1361
|
### Minor Changes
|
|
1209
1362
|
|
|
1210
|
-
-
|
|
1363
|
+
- fluid-framework: Type Erase ISharedObjectKind ([#21081](https://github.com/microsoft/FluidFramework/pull/21081)) [78f228e370](https://github.com/microsoft/FluidFramework/commit/78f228e37055bd4d9a8f02b3a1eefebf4da9c59c)
|
|
1211
1364
|
|
|
1212
|
-
|
|
1365
|
+
A new type, `SharedObjectKind` is added as a type erased version of `ISharedObjectKind` and `DataObjectClass`.
|
|
1213
1366
|
|
|
1214
|
-
|
|
1367
|
+
This type fills the role of both `ISharedObjectKind` and `DataObjectClass` in the `@public` "declarative API" exposed in the `fluid-framework` package.
|
|
1215
1368
|
|
|
1216
|
-
|
|
1369
|
+
This allows several types referenced by `ISharedObjectKind` to be made `@alpha` as they should only need to be used by legacy code and users of the unstable/alpha/legacy "encapsulated API".
|
|
1217
1370
|
|
|
1218
|
-
|
|
1219
|
-
|
|
1371
|
+
Access to these now less public types should not be required for users of the `@public` "declarative API" exposed in the `fluid-framework` package, but can still be accessed for those who need them under the `/legacy` import paths.
|
|
1372
|
+
The full list of such types is:
|
|
1220
1373
|
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1374
|
+
- `SharedTree` as exported from `@fluidframwork/tree`: It is still exported as `@public` from `fluid-framework` as `SharedObjectKind`.
|
|
1375
|
+
- `ISharedObjectKind`: See new `SharedObjectKind` type for use in `@public` APIs.
|
|
1376
|
+
`ISharedObject`
|
|
1377
|
+
- `IChannel`
|
|
1378
|
+
- `IChannelAttributes`
|
|
1379
|
+
- `IChannelFactory`
|
|
1380
|
+
- `IExperimentalIncrementalSummaryContext`
|
|
1381
|
+
- `IGarbageCollectionData`
|
|
1382
|
+
- `ISummaryStats`
|
|
1383
|
+
- `ISummaryTreeWithStats`
|
|
1384
|
+
- `ITelemetryContext`
|
|
1385
|
+
- `IDeltaManagerErased`
|
|
1386
|
+
- `IFluidDataStoreRuntimeEvents`
|
|
1387
|
+
- `IFluidHandleContext`
|
|
1388
|
+
- `IProvideFluidHandleContext`
|
|
1236
1389
|
|
|
1237
|
-
|
|
1390
|
+
Removed APIs:
|
|
1238
1391
|
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1392
|
+
- `DataObjectClass`: Usages replaced with `SharedObjectKind`.
|
|
1393
|
+
- `LoadableObjectClass`: Replaced with `SharedObjectKind`.
|
|
1394
|
+
- `LoadableObjectClassRecord`: Replaced with `Record<string, SharedObjectKind>`.
|
|
1395
|
+
-
|
|
1243
1396
|
|
|
1244
|
-
-
|
|
1397
|
+
- tree: Added support for optional schema validation on newly inserted content in SharedTree ([#21011](https://github.com/microsoft/FluidFramework/pull/21011)) [b14e9fa607](https://github.com/microsoft/FluidFramework/commit/b14e9fa607a8281f86d0cfac631e33ef12033e21)
|
|
1245
1398
|
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1399
|
+
When defining how to view a SharedTree, an application can now specify that new content inserted into the tree should
|
|
1400
|
+
be subject to schema validation at the time it is inserted, so if it's not valid according to the stored schema in the
|
|
1401
|
+
tree an error is thrown immediately.
|
|
1249
1402
|
|
|
1250
|
-
|
|
1251
|
-
|
|
1403
|
+
This can be accomplished by passing an `ITreeConfigurationOptions` argument with `enableSchemaValidation` set to `true`
|
|
1404
|
+
when creating a `TreeConfiguration` to use with the SharedTree.
|
|
1252
1405
|
|
|
1253
|
-
|
|
1406
|
+
Since this feature requires additional compute when inserting new content into the tree, it is not enabled by default.
|
|
1254
1407
|
|
|
1255
|
-
-
|
|
1408
|
+
- Update to TypeScript 5.4 ([#21214](https://github.com/microsoft/FluidFramework/pull/21214)) [0e6256c722](https://github.com/microsoft/FluidFramework/commit/0e6256c722d8bf024f4325bf02547daeeb18bfa6)
|
|
1256
1409
|
|
|
1257
|
-
|
|
1410
|
+
Update package implementations to use TypeScript 5.4.5.
|
|
1258
1411
|
|
|
1259
|
-
-
|
|
1412
|
+
- fluid-framework: Remove some types from `@public` that are not needed ([#21326](https://github.com/microsoft/FluidFramework/pull/21326)) [b629cb80b0](https://github.com/microsoft/FluidFramework/commit/b629cb80b0e5ecdc750270807f77a0e30fab4559)
|
|
1260
1413
|
|
|
1261
|
-
|
|
1414
|
+
Mark the following APIs `@alpha` instead of `@public`:
|
|
1262
1415
|
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1416
|
+
- IBranchOrigin
|
|
1417
|
+
- ISequencedDocumentMessage
|
|
1418
|
+
- ISignalMessage
|
|
1419
|
+
- ISignalMessageBase
|
|
1420
|
+
- ITrace
|
|
1268
1421
|
|
|
1269
|
-
-
|
|
1422
|
+
- tree: A new tree status has been added for SharedTree nodes. ([#21270](https://github.com/microsoft/FluidFramework/pull/21270)) [8760e321b0](https://github.com/microsoft/FluidFramework/commit/8760e321b02177babfb187ae293a17a65723f249)
|
|
1270
1423
|
|
|
1271
|
-
|
|
1272
|
-
|
|
1424
|
+
`TreeStatus.Created` indicates that a SharedTree node has been constructed but not yet inserted into the tree.
|
|
1425
|
+
Constraints passed to the `runTransaction` API are now marked as `readonly`.
|
|
1273
1426
|
|
|
1274
|
-
-
|
|
1427
|
+
- fluid-framework: Remove several types from `@public` scope ([#21142](https://github.com/microsoft/FluidFramework/pull/21142)) [983e9f09f7](https://github.com/microsoft/FluidFramework/commit/983e9f09f7b10fef9ffa1e9af86166f0ccda7e14)
|
|
1275
1428
|
|
|
1276
|
-
|
|
1429
|
+
The following types have been moved from `@public` to `@alpha`:
|
|
1277
1430
|
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1431
|
+
- `IFluidSerializer`
|
|
1432
|
+
- `ISharedObjectEvents`
|
|
1433
|
+
- `IChannelServices`
|
|
1434
|
+
- `IChannelStorageService`
|
|
1435
|
+
- `IDeltaConnection`
|
|
1436
|
+
- `IDeltaHandler`
|
|
1284
1437
|
|
|
1285
|
-
|
|
1438
|
+
These should not be needed by users of the declarative API, which is what `@public` is targeting.
|
|
1286
1439
|
|
|
1287
|
-
-
|
|
1440
|
+
- sequence: Stop ISharedString extending SharedObject ([#21067](https://github.com/microsoft/FluidFramework/pull/21067)) [47465f4b12](https://github.com/microsoft/FluidFramework/commit/47465f4b12056810112df30a6dad89282afc7a2d)
|
|
1288
1441
|
|
|
1289
|
-
|
|
1442
|
+
ISharedString no longer extends SharedSegmentSequence and instead extends the new ISharedSegmentSequence, which may be missing some APIs.
|
|
1290
1443
|
|
|
1291
|
-
|
|
1444
|
+
Attempt to migrate off the missing APIs, but if that is not practical, request they be added to ISharedSegmentSequence and cast to SharedSegmentSequence as a workaround temporally.
|
|
1292
1445
|
|
|
1293
|
-
-
|
|
1446
|
+
- Update to ES 2022 ([#21292](https://github.com/microsoft/FluidFramework/pull/21292)) [68921502f7](https://github.com/microsoft/FluidFramework/commit/68921502f79b1833c4cd6d0fe339bfb126a712c7)
|
|
1294
1447
|
|
|
1295
|
-
|
|
1448
|
+
Update tsconfig to target ES 2022.
|
|
1296
1449
|
|
|
1297
|
-
-
|
|
1450
|
+
- tree: Move several types into InternalTypes ([#21482](https://github.com/microsoft/FluidFramework/pull/21482)) [64d49dd362](https://github.com/microsoft/FluidFramework/commit/64d49dd3629cefe6260a1d6223e58b10c2ac0cb6)
|
|
1298
1451
|
|
|
1299
|
-
|
|
1300
|
-
|
|
1452
|
+
The stable public API surface for Tree has been reduced.
|
|
1453
|
+
Several types have been moved into InternalTypes, indicating that they are not fully stable nor intended to be referenced by users of Tree.
|
|
1301
1454
|
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1455
|
+
- NodeBuilderData
|
|
1456
|
+
- FieldHasDefault
|
|
1457
|
+
- TreeNodeSchemaNonClass
|
|
1458
|
+
- TreeArrayNodeBase
|
|
1459
|
+
- ScopedSchemaName
|
|
1460
|
+
- DefaultProvider
|
|
1461
|
+
- typeNameSymbol
|
|
1462
|
+
- InsertableObjectFromSchemaRecord
|
|
1463
|
+
- ObjectFromSchemaRecord
|
|
1464
|
+
- FieldHasDefaultUnsafe
|
|
1465
|
+
- ObjectFromSchemaRecordUnsafe
|
|
1466
|
+
- TreeObjectNodeUnsafe
|
|
1467
|
+
- TreeFieldFromImplicitFieldUnsafe
|
|
1468
|
+
- TreeNodeFromImplicitAllowedTypesUnsafe
|
|
1469
|
+
- InsertableTreeNodeFromImplicitAllowedTypesUnsafe
|
|
1470
|
+
- TreeArrayNodeUnsafe
|
|
1471
|
+
- TreeMapNodeUnsafe
|
|
1472
|
+
- InsertableObjectFromSchemaRecordUnsafe
|
|
1473
|
+
- InsertableTreeFieldFromImplicitFieldUnsafe
|
|
1474
|
+
- InsertableTypedNodeUnsafe
|
|
1475
|
+
- NodeBuilderDataUnsafe
|
|
1476
|
+
- NodeFromSchemaUnsafe
|
|
1477
|
+
- FlexList
|
|
1478
|
+
- TreeApi
|
|
1326
1479
|
|
|
1327
|
-
|
|
1480
|
+
Additionally a few more types which could not be moved due to technically limitations have been documented that they should be treated similarly.
|
|
1328
1481
|
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1482
|
+
- TreeNodeApi
|
|
1483
|
+
- TreeNodeSchemaCore
|
|
1484
|
+
- All \*Unsafe type (use for construction of recursive schema).
|
|
1485
|
+
- WithType
|
|
1486
|
+
- AllowedTypes
|
|
1487
|
+
- FieldSchemaUnsafe
|
|
1335
1488
|
|
|
1336
|
-
|
|
1489
|
+
Also to reduce confusion `type` was renamed to `typeNameSymbol`, and is now only type exported. `Tree.is` should be used to get type information from `TreeNodes` instead.
|
|
1337
1490
|
|
|
1338
|
-
-
|
|
1491
|
+
- tree: object node fields with statically known default values are now optional ([#21193](https://github.com/microsoft/FluidFramework/pull/21193)) [21eac41660](https://github.com/microsoft/FluidFramework/commit/21eac41660944208bad42b156d7df05fe6dc6b97)
|
|
1339
1492
|
|
|
1340
|
-
|
|
1493
|
+
Makes object node fields with statically known default values (i.e., `optional` and `identifier` fields) optional when creating trees, where they were previously required.
|
|
1341
1494
|
|
|
1342
|
-
|
|
1495
|
+
Example:
|
|
1343
1496
|
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1497
|
+
```typescript
|
|
1498
|
+
class Foo extends schemaFactory.object("Foo", {
|
|
1499
|
+
name: schemaFactory.string,
|
|
1500
|
+
id: schemaFactory.identifier,
|
|
1501
|
+
nickname: schemaFactory.optional(schemaFactory.string),
|
|
1502
|
+
}) {}
|
|
1350
1503
|
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1504
|
+
// Before
|
|
1505
|
+
const foo = new Foo({
|
|
1506
|
+
name: "Bar",
|
|
1507
|
+
id: undefined, // Had to explicitly specify `undefined` to opt into default behavior
|
|
1508
|
+
nickname: undefined, // Had to explicitly specify `undefined` for optional field
|
|
1509
|
+
});
|
|
1357
1510
|
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1511
|
+
// After
|
|
1512
|
+
const foo = new Foo({
|
|
1513
|
+
name: "Bar",
|
|
1514
|
+
// Can omit `id` and `nickname` fields, as both have statically known defaults!
|
|
1515
|
+
});
|
|
1516
|
+
```
|
|
1364
1517
|
|
|
1365
|
-
-
|
|
1518
|
+
- tree: Breaking change: `TreeStatus.Created` is now `TreeStatus.New` ([#21278](https://github.com/microsoft/FluidFramework/pull/21278)) [5a26346a14](https://github.com/microsoft/FluidFramework/commit/5a26346a145ed54d08cd5a9b4f1c9b177711bd7c)
|
|
1366
1519
|
|
|
1367
|
-
|
|
1520
|
+
`TreeStatus.Created` has been renamed to `TreeStatus.New`.
|
|
1368
1521
|
|
|
1369
|
-
-
|
|
1522
|
+
- core-interfaces, tree: Unify `IDisposable` interfaces ([#21184](https://github.com/microsoft/FluidFramework/pull/21184)) [cfcb827851](https://github.com/microsoft/FluidFramework/commit/cfcb827851ffc81486db6c718380150189fb95c5)
|
|
1370
1523
|
|
|
1371
|
-
|
|
1524
|
+
Public APIs in `@fluidframework/tree` now use `IDisposable` from `@fluidframework/core-interfaces` replacing `disposeSymbol` with "dispose".
|
|
1372
1525
|
|
|
1373
|
-
|
|
1526
|
+
`IDisposable` in `@fluidframework/core-interfaces` is now `@sealed` indicating that third parties should not implement it to reserve the ability for Fluid Framework to extend it to include `Symbol.dispose` as a future non-breaking change.
|
|
1374
1527
|
|
|
1375
|
-
-
|
|
1528
|
+
- fluid-framework: Cleanup `fluid-framework` legacy exports ([#21153](https://github.com/microsoft/FluidFramework/pull/21153)) [efee21c296](https://github.com/microsoft/FluidFramework/commit/efee21c2965a02288db6e0345fcf9b3713210953)
|
|
1376
1529
|
|
|
1377
|
-
|
|
1530
|
+
Cleanup `fluid-framework` legacy exports to remove no longer required types.
|
|
1378
1531
|
|
|
1379
1532
|
## 2.0.0-rc.4.0.0
|
|
1380
1533
|
|
|
1381
1534
|
### Minor Changes
|
|
1382
1535
|
|
|
1383
|
-
-
|
|
1536
|
+
- SharedString now uses ISharedObjectKind and does not export the factory [96872186d0](https://github.com/microsoft/FluidFramework/commit/96872186d0d0f245c1fece7d19b3743e501679b6)
|
|
1384
1537
|
|
|
1385
|
-
|
|
1386
|
-
|
|
1538
|
+
Most users of `SharedString` should be unaffected as long as they stick to the factory patterns supported by ISharedObjectKind.
|
|
1539
|
+
If the actual class type is needed it can be found as `SharedStringClass`.
|
|
1387
1540
|
|
|
1388
|
-
-
|
|
1541
|
+
- Deprecated members of IFluidHandle are split off into new IFluidHandleInternal interface [96872186d0](https://github.com/microsoft/FluidFramework/commit/96872186d0d0f245c1fece7d19b3743e501679b6)
|
|
1389
1542
|
|
|
1390
|
-
|
|
1391
|
-
|
|
1543
|
+
Split IFluidHandle into two interfaces, `IFluidHandle` and `IFluidHandleInternal`.
|
|
1544
|
+
Code depending on the previously deprecated members of IFluidHandle can access them by using `toFluidHandleInternal` from `@fluidframework/runtime-utils/legacy`.
|
|
1392
1545
|
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1546
|
+
External implementation of the `IFluidHandle` interface are not supported: this change makes the typing better convey this using the `ErasedType` pattern.
|
|
1547
|
+
Any existing and previously working, and now broken, external implementations of `IFluidHandle` should still work at runtime, but will need some unsafe type casts to compile.
|
|
1548
|
+
Such handle implementation may break in the future and thus should be replaced with use of handles produced by the Fluid Framework client packages.
|
|
1396
1549
|
|
|
1397
|
-
-
|
|
1550
|
+
- Minor API fixes for "@fluidframework/tree" package. [96872186d0](https://github.com/microsoft/FluidFramework/commit/96872186d0d0f245c1fece7d19b3743e501679b6)
|
|
1398
1551
|
|
|
1399
|
-
|
|
1552
|
+
Changes constructor for `FieldSchema` from public to private. Users should call `makeFieldSchema` to create instance of `FieldSchema`.
|
|
1400
1553
|
|
|
1401
|
-
-
|
|
1554
|
+
- Make several driver types no longer public [b7ad7d0b55](https://github.com/microsoft/FluidFramework/commit/b7ad7d0b55884dd8954abf7c398e518838b9bda0)
|
|
1402
1555
|
|
|
1403
|
-
|
|
1556
|
+
Move the following types from `@public` to `@alpha`:
|
|
1404
1557
|
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1558
|
+
- ITokenClaims
|
|
1559
|
+
- IDocumentMessage
|
|
1560
|
+
- IClientConfiguration
|
|
1561
|
+
- IAnyDriverError
|
|
1562
|
+
- IDriverErrorBase
|
|
1563
|
+
- DriverErrorTypes
|
|
1411
1564
|
|
|
1412
|
-
|
|
1565
|
+
`DriverErrorTypes` is no longer exported from the `fluid-framework` package.
|
|
1413
1566
|
|
|
1414
|
-
-
|
|
1567
|
+
- Rename `AzureMember.userName` to `AzureMember.name` and `IMember.userId` to `IMember.id` [96872186d0](https://github.com/microsoft/FluidFramework/commit/96872186d0d0f245c1fece7d19b3743e501679b6)
|
|
1415
1568
|
|
|
1416
|
-
|
|
1417
|
-
|
|
1569
|
+
1. Renamed `AzureMember.userName` to `AzureMember.name` to establish uniform naming across odsp-client and azure-client.
|
|
1570
|
+
2. Renamed `IMember.userId` to `IMember.id` to align with the properties received from AFR.
|
|
1418
1571
|
|
|
1419
1572
|
## 2.0.0-rc.3.0.0
|
|
1420
1573
|
|
|
1421
1574
|
### Major Changes
|
|
1422
1575
|
|
|
1423
|
-
-
|
|
1576
|
+
- fluid-framework: DDS classes are no longer publicly exported [97d68aa06b](https://github.com/microsoft/FluidFramework/commit/97d68aa06bd5c022ecb026655814aea222a062ae)
|
|
1424
1577
|
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1578
|
+
SharedDirectory now only exports its factory and the interface type.
|
|
1579
|
+
The actual concrete classes which leak implementation details are no longer exported.
|
|
1580
|
+
Users of the `SharedDirectory` type should use `ISharedDirectory`.
|
|
1428
1581
|
|
|
1429
|
-
|
|
1430
|
-
|
|
1582
|
+
Most of other internal crufts are also hided within the API surface, such as the encoded format,
|
|
1583
|
+
ILocalValue, ICreateInfo, local op metadata types, etc.
|
|
1431
1584
|
|
|
1432
|
-
-
|
|
1585
|
+
- Packages now use package.json "exports" and require modern module resolution [97d68aa06b](https://github.com/microsoft/FluidFramework/commit/97d68aa06bd5c022ecb026655814aea222a062ae)
|
|
1433
1586
|
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1587
|
+
Fluid Framework packages have been updated to use the [package.json "exports"
|
|
1588
|
+
field](https://nodejs.org/docs/latest-v18.x/api/packages.html#exports) to define explicit entry points for both
|
|
1589
|
+
TypeScript types and implementation code.
|
|
1437
1590
|
|
|
1438
|
-
|
|
1591
|
+
This means that using Fluid Framework packages require the following TypeScript settings in tsconfig.json:
|
|
1439
1592
|
|
|
1440
|
-
|
|
1441
|
-
|
|
1593
|
+
- `"moduleResolution": "Node16"` with `"module": "Node16"`
|
|
1594
|
+
- `"moduleResolution": "Bundler"` with `"module": "ESNext"`
|
|
1442
1595
|
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1596
|
+
We recommend using Node16/Node16 unless absolutely necessary. That will produce transpiled JavaScript that is suitable
|
|
1597
|
+
for use with modern versions of Node.js _and_ Bundlers.
|
|
1598
|
+
[See the TypeScript documentation](https://www.typescriptlang.org/tsconfig#moduleResolution) for more information
|
|
1599
|
+
regarding the module and moduleResolution options.
|
|
1447
1600
|
|
|
1448
|
-
|
|
1449
|
-
|
|
1601
|
+
**Node10 moduleResolution is not supported; it does not support Fluid Framework's API structuring pattern that is used
|
|
1602
|
+
to distinguish stable APIs from those that are in development.**
|
|
1450
1603
|
|
|
1451
1604
|
### Minor Changes
|
|
1452
1605
|
|
|
1453
|
-
-
|
|
1606
|
+
- tree: Allow root editing and make TreeView parameterized over schema. [97d68aa06b](https://github.com/microsoft/FluidFramework/commit/97d68aa06bd5c022ecb026655814aea222a062ae)
|
|
1454
1607
|
|
|
1455
|
-
|
|
1456
|
-
|
|
1608
|
+
TreeView now is parameterized over the field schema instead of the root field type. This was needed to infer the correct input type when reassigning the root.
|
|
1609
|
+
Code providing an explicit type to TreeView, like `TreeView<Foo>` can usually be updated by replacing that with `TreeView<typeof Foo>`.
|
|
1457
1610
|
|
|
1458
|
-
-
|
|
1611
|
+
- fluid-framework: Replace SharedObjectClass with new ISharedObjectKind type. [97d68aa06b](https://github.com/microsoft/FluidFramework/commit/97d68aa06bd5c022ecb026655814aea222a062ae)
|
|
1459
1612
|
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1613
|
+
The static objects used as SharedObjectClass now explicitly implement the new ISharedObjectKind type.
|
|
1614
|
+
SharedObjectClass has been removed as ISharedObjectKind now fills that role.
|
|
1615
|
+
LoadableObjectCtor has been inlined as it only had one use: an external user of it can replace it with `(new (...args: any[]) => T)`.
|
|
1463
1616
|
|
|
1464
|
-
-
|
|
1617
|
+
- fluid-framework: Moved SharedMap to 'fluid-framework/legacy' [97d68aa06b](https://github.com/microsoft/FluidFramework/commit/97d68aa06bd5c022ecb026655814aea222a062ae)
|
|
1465
1618
|
|
|
1466
|
-
|
|
1619
|
+
Please use SharedTree for new containers. SharedMap is supported for loading preexisting Fluid Framework 1.x containers only.
|
|
1467
1620
|
|
|
1468
|
-
|
|
1621
|
+
Fluid Framework 1.x users migrating to Fluid Framework 2.x will need to import SharedMap from the './legacy' import path.
|
|
1469
1622
|
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1623
|
+
```ts
|
|
1624
|
+
import { SharedMap } from "fluid-framework/legacy";
|
|
1625
|
+
```
|
|
1473
1626
|
|
|
1474
|
-
-
|
|
1627
|
+
- fluid-framework: Make some interface members readonly [97d68aa06b](https://github.com/microsoft/FluidFramework/commit/97d68aa06bd5c022ecb026655814aea222a062ae)
|
|
1475
1628
|
|
|
1476
|
-
|
|
1629
|
+
Remove unneeded mutability from some interface members.
|
|
1477
1630
|
|
|
1478
1631
|
## 2.0.0-rc.2.0.0
|
|
1479
1632
|
|
|
1480
1633
|
### Minor Changes
|
|
1481
1634
|
|
|
1482
|
-
-
|
|
1635
|
+
- fluid-framework: EventEmitterWithErrorHandling is no longer publicly exported ([#19717](https://github.com/microsoft/FluidFramework/issues/19717)) [ae1d0be26d](https://github.com/microsoft/FluidFramework/commits/ae1d0be26d61453cff316b3f622a9f3647149167)
|
|
1483
1636
|
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1637
|
+
EventEmitterWithErrorHandling is intended for authoring DDSes, and thus is only intended for use within the Fluid Framework client packages.
|
|
1638
|
+
It is no longer publicly exported: any users should fine their own solution or be upstreamed.
|
|
1639
|
+
EventEmitterWithErrorHandling is available for now as `@alpha` to make this migration less disrupting for any existing users.
|
|
1487
1640
|
|
|
1488
|
-
-
|
|
1641
|
+
- fluid-framework: SharedObject classes are no longer exported as public ([#19717](https://github.com/microsoft/FluidFramework/issues/19717)) [ae1d0be26d](https://github.com/microsoft/FluidFramework/commits/ae1d0be26d61453cff316b3f622a9f3647149167)
|
|
1489
1642
|
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1643
|
+
`SharedObject` and `SharedObjectCore` are intended for authoring DDSes, and thus are only intended for use within the Fluid Framework client packages.
|
|
1644
|
+
They is no longer publicly exported: any users should fine their own solution or be upstreamed.
|
|
1645
|
+
`SharedObject` and `SharedObjectCore` are available for now as `@alpha` to make this migration less disrupting for any existing users.
|
|
1493
1646
|
|
|
1494
|
-
-
|
|
1647
|
+
- API tightening ([#20012](https://github.com/microsoft/FluidFramework/issues/20012)) [049de899dd](https://github.com/microsoft/FluidFramework/commits/049de899ddfd5c0155251cb0ea00ecbe3a7f7665)
|
|
1495
1648
|
|
|
1496
|
-
|
|
1497
|
-
|
|
1649
|
+
The Fluid Framework API has been clarified with tags applied to package exports. As we are working toward a clear, safe,
|
|
1650
|
+
and stable API surface, some build settings and imports may need to be adjusted.
|
|
1498
1651
|
|
|
1499
|
-
|
|
1500
|
-
|
|
1652
|
+
**Now:** Most packages are specifying "exports" - import specifierss like` @fluidframework/foo/lib/internals` will
|
|
1653
|
+
become build errors. The fix is to use only public APIs from @fluidframework/foo.
|
|
1501
1654
|
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1655
|
+
**Coming soon:** Build resolutions (`moduleResolution` in tsconfig compilerOptions) will need to be resolved with
|
|
1656
|
+
Node16, NodeNext, or a bundler that supports resolution of named import/export paths. Internally, some FF packages will
|
|
1657
|
+
use `@fluidframework/foo/internal` import paths that allow packages to talk to each other using non-public APIs.
|
|
1505
1658
|
|
|
1506
|
-
|
|
1659
|
+
**Final stage:** APIs that are not tagged @public will be removed from @fluidframework/foo imports.
|
|
1507
1660
|
|
|
1508
|
-
-
|
|
1661
|
+
- Deprecated error-related enums have been removed ([#19067](https://github.com/microsoft/FluidFramework/issues/19067)) [59793302e5](https://github.com/microsoft/FluidFramework/commits/59793302e56784cfb6ace0e6469345f3565b3312)
|
|
1509
1662
|
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1663
|
+
Error-related enums `ContainerErrorType`, `DriverErrorType`, `OdspErrorType` and `RouterliciousErrorType` were previously
|
|
1664
|
+
deprecated and are now removed. There are replacement object-based enumerations of `ContainerErrorTypes`,
|
|
1665
|
+
`DriverErrorTypes`, `OdspErrorTypes` and `RouterliciousErrorTypes`. Refer to the release notes of [Fluid Framework version
|
|
1666
|
+
2.0.0-internal.7.0.0](https://github.com/microsoft/FluidFramework/releases/tag/client_v2.0.0-internal.7.0.0) for details
|
|
1667
|
+
on the replacements.
|
|
1515
1668
|
|
|
1516
|
-
-
|
|
1669
|
+
- map, tree: DDS classes are no longer publicly exported ([#19717](https://github.com/microsoft/FluidFramework/issues/19717)) [ae1d0be26d](https://github.com/microsoft/FluidFramework/commits/ae1d0be26d61453cff316b3f622a9f3647149167)
|
|
1517
1670
|
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1671
|
+
SharedMap and SharedTree now only export their factories and the interface types.
|
|
1672
|
+
The actual concrete classes which leak implementation details are no longer exported.
|
|
1673
|
+
Users of the `SharedMap` type should use `ISharedMap`.
|
|
1674
|
+
Users of the `SharedTree` type should use `ISharedTree`.
|
|
1522
1675
|
|
|
1523
|
-
-
|
|
1676
|
+
- tree: Minor API fixes for "@fluidframework/tree" package. ([#19057](https://github.com/microsoft/FluidFramework/issues/19057)) [3e0f218832](https://github.com/microsoft/FluidFramework/commits/3e0f21883255317f8bb1f7c420543650502a5b66)
|
|
1524
1677
|
|
|
1525
|
-
|
|
1678
|
+
Rename `IterableTreeListContent` to `IterableTreeArrayContent`, inline `TreeMapNodeBase` into `TreeMapNode`, rename `TreeArrayNode.spread` to `TreeArrayNode.spread` and remove `create` which was not supposed to be public (use `TreeArrayNode.spread` instead).
|
|
1526
1679
|
|
|
1527
|
-
-
|
|
1680
|
+
- fluid-framework: ContainerSchema is now readonly ([#19717](https://github.com/microsoft/FluidFramework/issues/19717)) [ae1d0be26d](https://github.com/microsoft/FluidFramework/commits/ae1d0be26d61453cff316b3f622a9f3647149167)
|
|
1528
1681
|
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1682
|
+
The `ContainerSchema` type is intended for defining input to these packages. This should make the APIs more tolerant and
|
|
1683
|
+
thus be non-breaking, however its possible for some users of `ContainerSchema` to use it in ways where this could be a
|
|
1684
|
+
breaking change: any such users should remove their mutations and/or use a different type.
|
|
1532
1685
|
|
|
1533
1686
|
## 2.0.0-rc.1.0.0
|
|
1534
1687
|
|
|
@@ -1538,33 +1691,33 @@ Dependency updates only.
|
|
|
1538
1691
|
|
|
1539
1692
|
### Major Changes
|
|
1540
1693
|
|
|
1541
|
-
-
|
|
1694
|
+
- azure-client: Removed deprecated FluidStatic classes [9a451d4946](https://github.com/microsoft/FluidFramework/commits/9a451d4946b5c51a52e4d1ab5bf51e7b285b0d74)
|
|
1542
1695
|
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1696
|
+
Several FluidStatic classes were unnecessarily exposed and were deprecated in an earlier release. They have been replaced with creation functions. This helps us
|
|
1697
|
+
keep implementations decoupled from usage which is easier to maintain and extend. It has very minimal impact on the
|
|
1698
|
+
public surface area of downstream packages. The removed classes are as follows:
|
|
1546
1699
|
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1700
|
+
- `AzureAudience` (use `IAzureAudience` instead)
|
|
1701
|
+
- `TinyliciousAudience` (use `ITinyliciousAudience` instead)
|
|
1702
|
+
- `DOProviderContainerRuntimeFactory`
|
|
1703
|
+
- `FluidContainer`
|
|
1704
|
+
- `ServiceAudience`
|
|
1552
1705
|
|
|
1553
1706
|
## 2.0.0-internal.7.4.0
|
|
1554
1707
|
|
|
1555
1708
|
### Minor Changes
|
|
1556
1709
|
|
|
1557
|
-
-
|
|
1710
|
+
- azure-client: Deprecated FluidStatic Classes ([#18402](https://github.com/microsoft/FluidFramework/issues/18402)) [589ec39de5](https://github.com/microsoft/FluidFramework/commits/589ec39de52116c7f782319e6f6aa61bc5aa9964)
|
|
1558
1711
|
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1712
|
+
Several FluidStatic classes were unnecessarily exposed. They have been replaced with creation functions. This helps us
|
|
1713
|
+
keep implementations decoupled from usage which is easier to maintain and extend. It has very minimal impact on the
|
|
1714
|
+
public surface area of downstream packages. The deprecated classes are as follows:
|
|
1562
1715
|
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1716
|
+
- `AzureAudience` (use `IAzureAudience` instead)
|
|
1717
|
+
- `TinyliciousAudience` (use `ITinyliciousAudience` instead)
|
|
1718
|
+
- `DOProviderContainerRuntimeFactory`
|
|
1719
|
+
- `FluidContainer`
|
|
1720
|
+
- `ServiceAudience`
|
|
1568
1721
|
|
|
1569
1722
|
## 2.0.0-internal.7.3.0
|
|
1570
1723
|
|
|
@@ -1582,9 +1735,9 @@ Dependency updates only.
|
|
|
1582
1735
|
|
|
1583
1736
|
### Major Changes
|
|
1584
1737
|
|
|
1585
|
-
-
|
|
1738
|
+
- Minimum TypeScript version now 5.1.6 [871b3493dd](https://github.com/microsoft/FluidFramework/commits/871b3493dd0d7ea3a89be64998ceb6cb9021a04e)
|
|
1586
1739
|
|
|
1587
|
-
|
|
1740
|
+
The minimum supported TypeScript version for Fluid 2.0 clients is now 5.1.6.
|
|
1588
1741
|
|
|
1589
1742
|
## 2.0.0-internal.6.4.0
|
|
1590
1743
|
|
|
@@ -1606,17 +1759,17 @@ Dependency updates only.
|
|
|
1606
1759
|
|
|
1607
1760
|
### Major Changes
|
|
1608
1761
|
|
|
1609
|
-
-
|
|
1762
|
+
- IntervalConflictResolver removed [8abce8cdb4](https://github.com/microsoft/FluidFramework/commits/8abce8cdb4e2832fb6405fb44e393bef03d5648a)
|
|
1610
1763
|
|
|
1611
|
-
|
|
1764
|
+
IntervalConflictResolver has been removed. Any lingering usages in application code can be removed as well. This change also marks APIs deprecated in #14318 as internal.
|
|
1612
1765
|
|
|
1613
|
-
-
|
|
1766
|
+
- RootDataObject and RootDataObjectProps no longer exported from fluid-static or fluid-framework packages [8abce8cdb4](https://github.com/microsoft/FluidFramework/commits/8abce8cdb4e2832fb6405fb44e393bef03d5648a)
|
|
1614
1767
|
|
|
1615
|
-
|
|
1768
|
+
RootDataObject and RootDataObjectProps are internal implementations and not intended for direct use. Instead use IRootDataObject to refer to the root data object.
|
|
1616
1769
|
|
|
1617
|
-
-
|
|
1770
|
+
- Upgraded typescript transpilation target to ES2020 [8abce8cdb4](https://github.com/microsoft/FluidFramework/commits/8abce8cdb4e2832fb6405fb44e393bef03d5648a)
|
|
1618
1771
|
|
|
1619
|
-
|
|
1772
|
+
Upgraded typescript transpilation target to ES2020. This is done in order to decrease the bundle sizes of Fluid Framework packages. This has provided size improvements across the board for ex. Loader, Driver, Runtime etc. Reduced bundle sizes helps to load lesser code in apps and hence also helps to improve the perf.If any app wants to target any older versions of browsers with which this target version is not compatible, then they can use packages like babel to transpile to a older target.
|
|
1620
1773
|
|
|
1621
1774
|
## 2.0.0-internal.5.4.0
|
|
1622
1775
|
|