@fluidframework/tree 2.117.0 → 2.118.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 +86 -0
- package/api-report/tree.alpha.api.md +44 -1
- package/api-report/tree.beta.api.md +38 -0
- package/api-report/tree.legacy.beta.api.md +38 -0
- package/dist/entrypoints/alpha.d.ts +1 -1
- package/dist/entrypoints/alpha.d.ts.map +1 -1
- package/dist/entrypoints/alpha.js.map +1 -1
- package/dist/entrypoints/beta.d.ts +1 -1
- package/dist/entrypoints/beta.d.ts.map +1 -1
- package/dist/entrypoints/beta.js.map +1 -1
- package/dist/entrypoints/legacy.d.ts +1 -1
- package/dist/entrypoints/legacy.d.ts.map +1 -1
- package/dist/entrypoints/legacy.js.map +1 -1
- package/dist/feature-libraries/index.d.ts +1 -1
- package/dist/feature-libraries/index.js.map +1 -1
- package/dist/feature-libraries/schemaChecker.d.ts +9 -19
- package/dist/feature-libraries/schemaChecker.d.ts.map +1 -1
- package/dist/feature-libraries/schemaChecker.js +130 -46
- package/dist/feature-libraries/schemaChecker.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/shared-tree/schematizingTreeView.d.ts +13 -3
- package/dist/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/dist/shared-tree/schematizingTreeView.js +48 -11
- package/dist/shared-tree/schematizingTreeView.js.map +1 -1
- package/dist/simple-tree/api/configuration.d.ts +4 -4
- package/dist/simple-tree/api/configuration.d.ts.map +1 -1
- package/dist/simple-tree/api/configuration.js.map +1 -1
- package/dist/simple-tree/api/discrepancies.d.ts +36 -3
- package/dist/simple-tree/api/discrepancies.d.ts.map +1 -1
- package/dist/simple-tree/api/discrepancies.js +40 -14
- package/dist/simple-tree/api/discrepancies.js.map +1 -1
- package/dist/simple-tree/api/index.d.ts +3 -2
- package/dist/simple-tree/api/index.d.ts.map +1 -1
- package/dist/simple-tree/api/index.js +3 -2
- package/dist/simple-tree/api/index.js.map +1 -1
- package/dist/simple-tree/api/schemaCompatibilityTester.d.ts +22 -3
- package/dist/simple-tree/api/schemaCompatibilityTester.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaCompatibilityTester.js +140 -10
- package/dist/simple-tree/api/schemaCompatibilityTester.js.map +1 -1
- package/dist/simple-tree/api/tree.d.ts +173 -7
- package/dist/simple-tree/api/tree.d.ts.map +1 -1
- package/dist/simple-tree/api/tree.js.map +1 -1
- package/dist/simple-tree/core/toStored.d.ts +7 -0
- package/dist/simple-tree/core/toStored.d.ts.map +1 -1
- package/dist/simple-tree/core/toStored.js.map +1 -1
- package/dist/simple-tree/core/treeNodeValid.d.ts.map +1 -1
- package/dist/simple-tree/core/treeNodeValid.js +2 -2
- package/dist/simple-tree/core/treeNodeValid.js.map +1 -1
- package/dist/simple-tree/index.d.ts +1 -1
- package/dist/simple-tree/index.d.ts.map +1 -1
- package/dist/simple-tree/index.js +4 -3
- package/dist/simple-tree/index.js.map +1 -1
- package/docs/main/glossary.md +163 -0
- package/lib/entrypoints/alpha.d.ts +1 -1
- package/lib/entrypoints/alpha.d.ts.map +1 -1
- package/lib/entrypoints/alpha.js.map +1 -1
- package/lib/entrypoints/beta.d.ts +1 -1
- package/lib/entrypoints/beta.d.ts.map +1 -1
- package/lib/entrypoints/beta.js.map +1 -1
- package/lib/entrypoints/legacy.d.ts +1 -1
- package/lib/entrypoints/legacy.d.ts.map +1 -1
- package/lib/entrypoints/legacy.js.map +1 -1
- package/lib/feature-libraries/index.d.ts +1 -1
- package/lib/feature-libraries/index.js.map +1 -1
- package/lib/feature-libraries/schemaChecker.d.ts +9 -19
- package/lib/feature-libraries/schemaChecker.d.ts.map +1 -1
- package/lib/feature-libraries/schemaChecker.js +133 -49
- package/lib/feature-libraries/schemaChecker.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/shared-tree/schematizingTreeView.d.ts +13 -3
- package/lib/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/lib/shared-tree/schematizingTreeView.js +49 -12
- package/lib/shared-tree/schematizingTreeView.js.map +1 -1
- package/lib/simple-tree/api/configuration.d.ts +4 -4
- package/lib/simple-tree/api/configuration.d.ts.map +1 -1
- package/lib/simple-tree/api/configuration.js.map +1 -1
- package/lib/simple-tree/api/discrepancies.d.ts +36 -3
- package/lib/simple-tree/api/discrepancies.d.ts.map +1 -1
- package/lib/simple-tree/api/discrepancies.js +40 -14
- package/lib/simple-tree/api/discrepancies.js.map +1 -1
- package/lib/simple-tree/api/index.d.ts +3 -2
- package/lib/simple-tree/api/index.d.ts.map +1 -1
- package/lib/simple-tree/api/index.js +1 -1
- package/lib/simple-tree/api/index.js.map +1 -1
- package/lib/simple-tree/api/schemaCompatibilityTester.d.ts +22 -3
- package/lib/simple-tree/api/schemaCompatibilityTester.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaCompatibilityTester.js +136 -7
- package/lib/simple-tree/api/schemaCompatibilityTester.js.map +1 -1
- package/lib/simple-tree/api/tree.d.ts +173 -7
- package/lib/simple-tree/api/tree.d.ts.map +1 -1
- package/lib/simple-tree/api/tree.js.map +1 -1
- package/lib/simple-tree/core/toStored.d.ts +7 -0
- package/lib/simple-tree/core/toStored.d.ts.map +1 -1
- package/lib/simple-tree/core/toStored.js.map +1 -1
- package/lib/simple-tree/core/treeNodeValid.d.ts.map +1 -1
- package/lib/simple-tree/core/treeNodeValid.js +3 -3
- package/lib/simple-tree/core/treeNodeValid.js.map +1 -1
- package/lib/simple-tree/index.d.ts +1 -1
- package/lib/simple-tree/index.d.ts.map +1 -1
- package/lib/simple-tree/index.js +1 -1
- package/lib/simple-tree/index.js.map +1 -1
- package/package.json +22 -22
- package/src/entrypoints/alpha.ts +3 -0
- package/src/entrypoints/beta.ts +2 -0
- package/src/entrypoints/legacy.ts +2 -0
- package/src/feature-libraries/index.ts +1 -1
- package/src/feature-libraries/schemaChecker.ts +198 -82
- package/src/index.ts +3 -0
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/schematizingTreeView.ts +75 -21
- package/src/simple-tree/api/configuration.ts +4 -4
- package/src/simple-tree/api/discrepancies.ts +100 -5
- package/src/simple-tree/api/index.ts +7 -1
- package/src/simple-tree/api/schemaCompatibilityTester.ts +185 -11
- package/src/simple-tree/api/tree.ts +185 -8
- package/src/simple-tree/core/toStored.ts +8 -0
- package/src/simple-tree/core/treeNodeValid.ts +3 -1
- package/src/simple-tree/index.ts +4 -0
- package/docs/main/runtime-schema-upgrade.md +0 -208
|
@@ -3,14 +3,119 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
import { unreachableCase } from "@fluidframework/core-utils/internal";
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
MapNodeStoredSchema,
|
|
10
|
+
ObjectNodeStoredSchema,
|
|
11
|
+
type TreeStoredSchema,
|
|
12
|
+
ValueSchema,
|
|
13
|
+
} from "../../core/index.js";
|
|
7
14
|
import type { SchemaUpgrade, StagedSchemaUpgradePolicy } from "../core/index.js";
|
|
15
|
+
import { NodeKind } from "../core/index.js";
|
|
8
16
|
import { allowsRepoSuperset, defaultSchemaPolicy } from "../../feature-libraries/index.js";
|
|
9
|
-
import { toUpgradeSchema } from "../toStoredSchema.js";
|
|
17
|
+
import { resolveStoredSchemaGenerationOptions, toUpgradeSchema } from "../toStoredSchema.js";
|
|
10
18
|
import type { TreeSchema } from "../treeSchema.js";
|
|
11
19
|
|
|
12
|
-
import {
|
|
13
|
-
|
|
20
|
+
import {
|
|
21
|
+
getDiscrepanciesInAllowedContent,
|
|
22
|
+
type Discrepancy,
|
|
23
|
+
type UpgradeLocationCollector,
|
|
24
|
+
} from "./discrepancies.js";
|
|
25
|
+
import type { SchemaCompatibilityStatusBeta, SchemaDiscrepancy } from "./tree.js";
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Describes the discrepancies that prevent a view schema from viewing a stored schema as a
|
|
29
|
+
* readonly array.
|
|
30
|
+
*/
|
|
31
|
+
export function getSchemaIncompatibilityDetails(
|
|
32
|
+
viewSchema: TreeSchema,
|
|
33
|
+
stored: TreeStoredSchema,
|
|
34
|
+
): readonly SchemaDiscrepancy[] | undefined {
|
|
35
|
+
const discrepancies = [...getDiscrepanciesInAllowedContent(viewSchema, stored)];
|
|
36
|
+
if (discrepancies.length === 0) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return discrepancies.map(formatSchemaDiscrepancy);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function formatSchemaDiscrepancy(value: Discrepancy): SchemaDiscrepancy {
|
|
44
|
+
switch (value.mismatch) {
|
|
45
|
+
case "allowedTypes": {
|
|
46
|
+
return {
|
|
47
|
+
mismatch: value.mismatch,
|
|
48
|
+
location:
|
|
49
|
+
value.identifier === undefined
|
|
50
|
+
? "root"
|
|
51
|
+
: {
|
|
52
|
+
nodeType: value.identifier,
|
|
53
|
+
fieldKey: value.fieldKey,
|
|
54
|
+
},
|
|
55
|
+
view: value.view.map(({ type }) => type.identifier).sort(),
|
|
56
|
+
...(value.stagedView === undefined
|
|
57
|
+
? {}
|
|
58
|
+
: {
|
|
59
|
+
stagedView: value.stagedView.map(({ type }) => type.identifier).sort(),
|
|
60
|
+
}),
|
|
61
|
+
stored: [...value.stored].sort(),
|
|
62
|
+
...(value.viewIsStagedOptional === true ? { viewIsStagedOptional: true } : {}),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
case "fieldKind": {
|
|
66
|
+
return {
|
|
67
|
+
mismatch: value.mismatch,
|
|
68
|
+
location:
|
|
69
|
+
value.identifier === undefined
|
|
70
|
+
? "root"
|
|
71
|
+
: {
|
|
72
|
+
nodeType: value.identifier,
|
|
73
|
+
fieldKey: value.fieldKey,
|
|
74
|
+
},
|
|
75
|
+
view: value.view,
|
|
76
|
+
stored: value.stored,
|
|
77
|
+
...(value.viewIsStagedOptional === true ? { viewIsStagedOptional: true } : {}),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
case "valueSchema": {
|
|
81
|
+
return {
|
|
82
|
+
mismatch: value.mismatch,
|
|
83
|
+
nodeType: value.identifier,
|
|
84
|
+
view: value.view === undefined ? undefined : ValueSchema[value.view],
|
|
85
|
+
stored: value.stored === undefined ? undefined : ValueSchema[value.stored],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
case "nodeKind": {
|
|
89
|
+
const storedNodeKind =
|
|
90
|
+
value.stored === ObjectNodeStoredSchema
|
|
91
|
+
? "Object"
|
|
92
|
+
: value.stored === MapNodeStoredSchema
|
|
93
|
+
? "Map"
|
|
94
|
+
: "Leaf";
|
|
95
|
+
return {
|
|
96
|
+
mismatch: value.mismatch,
|
|
97
|
+
nodeType: value.identifier,
|
|
98
|
+
view: NodeKind[value.view],
|
|
99
|
+
stored: storedNodeKind,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
default: {
|
|
103
|
+
return unreachableCase(value);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The enablement status of a staged schema upgrade in a document's stored schema.
|
|
110
|
+
*
|
|
111
|
+
* @remarks
|
|
112
|
+
* - `"disabled"` — no locations guarded by the upgrade are enabled in stored schema.
|
|
113
|
+
* - `"partial"` — at least one location is enabled but not all of them.
|
|
114
|
+
* - `"enabled"` — all locations guarded by the upgrade are enabled in stored schema.
|
|
115
|
+
*
|
|
116
|
+
* @alpha
|
|
117
|
+
*/
|
|
118
|
+
export type StagedUpgradeStatus = "disabled" | "partial" | "enabled";
|
|
14
119
|
|
|
15
120
|
/**
|
|
16
121
|
* Determines the compatibility of a stored document (based on its stored schema) with a viewer (based on its view schema).
|
|
@@ -24,27 +129,59 @@ import type { SchemaCompatibilityStatus } from "./tree.js";
|
|
|
24
129
|
* @param viewSchema - Schema for the view
|
|
25
130
|
* @param stored - The stored schema to check compatibility against
|
|
26
131
|
* @param stagedSchemaUpgrades - Staged schema upgrades enabled for this view, or explicit stored-schema generation options
|
|
132
|
+
*
|
|
27
133
|
*/
|
|
28
134
|
export function checkSchemaCompatibility(
|
|
29
135
|
viewSchema: TreeSchema,
|
|
30
136
|
stored: TreeStoredSchema,
|
|
31
137
|
stagedSchemaUpgrades?: Iterable<SchemaUpgrade> | StagedSchemaUpgradePolicy,
|
|
32
|
-
): Omit<
|
|
138
|
+
): Omit<SchemaCompatibilityStatusBeta, "canInitialize"> & {
|
|
139
|
+
enabledUpgrades: ReadonlyMap<SchemaUpgrade, StagedUpgradeStatus>;
|
|
140
|
+
} {
|
|
33
141
|
// The public API surface assumes defaultSchemaPolicy
|
|
34
142
|
const policy = defaultSchemaPolicy;
|
|
143
|
+
const configuredPolicy = resolveStoredSchemaGenerationOptions(stagedSchemaUpgrades);
|
|
144
|
+
const includeAlreadyEnabledUpgrades = configuredPolicy.includeAlreadyEnabledUpgrades ?? true;
|
|
145
|
+
|
|
146
|
+
// Collect upgrade locations during the discrepancy walk (single pass).
|
|
147
|
+
const totalLocations = new Map<SchemaUpgrade, number>();
|
|
148
|
+
const enabledLocations = new Map<SchemaUpgrade, number>();
|
|
149
|
+
const upgradeCollector: UpgradeLocationCollector = {
|
|
150
|
+
allowedType(upgrade, isEnabled) {
|
|
151
|
+
totalLocations.set(upgrade, (totalLocations.get(upgrade) ?? 0) + 1);
|
|
152
|
+
if (isEnabled) {
|
|
153
|
+
enabledLocations.set(upgrade, (enabledLocations.get(upgrade) ?? 0) + 1);
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
optionalField(upgrade, isEnabled) {
|
|
157
|
+
totalLocations.set(upgrade, (totalLocations.get(upgrade) ?? 0) + 1);
|
|
158
|
+
if (isEnabled) {
|
|
159
|
+
enabledLocations.set(upgrade, (enabledLocations.get(upgrade) ?? 0) + 1);
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
};
|
|
35
163
|
|
|
36
164
|
// View schema allows a subset of documents that stored schema does, and the discrepancies are allowed by policy
|
|
37
165
|
// determined by the view schema (i.e. objects with extra optional fields in the stored schema have opted into allowing this.
|
|
38
166
|
// In the future, this would also include things like:
|
|
39
167
|
// - fields with more allowed types in the stored schema than in the view schema have out-of-schema "unknown content" adapters
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
168
|
+
// Complete the full walk even after finding an incompatibility so discrepancy details and
|
|
169
|
+
// staged-upgrade status contain all available information for debugging.
|
|
170
|
+
const discrepancies: SchemaDiscrepancy[] = [];
|
|
171
|
+
for (const discrepancy of getDiscrepanciesInAllowedContent(
|
|
172
|
+
viewSchema,
|
|
173
|
+
stored,
|
|
174
|
+
upgradeCollector,
|
|
175
|
+
)) {
|
|
176
|
+
discrepancies.push(formatSchemaDiscrepancy(discrepancy));
|
|
45
177
|
}
|
|
178
|
+
const canView = discrepancies.length === 0;
|
|
46
179
|
|
|
47
|
-
const
|
|
180
|
+
const enabledUpgrades = computeUpgradeStatuses(totalLocations, enabledLocations);
|
|
181
|
+
const upgradePolicy = includeAlreadyEnabledUpgrades
|
|
182
|
+
? includeEnabledUpgrades(configuredPolicy, enabledUpgrades)
|
|
183
|
+
: configuredPolicy;
|
|
184
|
+
const wouldUpgradeTo = toUpgradeSchema(viewSchema.root, upgradePolicy);
|
|
48
185
|
|
|
49
186
|
const canUpgrade = allowsRepoSuperset(policy, stored, wouldUpgradeTo);
|
|
50
187
|
|
|
@@ -57,5 +194,42 @@ export function checkSchemaCompatibility(
|
|
|
57
194
|
canView,
|
|
58
195
|
canUpgrade,
|
|
59
196
|
isEquivalent,
|
|
197
|
+
discrepancies: canView ? undefined : discrepancies,
|
|
198
|
+
enabledUpgrades,
|
|
60
199
|
};
|
|
61
200
|
}
|
|
201
|
+
|
|
202
|
+
function includeEnabledUpgrades(
|
|
203
|
+
configuredPolicy: StagedSchemaUpgradePolicy,
|
|
204
|
+
enabledUpgrades: ReadonlyMap<SchemaUpgrade, StagedUpgradeStatus>,
|
|
205
|
+
): StagedSchemaUpgradePolicy {
|
|
206
|
+
if (enabledUpgrades.size === 0) {
|
|
207
|
+
return configuredPolicy;
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
includeStaged: (upgrade) =>
|
|
211
|
+
configuredPolicy.includeStaged(upgrade) || enabledUpgrades.has(upgrade),
|
|
212
|
+
includeStagedOptional: (upgrade) =>
|
|
213
|
+
configuredPolicy.includeStagedOptional(upgrade) || enabledUpgrades.has(upgrade),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Computes the {@link StagedUpgradeStatus} for each upgrade token from total and enabled location counts.
|
|
219
|
+
* Only tokens with at least one enabled location are included in the returned map.
|
|
220
|
+
*/
|
|
221
|
+
function computeUpgradeStatuses(
|
|
222
|
+
totalLocations: ReadonlyMap<SchemaUpgrade, number>,
|
|
223
|
+
enabledLocations: ReadonlyMap<SchemaUpgrade, number>,
|
|
224
|
+
): ReadonlyMap<SchemaUpgrade, StagedUpgradeStatus> {
|
|
225
|
+
const result = new Map<SchemaUpgrade, StagedUpgradeStatus>();
|
|
226
|
+
for (const [upgrade, total] of totalLocations) {
|
|
227
|
+
const enabled = enabledLocations.get(upgrade) ?? 0;
|
|
228
|
+
if (enabled > 0 && enabled < total) {
|
|
229
|
+
result.set(upgrade, "partial");
|
|
230
|
+
} else if (enabled >= total && enabled > 0) {
|
|
231
|
+
result.set(upgrade, "enabled");
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
@@ -26,7 +26,7 @@ import type {
|
|
|
26
26
|
JsonCompatibleReadOnlyObject,
|
|
27
27
|
} from "../../util/index.js";
|
|
28
28
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- This is referenced by doc comments.
|
|
29
|
-
import type { Unhydrated } from "../core/index.js";
|
|
29
|
+
import type { SchemaUpgrade, Unhydrated } from "../core/index.js";
|
|
30
30
|
import type {
|
|
31
31
|
ImplicitFieldSchema,
|
|
32
32
|
InsertableField,
|
|
@@ -39,6 +39,7 @@ import type { SimpleTreeSchema } from "../simpleSchema.js";
|
|
|
39
39
|
import type { UnsafeUnknownSchema } from "../unsafeUnknownSchema.js";
|
|
40
40
|
|
|
41
41
|
import type { TreeViewConfiguration } from "./configuration.js";
|
|
42
|
+
import type { StagedUpgradeStatus } from "./schemaCompatibilityTester.js";
|
|
42
43
|
import type {
|
|
43
44
|
RunTransactionParamsAlpha,
|
|
44
45
|
RunTransactionParamsBeta,
|
|
@@ -601,9 +602,9 @@ export interface TreeView<in out TSchema extends ImplicitFieldSchema> extends ID
|
|
|
601
602
|
*
|
|
602
603
|
* When using {@link TreeViewConfigurationAlpha} with a {@link ITreeViewConfigurationAlpha.stagedUpgradePolicy},
|
|
603
604
|
* staged schema upgrades matching the configured policy are included in the target stored schema.
|
|
604
|
-
*
|
|
605
|
-
*
|
|
606
|
-
*
|
|
605
|
+
* Staged upgrades that are already enabled in the document are also included by default. Set
|
|
606
|
+
* {@link (StagedSchemaUpgradePolicy:interface).includeAlreadyEnabledUpgrades} to `false` when
|
|
607
|
+
* creating the policy to only include staged upgrades selected explicitly by the policy.
|
|
607
608
|
*
|
|
608
609
|
* @example Enabling a staged allowed type for documents, selected by a feature flag
|
|
609
610
|
*
|
|
@@ -675,6 +676,164 @@ export interface TreeView<in out TSchema extends ImplicitFieldSchema> extends ID
|
|
|
675
676
|
readonly schema: TSchema;
|
|
676
677
|
}
|
|
677
678
|
|
|
679
|
+
/**
|
|
680
|
+
* A discrepancy between a view schema and a document's stored schema.
|
|
681
|
+
*
|
|
682
|
+
* @remarks
|
|
683
|
+
* The `mismatch` property discriminates the different discrepancy shapes.
|
|
684
|
+
*
|
|
685
|
+
* @sealed @beta
|
|
686
|
+
*/
|
|
687
|
+
export type SchemaDiscrepancy =
|
|
688
|
+
| {
|
|
689
|
+
/**
|
|
690
|
+
* Indicates that a field allows different node types in the view and stored schemas.
|
|
691
|
+
*/
|
|
692
|
+
readonly mismatch: "allowedTypes";
|
|
693
|
+
/**
|
|
694
|
+
* The field with the discrepancy.
|
|
695
|
+
*
|
|
696
|
+
* `"root"` identifies the root field. Otherwise, `nodeType` identifies the containing
|
|
697
|
+
* node schema and `fieldKey` identifies its field. `fieldKey` is undefined for a map
|
|
698
|
+
* node's implicit field.
|
|
699
|
+
*/
|
|
700
|
+
readonly location:
|
|
701
|
+
| "root"
|
|
702
|
+
| {
|
|
703
|
+
readonly nodeType: string;
|
|
704
|
+
readonly fieldKey: string | undefined;
|
|
705
|
+
};
|
|
706
|
+
/**
|
|
707
|
+
* Non-staged node type identifiers allowed by the view schema but not the stored schema.
|
|
708
|
+
*/
|
|
709
|
+
readonly view: readonly string[];
|
|
710
|
+
/**
|
|
711
|
+
* Staged node type identifiers allowed by the view schema but not the stored schema.
|
|
712
|
+
*
|
|
713
|
+
* @remarks These types provide rollout context but do not cause the discrepancy.
|
|
714
|
+
*/
|
|
715
|
+
readonly stagedView?: readonly string[];
|
|
716
|
+
/**
|
|
717
|
+
* Node type identifiers allowed by the stored schema but not the view schema.
|
|
718
|
+
*/
|
|
719
|
+
readonly stored: readonly string[];
|
|
720
|
+
/**
|
|
721
|
+
* Whether the view field is a staged optional field.
|
|
722
|
+
*
|
|
723
|
+
* @remarks Omitted when false.
|
|
724
|
+
*/
|
|
725
|
+
readonly viewIsStagedOptional?: true;
|
|
726
|
+
}
|
|
727
|
+
| {
|
|
728
|
+
/**
|
|
729
|
+
* Indicates that a field has different field kinds in the view and stored schemas.
|
|
730
|
+
*/
|
|
731
|
+
readonly mismatch: "fieldKind";
|
|
732
|
+
/**
|
|
733
|
+
* The field with the discrepancy.
|
|
734
|
+
*
|
|
735
|
+
* `"root"` identifies the root field. Otherwise, `nodeType` identifies the containing
|
|
736
|
+
* node schema and `fieldKey` identifies its field. `fieldKey` is undefined for a map
|
|
737
|
+
* node's implicit field.
|
|
738
|
+
*/
|
|
739
|
+
readonly location:
|
|
740
|
+
| "root"
|
|
741
|
+
| {
|
|
742
|
+
readonly nodeType: string;
|
|
743
|
+
readonly fieldKey: string | undefined;
|
|
744
|
+
};
|
|
745
|
+
/**
|
|
746
|
+
* The field kind required by the view schema.
|
|
747
|
+
*/
|
|
748
|
+
readonly view: string;
|
|
749
|
+
/**
|
|
750
|
+
* The field kind recorded in the stored schema.
|
|
751
|
+
*/
|
|
752
|
+
readonly stored: string;
|
|
753
|
+
/**
|
|
754
|
+
* Whether the view field is a staged optional field.
|
|
755
|
+
*
|
|
756
|
+
* @remarks Omitted when false.
|
|
757
|
+
*/
|
|
758
|
+
readonly viewIsStagedOptional?: true;
|
|
759
|
+
}
|
|
760
|
+
| {
|
|
761
|
+
/**
|
|
762
|
+
* Indicates that a leaf node accepts different value types in the view and stored schemas.
|
|
763
|
+
*/
|
|
764
|
+
readonly mismatch: "valueSchema";
|
|
765
|
+
/**
|
|
766
|
+
* The identifier of the leaf node schema with the discrepancy.
|
|
767
|
+
*/
|
|
768
|
+
readonly nodeType: string;
|
|
769
|
+
/**
|
|
770
|
+
* The value schema required by the view, or undefined when it does not constrain values.
|
|
771
|
+
*/
|
|
772
|
+
readonly view: string | undefined;
|
|
773
|
+
/**
|
|
774
|
+
* The value schema recorded in the stored schema, or undefined when it does not constrain values.
|
|
775
|
+
*/
|
|
776
|
+
readonly stored: string | undefined;
|
|
777
|
+
}
|
|
778
|
+
| {
|
|
779
|
+
/**
|
|
780
|
+
* Indicates that a node is represented by different node kinds in the view and stored schemas.
|
|
781
|
+
*/
|
|
782
|
+
readonly mismatch: "nodeKind";
|
|
783
|
+
/**
|
|
784
|
+
* The identifier of the node schema with the discrepancy.
|
|
785
|
+
*/
|
|
786
|
+
readonly nodeType: string;
|
|
787
|
+
/**
|
|
788
|
+
* The node kind required by the view schema.
|
|
789
|
+
*/
|
|
790
|
+
readonly view: string;
|
|
791
|
+
/**
|
|
792
|
+
* The node kind recorded in the stored schema.
|
|
793
|
+
*/
|
|
794
|
+
readonly stored: string;
|
|
795
|
+
};
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* {@link SchemaCompatibilityStatus} with additional beta APIs.
|
|
799
|
+
*
|
|
800
|
+
* @sealed @beta
|
|
801
|
+
*/
|
|
802
|
+
export interface SchemaCompatibilityStatusBeta extends SchemaCompatibilityStatus {
|
|
803
|
+
/**
|
|
804
|
+
* Details about the schema discrepancies that prevent this view from accessing the tree.
|
|
805
|
+
*
|
|
806
|
+
* @remarks
|
|
807
|
+
* This property is undefined when {@link SchemaCompatibilityStatus.canView} is true and present
|
|
808
|
+
* when `canView` is false.
|
|
809
|
+
* It can include application-defined schema identifiers and field keys.
|
|
810
|
+
*
|
|
811
|
+
* @example Interpreting an allowed-types discrepancy
|
|
812
|
+
*
|
|
813
|
+
* If a document's stored schema allows `string` for `Todo.title`, but the view schema expects
|
|
814
|
+
* `number`, the discrepancy identifies the field and the type permitted by each schema:
|
|
815
|
+
*
|
|
816
|
+
* ```typescript
|
|
817
|
+
* const sf = new SchemaFactory("com.example");
|
|
818
|
+
* class Todo extends sf.object("Todo", {
|
|
819
|
+
* title: sf.number,
|
|
820
|
+
* }) {}
|
|
821
|
+
*
|
|
822
|
+
* const view = asBeta(tree.viewWith(new TreeViewConfiguration({ schema: Todo })));
|
|
823
|
+
* if (!view.compatibility.canView) {
|
|
824
|
+
* // [{
|
|
825
|
+
* // mismatch: "allowedTypes",
|
|
826
|
+
* // location: { nodeType: "com.example.Todo", fieldKey: "title" },
|
|
827
|
+
* // view: ["com.fluidframework.leaf.number"],
|
|
828
|
+
* // stored: ["com.fluidframework.leaf.string"],
|
|
829
|
+
* // }]
|
|
830
|
+
* console.error(view.compatibility.discrepancies);
|
|
831
|
+
* }
|
|
832
|
+
* ```
|
|
833
|
+
*/
|
|
834
|
+
readonly discrepancies: readonly SchemaDiscrepancy[] | undefined;
|
|
835
|
+
}
|
|
836
|
+
|
|
678
837
|
/**
|
|
679
838
|
* {@link TreeView} with additional beta APIs.
|
|
680
839
|
* @sealed @beta
|
|
@@ -682,6 +841,11 @@ export interface TreeView<in out TSchema extends ImplicitFieldSchema> extends ID
|
|
|
682
841
|
export interface TreeViewBeta<in out TSchema extends ImplicitFieldSchema>
|
|
683
842
|
extends TreeView<TSchema>,
|
|
684
843
|
UntypedTreeView {
|
|
844
|
+
/**
|
|
845
|
+
* {@inheritDoc TreeView.compatibility}
|
|
846
|
+
*/
|
|
847
|
+
readonly compatibility: SchemaCompatibilityStatusBeta;
|
|
848
|
+
|
|
685
849
|
// Override the base branch method to return a typed view rather than merely a branch.
|
|
686
850
|
fork(): ReturnType<UntypedTreeView["fork"]> & TreeViewBeta<TSchema>;
|
|
687
851
|
|
|
@@ -773,16 +937,29 @@ export interface TreeViewAlpha<
|
|
|
773
937
|
* Only valid to call when this view's {@link SchemaCompatibilityStatus.canInitialize} is true.
|
|
774
938
|
*
|
|
775
939
|
* Enables staged schema upgrades declared by {@link ITreeViewConfigurationAlpha.stagedUpgradePolicy} when generating the initial stored schema.
|
|
776
|
-
* Once a staged schema upgrade has been enabled in a document's stored schema, loading that document
|
|
777
|
-
* with a view that does not include equivalent staged members in its construction-time policy will cause
|
|
778
|
-
* a subsequent `upgradeSchema` call to throw a `UsageError` because the stored schema already contains
|
|
779
|
-
* the upgraded members and the new target would narrow it.
|
|
780
940
|
*
|
|
781
941
|
* Applications should typically call this function before attaching a `SharedTree`.
|
|
782
942
|
* @param content - The content to initialize the tree with.
|
|
783
943
|
*/
|
|
784
944
|
initialize(content: InsertableField<TSchema>): void;
|
|
785
945
|
|
|
946
|
+
/**
|
|
947
|
+
* Checks whether a staged schema upgrade has been applied to the document's stored schema.
|
|
948
|
+
*
|
|
949
|
+
* @param upgrade - The upgrade token to check.
|
|
950
|
+
*
|
|
951
|
+
* @returns The {@link StagedUpgradeStatus} of the upgrade.
|
|
952
|
+
*
|
|
953
|
+
* @remarks
|
|
954
|
+
* Use this to determine whether a document has already been upgraded, for example when deciding
|
|
955
|
+
* whether to include an upgrade token in the view configuration after a feature flag rollback.
|
|
956
|
+
*
|
|
957
|
+
* Results are derived from this view's schema and the current stored schema.
|
|
958
|
+
* The full schema is checked even when the view is incompatible with the stored schema, so the
|
|
959
|
+
* result includes all locations declared by the view schema.
|
|
960
|
+
*/
|
|
961
|
+
isStagedUpgradeEnabled(upgrade: SchemaUpgrade): StagedUpgradeStatus;
|
|
962
|
+
|
|
786
963
|
readonly events: Listenable<TreeViewEvents & TreeBranchEvents>;
|
|
787
964
|
|
|
788
965
|
// Override the base fork method to return a TreeViewAlpha.
|
|
@@ -11,6 +11,14 @@ import type { SchemaUpgrade } from "./allowedTypes.js";
|
|
|
11
11
|
* @alpha
|
|
12
12
|
*/
|
|
13
13
|
export interface StagedSchemaUpgradePolicy {
|
|
14
|
+
/**
|
|
15
|
+
* Whether schema upgrades should include staged upgrades that are already enabled in the
|
|
16
|
+
* document's stored schema.
|
|
17
|
+
*
|
|
18
|
+
* @defaultValue `true`
|
|
19
|
+
*/
|
|
20
|
+
readonly includeAlreadyEnabledUpgrades?: boolean;
|
|
21
|
+
|
|
14
22
|
/**
|
|
15
23
|
* Determines whether to include staged allowed types in the resulting stored schema.
|
|
16
24
|
* @remarks
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { assert, fail } from "@fluidframework/core-utils/internal";
|
|
7
|
-
import { UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
7
|
+
import { tagSchemaArtifacts, UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
8
8
|
|
|
9
9
|
import { type FlexTreeNode, isFlexTreeNode } from "../../feature-libraries/index.js";
|
|
10
10
|
|
|
@@ -135,6 +135,7 @@ export abstract class TreeNodeValid<TInput> extends TreeNode {
|
|
|
135
135
|
}) which derived from the same SchemaFactory generated class (${JSON.stringify(
|
|
136
136
|
this.identifier,
|
|
137
137
|
)}). This is invalid.`,
|
|
138
|
+
tagSchemaArtifacts({ schemaIdentifier: this.identifier }),
|
|
138
139
|
);
|
|
139
140
|
}
|
|
140
141
|
|
|
@@ -237,6 +238,7 @@ export function schemaAsTreeNodeValid(
|
|
|
237
238
|
`Schema for ${JSON.stringify(
|
|
238
239
|
schema.identifier,
|
|
239
240
|
)} does not extend a SchemaFactory generated class. This is invalid.`,
|
|
241
|
+
tagSchemaArtifacts({ schemaIdentifier: schema.identifier }),
|
|
240
242
|
);
|
|
241
243
|
}
|
|
242
244
|
|
package/src/simple-tree/index.ts
CHANGED
|
@@ -77,6 +77,8 @@ export {
|
|
|
77
77
|
type ITreeViewConfiguration,
|
|
78
78
|
type ITreeViewConfigurationAlpha,
|
|
79
79
|
type SchemaCompatibilityStatus,
|
|
80
|
+
type SchemaCompatibilityStatusBeta,
|
|
81
|
+
type SchemaDiscrepancy,
|
|
80
82
|
type ITreeConfigurationOptions,
|
|
81
83
|
SchemaFactory,
|
|
82
84
|
scoped,
|
|
@@ -137,6 +139,7 @@ export {
|
|
|
137
139
|
type TreeSchemaEncodingOptions,
|
|
138
140
|
getJsonSchema,
|
|
139
141
|
getSimpleSchema,
|
|
142
|
+
type StagedUpgradeStatus,
|
|
140
143
|
type VerboseTreeNode,
|
|
141
144
|
type TreeEncodingOptions,
|
|
142
145
|
type VerboseTree,
|
|
@@ -144,6 +147,7 @@ export {
|
|
|
144
147
|
comparePersistedSchema,
|
|
145
148
|
type ConciseTree,
|
|
146
149
|
checkSchemaCompatibility,
|
|
150
|
+
getSchemaIncompatibilityDetails,
|
|
147
151
|
type Unenforced,
|
|
148
152
|
type System_Unsafe,
|
|
149
153
|
type ArrayNodeCustomizableSchemaUnsafe,
|