fluid-framework 3.2.0 → 3.4.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 CHANGED
@@ -1,5 +1,106 @@
1
1
  # fluid-framework
2
2
 
3
+ ## 3.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Add experimental SharedTree sandboxing APIs ([#28382](https://github.com/microsoft/FluidFramework/pull/28382)) [e41dc04d41](https://github.com/microsoft/FluidFramework/commit/e41dc04d41d1cb21ccd48a2a1b44d817f1a33c0c)
8
+
9
+ The new alpha `Sandboxing.createHost` and `Sandboxing.createGuest` APIs synchronize a SharedTree [`ViewableTree`](https://fluidframework.com/docs/api/fluid-framework/viewabletree-interface) across a `MessagePort`.
10
+ The Host remains connected to Fluid services while the Guest exposes a normal schema-aware tree view on the other side of the message channel.
11
+
12
+ > [!IMPORTANT]
13
+ > To use Sandboxing, you must set the container runtime's [`oldestSupportedClient`](https://fluidframework.com/docs/api/container-runtime/loadcontainerruntimeparams-interface#oldestsupportedclient-propertysignature) option to `"3.4.0"` or later.
14
+
15
+ ```typescript
16
+ import { asBeta } from "@fluidframework/tree/beta";
17
+ import { FormatValidatorBasic, Sandboxing } from "@fluidframework/tree/alpha";
18
+
19
+ // Create the application-owned view that remains connected to Fluid services.
20
+ const hostView = asBeta(tree.viewWith(config));
21
+
22
+ // Create the message channel that crosses the sandbox boundary.
23
+ const channel = new MessageChannel();
24
+
25
+ // Connect the Host endpoint to the collaborative tree.
26
+ const host = Sandboxing.createHost({ main: hostView, port: channel.port1 });
27
+
28
+ // Create the independent Guest tree on the other side of the channel.
29
+ const guest = await Sandboxing.createGuest({
30
+ port: channel.port2,
31
+ treeOptions: { jsonValidator: FormatValidatorBasic },
32
+ });
33
+
34
+ // Open a schema-aware view for application code running in the sandbox.
35
+ const guestView = guest.tree.viewWith(config);
36
+ ```
37
+
38
+ - Add an alpha incremental-summary field property ([#28285](https://github.com/microsoft/FluidFramework/pull/28285)) [5d1392bb81](https://github.com/microsoft/FluidFramework/commit/5d1392bb8170cb3dbdc6745b8e01227a20a4d75f)
39
+
40
+ The new alpha `summarizeIncrementally` property on [`FieldPropsAlpha`](https://fluidframework.com/docs/api/tree/fieldpropsalpha-interface) marks a field as an incremental-summary boundary without requiring direct use of allowed-types metadata or the [`incrementalSummaryHint`](https://fluidframework.com/docs/api/tree/#incrementalsummaryhint-variable) symbol.
41
+ This property is the preferred way to configure incremental summarization.
42
+ [`SchemaFactoryAlpha.requiredRecursive`](https://fluidframework.com/docs/api/tree/schemafactoryalpha-class#requiredrecursive-property) and [`optionalRecursive`](https://fluidframework.com/docs/api/tree/schemafactoryalpha-class#optionalrecursive-property) provide the same field configuration for recursive allowed types with relaxed compile-time constraints.
43
+ The [`SchemaFactoryAlpha.stagedOptional`](https://fluidframework.com/docs/api/tree/schemafactoryalpha-class#stagedoptional-property) and [`stagedOptionalRecursive`](https://fluidframework.com/docs/api/tree/schemafactoryalpha-class#stagedoptionalrecursive-property) field constructors also accept this option.
44
+
45
+ ```typescript
46
+ const sf = new SchemaFactoryAlpha("example");
47
+
48
+ class Document extends sf.objectAlpha("Document", {
49
+ sections: sf.required(sf.map(Section), { summarizeIncrementally: true }),
50
+ }) {}
51
+ ```
52
+
53
+ ## 3.3.0
54
+
55
+ ### Minor Changes
56
+
57
+ - Bug fix: revert preconditions no longer cause document corruption and other errors ([#28317](https://github.com/microsoft/FluidFramework/pull/28317)) [b4384d78657](https://github.com/microsoft/FluidFramework/commit/b4384d786575a2588b43df420d935ab749008a95)
58
+
59
+ Before this release, when a SharedTree client specified a [constraint](https://fluidframework.com/docs/data-structures/tree/transactions#constraints) as a [precondition for a revert](https://fluidframework.com/docs/api/fluid-framework/transactioncallbackstatusalpha-typealias) and (whether or not a revert was performed) such a constraint was violated,
60
+ that client could later error during the rebasing of its shared branches (when processing peer changes) or local branches
61
+ and was liable to generate invalid edits that would cause document corruption in the meantime.
62
+
63
+ - Preserve custom commit metadata when applying serialized changes ([#28330](https://github.com/microsoft/FluidFramework/pull/28330)) [89dc7355be6](https://github.com/microsoft/FluidFramework/commit/89dc7355be6e83d18d1a02a061e9aa0987844b7a)
64
+
65
+ Changes returned by `LocalChangeMetadata.getChange()` now include the commit's custom metadata, including metadata from nested transactions.
66
+ Applying these changes to another view preserves that metadata in its branch history.
67
+
68
+ - Reject reverts across schema changes ([#28320](https://github.com/microsoft/FluidFramework/pull/28320)) [ca6f67c1218](https://github.com/microsoft/FluidFramework/commit/ca6f67c12187c5ee423cbc2387b18e142869f015)
69
+
70
+ [`UntypedTreeViewAlpha.revertTo()`](https://fluidframework.com/docs/api/tree/untypedtreeviewalpha-interface#revertto-methodsignature) now throws a usage error if any commit being reverted contains a schema change.
71
+ The operation leaves the document unchanged, preserving transaction atomicity for commits that contain both schema and data changes.
72
+ You can still revert data changes made after a schema upgrade by targeting the revision of that upgrade or a later revision.
73
+
74
+ - createIndependentTreeAlpha no longer has the unused TSchema type parameter ([#28349](https://github.com/microsoft/FluidFramework/pull/28349)) [071fa2a9008](https://github.com/microsoft/FluidFramework/commit/071fa2a90080b9e8996a6dbe86c183dea6815aeb)
75
+
76
+ The unused `TSchema` type parameter has been removed from `createIndependentTreeAlpha`.
77
+ Calls that explicitly supply a type argument to `createIndependentTreeAlpha` must remove it.
78
+
79
+ `createIndependentTreeBeta` keeps its deprecated type parameter temporarily for compatibility, but the type parameter continues to have no effect.
80
+ Callers should omit it.
81
+
82
+ - Record node property read types now include undefined ([#28163](https://github.com/microsoft/FluidFramework/pull/28163)) [2de794b4a74](https://github.com/microsoft/FluidFramework/commit/2de794b4a74774f3686c65e64b8fee7d7e14e481)
83
+
84
+ Reading a property from a record node is now typed as `T | undefined` instead of `T`, matching the existing runtime behavior when the key is absent.
85
+ Consumers must narrow the result before using it as `T`.
86
+
87
+ ```typescript
88
+ const value = record.foo;
89
+ if (value !== undefined) {
90
+ // Use value as T.
91
+ }
92
+ ```
93
+
94
+ This is a bug fix to the `@beta` record node APIs: the previous typing incorrectly claimed that reading any key would produce a value, which could result in unexpected `undefined` values at runtime.
95
+
96
+ Note that this does not change what a record node can store; entries are still always defined.
97
+ Assigning `undefined` to a key continues to remove that entry, as before.
98
+
99
+ - Optimize memory use of arrays when using ForestTypeOptimized ([#27386](https://github.com/microsoft/FluidFramework/pull/27386)) [0735ff53d5c](https://github.com/microsoft/FluidFramework/commit/0735ff53d5cf384ce61aef039ab3c9414871fd73)
100
+
101
+ [`ForestTypeOptimized`](https://fluidframework.com/docs/api/fluid-framework#foresttypeoptimized-variable) now more efficiently deduplicates structural information for adjacent children in [array nodes](https://fluidframework.com/docs/api/tree/treearraynode-interface) after edits.
102
+ For arrays of small, uniformly shaped subtrees, such as [`PlainText`](https://fluidframework.com/docs/api/fluid-framework/plaintext-namespace), this reduces fragmentation and can reduce memory use by approximately 60%.
103
+
3
104
  ## 3.2.0
4
105
 
5
106
  ### Minor Changes
@@ -186,7 +186,7 @@ export enum AttachState {
186
186
  export type ChangeMetadata = LocalChangeMetadata | RemoteChangeMetadata;
187
187
 
188
188
  // @alpha
189
- export function checkCompatibility(viewWhichCreatedStoredSchema: TreeViewConfiguration, view: TreeViewConfiguration): Omit<SchemaCompatibilityStatus, "canInitialize">;
189
+ export function checkCompatibility(documentViewConfiguration: TreeViewConfiguration, clientViewConfiguration: TreeViewConfiguration): Omit<SchemaCompatibilityStatus, "canInitialize">;
190
190
 
191
191
  // @alpha
192
192
  export function cloneWithReplacements(root: unknown, rootKey: string, replacer: (key: string, value: unknown) => {
@@ -321,7 +321,7 @@ export function createBasicRegistryKey<T>(type: string): RegistryKey<T, T>;
321
321
  export function createIdentifierIndex<TSchema extends ImplicitFieldSchema>(view: TreeView<TSchema>): IdentifierIndex;
322
322
 
323
323
  // @alpha
324
- export function createIndependentTreeAlpha<const TSchema extends ImplicitFieldSchema>(options?: CreateIndependentTreeAlphaOptions): ViewableTree & Pick<ITreeAlpha, "exportVerbose" | "exportSimpleSchema">;
324
+ export function createIndependentTreeAlpha(options?: CreateIndependentTreeAlphaOptions): ViewableTree & Pick<ITreeAlpha, "exportVerbose" | "exportSimpleSchema">;
325
325
 
326
326
  // @alpha
327
327
  export type CreateIndependentTreeAlphaOptions = ForestOptions & IndependentViewTelemetryOptions & ((IndependentViewOptions & {
@@ -332,7 +332,7 @@ export type CreateIndependentTreeAlphaOptions = ForestOptions & IndependentViewT
332
332
  }));
333
333
 
334
334
  // @beta
335
- export function createIndependentTreeBeta<const TSchema extends ImplicitFieldSchema>(options?: ForestOptions): ViewableTree;
335
+ export function createIndependentTreeBeta<const Unused = unknown>(options?: ForestOptions): ViewableTree;
336
336
 
337
337
  // @beta
338
338
  export function createIndependentTreeView<const TSchema extends ImplicitFieldSchema>(config: TreeViewConfiguration<TSchema>, options?: ForestOptions): TreeViewBeta<TSchema>;
@@ -512,6 +512,7 @@ export interface FieldProps<TCustomMetadata = unknown> {
512
512
  export interface FieldPropsAlpha<TCustomMetadata = unknown> extends FieldProps<TCustomMetadata> {
513
513
  readonly persistedMetadata?: JsonCompatibleReadOnlyObject | undefined;
514
514
  readonly stagedOptionalUpgrade?: SchemaUpgrade;
515
+ readonly summarizeIncrementally?: boolean;
515
516
  }
516
517
 
517
518
  // @public @sealed
@@ -1802,6 +1803,39 @@ export interface RunTransactionParamsBeta {
1802
1803
  readonly label?: unknown;
1803
1804
  }
1804
1805
 
1806
+ // @alpha
1807
+ export namespace Sandboxing {
1808
+ export function createGuest(options: GuestOptions): Promise<Guest>;
1809
+ export function createHost(options: HostOptions): Host;
1810
+ // @input
1811
+ export interface EndpointOptions {
1812
+ readonly handleProtocolError?: (error: Error) => void;
1813
+ readonly logger?: ITelemetryBaseLogger;
1814
+ readonly port: InstanceType<typeof MessagePort>;
1815
+ }
1816
+ // @sealed
1817
+ export interface Guest {
1818
+ dispose(): void;
1819
+ readonly error: Error | undefined;
1820
+ readonly tree: ViewableTree;
1821
+ readonly updateHostPromise: Promise<void> | undefined;
1822
+ }
1823
+ // @input
1824
+ export interface GuestOptions extends EndpointOptions {
1825
+ readonly treeOptions: ForestOptions & ICodecOptions;
1826
+ }
1827
+ // @sealed
1828
+ export interface Host {
1829
+ dispose(): void;
1830
+ readonly error: Error | undefined;
1831
+ readonly updateGuestPromise: Promise<void> | undefined;
1832
+ }
1833
+ // @input
1834
+ export interface HostOptions extends EndpointOptions {
1835
+ readonly main: UntypedTreeView;
1836
+ }
1837
+ }
1838
+
1805
1839
  // @public @sealed
1806
1840
  export interface SchemaCompatibilityStatus {
1807
1841
  readonly canInitialize: boolean;
@@ -2743,7 +2777,7 @@ export type TreeObjectNode<T extends RestrictiveStringRecord<ImplicitFieldSchema
2743
2777
  export type TreeParsingOptions = TreeEncodingOptions<KeyEncodingOptions.usePropertyKeys | KeyEncodingOptions.knownStoredKeys>;
2744
2778
 
2745
2779
  // @beta
2746
- export interface TreeRecordNode<TAllowedTypes extends ImplicitAllowedTypes = ImplicitAllowedTypes> extends TreeNode, Record<string, TreeNodeFromImplicitAllowedTypes<TAllowedTypes>> {
2780
+ export interface TreeRecordNode<TAllowedTypes extends ImplicitAllowedTypes = ImplicitAllowedTypes> extends TreeNode, Record<string, TreeNodeFromImplicitAllowedTypes<TAllowedTypes> | undefined> {
2747
2781
  [Symbol.iterator](): FluidIterableIterator<[
2748
2782
  string,
2749
2783
  TreeNodeFromImplicitAllowedTypes<TAllowedTypes>
@@ -2751,7 +2785,7 @@ export interface TreeRecordNode<TAllowedTypes extends ImplicitAllowedTypes = Imp
2751
2785
  }
2752
2786
 
2753
2787
  // @beta @sealed @system
2754
- export interface TreeRecordNodeUnsafe<TAllowedTypes extends System_Unsafe.ImplicitAllowedTypesUnsafe> extends Record<string, System_Unsafe.TreeNodeFromImplicitAllowedTypesUnsafe<TAllowedTypes>>, TreeNode {
2788
+ export interface TreeRecordNodeUnsafe<TAllowedTypes extends System_Unsafe.ImplicitAllowedTypesUnsafe> extends Record<string, System_Unsafe.TreeNodeFromImplicitAllowedTypesUnsafe<TAllowedTypes> | undefined>, TreeNode {
2755
2789
  // (undocumented)
2756
2790
  [Symbol.iterator](): FluidIterableIterator<[
2757
2791
  string,
@@ -191,7 +191,7 @@ export interface ContainerSchema {
191
191
  export function createIdentifierIndex<TSchema extends ImplicitFieldSchema>(view: TreeView<TSchema>): IdentifierIndex;
192
192
 
193
193
  // @beta
194
- export function createIndependentTreeBeta<const TSchema extends ImplicitFieldSchema>(options?: ForestOptions): ViewableTree;
194
+ export function createIndependentTreeBeta<const Unused = unknown>(options?: ForestOptions): ViewableTree;
195
195
 
196
196
  // @beta
197
197
  export function createIndependentTreeView<const TSchema extends ImplicitFieldSchema>(config: TreeViewConfiguration<TSchema>, options?: ForestOptions): TreeViewBeta<TSchema>;
@@ -1632,7 +1632,7 @@ export type TreeNodeSchemaNonClass<Name extends string = string, Kind extends No
1632
1632
  export type TreeObjectNode<T extends RestrictiveStringRecord<ImplicitFieldSchema>, TypeName extends string = string> = TreeNode & ObjectFromSchemaRecord<T> & WithType<TypeName, NodeKind.Object, T>;
1633
1633
 
1634
1634
  // @beta
1635
- export interface TreeRecordNode<TAllowedTypes extends ImplicitAllowedTypes = ImplicitAllowedTypes> extends TreeNode, Record<string, TreeNodeFromImplicitAllowedTypes<TAllowedTypes>> {
1635
+ export interface TreeRecordNode<TAllowedTypes extends ImplicitAllowedTypes = ImplicitAllowedTypes> extends TreeNode, Record<string, TreeNodeFromImplicitAllowedTypes<TAllowedTypes> | undefined> {
1636
1636
  [Symbol.iterator](): FluidIterableIterator<[
1637
1637
  string,
1638
1638
  TreeNodeFromImplicitAllowedTypes<TAllowedTypes>
@@ -1640,7 +1640,7 @@ export interface TreeRecordNode<TAllowedTypes extends ImplicitAllowedTypes = Imp
1640
1640
  }
1641
1641
 
1642
1642
  // @beta @sealed @system
1643
- export interface TreeRecordNodeUnsafe<TAllowedTypes extends System_Unsafe.ImplicitAllowedTypesUnsafe> extends Record<string, System_Unsafe.TreeNodeFromImplicitAllowedTypesUnsafe<TAllowedTypes>>, TreeNode {
1643
+ export interface TreeRecordNodeUnsafe<TAllowedTypes extends System_Unsafe.ImplicitAllowedTypesUnsafe> extends Record<string, System_Unsafe.TreeNodeFromImplicitAllowedTypesUnsafe<TAllowedTypes> | undefined>, TreeNode {
1644
1644
  // (undocumented)
1645
1645
  [Symbol.iterator](): FluidIterableIterator<[
1646
1646
  string,
@@ -191,7 +191,7 @@ export interface ContainerSchema {
191
191
  export function createIdentifierIndex<TSchema extends ImplicitFieldSchema>(view: TreeView<TSchema>): IdentifierIndex;
192
192
 
193
193
  // @beta
194
- export function createIndependentTreeBeta<const TSchema extends ImplicitFieldSchema>(options?: ForestOptions): ViewableTree;
194
+ export function createIndependentTreeBeta<const Unused = unknown>(options?: ForestOptions): ViewableTree;
195
195
 
196
196
  // @beta
197
197
  export function createIndependentTreeView<const TSchema extends ImplicitFieldSchema>(config: TreeViewConfiguration<TSchema>, options?: ForestOptions): TreeViewBeta<TSchema>;
@@ -2002,7 +2002,7 @@ export type TreeNodeSchemaNonClass<Name extends string = string, Kind extends No
2002
2002
  export type TreeObjectNode<T extends RestrictiveStringRecord<ImplicitFieldSchema>, TypeName extends string = string> = TreeNode & ObjectFromSchemaRecord<T> & WithType<TypeName, NodeKind.Object, T>;
2003
2003
 
2004
2004
  // @beta
2005
- export interface TreeRecordNode<TAllowedTypes extends ImplicitAllowedTypes = ImplicitAllowedTypes> extends TreeNode, Record<string, TreeNodeFromImplicitAllowedTypes<TAllowedTypes>> {
2005
+ export interface TreeRecordNode<TAllowedTypes extends ImplicitAllowedTypes = ImplicitAllowedTypes> extends TreeNode, Record<string, TreeNodeFromImplicitAllowedTypes<TAllowedTypes> | undefined> {
2006
2006
  [Symbol.iterator](): FluidIterableIterator<[
2007
2007
  string,
2008
2008
  TreeNodeFromImplicitAllowedTypes<TAllowedTypes>
@@ -2010,7 +2010,7 @@ export interface TreeRecordNode<TAllowedTypes extends ImplicitAllowedTypes = Imp
2010
2010
  }
2011
2011
 
2012
2012
  // @beta @sealed @system
2013
- export interface TreeRecordNodeUnsafe<TAllowedTypes extends System_Unsafe.ImplicitAllowedTypesUnsafe> extends Record<string, System_Unsafe.TreeNodeFromImplicitAllowedTypesUnsafe<TAllowedTypes>>, TreeNode {
2013
+ export interface TreeRecordNodeUnsafe<TAllowedTypes extends System_Unsafe.ImplicitAllowedTypesUnsafe> extends Record<string, System_Unsafe.TreeNodeFromImplicitAllowedTypesUnsafe<TAllowedTypes> | undefined>, TreeNode {
2014
2014
  // (undocumented)
2015
2015
  [Symbol.iterator](): FluidIterableIterator<[
2016
2016
  string,
package/dist/alpha.d.ts CHANGED
@@ -337,6 +337,7 @@ export {
337
337
  RevertibleAlpha,
338
338
  RevertibleAlphaFactory,
339
339
  RunTransactionParamsAlpha,
340
+ Sandboxing,
340
341
  SchemaFactoryAlpha,
341
342
  SchemaStaticsAlpha,
342
343
  SchemaType,
package/lib/alpha.d.ts CHANGED
@@ -337,6 +337,7 @@ export {
337
337
  RevertibleAlpha,
338
338
  RevertibleAlphaFactory,
339
339
  RunTransactionParamsAlpha,
340
+ Sandboxing,
340
341
  SchemaFactoryAlpha,
341
342
  SchemaStaticsAlpha,
342
343
  SchemaType,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluid-framework",
3
- "version": "3.2.0",
3
+ "version": "3.4.0",
4
4
  "description": "The main entry point into Fluid Framework public packages",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -43,17 +43,17 @@
43
43
  }
44
44
  },
45
45
  "dependencies": {
46
- "@fluidframework/container-definitions": "~3.2.0",
47
- "@fluidframework/container-loader": "~3.2.0",
48
- "@fluidframework/core-interfaces": "~3.2.0",
49
- "@fluidframework/core-utils": "~3.2.0",
50
- "@fluidframework/driver-definitions": "~3.2.0",
51
- "@fluidframework/fluid-static": "~3.2.0",
52
- "@fluidframework/map": "~3.2.0",
53
- "@fluidframework/runtime-utils": "~3.2.0",
54
- "@fluidframework/sequence": "~3.2.0",
55
- "@fluidframework/shared-object-base": "~3.2.0",
56
- "@fluidframework/tree": "~3.2.0"
46
+ "@fluidframework/container-definitions": "~3.4.0",
47
+ "@fluidframework/container-loader": "~3.4.0",
48
+ "@fluidframework/core-interfaces": "~3.4.0",
49
+ "@fluidframework/core-utils": "~3.4.0",
50
+ "@fluidframework/driver-definitions": "~3.4.0",
51
+ "@fluidframework/fluid-static": "~3.4.0",
52
+ "@fluidframework/map": "~3.4.0",
53
+ "@fluidframework/runtime-utils": "~3.4.0",
54
+ "@fluidframework/sequence": "~3.4.0",
55
+ "@fluidframework/shared-object-base": "~3.4.0",
56
+ "@fluidframework/tree": "~3.4.0"
57
57
  },
58
58
  "devDependencies": {
59
59
  "@arethetypeswrong/cli": "^0.18.5",
@@ -67,7 +67,7 @@
67
67
  "concurrently": "^10.0.3",
68
68
  "copyfiles": "^2.4.1",
69
69
  "eslint": "~9.39.1",
70
- "fluid-framework-previous": "npm:fluid-framework@3.1.0",
70
+ "fluid-framework-previous": "npm:fluid-framework@3.3.0",
71
71
  "jiti": "^2.6.1",
72
72
  "rimraf": "^6.1.3",
73
73
  "typescript": "~6.0.3"