@fluidframework/tree 2.0.2 → 2.1.0-276326
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 +16 -0
- package/README.md +6 -9
- package/api-report/tree.alpha.api.md +0 -15
- package/api-report/tree.beta.api.md +0 -12
- package/api-report/tree.public.api.md +0 -12
- package/dist/core/tree/anchorSet.js +2 -2
- package/dist/core/tree/anchorSet.js.map +1 -1
- package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts +1 -1
- package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.d.ts +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/dist/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.js +4 -0
- package/dist/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFormat.d.ts +4 -0
- package/dist/feature-libraries/modular-schema/modularChangeFormat.d.ts.map +1 -1
- package/dist/feature-libraries/modular-schema/modularChangeFormat.js +4 -0
- package/dist/feature-libraries/modular-schema/modularChangeFormat.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.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/shared-tree/index.d.ts +1 -1
- package/dist/shared-tree/index.d.ts.map +1 -1
- package/dist/shared-tree/index.js.map +1 -1
- package/dist/shared-tree/schematizingTreeView.d.ts +4 -6
- package/dist/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/dist/shared-tree/schematizingTreeView.js +16 -12
- package/dist/shared-tree/schematizingTreeView.js.map +1 -1
- package/dist/shared-tree/sharedTree.d.ts +1 -2
- package/dist/shared-tree/sharedTree.d.ts.map +1 -1
- package/dist/shared-tree/sharedTree.js +0 -10
- package/dist/shared-tree/sharedTree.js.map +1 -1
- package/dist/shared-tree/treeApi.js.map +1 -1
- package/dist/shared-tree/treeView.d.ts +13 -6
- package/dist/shared-tree/treeView.d.ts.map +1 -1
- package/dist/shared-tree/treeView.js +0 -2
- package/dist/shared-tree/treeView.js.map +1 -1
- package/dist/simple-tree/index.d.ts +4 -3
- package/dist/simple-tree/index.d.ts.map +1 -1
- package/dist/simple-tree/index.js +5 -3
- 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 +4 -0
- package/dist/simple-tree/objectNode.js.map +1 -1
- package/dist/simple-tree/proxies.d.ts.map +1 -1
- package/dist/simple-tree/proxies.js +13 -16
- package/dist/simple-tree/proxies.js.map +1 -1
- package/dist/simple-tree/schemaFactory.d.ts.map +1 -1
- package/dist/simple-tree/schemaFactory.js +2 -24
- package/dist/simple-tree/schemaFactory.js.map +1 -1
- package/dist/simple-tree/toFlexSchema.d.ts +0 -15
- package/dist/simple-tree/toFlexSchema.d.ts.map +1 -1
- package/dist/simple-tree/toFlexSchema.js +1 -35
- package/dist/simple-tree/toFlexSchema.js.map +1 -1
- package/dist/simple-tree/tree.d.ts +0 -29
- package/dist/simple-tree/tree.d.ts.map +1 -1
- package/dist/simple-tree/tree.js +1 -24
- package/dist/simple-tree/tree.js.map +1 -1
- package/dist/treeFactory.d.ts +1 -1
- package/dist/treeFactory.js +1 -1
- package/dist/treeFactory.js.map +1 -1
- package/dist/util/brandedMap.d.ts +9 -2
- package/dist/util/brandedMap.d.ts.map +1 -1
- package/dist/util/brandedMap.js +3 -4
- package/dist/util/brandedMap.js.map +1 -1
- package/lib/core/tree/anchorSet.js +2 -2
- package/lib/core/tree/anchorSet.js.map +1 -1
- package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts +1 -1
- package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.d.ts +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.d.ts.map +1 -1
- package/lib/feature-libraries/flex-tree/lazyField.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.js +4 -0
- package/lib/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFormat.d.ts +4 -0
- package/lib/feature-libraries/modular-schema/modularChangeFormat.d.ts.map +1 -1
- package/lib/feature-libraries/modular-schema/modularChangeFormat.js +4 -0
- package/lib/feature-libraries/modular-schema/modularChangeFormat.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.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/shared-tree/index.d.ts +1 -1
- package/lib/shared-tree/index.d.ts.map +1 -1
- package/lib/shared-tree/index.js +1 -1
- package/lib/shared-tree/index.js.map +1 -1
- package/lib/shared-tree/schematizingTreeView.d.ts +4 -6
- package/lib/shared-tree/schematizingTreeView.d.ts.map +1 -1
- package/lib/shared-tree/schematizingTreeView.js +19 -15
- package/lib/shared-tree/schematizingTreeView.js.map +1 -1
- package/lib/shared-tree/sharedTree.d.ts +1 -2
- package/lib/shared-tree/sharedTree.d.ts.map +1 -1
- package/lib/shared-tree/sharedTree.js +0 -10
- package/lib/shared-tree/sharedTree.js.map +1 -1
- package/lib/shared-tree/treeApi.js.map +1 -1
- package/lib/shared-tree/treeView.d.ts +13 -6
- package/lib/shared-tree/treeView.d.ts.map +1 -1
- package/lib/shared-tree/treeView.js +0 -2
- package/lib/shared-tree/treeView.js.map +1 -1
- package/lib/simple-tree/index.d.ts +4 -3
- package/lib/simple-tree/index.d.ts.map +1 -1
- package/lib/simple-tree/index.js +4 -3
- 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 -0
- package/lib/simple-tree/objectNode.js.map +1 -1
- package/lib/simple-tree/proxies.d.ts.map +1 -1
- package/lib/simple-tree/proxies.js +14 -17
- package/lib/simple-tree/proxies.js.map +1 -1
- package/lib/simple-tree/schemaFactory.d.ts.map +1 -1
- package/lib/simple-tree/schemaFactory.js +3 -25
- package/lib/simple-tree/schemaFactory.js.map +1 -1
- package/lib/simple-tree/toFlexSchema.d.ts +0 -15
- package/lib/simple-tree/toFlexSchema.d.ts.map +1 -1
- package/lib/simple-tree/toFlexSchema.js +0 -33
- package/lib/simple-tree/toFlexSchema.js.map +1 -1
- package/lib/simple-tree/tree.d.ts +0 -29
- package/lib/simple-tree/tree.d.ts.map +1 -1
- package/lib/simple-tree/tree.js +0 -22
- package/lib/simple-tree/tree.js.map +1 -1
- package/lib/treeFactory.d.ts +1 -1
- package/lib/treeFactory.js +1 -1
- package/lib/treeFactory.js.map +1 -1
- package/lib/util/brandedMap.d.ts +9 -2
- package/lib/util/brandedMap.d.ts.map +1 -1
- package/lib/util/brandedMap.js +3 -4
- package/lib/util/brandedMap.js.map +1 -1
- package/package.json +23 -23
- package/src/core/tree/anchorSet.ts +3 -3
- package/src/feature-libraries/flex-tree/flexTreeTypes.ts +5 -1
- package/src/feature-libraries/flex-tree/lazyField.ts +8 -5
- package/src/feature-libraries/modular-schema/modularChangeCodecs.ts +5 -0
- package/src/feature-libraries/modular-schema/modularChangeFormat.ts +4 -0
- package/src/index.ts +1 -0
- package/src/packageVersion.ts +1 -1
- package/src/shared-tree/index.ts +6 -1
- package/src/shared-tree/schematizingTreeView.ts +32 -26
- package/src/shared-tree/sharedTree.ts +0 -18
- package/src/shared-tree/treeApi.ts +2 -2
- package/src/shared-tree/treeView.ts +14 -8
- package/src/simple-tree/index.ts +7 -3
- package/src/simple-tree/objectNode.ts +6 -0
- package/src/simple-tree/proxies.ts +22 -20
- package/src/simple-tree/schemaFactory.ts +5 -41
- package/src/simple-tree/toFlexSchema.ts +0 -47
- package/src/simple-tree/tree.ts +0 -37
- package/src/treeFactory.ts +1 -1
- package/src/util/brandedMap.ts +18 -11
package/src/index.ts
CHANGED
package/src/packageVersion.ts
CHANGED
package/src/shared-tree/index.ts
CHANGED
|
@@ -33,7 +33,12 @@ export {
|
|
|
33
33
|
buildTreeConfiguration,
|
|
34
34
|
} from "./schematizeTree.js";
|
|
35
35
|
|
|
36
|
-
export {
|
|
36
|
+
export {
|
|
37
|
+
type FlexTreeView,
|
|
38
|
+
CheckoutFlexTreeView,
|
|
39
|
+
type ITreeViewFork,
|
|
40
|
+
type FlexTreeViewGeneric,
|
|
41
|
+
} from "./treeView.js";
|
|
37
42
|
|
|
38
43
|
export type { ISharedTreeEditor, ISchemaEditor } from "./sharedTreeEditBuilder.js";
|
|
39
44
|
|
|
@@ -19,33 +19,29 @@ import {
|
|
|
19
19
|
ViewSchema,
|
|
20
20
|
defaultSchemaPolicy,
|
|
21
21
|
ContextSlot,
|
|
22
|
+
cursorForMapTreeNode,
|
|
23
|
+
type FlexTreeSchema,
|
|
22
24
|
} from "../feature-libraries/index.js";
|
|
23
25
|
import {
|
|
24
26
|
type FieldSchema,
|
|
25
27
|
type ImplicitFieldSchema,
|
|
26
28
|
type SchemaCompatibilityStatus,
|
|
27
29
|
type InsertableTreeFieldFromImplicitField,
|
|
28
|
-
// eslint-disable-next-line import/no-deprecated
|
|
29
|
-
type TreeConfiguration,
|
|
30
30
|
type TreeFieldFromImplicitField,
|
|
31
31
|
type TreeView,
|
|
32
32
|
type TreeViewEvents,
|
|
33
33
|
getProxyForField,
|
|
34
|
-
|
|
34
|
+
toFlexSchema,
|
|
35
35
|
setField,
|
|
36
36
|
normalizeFieldSchema,
|
|
37
37
|
type InsertableContent,
|
|
38
|
-
cursorFromUnhydratedRoot,
|
|
39
38
|
type TreeViewConfiguration,
|
|
39
|
+
mapTreeFromNodeData,
|
|
40
|
+
prepareContentForHydration,
|
|
40
41
|
} from "../simple-tree/index.js";
|
|
41
42
|
import { disposeSymbol } from "../util/index.js";
|
|
42
43
|
|
|
43
|
-
import {
|
|
44
|
-
type TreeContent,
|
|
45
|
-
canInitialize,
|
|
46
|
-
ensureSchema,
|
|
47
|
-
initialize,
|
|
48
|
-
} from "./schematizeTree.js";
|
|
44
|
+
import { canInitialize, ensureSchema, initialize } from "./schematizeTree.js";
|
|
49
45
|
import type { TreeCheckout } from "./treeCheckout.js";
|
|
50
46
|
import { CheckoutFlexTreeView } from "./treeView.js";
|
|
51
47
|
|
|
@@ -66,7 +62,7 @@ export class SchematizingSimpleTreeView<in out TRootSchema extends ImplicitField
|
|
|
66
62
|
* Undefined iff uninitialized or disposed.
|
|
67
63
|
*/
|
|
68
64
|
private currentCompatibility: SchemaCompatibilityStatus | undefined;
|
|
69
|
-
private readonly
|
|
65
|
+
private readonly flexSchema: FlexTreeSchema;
|
|
70
66
|
public readonly events: Listenable<TreeViewEvents> &
|
|
71
67
|
IEmitter<TreeViewEvents> &
|
|
72
68
|
HasListeners<TreeViewEvents> = createEmitter();
|
|
@@ -88,8 +84,7 @@ export class SchematizingSimpleTreeView<in out TRootSchema extends ImplicitField
|
|
|
88
84
|
|
|
89
85
|
public constructor(
|
|
90
86
|
public readonly checkout: TreeCheckout,
|
|
91
|
-
public readonly config:
|
|
92
|
-
TreeConfiguration<TRootSchema> | TreeViewConfiguration<TRootSchema>,
|
|
87
|
+
public readonly config: TreeViewConfiguration<TRootSchema>,
|
|
93
88
|
public readonly nodeKeyManager: NodeKeyManager,
|
|
94
89
|
) {
|
|
95
90
|
const policy = {
|
|
@@ -97,11 +92,9 @@ export class SchematizingSimpleTreeView<in out TRootSchema extends ImplicitField
|
|
|
97
92
|
validateSchema: config.enableSchemaValidation,
|
|
98
93
|
};
|
|
99
94
|
this.rootFieldSchema = normalizeFieldSchema(config.schema);
|
|
100
|
-
this.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
});
|
|
104
|
-
this.viewSchema = new ViewSchema(policy, {}, this.flexConfig.schema);
|
|
95
|
+
this.flexSchema = toFlexSchema(config.schema);
|
|
96
|
+
|
|
97
|
+
this.viewSchema = new ViewSchema(policy, {}, this.flexSchema);
|
|
105
98
|
// This must be initialized before `update` can be called.
|
|
106
99
|
this.currentCompatibility = {
|
|
107
100
|
canView: false,
|
|
@@ -127,12 +120,23 @@ export class SchematizingSimpleTreeView<in out TRootSchema extends ImplicitField
|
|
|
127
120
|
}
|
|
128
121
|
|
|
129
122
|
this.runSchemaEdit(() => {
|
|
123
|
+
const mapTree = mapTreeFromNodeData(
|
|
124
|
+
content as InsertableContent,
|
|
125
|
+
this.rootFieldSchema.allowedTypes,
|
|
126
|
+
this.nodeKeyManager,
|
|
127
|
+
{
|
|
128
|
+
schema: this.checkout.storedSchema,
|
|
129
|
+
policy: {
|
|
130
|
+
...defaultSchemaPolicy,
|
|
131
|
+
validateSchema: this.config.enableSchemaValidation,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
prepareContentForHydration(mapTree, this.checkout.forest);
|
|
130
137
|
initialize(this.checkout, {
|
|
131
|
-
schema: this.
|
|
132
|
-
initialTree:
|
|
133
|
-
content === undefined
|
|
134
|
-
? undefined
|
|
135
|
-
: cursorFromUnhydratedRoot(this.config.schema, content, this.nodeKeyManager),
|
|
138
|
+
schema: this.flexSchema,
|
|
139
|
+
initialTree: mapTree === undefined ? undefined : cursorForMapTreeNode(mapTree),
|
|
136
140
|
});
|
|
137
141
|
});
|
|
138
142
|
}
|
|
@@ -155,10 +159,12 @@ export class SchematizingSimpleTreeView<in out TRootSchema extends ImplicitField
|
|
|
155
159
|
this.runSchemaEdit(() => {
|
|
156
160
|
const result = ensureSchema(
|
|
157
161
|
this.viewSchema,
|
|
158
|
-
|
|
159
|
-
AllowedUpdateType.SchemaCompatible | AllowedUpdateType.Initialize,
|
|
162
|
+
AllowedUpdateType.SchemaCompatible,
|
|
160
163
|
this.checkout,
|
|
161
|
-
|
|
164
|
+
{
|
|
165
|
+
schema: this.flexSchema,
|
|
166
|
+
initialTree: undefined,
|
|
167
|
+
},
|
|
162
168
|
);
|
|
163
169
|
assert(result, 0x8bf /* Schema upgrade should always work if canUpgrade is set. */);
|
|
164
170
|
});
|
|
@@ -53,8 +53,6 @@ import {
|
|
|
53
53
|
import type {
|
|
54
54
|
ITree,
|
|
55
55
|
ImplicitFieldSchema,
|
|
56
|
-
// eslint-disable-next-line import/no-deprecated
|
|
57
|
-
TreeConfiguration,
|
|
58
56
|
TreeView,
|
|
59
57
|
TreeViewConfiguration,
|
|
60
58
|
} from "../simple-tree/index.js";
|
|
@@ -322,22 +320,6 @@ export class SharedTree
|
|
|
322
320
|
);
|
|
323
321
|
}
|
|
324
322
|
|
|
325
|
-
public schematize<TRoot extends ImplicitFieldSchema>(
|
|
326
|
-
// eslint-disable-next-line import/no-deprecated
|
|
327
|
-
config: TreeConfiguration<TRoot>,
|
|
328
|
-
): TreeView<TRoot> {
|
|
329
|
-
const view = new SchematizingSimpleTreeView(
|
|
330
|
-
this.checkout,
|
|
331
|
-
config,
|
|
332
|
-
createNodeKeyManager(this.runtime.idCompressor),
|
|
333
|
-
);
|
|
334
|
-
// As a subjective API design choice, we initialize the tree here if it is not already initialized.
|
|
335
|
-
if (view.compatibility.canInitialize === true) {
|
|
336
|
-
view.initialize(config.initialTree());
|
|
337
|
-
}
|
|
338
|
-
return view;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
323
|
public viewWith<TRoot extends ImplicitFieldSchema>(
|
|
342
324
|
config: TreeViewConfiguration<TRoot>,
|
|
343
325
|
): TreeView<TRoot> {
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
import { fail } from "../util/index.js";
|
|
18
18
|
|
|
19
19
|
import { SchematizingSimpleTreeView } from "./schematizingTreeView.js";
|
|
20
|
-
import type {
|
|
20
|
+
import type { ITreeCheckout } from "./treeCheckout.js";
|
|
21
21
|
import { contextToTreeView } from "./treeView.js";
|
|
22
22
|
|
|
23
23
|
/**
|
|
@@ -445,7 +445,7 @@ export function runTransaction<
|
|
|
445
445
|
}
|
|
446
446
|
|
|
447
447
|
function runTransactionInCheckout<TResult>(
|
|
448
|
-
checkout:
|
|
448
|
+
checkout: ITreeCheckout,
|
|
449
449
|
transaction: () => TResult | typeof rollback,
|
|
450
450
|
preconditions: readonly TransactionConstraint[],
|
|
451
451
|
): TResult | typeof rollback {
|
|
@@ -17,14 +17,12 @@ import { type IDisposable, disposeSymbol } from "../util/index.js";
|
|
|
17
17
|
import type { ITreeCheckout, ITreeCheckoutFork, TreeCheckout } from "./treeCheckout.js";
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* The portion of {@link FlexTreeView} that does not depend on the schema's type.
|
|
21
21
|
* @privateRemarks
|
|
22
|
-
*
|
|
23
|
-
* 1. Once ISharedTreeView is renamed this can become ISharedTreeView.
|
|
24
|
-
* 2. This object should be combined with or accessible from the TreeContext to allow easy access to thinks like branching.
|
|
22
|
+
* Since {@link FlexTreeView}'s schema is invariant, `FlexTreeView<FlexFieldSchema>` does not cover this use case.
|
|
25
23
|
* @internal
|
|
26
24
|
*/
|
|
27
|
-
export interface
|
|
25
|
+
export interface FlexTreeViewGeneric extends IDisposable {
|
|
28
26
|
/**
|
|
29
27
|
* Context for controlling the FlexTree nodes produced from {@link FlexTreeView.flexTree}.
|
|
30
28
|
*
|
|
@@ -40,7 +38,17 @@ export interface FlexTreeView<in out TRoot extends FlexFieldSchema> extends IDis
|
|
|
40
38
|
* This is a non-owning reference: disposing of this view does not impact the branch.
|
|
41
39
|
*/
|
|
42
40
|
readonly checkout: ITreeCheckout;
|
|
41
|
+
}
|
|
43
42
|
|
|
43
|
+
/**
|
|
44
|
+
* An editable view of a (version control style) branch of a shared tree.
|
|
45
|
+
* @privateRemarks
|
|
46
|
+
* TODO:
|
|
47
|
+
* If schema aware APIs are removed from flex tree, this can be combined with {@link FlexTreeViewGeneric}.
|
|
48
|
+
* @internal
|
|
49
|
+
*/
|
|
50
|
+
export interface FlexTreeView<in out TRoot extends FlexFieldSchema>
|
|
51
|
+
extends FlexTreeViewGeneric {
|
|
44
52
|
/**
|
|
45
53
|
* Get a typed view of the tree content using the flex-tree API.
|
|
46
54
|
*/
|
|
@@ -100,6 +108,4 @@ export class CheckoutFlexTreeView<
|
|
|
100
108
|
* Maps the context of every {@link CheckoutFlexTreeView} to the view.
|
|
101
109
|
* In practice, this allows the view or checkout to be obtained from a flex node by first getting the context from the flex node and then using this map.
|
|
102
110
|
*/
|
|
103
|
-
|
|
104
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
105
|
-
export const contextToTreeView = new WeakMap<Context, CheckoutFlexTreeView<any>>();
|
|
111
|
+
export const contextToTreeView = new WeakMap<Context, FlexTreeViewGeneric>();
|
package/src/simple-tree/index.ts
CHANGED
|
@@ -7,7 +7,6 @@ export {
|
|
|
7
7
|
type ITree,
|
|
8
8
|
type TreeView,
|
|
9
9
|
type TreeViewEvents,
|
|
10
|
-
TreeConfiguration,
|
|
11
10
|
TreeViewConfiguration,
|
|
12
11
|
type ITreeViewConfiguration,
|
|
13
12
|
type SchemaCompatibilityStatus,
|
|
@@ -42,7 +41,7 @@ export {
|
|
|
42
41
|
export { SchemaFactory, type ScopedSchemaName } from "./schemaFactory.js";
|
|
43
42
|
export { getFlexNode } from "./proxyBinding.js";
|
|
44
43
|
export { treeNodeApi, type TreeNodeApi, type TreeChangeEvents } from "./treeNodeApi.js";
|
|
45
|
-
export {
|
|
44
|
+
export { toFlexSchema, cursorFromUnhydratedRoot } from "./toFlexSchema.js";
|
|
46
45
|
export type {
|
|
47
46
|
FieldHasDefaultUnsafe,
|
|
48
47
|
ObjectFromSchemaRecordUnsafe,
|
|
@@ -60,7 +59,11 @@ export type {
|
|
|
60
59
|
NodeFromSchemaUnsafe,
|
|
61
60
|
} from "./typesUnsafe.js";
|
|
62
61
|
export type { ValidateRecursiveSchema } from "./schemaFactoryRecursive.js";
|
|
63
|
-
export {
|
|
62
|
+
export {
|
|
63
|
+
getProxyForField,
|
|
64
|
+
type InsertableContent,
|
|
65
|
+
prepareContentForHydration,
|
|
66
|
+
} from "./proxies.js";
|
|
64
67
|
|
|
65
68
|
export {
|
|
66
69
|
adaptEnum,
|
|
@@ -93,3 +96,4 @@ export {
|
|
|
93
96
|
setField,
|
|
94
97
|
} from "./objectNode.js";
|
|
95
98
|
export type { TreeMapNode } from "./mapNode.js";
|
|
99
|
+
export { mapTreeFromNodeData } from "./toMapTree.js";
|
|
@@ -200,6 +200,12 @@ function createProxyHandler(
|
|
|
200
200
|
setField(flexNode.getBoxed(fieldInfo.storedKey), fieldInfo.schema, value);
|
|
201
201
|
return true;
|
|
202
202
|
},
|
|
203
|
+
deleteProperty(target, viewKey): boolean {
|
|
204
|
+
// TODO: supporting delete when it makes sense (custom local fields, and optional field) could be added as a feature in the future.
|
|
205
|
+
throw new UsageError(
|
|
206
|
+
`Object nodes do not support the delete operator. Optional fields can be assigned to undefined instead.`,
|
|
207
|
+
);
|
|
208
|
+
},
|
|
203
209
|
has: (target, viewKey) => {
|
|
204
210
|
return (
|
|
205
211
|
flexKeyMap.has(viewKey) ||
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
type MapTreeNode,
|
|
26
26
|
tryGetMapTreeNode,
|
|
27
27
|
typeNameSymbol,
|
|
28
|
+
isFlexTreeNode,
|
|
28
29
|
} from "../feature-libraries/index.js";
|
|
29
30
|
import { type Mutable, fail, isReadonlyArray } from "../util/index.js";
|
|
30
31
|
|
|
@@ -55,27 +56,28 @@ export function isTreeNode(candidate: unknown): candidate is TreeNode | Unhydrat
|
|
|
55
56
|
* Retrieve the associated proxy for the given field.
|
|
56
57
|
* */
|
|
57
58
|
export function getProxyForField(field: FlexTreeField): TreeNode | TreeValue | undefined {
|
|
59
|
+
function tryToUnboxLeaves(
|
|
60
|
+
flexField: FlexTreeTypedField<
|
|
61
|
+
FlexFieldSchema<typeof FieldKinds.required | typeof FieldKinds.optional>
|
|
62
|
+
>,
|
|
63
|
+
): TreeNode | TreeValue | undefined {
|
|
64
|
+
const maybeUnboxedContent = flexField.content;
|
|
65
|
+
return isFlexTreeNode(maybeUnboxedContent)
|
|
66
|
+
? getOrCreateNodeProxy(maybeUnboxedContent)
|
|
67
|
+
: maybeUnboxedContent;
|
|
68
|
+
}
|
|
58
69
|
switch (field.schema.kind) {
|
|
59
70
|
case FieldKinds.required: {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
// inner field.
|
|
65
|
-
return getOrCreateNodeProxy(asValue.boxedContent);
|
|
71
|
+
const typedField = field as FlexTreeTypedField<
|
|
72
|
+
FlexFieldSchema<typeof FieldKinds.required>
|
|
73
|
+
>;
|
|
74
|
+
return tryToUnboxLeaves(typedField);
|
|
66
75
|
}
|
|
67
76
|
case FieldKinds.optional: {
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
// inner field.
|
|
73
|
-
|
|
74
|
-
const maybeContent = asValue.boxedContent;
|
|
75
|
-
|
|
76
|
-
// Normally, empty fields are unreachable due to the behavior of 'tryGetField'. However, the
|
|
77
|
-
// root field is a special case where the field is always present (even if empty).
|
|
78
|
-
return maybeContent === undefined ? undefined : getOrCreateNodeProxy(maybeContent);
|
|
77
|
+
const typedField = field as FlexTreeTypedField<
|
|
78
|
+
FlexFieldSchema<typeof FieldKinds.optional>
|
|
79
|
+
>;
|
|
80
|
+
return tryToUnboxLeaves(typedField);
|
|
79
81
|
}
|
|
80
82
|
// TODO: Remove if/when 'FieldNode' is removed.
|
|
81
83
|
case FieldKinds.sequence: {
|
|
@@ -84,9 +86,9 @@ export function getProxyForField(field: FlexTreeField): TreeNode | TreeValue | u
|
|
|
84
86
|
fail("'sequence' field is unexpected.");
|
|
85
87
|
}
|
|
86
88
|
case FieldKinds.identifier: {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
// Identifier fields are just value fields that hold strings
|
|
90
|
+
return (field as FlexTreeTypedField<FlexFieldSchema<typeof FieldKinds.required>>)
|
|
91
|
+
.content as string;
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
default:
|
|
@@ -10,13 +10,7 @@ import { assert, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
|
10
10
|
import type { IFluidHandle as _dummyImport } from "@fluidframework/core-interfaces";
|
|
11
11
|
|
|
12
12
|
import type { TreeValue } from "../core/index.js";
|
|
13
|
-
import {
|
|
14
|
-
type FlexTreeNode,
|
|
15
|
-
type NodeKeyManager,
|
|
16
|
-
type Unenforced,
|
|
17
|
-
isFlexTreeNode,
|
|
18
|
-
isLazy,
|
|
19
|
-
} from "../feature-libraries/index.js";
|
|
13
|
+
import { type NodeKeyManager, type Unenforced, isLazy } from "../feature-libraries/index.js";
|
|
20
14
|
import {
|
|
21
15
|
type RestrictiveReadonlyRecord,
|
|
22
16
|
getOrCreate,
|
|
@@ -641,26 +635,12 @@ export class SchemaFactory<
|
|
|
641
635
|
const Name extends TName,
|
|
642
636
|
const T extends Unenforced<ImplicitAllowedTypes>,
|
|
643
637
|
>(name: Name, allowedTypes: T) {
|
|
644
|
-
|
|
638
|
+
const RecursiveArray = this.namedArray(
|
|
645
639
|
name,
|
|
646
640
|
allowedTypes as T & ImplicitAllowedTypes,
|
|
647
641
|
true,
|
|
648
642
|
false,
|
|
649
|
-
)
|
|
650
|
-
public constructor(
|
|
651
|
-
data:
|
|
652
|
-
| Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T & ImplicitAllowedTypes>>
|
|
653
|
-
| FlexTreeNode,
|
|
654
|
-
) {
|
|
655
|
-
if (isFlexTreeNode(data)) {
|
|
656
|
-
// TODO: use something other than `any`
|
|
657
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
658
|
-
super(data as any);
|
|
659
|
-
} else {
|
|
660
|
-
super(data);
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
}
|
|
643
|
+
);
|
|
664
644
|
|
|
665
645
|
return RecursiveArray as TreeNodeSchemaClass<
|
|
666
646
|
ScopedSchemaName<TScope, Name>,
|
|
@@ -697,28 +677,12 @@ export class SchemaFactory<
|
|
|
697
677
|
name: Name,
|
|
698
678
|
allowedTypes: T,
|
|
699
679
|
) {
|
|
700
|
-
|
|
680
|
+
const MapSchema = this.namedMap(
|
|
701
681
|
name,
|
|
702
682
|
allowedTypes as T & ImplicitAllowedTypes,
|
|
703
683
|
true,
|
|
704
684
|
false,
|
|
705
|
-
)
|
|
706
|
-
public constructor(
|
|
707
|
-
data:
|
|
708
|
-
| Iterable<
|
|
709
|
-
[string, InsertableTreeNodeFromImplicitAllowedTypes<T & ImplicitAllowedTypes>]
|
|
710
|
-
>
|
|
711
|
-
| FlexTreeNode,
|
|
712
|
-
) {
|
|
713
|
-
if (isFlexTreeNode(data)) {
|
|
714
|
-
// TODO: use something other than `any`
|
|
715
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
716
|
-
super(data as any);
|
|
717
|
-
} else {
|
|
718
|
-
super(new Map(data));
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
}
|
|
685
|
+
);
|
|
722
686
|
|
|
723
687
|
return MapSchema as TreeNodeSchemaClass<
|
|
724
688
|
ScopedSchemaName<TScope, Name>,
|
|
@@ -27,7 +27,6 @@ import {
|
|
|
27
27
|
schemaIsLeaf,
|
|
28
28
|
} from "../feature-libraries/index.js";
|
|
29
29
|
import { normalizeFlexListEager } from "../feature-libraries/typed-schema/flexList.js";
|
|
30
|
-
import type { TreeContent } from "../shared-tree/index.js";
|
|
31
30
|
import { brand, fail, isReadonlyArray, mapIterable } from "../util/index.js";
|
|
32
31
|
|
|
33
32
|
import type { InsertableContent } from "./proxies.js";
|
|
@@ -48,8 +47,6 @@ import {
|
|
|
48
47
|
getStoredKey,
|
|
49
48
|
} from "./schemaTypes.js";
|
|
50
49
|
import { cursorFromNodeData } from "./toMapTree.js";
|
|
51
|
-
// eslint-disable-next-line import/no-deprecated
|
|
52
|
-
import { TreeConfiguration, type TreeViewConfiguration } from "./tree.js";
|
|
53
50
|
|
|
54
51
|
/**
|
|
55
52
|
* Returns a cursor (in nodes mode) for the root node.
|
|
@@ -77,50 +74,6 @@ export function cursorFromUnhydratedRoot(
|
|
|
77
74
|
);
|
|
78
75
|
}
|
|
79
76
|
|
|
80
|
-
/* eslint-disable import/no-deprecated */
|
|
81
|
-
function isTreeConfiguration(
|
|
82
|
-
config: TreeViewConfiguration | TreeConfiguration,
|
|
83
|
-
): config is TreeConfiguration {
|
|
84
|
-
return config instanceof TreeConfiguration;
|
|
85
|
-
}
|
|
86
|
-
/* eslint-enable import/no-deprecated */
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Generates a configuration object (schema + initial tree) for a FlexTree.
|
|
90
|
-
* @param config - Configuration for how to {@link ITree.schematize|schematize} a tree.
|
|
91
|
-
* @param nodeKeyManager - See {@link NodeKeyManager}.
|
|
92
|
-
* @param schemaValidationPolicy - Stored schema and policy for the tree. If the policy specifies
|
|
93
|
-
* `{@link SchemaPolicy.validateSchema} === true`, new content inserted into the tree will be validated using this
|
|
94
|
-
* object.
|
|
95
|
-
* @returns A configuration object for a FlexTree.
|
|
96
|
-
*
|
|
97
|
-
* @privateremarks
|
|
98
|
-
* I wrote these docs without a ton of context, they can probably be improved.
|
|
99
|
-
*/
|
|
100
|
-
export function toFlexConfig(
|
|
101
|
-
// eslint-disable-next-line import/no-deprecated
|
|
102
|
-
config: TreeViewConfiguration | TreeConfiguration,
|
|
103
|
-
nodeKeyManager: NodeKeyManager,
|
|
104
|
-
schemaValidationPolicy: SchemaAndPolicy | undefined = undefined,
|
|
105
|
-
): TreeContent {
|
|
106
|
-
const unhydrated = isTreeConfiguration(config) ? config.initialTree() : undefined;
|
|
107
|
-
const initialTree =
|
|
108
|
-
unhydrated === undefined
|
|
109
|
-
? undefined
|
|
110
|
-
: [
|
|
111
|
-
cursorFromUnhydratedRoot(
|
|
112
|
-
config.schema,
|
|
113
|
-
unhydrated,
|
|
114
|
-
nodeKeyManager,
|
|
115
|
-
schemaValidationPolicy,
|
|
116
|
-
),
|
|
117
|
-
];
|
|
118
|
-
return {
|
|
119
|
-
schema: toFlexSchema(config.schema),
|
|
120
|
-
initialTree,
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
|
|
124
77
|
interface SchemaInfo {
|
|
125
78
|
toFlex: () => FlexTreeNodeSchema;
|
|
126
79
|
original: TreeNodeSchema;
|
package/src/simple-tree/tree.ts
CHANGED
|
@@ -133,43 +133,6 @@ export class TreeViewConfiguration<TSchema extends ImplicitFieldSchema = Implici
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
/**
|
|
137
|
-
* Configuration for how to {@link ITree.schematize | schematize} a tree.
|
|
138
|
-
* @sealed @public
|
|
139
|
-
* @deprecated Please migrate to use {@link TreeViewConfiguration} with {@link ITree.viewWith} instead.
|
|
140
|
-
*/
|
|
141
|
-
export class TreeConfiguration<TSchema extends ImplicitFieldSchema = ImplicitFieldSchema> {
|
|
142
|
-
/**
|
|
143
|
-
* If `true`, the tree will validate new content against its stored schema at insertion time
|
|
144
|
-
* and throw an error if the new content doesn't match the expected schema.
|
|
145
|
-
*
|
|
146
|
-
* @defaultValue `false`.
|
|
147
|
-
*
|
|
148
|
-
* @remarks Enabling schema validation has a performance penalty when inserting new content into the tree because
|
|
149
|
-
* additional checks are done. Enable this option only in scenarios where you are ok with that operation being a
|
|
150
|
-
* bit slower.
|
|
151
|
-
*/
|
|
152
|
-
public readonly enableSchemaValidation: boolean;
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* @param schema - The schema which the application wants to view the tree with.
|
|
156
|
-
* @param initialTree - A function that returns the default tree content to initialize the tree with iff the tree is uninitialized
|
|
157
|
-
* (meaning it does not even have any schema set at all).
|
|
158
|
-
* If `initialTree` returns any actual node instances, they should be recreated each time `initialTree` runs.
|
|
159
|
-
* This is because if the config is used a second time any nodes that were not recreated could error since nodes cannot be inserted into the tree multiple times.
|
|
160
|
-
* @param options - Additional options that can be specified when {@link ITree.schematize | schematizing } a tree.
|
|
161
|
-
*/
|
|
162
|
-
public constructor(
|
|
163
|
-
public readonly schema: TSchema,
|
|
164
|
-
public readonly initialTree: () => InsertableTreeFieldFromImplicitField<TSchema>,
|
|
165
|
-
options?: ITreeConfigurationOptions,
|
|
166
|
-
) {
|
|
167
|
-
this.enableSchemaValidation =
|
|
168
|
-
options?.enableSchemaValidation ??
|
|
169
|
-
defaultTreeConfigurationOptions.enableSchemaValidation;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
136
|
/**
|
|
174
137
|
* An editable view of a (version control style) branch of a shared tree based on some schema.
|
|
175
138
|
*
|
package/src/treeFactory.ts
CHANGED
|
@@ -56,7 +56,7 @@ export class TreeFactory implements IChannelFactory<ITree> {
|
|
|
56
56
|
/**
|
|
57
57
|
* SharedTree is a hierarchical data structure for collaboratively editing strongly typed JSON-like trees
|
|
58
58
|
* of objects, arrays, and other data types.
|
|
59
|
-
* @
|
|
59
|
+
* @internal
|
|
60
60
|
*/
|
|
61
61
|
export const SharedTree = configuredSharedTree({});
|
|
62
62
|
|
package/src/util/brandedMap.ts
CHANGED
|
@@ -3,11 +3,16 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import type { Brand } from "./brand.js";
|
|
7
|
+
import type { Opaque } from "./opaque.js";
|
|
6
8
|
import type { Invariant } from "./typeCheck.js";
|
|
7
9
|
import { getOrCreate } from "./utils.js";
|
|
8
10
|
|
|
9
11
|
/**
|
|
10
12
|
* Key in a {@link BrandedMapSubset}.
|
|
13
|
+
* @remarks
|
|
14
|
+
* Due to the `TContent` type parameter being invariant (which it has to be since keys are used to both read and write data),
|
|
15
|
+
* generic collections end up needing to constrain their key's `TContent` to `any`.
|
|
11
16
|
* @internal
|
|
12
17
|
*/
|
|
13
18
|
export type BrandedKey<TKey, TContent> = TKey & Invariant<TContent>;
|
|
@@ -49,16 +54,15 @@ export interface BrandedMapSubset<K extends BrandedKey<unknown, any>> {
|
|
|
49
54
|
|
|
50
55
|
/**
|
|
51
56
|
* Version of {@link getOrCreate} with better typing for {@link BrandedMapSubset}.
|
|
57
|
+
* @privateRemarks
|
|
58
|
+
* Only infers type from key to avoid inferring `any` from map's key.
|
|
52
59
|
*/
|
|
53
|
-
export function getOrCreateSlotContent<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
>(map
|
|
59
|
-
const result: BrandedKeyContent<K> = getOrCreate(map, key, defaultValue);
|
|
60
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
61
|
-
return result;
|
|
60
|
+
export function getOrCreateSlotContent<K, V>(
|
|
61
|
+
map: NoInfer<BrandedMapSubset<BrandedKey<K, V>>>,
|
|
62
|
+
key: BrandedKey<K, V>,
|
|
63
|
+
defaultValue: NoInfer<(key: BrandedKey<K, V>) => V>,
|
|
64
|
+
): V {
|
|
65
|
+
return getOrCreate<BrandedKey<K, V>, V>(map, key, defaultValue);
|
|
62
66
|
}
|
|
63
67
|
|
|
64
68
|
/**
|
|
@@ -72,7 +76,10 @@ let slotCounter = 0;
|
|
|
72
76
|
* Define a strongly typed slot in which data can be stored in a {@link BrandedMapSubset}.
|
|
73
77
|
* @internal
|
|
74
78
|
*/
|
|
75
|
-
|
|
76
|
-
|
|
79
|
+
export function brandedSlot<
|
|
80
|
+
// See note on BrandedKey.
|
|
81
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
82
|
+
TSlot extends BrandedKey<number | Opaque<Brand<number, string>>, any>,
|
|
83
|
+
>(): TSlot {
|
|
77
84
|
return slotCounter++ as TSlot;
|
|
78
85
|
}
|