@fluidframework/tree 2.31.1 → 2.33.0-333010
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/.vscode/settings.json +1 -1
- package/CHANGELOG.md +44 -0
- package/api-extractor/api-extractor.current.json +5 -1
- package/api-report/tree.alpha.api.md +44 -20
- package/dist/alpha.d.ts +6 -2
- package/dist/feature-libraries/flex-tree/context.d.ts +6 -1
- package/dist/feature-libraries/flex-tree/context.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/context.js +5 -2
- package/dist/feature-libraries/flex-tree/context.js.map +1 -1
- package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts +8 -0
- package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/flexTreeTypes.js +8 -0
- package/dist/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
- package/dist/feature-libraries/flex-tree/index.d.ts +1 -1
- package/dist/feature-libraries/flex-tree/index.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/index.js +1 -2
- package/dist/feature-libraries/flex-tree/index.js.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyEntity.d.ts +6 -15
- package/dist/feature-libraries/flex-tree/lazyEntity.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyEntity.js +9 -18
- package/dist/feature-libraries/flex-tree/lazyEntity.js.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.d.ts +3 -3
- package/dist/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.js +14 -14
- package/dist/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyNode.d.ts +4 -4
- package/dist/feature-libraries/flex-tree/lazyNode.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyNode.js +12 -12
- package/dist/feature-libraries/flex-tree/lazyNode.js.map +1 -1
- package/dist/feature-libraries/index.d.ts +1 -1
- package/dist/feature-libraries/index.d.ts.map +1 -1
- package/dist/feature-libraries/index.js +1 -2
- package/dist/feature-libraries/index.js.map +1 -1
- package/dist/feature-libraries/node-identifier/nodeIdentifierManager.d.ts.map +1 -1
- package/dist/feature-libraries/node-identifier/nodeIdentifierManager.js +29 -25
- package/dist/feature-libraries/node-identifier/nodeIdentifierManager.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/shared-tree/checkoutFlexTreeView.d.ts +1 -0
- package/dist/shared-tree/checkoutFlexTreeView.d.ts.map +1 -1
- package/dist/shared-tree/checkoutFlexTreeView.js +4 -0
- package/dist/shared-tree/checkoutFlexTreeView.js.map +1 -1
- package/dist/shared-tree/sharedTree.js +2 -2
- package/dist/shared-tree/sharedTree.js.map +1 -1
- package/dist/shared-tree/treeApiAlpha.d.ts +6 -6
- package/dist/shared-tree/treeApiAlpha.d.ts.map +1 -1
- package/dist/shared-tree/treeApiAlpha.js.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.d.ts +0 -6
- package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/dist/shared-tree-core/sharedTreeCore.js +0 -17
- package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/dist/simple-tree/api/conciseTree.d.ts +2 -2
- package/dist/simple-tree/api/conciseTree.d.ts.map +1 -1
- package/dist/simple-tree/api/conciseTree.js.map +1 -1
- package/dist/simple-tree/api/customTree.d.ts +14 -12
- package/dist/simple-tree/api/customTree.d.ts.map +1 -1
- package/dist/simple-tree/api/customTree.js.map +1 -1
- package/dist/simple-tree/api/getJsonSchema.d.ts +21 -7
- package/dist/simple-tree/api/getJsonSchema.d.ts.map +1 -1
- package/dist/simple-tree/api/getJsonSchema.js +8 -16
- package/dist/simple-tree/api/getJsonSchema.js.map +1 -1
- package/dist/simple-tree/api/getSimpleSchema.d.ts +3 -10
- package/dist/simple-tree/api/getSimpleSchema.d.ts.map +1 -1
- package/dist/simple-tree/api/getSimpleSchema.js +4 -16
- package/dist/simple-tree/api/getSimpleSchema.js.map +1 -1
- package/dist/simple-tree/api/index.d.ts +4 -3
- package/dist/simple-tree/api/index.d.ts.map +1 -1
- package/dist/simple-tree/api/index.js +2 -1
- package/dist/simple-tree/api/index.js.map +1 -1
- package/dist/simple-tree/api/schemaFactoryAlpha.d.ts +17 -1
- package/dist/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaFactoryAlpha.js +4 -0
- package/dist/simple-tree/api/schemaFactoryAlpha.js.map +1 -1
- package/dist/simple-tree/api/schemaFromSimple.d.ts +5 -2
- package/dist/simple-tree/api/schemaFromSimple.d.ts.map +1 -1
- package/dist/simple-tree/api/schemaFromSimple.js +24 -8
- package/dist/simple-tree/api/schemaFromSimple.js.map +1 -1
- package/dist/simple-tree/api/simpleSchemaToJsonSchema.d.ts +11 -3
- package/dist/simple-tree/api/simpleSchemaToJsonSchema.d.ts.map +1 -1
- package/dist/simple-tree/api/simpleSchemaToJsonSchema.js +40 -28
- package/dist/simple-tree/api/simpleSchemaToJsonSchema.js.map +1 -1
- package/dist/simple-tree/api/tree.d.ts +32 -5
- package/dist/simple-tree/api/tree.d.ts.map +1 -1
- package/dist/simple-tree/api/tree.js +17 -1
- package/dist/simple-tree/api/tree.js.map +1 -1
- package/dist/simple-tree/api/verboseTree.d.ts +4 -28
- package/dist/simple-tree/api/verboseTree.d.ts.map +1 -1
- package/dist/simple-tree/api/verboseTree.js.map +1 -1
- package/dist/simple-tree/api/viewSchemaToSimpleSchema.d.ts.map +1 -1
- package/dist/simple-tree/api/viewSchemaToSimpleSchema.js +7 -3
- package/dist/simple-tree/api/viewSchemaToSimpleSchema.js.map +1 -1
- package/dist/simple-tree/core/treeNodeKernel.d.ts +9 -2
- package/dist/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
- package/dist/simple-tree/core/treeNodeKernel.js +46 -30
- package/dist/simple-tree/core/treeNodeKernel.js.map +1 -1
- package/dist/simple-tree/core/unhydratedFlexTree.d.ts +2 -1
- package/dist/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
- package/dist/simple-tree/core/unhydratedFlexTree.js +15 -1
- package/dist/simple-tree/core/unhydratedFlexTree.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 +3 -2
- package/dist/simple-tree/index.js.map +1 -1
- package/dist/simple-tree/objectNode.d.ts.map +1 -1
- package/dist/simple-tree/objectNode.js +3 -0
- package/dist/simple-tree/objectNode.js.map +1 -1
- package/dist/simple-tree/simpleSchema.d.ts +4 -11
- package/dist/simple-tree/simpleSchema.d.ts.map +1 -1
- package/dist/simple-tree/simpleSchema.js.map +1 -1
- package/dist/tableSchema.d.ts +241 -0
- package/dist/tableSchema.d.ts.map +1 -0
- package/dist/tableSchema.js +238 -0
- package/dist/tableSchema.js.map +1 -0
- package/dist/treeFactory.d.ts +4 -4
- package/dist/treeFactory.d.ts.map +1 -1
- package/dist/treeFactory.js.map +1 -1
- package/dist/util/breakable.d.ts.map +1 -1
- package/dist/util/breakable.js +9 -7
- package/dist/util/breakable.js.map +1 -1
- package/lib/alpha.d.ts +6 -2
- package/lib/feature-libraries/flex-tree/context.d.ts +6 -1
- package/lib/feature-libraries/flex-tree/context.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/context.js +6 -3
- package/lib/feature-libraries/flex-tree/context.js.map +1 -1
- package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts +8 -0
- package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/flexTreeTypes.js +8 -0
- package/lib/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
- package/lib/feature-libraries/flex-tree/index.d.ts +1 -1
- package/lib/feature-libraries/flex-tree/index.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/index.js +1 -1
- package/lib/feature-libraries/flex-tree/index.js.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyEntity.d.ts +6 -15
- package/lib/feature-libraries/flex-tree/lazyEntity.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyEntity.js +8 -17
- package/lib/feature-libraries/flex-tree/lazyEntity.js.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.d.ts +3 -3
- package/lib/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.js +15 -15
- package/lib/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyNode.d.ts +4 -4
- package/lib/feature-libraries/flex-tree/lazyNode.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyNode.js +13 -13
- package/lib/feature-libraries/flex-tree/lazyNode.js.map +1 -1
- package/lib/feature-libraries/index.d.ts +1 -1
- package/lib/feature-libraries/index.d.ts.map +1 -1
- package/lib/feature-libraries/index.js +1 -1
- package/lib/feature-libraries/index.js.map +1 -1
- package/lib/feature-libraries/node-identifier/nodeIdentifierManager.d.ts.map +1 -1
- package/lib/feature-libraries/node-identifier/nodeIdentifierManager.js +28 -24
- package/lib/feature-libraries/node-identifier/nodeIdentifierManager.js.map +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/shared-tree/checkoutFlexTreeView.d.ts +1 -0
- package/lib/shared-tree/checkoutFlexTreeView.d.ts.map +1 -1
- package/lib/shared-tree/checkoutFlexTreeView.js +4 -0
- package/lib/shared-tree/checkoutFlexTreeView.js.map +1 -1
- package/lib/shared-tree/sharedTree.js +2 -2
- package/lib/shared-tree/sharedTree.js.map +1 -1
- package/lib/shared-tree/treeApiAlpha.d.ts +6 -6
- package/lib/shared-tree/treeApiAlpha.d.ts.map +1 -1
- package/lib/shared-tree/treeApiAlpha.js.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.d.ts +0 -6
- package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
- package/lib/shared-tree-core/sharedTreeCore.js +0 -17
- package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
- package/lib/simple-tree/api/conciseTree.d.ts +2 -2
- package/lib/simple-tree/api/conciseTree.d.ts.map +1 -1
- package/lib/simple-tree/api/conciseTree.js.map +1 -1
- package/lib/simple-tree/api/customTree.d.ts +14 -12
- package/lib/simple-tree/api/customTree.d.ts.map +1 -1
- package/lib/simple-tree/api/customTree.js.map +1 -1
- package/lib/simple-tree/api/getJsonSchema.d.ts +21 -7
- package/lib/simple-tree/api/getJsonSchema.d.ts.map +1 -1
- package/lib/simple-tree/api/getJsonSchema.js +8 -16
- package/lib/simple-tree/api/getJsonSchema.js.map +1 -1
- package/lib/simple-tree/api/getSimpleSchema.d.ts +3 -10
- package/lib/simple-tree/api/getSimpleSchema.d.ts.map +1 -1
- package/lib/simple-tree/api/getSimpleSchema.js +4 -16
- package/lib/simple-tree/api/getSimpleSchema.js.map +1 -1
- package/lib/simple-tree/api/index.d.ts +4 -3
- 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/schemaFactoryAlpha.d.ts +17 -1
- package/lib/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaFactoryAlpha.js +4 -0
- package/lib/simple-tree/api/schemaFactoryAlpha.js.map +1 -1
- package/lib/simple-tree/api/schemaFromSimple.d.ts +5 -2
- package/lib/simple-tree/api/schemaFromSimple.d.ts.map +1 -1
- package/lib/simple-tree/api/schemaFromSimple.js +24 -8
- package/lib/simple-tree/api/schemaFromSimple.js.map +1 -1
- package/lib/simple-tree/api/simpleSchemaToJsonSchema.d.ts +11 -3
- package/lib/simple-tree/api/simpleSchemaToJsonSchema.d.ts.map +1 -1
- package/lib/simple-tree/api/simpleSchemaToJsonSchema.js +41 -29
- package/lib/simple-tree/api/simpleSchemaToJsonSchema.js.map +1 -1
- package/lib/simple-tree/api/tree.d.ts +32 -5
- package/lib/simple-tree/api/tree.d.ts.map +1 -1
- package/lib/simple-tree/api/tree.js +16 -1
- package/lib/simple-tree/api/tree.js.map +1 -1
- package/lib/simple-tree/api/verboseTree.d.ts +4 -28
- package/lib/simple-tree/api/verboseTree.d.ts.map +1 -1
- package/lib/simple-tree/api/verboseTree.js.map +1 -1
- package/lib/simple-tree/api/viewSchemaToSimpleSchema.d.ts.map +1 -1
- package/lib/simple-tree/api/viewSchemaToSimpleSchema.js +7 -3
- package/lib/simple-tree/api/viewSchemaToSimpleSchema.js.map +1 -1
- package/lib/simple-tree/core/treeNodeKernel.d.ts +9 -2
- package/lib/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
- package/lib/simple-tree/core/treeNodeKernel.js +48 -32
- package/lib/simple-tree/core/treeNodeKernel.js.map +1 -1
- package/lib/simple-tree/core/unhydratedFlexTree.d.ts +2 -1
- package/lib/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
- package/lib/simple-tree/core/unhydratedFlexTree.js +15 -1
- package/lib/simple-tree/core/unhydratedFlexTree.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/lib/simple-tree/objectNode.d.ts.map +1 -1
- package/lib/simple-tree/objectNode.js +4 -1
- package/lib/simple-tree/objectNode.js.map +1 -1
- package/lib/simple-tree/simpleSchema.d.ts +4 -11
- package/lib/simple-tree/simpleSchema.d.ts.map +1 -1
- package/lib/simple-tree/simpleSchema.js.map +1 -1
- package/lib/tableSchema.d.ts +241 -0
- package/lib/tableSchema.d.ts.map +1 -0
- package/lib/tableSchema.js +235 -0
- package/lib/tableSchema.js.map +1 -0
- package/lib/treeFactory.d.ts +4 -4
- package/lib/treeFactory.d.ts.map +1 -1
- package/lib/treeFactory.js.map +1 -1
- package/lib/util/breakable.d.ts.map +1 -1
- package/lib/util/breakable.js +9 -7
- package/lib/util/breakable.js.map +1 -1
- package/package.json +23 -22
- package/src/feature-libraries/flex-tree/context.ts +13 -3
- package/src/feature-libraries/flex-tree/flexTreeTypes.ts +8 -0
- package/src/feature-libraries/flex-tree/index.ts +0 -1
- package/src/feature-libraries/flex-tree/lazyEntity.ts +11 -21
- package/src/feature-libraries/flex-tree/lazyField.ts +17 -26
- package/src/feature-libraries/flex-tree/lazyNode.ts +13 -19
- package/src/feature-libraries/index.ts +0 -1
- package/src/feature-libraries/node-identifier/nodeIdentifierManager.ts +39 -38
- package/src/index.ts +6 -2
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/checkoutFlexTreeView.ts +6 -0
- package/src/shared-tree/sharedTree.ts +2 -2
- package/src/shared-tree/treeApiAlpha.ts +17 -15
- package/src/shared-tree-core/sharedTreeCore.ts +0 -23
- package/src/simple-tree/api/conciseTree.ts +4 -4
- package/src/simple-tree/api/customTree.ts +16 -14
- package/src/simple-tree/api/getJsonSchema.ts +25 -16
- package/src/simple-tree/api/getSimpleSchema.ts +4 -18
- package/src/simple-tree/api/index.ts +4 -2
- package/src/simple-tree/api/schemaFactoryAlpha.ts +18 -1
- package/src/simple-tree/api/schemaFromSimple.ts +45 -16
- package/src/simple-tree/api/simpleSchemaToJsonSchema.ts +53 -34
- package/src/simple-tree/api/tree.ts +51 -4
- package/src/simple-tree/api/verboseTree.ts +7 -32
- package/src/simple-tree/api/viewSchemaToSimpleSchema.ts +8 -3
- package/src/simple-tree/core/treeNodeKernel.ts +57 -35
- package/src/simple-tree/core/unhydratedFlexTree.ts +22 -5
- package/src/simple-tree/index.ts +4 -2
- package/src/simple-tree/objectNode.ts +4 -2
- package/src/simple-tree/simpleSchema.ts +4 -12
- package/src/tableSchema.ts +668 -0
- package/src/treeFactory.ts +4 -3
- package/src/util/breakable.ts +9 -6
|
@@ -10,14 +10,15 @@ import {
|
|
|
10
10
|
type AllowedTypes,
|
|
11
11
|
type FieldSchemaAlpha,
|
|
12
12
|
FieldKind,
|
|
13
|
+
type FieldProps,
|
|
13
14
|
} from "../schemaTypes.js";
|
|
14
|
-
import { SchemaFactory } from "./schemaFactory.js";
|
|
15
15
|
import type {
|
|
16
16
|
SimpleFieldSchema,
|
|
17
17
|
SimpleNodeSchema,
|
|
18
18
|
SimpleTreeSchema,
|
|
19
19
|
} from "../simpleSchema.js";
|
|
20
20
|
import { SchemaFactoryAlpha } from "./schemaFactoryAlpha.js";
|
|
21
|
+
import type { TreeSchema } from "./tree.js";
|
|
21
22
|
|
|
22
23
|
const factory = new SchemaFactoryAlpha(undefined);
|
|
23
24
|
|
|
@@ -30,31 +31,53 @@ const factory = new SchemaFactoryAlpha(undefined);
|
|
|
30
31
|
* will produce a poor TypeScript typing experience which is subject to change.
|
|
31
32
|
*
|
|
32
33
|
* Editing through a view produced using this schema can easily violate invariants other users of the document might expect and must be done with great care.
|
|
34
|
+
*
|
|
35
|
+
* This API bakes in some arbitrary policy choices for how to handle data that is not included in the SimpleTreeSchema API, for example the value of `allowUnknownOptionalFields`.
|
|
36
|
+
* If any particular choice is required for such cases, this API should not be used.
|
|
33
37
|
* @alpha
|
|
34
38
|
*/
|
|
35
|
-
export function generateSchemaFromSimpleSchema(simple: SimpleTreeSchema):
|
|
39
|
+
export function generateSchemaFromSimpleSchema(simple: SimpleTreeSchema): TreeSchema {
|
|
36
40
|
const context: Context = new Map(
|
|
37
|
-
[...simple.definitions].map(
|
|
38
|
-
id,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
[...simple.definitions].map(
|
|
42
|
+
([id, schema]): [string, () => TreeNodeSchema & SimpleNodeSchema] => [
|
|
43
|
+
id,
|
|
44
|
+
// This relies on the caching in evaluateLazySchema so that it only runs once.
|
|
45
|
+
() => generateNode(id, schema, context),
|
|
46
|
+
],
|
|
47
|
+
),
|
|
42
48
|
);
|
|
43
|
-
|
|
49
|
+
const root = generateFieldSchema(simple.root, context, undefined);
|
|
50
|
+
const definitions = new Map<string, TreeNodeSchema & SimpleNodeSchema>();
|
|
51
|
+
for (const [id, lazy] of context) {
|
|
52
|
+
definitions.set(id, lazy());
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
root,
|
|
56
|
+
definitions,
|
|
57
|
+
};
|
|
44
58
|
}
|
|
45
59
|
|
|
46
|
-
type Context = ReadonlyMap<string, () => TreeNodeSchema>;
|
|
60
|
+
type Context = ReadonlyMap<string, () => TreeNodeSchema & SimpleNodeSchema>;
|
|
47
61
|
|
|
48
|
-
function generateFieldSchema(
|
|
62
|
+
function generateFieldSchema(
|
|
63
|
+
simple: SimpleFieldSchema,
|
|
64
|
+
context: Context,
|
|
65
|
+
storedKey: string | undefined,
|
|
66
|
+
): FieldSchemaAlpha {
|
|
49
67
|
const allowed = generateAllowedTypes(simple.allowedTypesIdentifiers, context);
|
|
68
|
+
const props: Omit<FieldProps, "defaultProvider"> = {
|
|
69
|
+
metadata: simple.metadata,
|
|
70
|
+
key: storedKey,
|
|
71
|
+
};
|
|
72
|
+
|
|
50
73
|
// Using createFieldSchema could work, but would require setting up the default providers.
|
|
51
74
|
switch (simple.kind) {
|
|
52
75
|
case FieldKind.Identifier:
|
|
53
|
-
return SchemaFactoryAlpha.identifier(
|
|
76
|
+
return SchemaFactoryAlpha.identifier(props);
|
|
54
77
|
case FieldKind.Optional:
|
|
55
|
-
return SchemaFactoryAlpha.optional(allowed,
|
|
78
|
+
return SchemaFactoryAlpha.optional(allowed, props);
|
|
56
79
|
case FieldKind.Required:
|
|
57
|
-
return SchemaFactoryAlpha.required(allowed,
|
|
80
|
+
return SchemaFactoryAlpha.required(allowed, props);
|
|
58
81
|
default:
|
|
59
82
|
return unreachableCase(simple.kind);
|
|
60
83
|
}
|
|
@@ -64,13 +87,19 @@ function generateAllowedTypes(allowed: ReadonlySet<string>, context: Context): A
|
|
|
64
87
|
return [...allowed].map((id) => context.get(id) ?? fail(0xb5a /* Missing schema */));
|
|
65
88
|
}
|
|
66
89
|
|
|
67
|
-
function generateNode(
|
|
90
|
+
function generateNode(
|
|
91
|
+
id: string,
|
|
92
|
+
schema: SimpleNodeSchema,
|
|
93
|
+
context: Context,
|
|
94
|
+
): TreeNodeSchema & SimpleNodeSchema {
|
|
68
95
|
switch (schema.kind) {
|
|
69
96
|
case NodeKind.Object: {
|
|
70
97
|
const fields: Record<string, FieldSchema> = {};
|
|
71
98
|
for (const [key, field] of schema.fields) {
|
|
72
|
-
fields[key] = generateFieldSchema(field, context);
|
|
99
|
+
fields[key] = generateFieldSchema(field, context, field.storedKey);
|
|
73
100
|
}
|
|
101
|
+
// Here allowUnknownOptionalFields is implicitly defaulting. This is a subjective policy choice:
|
|
102
|
+
// users of this code are expected to handle what ever choice this code makes for cases like this.
|
|
74
103
|
return factory.object(id, fields, { metadata: schema.metadata });
|
|
75
104
|
}
|
|
76
105
|
case NodeKind.Array:
|
|
@@ -87,7 +116,7 @@ function generateNode(id: string, schema: SimpleNodeSchema, context: Context): T
|
|
|
87
116
|
);
|
|
88
117
|
case NodeKind.Leaf:
|
|
89
118
|
return (
|
|
90
|
-
|
|
119
|
+
SchemaFactoryAlpha.leaves.find((leaf) => leaf.identifier === id) ??
|
|
91
120
|
fail(0xb5b /* Missing schema */)
|
|
92
121
|
);
|
|
93
122
|
default:
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { unreachableCase } from "@fluidframework/core-utils/internal";
|
|
7
7
|
import { UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
8
8
|
import { ValueSchema } from "../../core/index.js";
|
|
9
|
-
import { copyProperty,
|
|
9
|
+
import { copyProperty, hasSingle, type Mutable } from "../../util/index.js";
|
|
10
10
|
import type {
|
|
11
11
|
JsonArrayNodeSchema,
|
|
12
12
|
JsonFieldSchema,
|
|
@@ -24,24 +24,39 @@ import type {
|
|
|
24
24
|
SimpleArrayNodeSchema,
|
|
25
25
|
SimpleLeafNodeSchema,
|
|
26
26
|
SimpleMapNodeSchema,
|
|
27
|
-
SimpleNodeSchema,
|
|
28
|
-
SimpleObjectNodeSchema,
|
|
29
|
-
SimpleTreeSchema,
|
|
30
27
|
} from "../simpleSchema.js";
|
|
31
|
-
import { NodeKind } from "../core/index.js";
|
|
28
|
+
import { NodeKind, type TreeNodeSchema } from "../core/index.js";
|
|
29
|
+
import type { TreeSchema } from "./tree.js";
|
|
30
|
+
import type { TreeSchemaEncodingOptions } from "./getJsonSchema.js";
|
|
31
|
+
import { ObjectNodeSchema } from "../objectNodeTypes.js";
|
|
32
|
+
import { ArrayNodeSchema } from "../arrayNodeTypes.js";
|
|
33
|
+
import { MapNodeSchema } from "../mapNodeTypes.js";
|
|
34
|
+
import { LeafNodeSchema } from "../leafNodeSchema.js";
|
|
32
35
|
|
|
33
36
|
/**
|
|
34
37
|
* Generates a JSON Schema representation from a simple tree schema.
|
|
38
|
+
* @remarks
|
|
39
|
+
* This expects the data to be in the {@link ConciseTree} format.
|
|
40
|
+
*
|
|
41
|
+
* This cannot handle the case where the root is undefined since undefined is not a concept in JSON.
|
|
42
|
+
* This also cannot handle {@link SchemaStatics.handle} since they also are not supported in JSON.
|
|
43
|
+
*
|
|
35
44
|
* @internal
|
|
36
45
|
*/
|
|
37
|
-
export function toJsonSchema(
|
|
38
|
-
|
|
46
|
+
export function toJsonSchema(
|
|
47
|
+
schema: TreeSchema,
|
|
48
|
+
options: Required<TreeSchemaEncodingOptions>,
|
|
49
|
+
): JsonTreeSchema {
|
|
50
|
+
const definitions = convertDefinitions(schema.definitions, options);
|
|
39
51
|
|
|
40
52
|
const allowedTypes: JsonSchemaRef[] = [];
|
|
41
|
-
for (const allowedType of schema.allowedTypesIdentifiers) {
|
|
53
|
+
for (const allowedType of schema.root.allowedTypesIdentifiers) {
|
|
42
54
|
allowedTypes.push(createSchemaRef(allowedType));
|
|
43
55
|
}
|
|
44
56
|
|
|
57
|
+
// TODO: deduplicate field handling logic from convertObjectNodeSchema: at least include metadata's description.
|
|
58
|
+
// TODO: maybe account for consider schema.kind, or just take in ImplicitAllowedTypes
|
|
59
|
+
// TODO: handle case where allowedTypes is empty.
|
|
45
60
|
return hasSingle(allowedTypes)
|
|
46
61
|
? {
|
|
47
62
|
...allowedTypes[0],
|
|
@@ -54,40 +69,35 @@ export function toJsonSchema(schema: SimpleTreeSchema): JsonTreeSchema {
|
|
|
54
69
|
}
|
|
55
70
|
|
|
56
71
|
function convertDefinitions(
|
|
57
|
-
definitions: ReadonlyMap<string,
|
|
72
|
+
definitions: ReadonlyMap<string, TreeNodeSchema>,
|
|
73
|
+
options: Required<TreeSchemaEncodingOptions>,
|
|
58
74
|
): Record<string, JsonNodeSchema> {
|
|
59
75
|
const result: Record<string, JsonNodeSchema> = {};
|
|
60
76
|
for (const [key, value] of definitions) {
|
|
61
|
-
result[key] = convertNodeSchema(value);
|
|
77
|
+
result[key] = convertNodeSchema(value, options);
|
|
62
78
|
}
|
|
63
79
|
return result;
|
|
64
80
|
}
|
|
65
81
|
|
|
66
|
-
/**
|
|
67
|
-
* Private symbol under which the results of {@link convertNodeSchema} are cached on an input {@link SimpleNodeSchema}.
|
|
68
|
-
*/
|
|
69
|
-
const nodeJsonSchemaCache = new WeakMap<SimpleNodeSchema, JsonNodeSchema>();
|
|
70
|
-
|
|
71
82
|
/**
|
|
72
83
|
* Converts an input {@link SimpleNodeSchema} to a {@link JsonNodeSchema}.
|
|
73
84
|
*
|
|
74
85
|
* @remarks Caches the result on the input schema for future calls.
|
|
75
86
|
*/
|
|
76
|
-
function convertNodeSchema(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
});
|
|
87
|
+
function convertNodeSchema(
|
|
88
|
+
schema: TreeNodeSchema,
|
|
89
|
+
options: Required<TreeSchemaEncodingOptions>,
|
|
90
|
+
): JsonNodeSchema {
|
|
91
|
+
if (schema instanceof ArrayNodeSchema) {
|
|
92
|
+
return convertArrayNodeSchema(schema);
|
|
93
|
+
} else if (schema instanceof MapNodeSchema) {
|
|
94
|
+
return convertMapNodeSchema(schema);
|
|
95
|
+
} else if (schema instanceof ObjectNodeSchema) {
|
|
96
|
+
return convertObjectNodeSchema(schema, options);
|
|
97
|
+
} else if (schema instanceof LeafNodeSchema) {
|
|
98
|
+
return convertLeafNodeSchema(schema);
|
|
99
|
+
}
|
|
100
|
+
throw new TypeError(`Unknown node schema kind: ${schema.kind}`);
|
|
91
101
|
}
|
|
92
102
|
|
|
93
103
|
function convertArrayNodeSchema(schema: SimpleArrayNodeSchema): JsonArrayNodeSchema {
|
|
@@ -138,10 +148,14 @@ function convertLeafNodeSchema(schema: SimpleLeafNodeSchema): JsonLeafNodeSchema
|
|
|
138
148
|
};
|
|
139
149
|
}
|
|
140
150
|
|
|
141
|
-
export function convertObjectNodeSchema(
|
|
151
|
+
export function convertObjectNodeSchema(
|
|
152
|
+
schema: ObjectNodeSchema,
|
|
153
|
+
options: Required<TreeSchemaEncodingOptions>,
|
|
154
|
+
): JsonObjectNodeSchema {
|
|
142
155
|
const properties: Record<string, JsonFieldSchema> = {};
|
|
143
156
|
const required: string[] = [];
|
|
144
|
-
for (const [
|
|
157
|
+
for (const [propertyKey, fieldSchema] of schema.fields) {
|
|
158
|
+
const key = options.useStoredKeys ? fieldSchema.storedKey : propertyKey;
|
|
145
159
|
const allowedTypes: JsonSchemaRef[] = [];
|
|
146
160
|
for (const allowedType of fieldSchema.allowedTypesIdentifiers) {
|
|
147
161
|
allowedTypes.push(createSchemaRef(allowedType));
|
|
@@ -156,8 +170,13 @@ export function convertObjectNodeSchema(schema: SimpleObjectNodeSchema): JsonObj
|
|
|
156
170
|
copyProperty(fieldSchema.metadata, "description", output);
|
|
157
171
|
properties[key] = output;
|
|
158
172
|
|
|
159
|
-
if (fieldSchema.kind
|
|
160
|
-
|
|
173
|
+
if (fieldSchema.kind !== FieldKind.Optional) {
|
|
174
|
+
if (
|
|
175
|
+
options.requireFieldsWithDefaults ||
|
|
176
|
+
fieldSchema.props?.defaultProvider === undefined
|
|
177
|
+
) {
|
|
178
|
+
required.push(key);
|
|
179
|
+
}
|
|
161
180
|
}
|
|
162
181
|
}
|
|
163
182
|
|
|
@@ -20,6 +20,7 @@ import type {
|
|
|
20
20
|
} from "../../shared-tree/index.js";
|
|
21
21
|
|
|
22
22
|
import {
|
|
23
|
+
type FieldSchemaAlpha,
|
|
23
24
|
type ImplicitFieldSchema,
|
|
24
25
|
type InsertableField,
|
|
25
26
|
type InsertableTreeFieldFromImplicitField,
|
|
@@ -29,6 +30,7 @@ import {
|
|
|
29
30
|
type UnsafeUnknownSchema,
|
|
30
31
|
FieldKind,
|
|
31
32
|
markSchemaMostDerived,
|
|
33
|
+
normalizeFieldSchema,
|
|
32
34
|
} from "../schemaTypes.js";
|
|
33
35
|
import { NodeKind, type TreeNodeSchema } from "../core/index.js";
|
|
34
36
|
import { toStoredSchema } from "../toStoredSchema.js";
|
|
@@ -38,7 +40,7 @@ import { getOrCreate } from "../../util/index.js";
|
|
|
38
40
|
import type { MakeNominal } from "../../util/index.js";
|
|
39
41
|
import { walkFieldSchema } from "../walkFieldSchema.js";
|
|
40
42
|
import type { VerboseTree } from "./verboseTree.js";
|
|
41
|
-
import type { SimpleTreeSchema } from "../simpleSchema.js";
|
|
43
|
+
import type { SimpleNodeSchema, SimpleTreeSchema } from "../simpleSchema.js";
|
|
42
44
|
import type {
|
|
43
45
|
RunTransactionParams,
|
|
44
46
|
TransactionCallbackStatus,
|
|
@@ -106,9 +108,7 @@ export interface ITree extends ViewableTree, IFluidLoadable {}
|
|
|
106
108
|
|
|
107
109
|
/**
|
|
108
110
|
* {@link ITree} extended with some alpha APIs.
|
|
109
|
-
* @
|
|
110
|
-
* TODO: Promote this to alpha.
|
|
111
|
-
* @internal
|
|
111
|
+
* @sealed @alpha
|
|
112
112
|
*/
|
|
113
113
|
export interface ITreeAlpha extends ITree {
|
|
114
114
|
/**
|
|
@@ -309,6 +309,53 @@ export class TreeViewConfiguration<
|
|
|
309
309
|
}
|
|
310
310
|
}
|
|
311
311
|
|
|
312
|
+
/**
|
|
313
|
+
* {@link TreeViewConfiguration} extended with some alpha APIs.
|
|
314
|
+
* @sealed @alpha
|
|
315
|
+
*/
|
|
316
|
+
export class TreeViewConfigurationAlpha<
|
|
317
|
+
const TSchema extends ImplicitFieldSchema = ImplicitFieldSchema,
|
|
318
|
+
>
|
|
319
|
+
extends TreeViewConfiguration<TSchema>
|
|
320
|
+
implements TreeSchema
|
|
321
|
+
{
|
|
322
|
+
/**
|
|
323
|
+
* {@inheritDoc TreeSchema.root}
|
|
324
|
+
*/
|
|
325
|
+
public readonly root: FieldSchemaAlpha;
|
|
326
|
+
/**
|
|
327
|
+
* {@inheritDoc TreeSchema.definitions}
|
|
328
|
+
*/
|
|
329
|
+
public readonly definitions: ReadonlyMap<string, SimpleNodeSchema & TreeNodeSchema>;
|
|
330
|
+
|
|
331
|
+
public constructor(props: ITreeViewConfiguration<TSchema>) {
|
|
332
|
+
super(props);
|
|
333
|
+
this.root = normalizeFieldSchema(props.schema);
|
|
334
|
+
const definitions = new Map<string, SimpleNodeSchema & TreeNodeSchema>();
|
|
335
|
+
walkFieldSchema(props.schema, {
|
|
336
|
+
node: (schema) =>
|
|
337
|
+
definitions.set(schema.identifier, schema as SimpleNodeSchema & TreeNodeSchema),
|
|
338
|
+
});
|
|
339
|
+
this.definitions = definitions;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* {@link TreeViewConfigurationAlpha}
|
|
345
|
+
* @sealed @alpha
|
|
346
|
+
*/
|
|
347
|
+
export interface TreeSchema extends SimpleTreeSchema {
|
|
348
|
+
/**
|
|
349
|
+
* {@inheritDoc SimpleTreeSchema.root}
|
|
350
|
+
*/
|
|
351
|
+
readonly root: FieldSchemaAlpha;
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* {@inheritDoc SimpleTreeSchema.definitions}
|
|
355
|
+
*/
|
|
356
|
+
readonly definitions: ReadonlyMap<string, SimpleNodeSchema & TreeNodeSchema>;
|
|
357
|
+
}
|
|
358
|
+
|
|
312
359
|
/**
|
|
313
360
|
* Pretty print a set of types for use in error messages.
|
|
314
361
|
*/
|
|
@@ -41,8 +41,9 @@ import {
|
|
|
41
41
|
customFromCursor,
|
|
42
42
|
replaceHandles,
|
|
43
43
|
type CustomTreeNode,
|
|
44
|
-
type EncodeOptions,
|
|
45
44
|
type HandleConverter,
|
|
45
|
+
type SchemalessParseOptions,
|
|
46
|
+
type TreeEncodingOptions,
|
|
46
47
|
} from "./customTree.js";
|
|
47
48
|
import { getUnhydratedContext } from "../createContext.js";
|
|
48
49
|
|
|
@@ -110,40 +111,14 @@ export interface VerboseTreeNode<THandle = IFluidHandle> {
|
|
|
110
111
|
};
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
/**
|
|
114
|
-
* Options for how to interpret a `VerboseTree` when schema information is available.
|
|
115
|
-
* @alpha
|
|
116
|
-
*/
|
|
117
|
-
export interface ParseOptions {
|
|
118
|
-
/**
|
|
119
|
-
* If true, interpret the input keys of object nodes as stored keys.
|
|
120
|
-
* If false, interpret them as property keys.
|
|
121
|
-
* @defaultValue false.
|
|
122
|
-
*/
|
|
123
|
-
readonly useStoredKeys?: boolean;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Options for how to interpret a `VerboseTree` without relying on schema.
|
|
128
|
-
*/
|
|
129
|
-
export interface SchemalessParseOptions {
|
|
130
|
-
/**
|
|
131
|
-
* Converts stored keys into whatever key the tree is using in its encoding.
|
|
132
|
-
*/
|
|
133
|
-
keyConverter?: {
|
|
134
|
-
parse(type: string, inputKey: string): FieldKey;
|
|
135
|
-
encode(type: string, key: FieldKey): string;
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
|
|
139
114
|
/**
|
|
140
115
|
* Use info from `schema` to convert `options` to {@link SchemalessParseOptions}.
|
|
141
116
|
*/
|
|
142
117
|
export function applySchemaToParserOptions(
|
|
143
118
|
schema: ImplicitFieldSchema,
|
|
144
|
-
options:
|
|
119
|
+
options: TreeEncodingOptions,
|
|
145
120
|
): SchemalessParseOptions {
|
|
146
|
-
const config: Required<
|
|
121
|
+
const config: Required<TreeEncodingOptions> = {
|
|
147
122
|
useStoredKeys: false,
|
|
148
123
|
...options,
|
|
149
124
|
};
|
|
@@ -305,9 +280,9 @@ function verboseTreeAdapter(options: SchemalessParseOptions): CursorAdapter<Verb
|
|
|
305
280
|
export function verboseFromCursor(
|
|
306
281
|
reader: ITreeCursor,
|
|
307
282
|
rootSchema: ImplicitAllowedTypes,
|
|
308
|
-
options:
|
|
283
|
+
options: TreeEncodingOptions,
|
|
309
284
|
): VerboseTree {
|
|
310
|
-
const config: Required<
|
|
285
|
+
const config: Required<TreeEncodingOptions> = {
|
|
311
286
|
useStoredKeys: false,
|
|
312
287
|
...options,
|
|
313
288
|
};
|
|
@@ -319,7 +294,7 @@ export function verboseFromCursor(
|
|
|
319
294
|
|
|
320
295
|
function verboseFromCursorInner(
|
|
321
296
|
reader: ITreeCursor,
|
|
322
|
-
options: Required<
|
|
297
|
+
options: Required<TreeEncodingOptions>,
|
|
323
298
|
schema: ReadonlyMap<string, TreeNodeSchema>,
|
|
324
299
|
): VerboseTree {
|
|
325
300
|
const fields = customFromCursor(reader, options, schema, verboseFromCursorInner);
|
|
@@ -7,6 +7,7 @@ import { assert, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
|
7
7
|
import { normalizeFieldSchema, type ImplicitFieldSchema } from "../schemaTypes.js";
|
|
8
8
|
import type {
|
|
9
9
|
SimpleArrayNodeSchema,
|
|
10
|
+
SimpleFieldSchema,
|
|
10
11
|
SimpleLeafNodeSchema,
|
|
11
12
|
SimpleMapNodeSchema,
|
|
12
13
|
SimpleNodeSchema,
|
|
@@ -59,10 +60,14 @@ export function toSimpleTreeSchema(
|
|
|
59
60
|
});
|
|
60
61
|
|
|
61
62
|
return {
|
|
62
|
-
|
|
63
|
-
|
|
63
|
+
root: copySchemaObjects
|
|
64
|
+
? ({
|
|
65
|
+
allowedTypesIdentifiers: normalizedSchema.allowedTypesIdentifiers,
|
|
66
|
+
kind: normalizedSchema.kind,
|
|
67
|
+
metadata: normalizedSchema.metadata,
|
|
68
|
+
} satisfies SimpleFieldSchema)
|
|
69
|
+
: normalizedSchema,
|
|
64
70
|
definitions,
|
|
65
|
-
metadata: normalizedSchema.metadata,
|
|
66
71
|
};
|
|
67
72
|
}
|
|
68
73
|
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { assert, Lazy, fail } from "@fluidframework/core-utils/internal";
|
|
6
|
+
import { assert, Lazy, fail, debugAssert } from "@fluidframework/core-utils/internal";
|
|
7
|
+
import { UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
7
8
|
import { createEmitter } from "@fluid-internal/client-utils";
|
|
8
9
|
import type { Listenable, Off } from "@fluidframework/core-interfaces";
|
|
9
10
|
import type { InternalTreeNode, TreeNode, Unhydrated } from "./types.js";
|
|
@@ -19,7 +20,6 @@ import {
|
|
|
19
20
|
assertFlexTreeEntityNotFreed,
|
|
20
21
|
ContextSlot,
|
|
21
22
|
flexTreeSlot,
|
|
22
|
-
isFreedSymbol,
|
|
23
23
|
LazyEntity,
|
|
24
24
|
TreeStatus,
|
|
25
25
|
treeStatusFromAnchorCache,
|
|
@@ -73,7 +73,7 @@ export function tryGetTreeNodeSchema(value: unknown): undefined | TreeNodeSchema
|
|
|
73
73
|
/** The {@link HydrationState} of a {@link TreeNodeKernel} before the kernel is hydrated */
|
|
74
74
|
interface UnhydratedState {
|
|
75
75
|
off: Off;
|
|
76
|
-
innerNode: UnhydratedFlexTreeNode;
|
|
76
|
+
readonly innerNode: UnhydratedFlexTreeNode;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
/** The {@link HydrationState} of a {@link TreeNodeKernel} after the kernel is hydrated */
|
|
@@ -81,9 +81,9 @@ interface HydratedState {
|
|
|
81
81
|
/** The flex node for this kernel (lazy - undefined if it has not yet been demanded) */
|
|
82
82
|
innerNode?: FlexTreeNode;
|
|
83
83
|
/** The {@link AnchorNode} that this node is associated with. */
|
|
84
|
-
anchorNode: AnchorNode;
|
|
84
|
+
readonly anchorNode: AnchorNode;
|
|
85
85
|
/** All {@link Off | event deregistration functions} that should be run when the kernel is disposed. */
|
|
86
|
-
offAnchorNode: Set<Off>;
|
|
86
|
+
readonly offAnchorNode: Set<Off>;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
/** State within a {@link TreeNodeKernel} that is related to the hydration process */
|
|
@@ -155,15 +155,20 @@ export class TreeNodeKernel {
|
|
|
155
155
|
changedFields,
|
|
156
156
|
});
|
|
157
157
|
|
|
158
|
-
let
|
|
159
|
-
while (
|
|
160
|
-
const treeNode = unhydratedFlexTreeNodeToTreeNodeInternal.get(
|
|
158
|
+
let unhydratedNode: UnhydratedFlexTreeNode | undefined = innerNode;
|
|
159
|
+
while (unhydratedNode !== undefined) {
|
|
160
|
+
const treeNode = unhydratedFlexTreeNodeToTreeNodeInternal.get(unhydratedNode);
|
|
161
161
|
if (treeNode !== undefined) {
|
|
162
162
|
const kernel = getKernel(treeNode);
|
|
163
163
|
kernel.#unhydratedEvents.value.emit("subtreeChangedAfterBatch");
|
|
164
164
|
}
|
|
165
|
-
|
|
166
|
-
|
|
165
|
+
const parentNode: FlexTreeNode | undefined =
|
|
166
|
+
unhydratedNode.parentField.parent.parent;
|
|
167
|
+
assert(
|
|
168
|
+
parentNode === undefined || parentNode instanceof UnhydratedFlexTreeNode,
|
|
169
|
+
0xb76 /* Unhydrated node's parent should be an unhydrated node */,
|
|
170
|
+
);
|
|
171
|
+
unhydratedNode = parentNode;
|
|
167
172
|
}
|
|
168
173
|
}),
|
|
169
174
|
};
|
|
@@ -243,7 +248,7 @@ export class TreeNodeKernel {
|
|
|
243
248
|
const flex = this.#hydrationState.anchorNode.slots.get(flexTreeSlot);
|
|
244
249
|
if (flex !== undefined) {
|
|
245
250
|
assert(flex instanceof LazyEntity, 0x9b4 /* Unexpected flex node implementation */);
|
|
246
|
-
if (flex
|
|
251
|
+
if (flex.isFreed()) {
|
|
247
252
|
return TreeStatus.Deleted;
|
|
248
253
|
}
|
|
249
254
|
}
|
|
@@ -283,35 +288,46 @@ export class TreeNodeKernel {
|
|
|
283
288
|
*
|
|
284
289
|
* For hydrated nodes it returns a FlexTreeNode backed by the forest.
|
|
285
290
|
* Note that for "marinated" nodes, this FlexTreeNode exists and returns it: it does not return the MapTreeNode which is the current InnerNode.
|
|
291
|
+
*
|
|
292
|
+
* If `allowDeleted` is false, this will throw a UsageError if the node is deleted.
|
|
286
293
|
*/
|
|
287
|
-
public getOrCreateInnerNode(
|
|
294
|
+
public getOrCreateInnerNode(allowDeleted = false): InnerNode {
|
|
288
295
|
if (!isHydrated(this.#hydrationState)) {
|
|
296
|
+
debugAssert(
|
|
297
|
+
() =>
|
|
298
|
+
this.#hydrationState.innerNode?.context.isDisposed() === false ||
|
|
299
|
+
"Unhydrated node should never be disposed",
|
|
300
|
+
);
|
|
289
301
|
return this.#hydrationState.innerNode; // Unhydrated case
|
|
290
302
|
}
|
|
291
303
|
|
|
292
|
-
if (this.#hydrationState.innerNode
|
|
293
|
-
|
|
304
|
+
if (this.#hydrationState.innerNode === undefined) {
|
|
305
|
+
// Marinated case -> cooked
|
|
306
|
+
const anchorNode = this.#hydrationState.anchorNode;
|
|
307
|
+
// The proxy is bound to an anchor node, but it may or may not have an actual flex node yet
|
|
308
|
+
const flexNode = anchorNode.slots.get(flexTreeSlot);
|
|
309
|
+
if (flexNode !== undefined) {
|
|
310
|
+
// If the flex node already exists, use it...
|
|
311
|
+
this.#hydrationState.innerNode = flexNode;
|
|
312
|
+
} else {
|
|
313
|
+
// ...otherwise, the flex node must be created
|
|
314
|
+
const context =
|
|
315
|
+
anchorNode.anchorSet.slots.get(ContextSlot) ?? fail(0xb41 /* missing context */);
|
|
316
|
+
const cursor = context.checkout.forest.allocateCursor("getFlexNode");
|
|
317
|
+
context.checkout.forest.moveCursorToPath(anchorNode, cursor);
|
|
318
|
+
this.#hydrationState.innerNode = makeTree(context, cursor);
|
|
319
|
+
cursor.free();
|
|
320
|
+
// Calling this is a performance improvement, however, do this only after demand to avoid momentarily having no anchors to anchorNode
|
|
321
|
+
anchorForgetters?.get(this.node)?.();
|
|
322
|
+
if (!allowDeleted) {
|
|
323
|
+
assertFlexTreeEntityNotFreed(this.#hydrationState.innerNode);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
294
326
|
}
|
|
295
327
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
const flexNode = anchorNode.slots.get(flexTreeSlot);
|
|
300
|
-
if (flexNode !== undefined) {
|
|
301
|
-
// If the flex node already exists, use it...
|
|
302
|
-
this.#hydrationState.innerNode = flexNode;
|
|
303
|
-
} else {
|
|
304
|
-
// ...otherwise, the flex node must be created
|
|
305
|
-
const context =
|
|
306
|
-
anchorNode.anchorSet.slots.get(ContextSlot) ?? fail(0xb41 /* missing context */);
|
|
307
|
-
const cursor = context.checkout.forest.allocateCursor("getFlexNode");
|
|
308
|
-
context.checkout.forest.moveCursorToPath(anchorNode, cursor);
|
|
309
|
-
this.#hydrationState.innerNode = makeTree(context, cursor);
|
|
310
|
-
cursor.free();
|
|
311
|
-
// Calling this is a performance improvement, however, do this only after demand to avoid momentarily having no anchors to anchorNode
|
|
312
|
-
anchorForgetters?.get(this.node)?.();
|
|
313
|
-
if (!allowFreed) {
|
|
314
|
-
assertFlexTreeEntityNotFreed(this.#hydrationState.innerNode);
|
|
328
|
+
if (!allowDeleted) {
|
|
329
|
+
if (this.#hydrationState.innerNode.context.isDisposed()) {
|
|
330
|
+
throw new UsageError("Cannot access a Deleted node.");
|
|
315
331
|
}
|
|
316
332
|
}
|
|
317
333
|
|
|
@@ -413,11 +429,15 @@ export const unhydratedFlexTreeNodeToTreeNode =
|
|
|
413
429
|
*/
|
|
414
430
|
export const proxySlot = anchorSlot<TreeNode>();
|
|
415
431
|
|
|
432
|
+
/**
|
|
433
|
+
* Dispose a TreeNode (if any) for an existing anchor without disposing the anchor.
|
|
434
|
+
*/
|
|
416
435
|
export function tryDisposeTreeNode(anchorNode: AnchorNode): void {
|
|
417
436
|
const treeNode = anchorNode.slots.get(proxySlot);
|
|
418
437
|
if (treeNode !== undefined) {
|
|
419
438
|
const kernel = getKernel(treeNode);
|
|
420
439
|
kernel.dispose();
|
|
440
|
+
anchorNode.slots.delete(proxySlot);
|
|
421
441
|
}
|
|
422
442
|
}
|
|
423
443
|
|
|
@@ -450,10 +470,12 @@ export function getSimpleContextFromInnerNode(innerNode: InnerNode): Context {
|
|
|
450
470
|
*
|
|
451
471
|
* For hydrated nodes it returns a FlexTreeNode backed by the forest.
|
|
452
472
|
* Note that for "marinated" nodes, this FlexTreeNode exists and returns it: it does not return the MapTreeNode which is the current InnerNode.
|
|
473
|
+
*
|
|
474
|
+
* If `allowDeleted` is false, this will throw a UsageError if the node is deleted.
|
|
453
475
|
*/
|
|
454
|
-
export function getOrCreateInnerNode(treeNode: TreeNode,
|
|
476
|
+
export function getOrCreateInnerNode(treeNode: TreeNode, allowDeleted = false): InnerNode {
|
|
455
477
|
const kernel = getKernel(treeNode);
|
|
456
|
-
return kernel.getOrCreateInnerNode(
|
|
478
|
+
return kernel.getOrCreateInnerNode(allowDeleted);
|
|
457
479
|
}
|
|
458
480
|
|
|
459
481
|
/**
|
|
@@ -73,7 +73,7 @@ interface LocationInField {
|
|
|
73
73
|
*
|
|
74
74
|
* Create a `UnhydratedFlexTreeNode` by calling {@link getOrCreate}.
|
|
75
75
|
*/
|
|
76
|
-
export class UnhydratedFlexTreeNode implements
|
|
76
|
+
export class UnhydratedFlexTreeNode implements FlexTreeNode {
|
|
77
77
|
public get schema(): TreeNodeSchemaIdentifier {
|
|
78
78
|
return this.mapTree.type;
|
|
79
79
|
}
|
|
@@ -150,11 +150,24 @@ export class UnhydratedFlexTreeNode implements UnhydratedFlexTreeNode {
|
|
|
150
150
|
public adoptBy(parent: UnhydratedFlexTreeField, index: number): void;
|
|
151
151
|
public adoptBy(parent: UnhydratedFlexTreeField | undefined, index?: number): void {
|
|
152
152
|
if (parent !== undefined) {
|
|
153
|
-
assert(
|
|
154
|
-
this.location === unparentedLocation,
|
|
155
|
-
0x98c /* Node may not be adopted if it already has a parent */,
|
|
156
|
-
);
|
|
157
153
|
assert(index !== undefined, 0xa08 /* Expected index */);
|
|
154
|
+
if (this.location !== unparentedLocation) {
|
|
155
|
+
throw new UsageError("A node may not be inserted if it's already in a tree");
|
|
156
|
+
}
|
|
157
|
+
let unhydratedNode: UnhydratedFlexTreeNode | undefined = parent.parent;
|
|
158
|
+
while (unhydratedNode !== undefined) {
|
|
159
|
+
if (unhydratedNode === this) {
|
|
160
|
+
throw new UsageError(
|
|
161
|
+
"A node may not be inserted into a location that is under itself",
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
const parentNode: FlexTreeNode | undefined = unhydratedNode.parentField.parent.parent;
|
|
165
|
+
assert(
|
|
166
|
+
parentNode === undefined || parentNode instanceof UnhydratedFlexTreeNode,
|
|
167
|
+
0xb77 /* Unhydrated node's parent should be an unhydrated node */,
|
|
168
|
+
);
|
|
169
|
+
unhydratedNode = parentNode;
|
|
170
|
+
}
|
|
158
171
|
this.location = { parent, index };
|
|
159
172
|
} else {
|
|
160
173
|
assert(
|
|
@@ -264,6 +277,10 @@ export class UnhydratedContext implements FlexTreeContext {
|
|
|
264
277
|
public readonly schema: TreeStoredSchema,
|
|
265
278
|
) {}
|
|
266
279
|
|
|
280
|
+
public isDisposed(): boolean {
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
|
|
267
284
|
public isHydrated(): this is FlexTreeHydratedContext {
|
|
268
285
|
return false;
|
|
269
286
|
}
|