fluid-framework 2.113.0-411909 → 2.113.1

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.
Files changed (2) hide show
  1. package/CHANGELOG.md +174 -0
  2. package/package.json +12 -12
package/CHANGELOG.md CHANGED
@@ -1,5 +1,179 @@
1
1
  # fluid-framework
2
2
 
3
+ ## 2.113.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Enable select staged schema upgrades at runtime via view configuration ([#27542](https://github.com/microsoft/FluidFramework/pull/27542)) [44f40e8411](https://github.com/microsoft/FluidFramework/commit/44f40e8411d53bc22939a8f53343863f420bb0de)
8
+
9
+ SharedTree now supports enabling selected staged schema upgrades when initializing or upgrading a document's stored schema.
10
+ This lets applications deploy code that understands a schema change before enabling that change in documents.
11
+ It separates code rollout from feature rollout.
12
+
13
+ #### API
14
+
15
+ Pass `stagedUpgradePolicy` in the configuration object to
16
+ [`ITreeAlpha.viewWith`](https://fluidframework.com/docs/api/tree/viewabletree-interface#viewwith-methodsignature)
17
+ to select which schema upgrades to enable at runtime.
18
+
19
+ Use `StagedSchemaUpgradePolicy.enabledStagedUpgrades(...)` with `SchemaUpgrade` objects from
20
+ [`SchemaFactoryBeta.staged`](https://fluidframework.com/docs/api/tree/schemastaticsbeta-interface#staged-propertysignature)
21
+ or [`SchemaFactoryAlpha.stagedOptional`](https://fluidframework.com/docs/api/tree/schemafactoryalpha-class#stagedoptional-property):
22
+
23
+ The following example defines a staged type, extracts its `SchemaUpgrade` token, and passes it to the view configuration so the staged type is enabled when the schema is upgraded:
24
+
25
+ ```typescript
26
+ const sf = new SchemaFactoryBeta("my-app");
27
+
28
+ class ChecklistItem extends sf.object("ChecklistItem", { text: sf.string }) {}
29
+
30
+ // `staged` wraps the type so it can be enabled at runtime.
31
+ const stagedChecklist = SchemaFactoryBeta.staged(ChecklistItem);
32
+ // The SchemaUpgrade token identifies this staged type.
33
+ const checklistUpgrade = stagedChecklist.metadata.stagedSchemaUpgrade;
34
+
35
+ class AppSchema extends sf.object("AppSchema", {
36
+ items: sf.array([sf.string, stagedChecklist]),
37
+ }) {}
38
+
39
+ const view = tree.viewWith(
40
+ new TreeViewConfigurationAlpha({
41
+ schema: AppSchema,
42
+ stagedUpgradePolicy:
43
+ StagedSchemaUpgradePolicy.enabledStagedUpgrades(checklistUpgrade),
44
+ }),
45
+ );
46
+ ```
47
+
48
+ When `stagedUpgradePolicy` is omitted or `undefined`, the default is
49
+ `StagedSchemaUpgradePolicy.restrictive`.
50
+ This excludes all staged schema upgrades, producing the most conservative stored schema.
51
+
52
+ Advanced callers can provide a custom `StagedSchemaUpgradePolicy` object:
53
+
54
+ ```typescript
55
+ const enabledFeatures = new Set<SchemaUpgrade>([checklistUpgrade]);
56
+
57
+ const view = tree.viewWith(
58
+ new TreeViewConfigurationAlpha({
59
+ schema: AppSchema,
60
+ stagedUpgradePolicy: {
61
+ includeStaged: (upgrade) => enabledFeatures.has(upgrade),
62
+ includeStagedOptional: (upgrade) => enabledFeatures.has(upgrade),
63
+ },
64
+ }),
65
+ );
66
+ ```
67
+
68
+ This is useful for fine-grained rollout control or integration tests.
69
+
70
+ #### Pre-built Policies
71
+
72
+ The `StagedSchemaUpgradePolicy` namespace provides convenient pre-built policies:
73
+ - **`restrictive`** (default): excludes all staged upgrades.
74
+ - **`permissive`**: includes all staged upgrades. Useful in tests.
75
+ - **`enabledStagedUpgrades(...)`**: includes only the specified upgrades.
76
+
77
+ #### Production
78
+
79
+ Applications can use feature flags to control when staged schema upgrades are enabled.
80
+ Previously, enabling a staged schema required a code change that removed the staged wrapper.
81
+ With this API, the staged wrapper stays in code while `stagedUpgradePolicy` decides at runtime which documents enable it.
82
+
83
+ For example, an application adding checklist items can deploy clients that understand the new schema first,
84
+ then enable the stored-schema upgrade only where a feature flag is active:
85
+
86
+ ```typescript
87
+ const sf = new SchemaFactoryBeta("example-app");
88
+
89
+ class ChecklistItem extends sf.object("ChecklistItem", {
90
+ text: sf.string,
91
+ }) {}
92
+
93
+ const stagedChecklistItem = SchemaFactoryBeta.staged(ChecklistItem);
94
+ const checklistItemSchemaUpgrade =
95
+ stagedChecklistItem.metadata.stagedSchemaUpgrade;
96
+
97
+ class AppSchema extends sf.object("AppSchema", {
98
+ // `taskItem` allows plain text today; the staged type is added for future rollout.
99
+ taskItem: sf.optional([sf.string, stagedChecklistItem]),
100
+ }) {}
101
+
102
+ const enableChecklistItems = featureFlags.enableChecklistItems;
103
+
104
+ const view = tree.viewWith(
105
+ new TreeViewConfigurationAlpha({
106
+ schema: AppSchema,
107
+ stagedUpgradePolicy: enableChecklistItems
108
+ ? StagedSchemaUpgradePolicy.enabledStagedUpgrades(
109
+ checklistItemSchemaUpgrade,
110
+ )
111
+ : undefined,
112
+ }),
113
+ );
114
+
115
+ if (view.compatibility.canInitialize) {
116
+ // New documents include the checklist schema only while the rollout is enabled.
117
+ view.initialize(initialContent);
118
+ } else if (view.compatibility.canUpgrade) {
119
+ // Writes the staged type into the stored schema for this document.
120
+ view.upgradeSchema();
121
+ }
122
+ ```
123
+
124
+ Once a staged schema upgrade has been written to a document's stored schema, that change is permanent.
125
+ If `upgradeSchema` is later called from a view that does not include the previously enabled token,
126
+ it throws a `UsageError` because the new target would narrow the stored schema.
127
+
128
+ In practice, keep the upgrade token configured for as long as any document may have been upgraded.
129
+ Once the staged wrapper is removed from the code, the token is no longer needed.
130
+
131
+ #### Testing
132
+
133
+ Tests can verify that the current application version handles documents with staged types enabled.
134
+ Without such testing, it is hard to confirm that staging prepared the application—not just the schema—for the new types.
135
+
136
+ ```typescript
137
+ const currentView = currentAppTree.viewWith(
138
+ new TreeViewConfiguration({ schema: CurrentAppSchema }),
139
+ );
140
+ currentView.initialize(existingTaskDocument);
141
+ await ensureSynchronized();
142
+
143
+ const nextView = asAlpha(nextAppTree).viewWith(
144
+ new TreeViewConfigurationAlpha({
145
+ schema: AppSchemaWithStagedChecklist,
146
+ stagedUpgradePolicy: StagedSchemaUpgradePolicy.enabledStagedUpgrades(
147
+ checklistItemSchemaUpgrade,
148
+ ),
149
+ }),
150
+ );
151
+
152
+ // The next version can read the document, but the checklist shape is not yet
153
+ // in stored schema and cannot be written.
154
+ assert.throws(() =>
155
+ addChecklistItem(nextView.root, { text: "Review rollout" }),
156
+ );
157
+
158
+ nextView.upgradeSchema();
159
+ await ensureSynchronized();
160
+
161
+ // Older clients are now incompatible; the next version can use the staged shape.
162
+ assert.equal(currentView.compatibility.canView, false);
163
+ addChecklistItem(nextView.root, { text: "Review rollout" });
164
+ await validateChecklistScenario(nextView);
165
+ ```
166
+
167
+ - Fix assert when inserting the same node multiple times ([#27734](https://github.com/microsoft/FluidFramework/pull/27734)) [b509d00166](https://github.com/microsoft/FluidFramework/commit/b509d00166773585c42c60e97ec30a86fbd20cd5)
168
+
169
+ When inserting the same node multiple times in a single array insertion, a `UsageError` is now thrown instead of an assert `0xa2b`.
170
+
171
+ For example, this now throws a `UsageError` with message `A "ArrayNodeTest.Item" node was provided more than once in a single insertion. A node may not be in more than one place in the tree.`:
172
+
173
+ ```TypeScript
174
+ array.insertAtEnd(item, item);
175
+ ```
176
+
3
177
  ## 2.112.0
4
178
 
5
179
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluid-framework",
3
- "version": "2.113.0-411909",
3
+ "version": "2.113.1",
4
4
  "description": "The main entry point into Fluid Framework public packages",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -57,17 +57,17 @@
57
57
  "main": "lib/index.js",
58
58
  "types": "lib/public.d.ts",
59
59
  "dependencies": {
60
- "@fluidframework/container-definitions": "2.113.0-411909",
61
- "@fluidframework/container-loader": "2.113.0-411909",
62
- "@fluidframework/core-interfaces": "2.113.0-411909",
63
- "@fluidframework/core-utils": "2.113.0-411909",
64
- "@fluidframework/driver-definitions": "2.113.0-411909",
65
- "@fluidframework/fluid-static": "2.113.0-411909",
66
- "@fluidframework/map": "2.113.0-411909",
67
- "@fluidframework/runtime-utils": "2.113.0-411909",
68
- "@fluidframework/sequence": "2.113.0-411909",
69
- "@fluidframework/shared-object-base": "2.113.0-411909",
70
- "@fluidframework/tree": "2.113.0-411909"
60
+ "@fluidframework/container-definitions": "~2.113.1",
61
+ "@fluidframework/container-loader": "~2.113.1",
62
+ "@fluidframework/core-interfaces": "~2.113.1",
63
+ "@fluidframework/core-utils": "~2.113.1",
64
+ "@fluidframework/driver-definitions": "~2.113.1",
65
+ "@fluidframework/fluid-static": "~2.113.1",
66
+ "@fluidframework/map": "~2.113.1",
67
+ "@fluidframework/runtime-utils": "~2.113.1",
68
+ "@fluidframework/sequence": "~2.113.1",
69
+ "@fluidframework/shared-object-base": "~2.113.1",
70
+ "@fluidframework/tree": "~2.113.1"
71
71
  },
72
72
  "devDependencies": {
73
73
  "@arethetypeswrong/cli": "^0.18.2",