@fluidframework/tree 2.4.0-299374 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/.vscode/settings.json +1 -9
  2. package/CHANGELOG.md +192 -0
  3. package/api-report/tree.alpha.api.md +23 -79
  4. package/api-report/tree.beta.api.md +23 -47
  5. package/api-report/tree.legacy.alpha.api.md +21 -46
  6. package/api-report/tree.legacy.public.api.md +21 -46
  7. package/api-report/tree.public.api.md +21 -46
  8. package/dist/alpha.d.ts +0 -9
  9. package/dist/beta.d.ts +0 -2
  10. package/dist/feature-libraries/flex-tree/lazyField.js +1 -1
  11. package/dist/feature-libraries/flex-tree/lazyField.js.map +1 -1
  12. package/dist/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
  13. package/dist/feature-libraries/modular-schema/modularChangeFamily.js +3 -3
  14. package/dist/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
  15. package/dist/index.d.ts +1 -1
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/internalTypes.d.ts +1 -1
  19. package/dist/internalTypes.d.ts.map +1 -1
  20. package/dist/internalTypes.js.map +1 -1
  21. package/dist/legacy.d.ts +0 -2
  22. package/dist/packageVersion.d.ts +1 -1
  23. package/dist/packageVersion.d.ts.map +1 -1
  24. package/dist/packageVersion.js +1 -1
  25. package/dist/packageVersion.js.map +1 -1
  26. package/dist/public.d.ts +0 -2
  27. package/dist/shared-tree/schematizingTreeView.js +1 -1
  28. package/dist/shared-tree/schematizingTreeView.js.map +1 -1
  29. package/dist/shared-tree/sharedTree.js +1 -1
  30. package/dist/shared-tree/sharedTree.js.map +1 -1
  31. package/dist/shared-tree/treeApi.d.ts +6 -6
  32. package/dist/shared-tree/treeApi.d.ts.map +1 -1
  33. package/dist/shared-tree/treeApi.js.map +1 -1
  34. package/dist/shared-tree-core/branch.js +1 -1
  35. package/dist/shared-tree-core/branch.js.map +1 -1
  36. package/dist/simple-tree/api/customTree.js +5 -5
  37. package/dist/simple-tree/api/customTree.js.map +1 -1
  38. package/dist/simple-tree/api/index.d.ts +2 -2
  39. package/dist/simple-tree/api/index.d.ts.map +1 -1
  40. package/dist/simple-tree/api/index.js.map +1 -1
  41. package/dist/simple-tree/api/tree.d.ts +3 -12
  42. package/dist/simple-tree/api/tree.d.ts.map +1 -1
  43. package/dist/simple-tree/api/tree.js.map +1 -1
  44. package/dist/simple-tree/api/treeApiBeta.d.ts +14 -2
  45. package/dist/simple-tree/api/treeApiBeta.d.ts.map +1 -1
  46. package/dist/simple-tree/api/treeApiBeta.js +23 -8
  47. package/dist/simple-tree/api/treeApiBeta.js.map +1 -1
  48. package/dist/simple-tree/api/typesUnsafe.d.ts +9 -48
  49. package/dist/simple-tree/api/typesUnsafe.d.ts.map +1 -1
  50. package/dist/simple-tree/api/typesUnsafe.js.map +1 -1
  51. package/dist/simple-tree/arrayNode.d.ts +3 -14
  52. package/dist/simple-tree/arrayNode.d.ts.map +1 -1
  53. package/dist/simple-tree/arrayNode.js.map +1 -1
  54. package/dist/simple-tree/core/schemaCaching.js +1 -1
  55. package/dist/simple-tree/core/schemaCaching.js.map +1 -1
  56. package/dist/simple-tree/core/treeNodeKernel.d.ts +6 -1
  57. package/dist/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
  58. package/dist/simple-tree/core/treeNodeKernel.js +7 -1
  59. package/dist/simple-tree/core/treeNodeKernel.js.map +1 -1
  60. package/dist/simple-tree/core/treeNodeSchema.d.ts +5 -6
  61. package/dist/simple-tree/core/treeNodeSchema.d.ts.map +1 -1
  62. package/dist/simple-tree/core/treeNodeSchema.js.map +1 -1
  63. package/dist/simple-tree/core/unhydratedFlexTree.js +1 -1
  64. package/dist/simple-tree/core/unhydratedFlexTree.js.map +1 -1
  65. package/dist/simple-tree/core/withType.d.ts +1 -3
  66. package/dist/simple-tree/core/withType.d.ts.map +1 -1
  67. package/dist/simple-tree/core/withType.js.map +1 -1
  68. package/dist/simple-tree/index.d.ts +4 -4
  69. package/dist/simple-tree/index.d.ts.map +1 -1
  70. package/dist/simple-tree/index.js.map +1 -1
  71. package/dist/simple-tree/schemaTypes.d.ts +6 -58
  72. package/dist/simple-tree/schemaTypes.d.ts.map +1 -1
  73. package/dist/simple-tree/schemaTypes.js +1 -6
  74. package/dist/simple-tree/schemaTypes.js.map +1 -1
  75. package/dist/simple-tree/toFlexSchema.js +2 -2
  76. package/dist/simple-tree/toFlexSchema.js.map +1 -1
  77. package/dist/simple-tree/toMapTree.d.ts +2 -4
  78. package/dist/simple-tree/toMapTree.d.ts.map +1 -1
  79. package/dist/simple-tree/toMapTree.js.map +1 -1
  80. package/lib/alpha.d.ts +0 -9
  81. package/lib/beta.d.ts +0 -2
  82. package/lib/feature-libraries/flex-tree/lazyField.js +1 -1
  83. package/lib/feature-libraries/flex-tree/lazyField.js.map +1 -1
  84. package/lib/feature-libraries/modular-schema/modularChangeFamily.d.ts.map +1 -1
  85. package/lib/feature-libraries/modular-schema/modularChangeFamily.js +3 -3
  86. package/lib/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
  87. package/lib/index.d.ts +1 -1
  88. package/lib/index.d.ts.map +1 -1
  89. package/lib/index.js.map +1 -1
  90. package/lib/internalTypes.d.ts +1 -1
  91. package/lib/internalTypes.d.ts.map +1 -1
  92. package/lib/internalTypes.js.map +1 -1
  93. package/lib/legacy.d.ts +0 -2
  94. package/lib/packageVersion.d.ts +1 -1
  95. package/lib/packageVersion.d.ts.map +1 -1
  96. package/lib/packageVersion.js +1 -1
  97. package/lib/packageVersion.js.map +1 -1
  98. package/lib/public.d.ts +0 -2
  99. package/lib/shared-tree/schematizingTreeView.js +1 -1
  100. package/lib/shared-tree/schematizingTreeView.js.map +1 -1
  101. package/lib/shared-tree/sharedTree.js +1 -1
  102. package/lib/shared-tree/sharedTree.js.map +1 -1
  103. package/lib/shared-tree/treeApi.d.ts +6 -6
  104. package/lib/shared-tree/treeApi.d.ts.map +1 -1
  105. package/lib/shared-tree/treeApi.js.map +1 -1
  106. package/lib/shared-tree-core/branch.js +1 -1
  107. package/lib/shared-tree-core/branch.js.map +1 -1
  108. package/lib/simple-tree/api/customTree.js +5 -5
  109. package/lib/simple-tree/api/customTree.js.map +1 -1
  110. package/lib/simple-tree/api/index.d.ts +2 -2
  111. package/lib/simple-tree/api/index.d.ts.map +1 -1
  112. package/lib/simple-tree/api/index.js.map +1 -1
  113. package/lib/simple-tree/api/tree.d.ts +3 -12
  114. package/lib/simple-tree/api/tree.d.ts.map +1 -1
  115. package/lib/simple-tree/api/tree.js.map +1 -1
  116. package/lib/simple-tree/api/treeApiBeta.d.ts +14 -2
  117. package/lib/simple-tree/api/treeApiBeta.d.ts.map +1 -1
  118. package/lib/simple-tree/api/treeApiBeta.js +23 -8
  119. package/lib/simple-tree/api/treeApiBeta.js.map +1 -1
  120. package/lib/simple-tree/api/typesUnsafe.d.ts +9 -48
  121. package/lib/simple-tree/api/typesUnsafe.d.ts.map +1 -1
  122. package/lib/simple-tree/api/typesUnsafe.js.map +1 -1
  123. package/lib/simple-tree/arrayNode.d.ts +3 -14
  124. package/lib/simple-tree/arrayNode.d.ts.map +1 -1
  125. package/lib/simple-tree/arrayNode.js.map +1 -1
  126. package/lib/simple-tree/core/schemaCaching.js +1 -1
  127. package/lib/simple-tree/core/schemaCaching.js.map +1 -1
  128. package/lib/simple-tree/core/treeNodeKernel.d.ts +6 -1
  129. package/lib/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
  130. package/lib/simple-tree/core/treeNodeKernel.js +7 -1
  131. package/lib/simple-tree/core/treeNodeKernel.js.map +1 -1
  132. package/lib/simple-tree/core/treeNodeSchema.d.ts +5 -6
  133. package/lib/simple-tree/core/treeNodeSchema.d.ts.map +1 -1
  134. package/lib/simple-tree/core/treeNodeSchema.js.map +1 -1
  135. package/lib/simple-tree/core/unhydratedFlexTree.js +1 -1
  136. package/lib/simple-tree/core/unhydratedFlexTree.js.map +1 -1
  137. package/lib/simple-tree/core/withType.d.ts +1 -3
  138. package/lib/simple-tree/core/withType.d.ts.map +1 -1
  139. package/lib/simple-tree/core/withType.js.map +1 -1
  140. package/lib/simple-tree/index.d.ts +4 -4
  141. package/lib/simple-tree/index.d.ts.map +1 -1
  142. package/lib/simple-tree/index.js +1 -1
  143. package/lib/simple-tree/index.js.map +1 -1
  144. package/lib/simple-tree/schemaTypes.d.ts +6 -58
  145. package/lib/simple-tree/schemaTypes.d.ts.map +1 -1
  146. package/lib/simple-tree/schemaTypes.js +0 -5
  147. package/lib/simple-tree/schemaTypes.js.map +1 -1
  148. package/lib/simple-tree/toFlexSchema.js +2 -2
  149. package/lib/simple-tree/toFlexSchema.js.map +1 -1
  150. package/lib/simple-tree/toMapTree.d.ts +2 -4
  151. package/lib/simple-tree/toMapTree.d.ts.map +1 -1
  152. package/lib/simple-tree/toMapTree.js.map +1 -1
  153. package/package.json +23 -39
  154. package/src/feature-libraries/flex-tree/lazyField.ts +1 -1
  155. package/src/feature-libraries/modular-schema/modularChangeFamily.ts +9 -3
  156. package/src/index.ts +0 -9
  157. package/src/internalTypes.ts +0 -3
  158. package/src/packageVersion.ts +1 -1
  159. package/src/shared-tree/schematizingTreeView.ts +1 -1
  160. package/src/shared-tree/sharedTree.ts +1 -1
  161. package/src/shared-tree/treeApi.ts +9 -19
  162. package/src/shared-tree-core/branch.ts +1 -1
  163. package/src/simple-tree/api/customTree.ts +5 -5
  164. package/src/simple-tree/api/index.ts +0 -5
  165. package/src/simple-tree/api/tree.ts +2 -24
  166. package/src/simple-tree/api/treeApiBeta.ts +65 -3
  167. package/src/simple-tree/api/typesUnsafe.ts +18 -82
  168. package/src/simple-tree/arrayNode.ts +14 -34
  169. package/src/simple-tree/core/schemaCaching.ts +1 -1
  170. package/src/simple-tree/core/treeNodeKernel.ts +10 -2
  171. package/src/simple-tree/core/treeNodeSchema.ts +5 -7
  172. package/src/simple-tree/core/unhydratedFlexTree.ts +1 -1
  173. package/src/simple-tree/core/withType.ts +1 -10
  174. package/src/simple-tree/index.ts +1 -15
  175. package/src/simple-tree/schemaTypes.ts +5 -68
  176. package/src/simple-tree/toFlexSchema.ts +2 -2
  177. package/src/simple-tree/toMapTree.ts +1 -4
@@ -273,7 +273,7 @@ export class SchematizingSimpleTreeView<in out TRootSchema extends ImplicitField
273
273
  this.view = view;
274
274
  assert(
275
275
  !this.checkout.forest.anchors.slots.has(SimpleContextSlot),
276
- "extra simple tree context",
276
+ 0xa47 /* extra simple tree context */,
277
277
  );
278
278
  this.checkout.forest.anchors.slots.set(
279
279
  SimpleContextSlot,
@@ -357,7 +357,7 @@ export function getBranch(view: TreeView<ImplicitFieldSchema>): TreeBranch;
357
357
  export function getBranch(treeOrView: ITree | TreeView<ImplicitFieldSchema>): TreeBranch {
358
358
  assert(
359
359
  treeOrView instanceof SharedTree || treeOrView instanceof SchematizingSimpleTreeView,
360
- "Unsupported implementation",
360
+ 0xa48 /* Unsupported implementation */,
361
361
  );
362
362
  const checkout: TreeCheckout = treeOrView.checkout;
363
363
  // This cast is safe so long as TreeCheckout supports all the operations on the branch interface.
@@ -78,10 +78,7 @@ export interface RunTransaction {
78
78
  * If the transaction function throws an error then the transaction will be automatically rolled back (discarding any changes made to the tree so far) before the error is propagated up from this function.
79
79
  * If the transaction is rolled back, a corresponding change event will also be emitted for the rollback.
80
80
  */
81
- // TODO: TreeView is invariant over the schema, so to accept any view, `any` is the only real option unless a non generic (or covariant) base type for view is introduced (which is planned).
82
- // This use of any is actually type safe as it is only used as a constraint, and the actual strongly typed view (TView) is passed to the callback.
83
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
84
- <TView extends TreeView<any>, TResult>(
81
+ <TView extends TreeView<ImplicitFieldSchema>, TResult>(
85
82
  tree: TView,
86
83
  transaction: (root: TView["root"]) => TResult,
87
84
  ): TResult;
@@ -126,9 +123,7 @@ export interface RunTransaction {
126
123
  * If the transaction function throws an error then the transaction will be automatically rolled back (discarding any changes made to the tree so far) before the error is propagated up from this function.
127
124
  * If the transaction is rolled back (whether by an error or by returning the {@link RunTransaction.rollback} | rollback value), a corresponding change event will also be emitted for the rollback.
128
125
  */
129
- // See comment on previous overload about use of any here.
130
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
131
- <TView extends TreeView<any>, TResult>(
126
+ <TView extends TreeView<ImplicitFieldSchema>, TResult>(
132
127
  tree: TView,
133
128
  transaction: (root: TView["root"]) => TResult | typeof rollback,
134
129
  ): TResult | typeof rollback;
@@ -166,9 +161,10 @@ export interface RunTransaction {
166
161
  * If the transaction function throws an error then the transaction will be automatically rolled back (discarding any changes made to the tree so far) before the error is propagated up from this function.
167
162
  * If the transaction is rolled back, a corresponding change event will also be emitted for the rollback.
168
163
  */
169
- // See comment on previous overload about use of any here.
170
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
171
- <TView extends TreeView<any>>(tree: TView, transaction: (root: TView["root"]) => void): void;
164
+ <TView extends TreeView<ImplicitFieldSchema>>(
165
+ tree: TView,
166
+ transaction: (root: TView["root"]) => void,
167
+ ): void;
172
168
  /**
173
169
  * Apply one or more edits to the tree as a single atomic unit.
174
170
  * @param node - The node that will be passed to `transaction`.
@@ -215,9 +211,7 @@ export interface RunTransaction {
215
211
  * If the transaction function throws an error then the transaction will be automatically rolled back (discarding any changes made to the tree so far) before the error is propagated up from this function.
216
212
  * If the transaction is rolled back, a corresponding change event will also be emitted for the rollback.
217
213
  */
218
- // See comment on previous overload about use of any here.
219
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
220
- <TView extends TreeView<any>, TResult>(
214
+ <TView extends TreeView<ImplicitFieldSchema>, TResult>(
221
215
  tree: TView,
222
216
  transaction: (root: TView["root"]) => TResult,
223
217
  preconditions?: readonly TransactionConstraint[],
@@ -270,9 +264,7 @@ export interface RunTransaction {
270
264
  * If the transaction function throws an error then the transaction will be automatically rolled back (discarding any changes made to the tree so far) before the error is propagated up from this function.
271
265
  * If the transaction is rolled back (whether by an error or by returning the {@link RunTransaction.rollback} | rollback value), a corresponding change event will also be emitted for the rollback.
272
266
  */
273
- // See comment on previous overload about use of any here.
274
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
275
- <TView extends TreeView<any>, TResult>(
267
+ <TView extends TreeView<ImplicitFieldSchema>, TResult>(
276
268
  tree: TView,
277
269
  transaction: (root: TView["root"]) => TResult | typeof rollback,
278
270
  preconditions?: readonly TransactionConstraint[],
@@ -321,9 +313,7 @@ export interface RunTransaction {
321
313
  * If the transaction function throws an error then the transaction will be automatically rolled back (discarding any changes made to the tree so far) before the error is propagated up from this function.
322
314
  * If the transaction is rolled back, a corresponding change event will also be emitted for the rollback.
323
315
  */
324
- // See comment on previous overload about use of any here.
325
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
326
- <TView extends TreeView<any>>(
316
+ <TView extends TreeView<ImplicitFieldSchema>>(
327
317
  tree: TView,
328
318
  transaction: (root: TView["root"]) => void,
329
319
  preconditions?: readonly TransactionConstraint[],
@@ -253,7 +253,7 @@ export class SharedTreeBranch<
253
253
  this.assertNotDisposed();
254
254
 
255
255
  const revisionTag = taggedChange.revision;
256
- assert(revisionTag !== undefined, "Revision tag must be provided");
256
+ assert(revisionTag !== undefined, 0xa49 /* Revision tag must be provided */);
257
257
 
258
258
  const newHead = mintCommit(this.head, {
259
259
  revision: revisionTag,
@@ -80,15 +80,15 @@ export function customFromCursorInner<TChild, THandle>(
80
80
  case booleanSchema.identifier:
81
81
  case nullSchema.identifier:
82
82
  case stringSchema.identifier:
83
- assert(reader.value !== undefined, "out of schema: missing value");
84
- assert(!isFluidHandle(reader.value), "out of schema: unexpected FluidHandle");
83
+ assert(reader.value !== undefined, 0xa50 /* out of schema: missing value */);
84
+ assert(!isFluidHandle(reader.value), 0xa51 /* out of schema: unexpected FluidHandle */);
85
85
  return reader.value;
86
86
  case handleSchema.identifier:
87
- assert(reader.value !== undefined, "out of schema: missing value");
88
- assert(isFluidHandle(reader.value), "out of schema: expected FluidHandle");
87
+ assert(reader.value !== undefined, 0xa52 /* out of schema: missing value */);
88
+ assert(isFluidHandle(reader.value), 0xa53 /* out of schema: expected FluidHandle */);
89
89
  return options.valueConverter(reader.value);
90
90
  default: {
91
- assert(reader.value === undefined, "out of schema: unexpected value");
91
+ assert(reader.value === undefined, 0xa54 /* out of schema: unexpected value */);
92
92
  if (nodeSchema.kind === NodeKind.Array) {
93
93
  const fields = inCursorField(reader, EmptyKey, () =>
94
94
  mapCursorField(reader, () => childHandler(reader, options, schema)),
@@ -12,7 +12,6 @@ export {
12
12
  type ITreeViewConfiguration,
13
13
  type SchemaCompatibilityStatus,
14
14
  type ITreeConfigurationOptions,
15
- type TreeViewAlpha,
16
15
  } from "./tree.js";
17
16
  export { SchemaFactory, type ScopedSchemaName } from "./schemaFactory.js";
18
17
  export type {
@@ -63,10 +62,6 @@ export type {
63
62
  NodeBuilderDataUnsafe,
64
63
  NodeFromSchemaUnsafe,
65
64
  ReadonlyMapInlined,
66
- TreeNodeSchemaClassUnsafe,
67
- TreeNodeSchemaUnsafe,
68
- AllowedTypesUnsafe,
69
- TreeNodeSchemaNonClassUnsafe,
70
65
  } from "./typesUnsafe.js";
71
66
 
72
67
  export type {
@@ -11,14 +11,11 @@ import type { Listenable } from "../../events/index.js";
11
11
 
12
12
  import {
13
13
  type ImplicitFieldSchema,
14
- type InsertableField,
15
14
  type InsertableTreeFieldFromImplicitField,
16
15
  type TreeFieldFromImplicitField,
17
- type TreeLeafValue,
18
- type UnsafeUnknownSchema,
19
16
  FieldKind,
20
17
  } from "../schemaTypes.js";
21
- import { NodeKind, type TreeNode, type TreeNodeSchema } from "../core/index.js";
18
+ import { NodeKind, type TreeNodeSchema } from "../core/index.js";
22
19
  import { toStoredSchema } from "../toFlexSchema.js";
23
20
  import { LeafNodeSchema } from "../leafNodeSchema.js";
24
21
  import { assert } from "@fluidframework/core-utils/internal";
@@ -366,7 +363,7 @@ export function checkUnion(union: Iterable<TreeNodeSchema>, errors: string[]): v
366
363
  * Thus this design was chosen at the risk of apps blindly accessing `root` then breaking unexpectedly when the document is incompatible.
367
364
  * @sealed @public
368
365
  */
369
- export interface TreeView<in out TSchema extends ImplicitFieldSchema> extends IDisposable {
366
+ export interface TreeView<TSchema extends ImplicitFieldSchema> extends IDisposable {
370
367
  /**
371
368
  * The current root of the tree.
372
369
  *
@@ -427,25 +424,6 @@ export interface TreeView<in out TSchema extends ImplicitFieldSchema> extends ID
427
424
  readonly schema: TSchema;
428
425
  }
429
426
 
430
- /**
431
- * {@link TreeView} with proposed changes to the schema aware typing to allow use with `UnsafeUnknownSchema`.
432
- * @alpha
433
- */
434
- export interface TreeViewAlpha<
435
- in out TSchema extends ImplicitFieldSchema | UnsafeUnknownSchema,
436
- > extends Omit<
437
- TreeView<TSchema extends ImplicitFieldSchema ? TSchema : ImplicitFieldSchema>,
438
- "root" | "initialize"
439
- > {
440
- get root(): TSchema extends ImplicitFieldSchema
441
- ? TreeFieldFromImplicitField<TSchema>
442
- : TreeLeafValue | TreeNode;
443
-
444
- set root(newRoot: InsertableField<TSchema>);
445
-
446
- initialize(content: InsertableField<TSchema>): void;
447
- }
448
-
449
427
  /**
450
428
  * Information about a view schema's compatibility with the document's stored schema.
451
429
  *
@@ -3,8 +3,19 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import type { NodeKind, TreeChangeEvents, TreeNode, WithType } from "../core/index.js";
6
+ import {
7
+ getKernel,
8
+ isTreeNode,
9
+ type NodeKind,
10
+ type TreeChangeEvents,
11
+ type TreeNode,
12
+ type Unhydrated,
13
+ type WithType,
14
+ } from "../core/index.js";
15
+ import type { ImplicitFieldSchema, TreeFieldFromImplicitField } from "../schemaTypes.js";
7
16
  import { treeNodeApi } from "./treeNodeApi.js";
17
+ import { createFromCursor, cursorFromInsertable } from "./create.js";
18
+ import type { ITreeCursorSynchronous } from "../../core/index.js";
8
19
 
9
20
  /**
10
21
  * Data included for {@link TreeChangeEventsBeta.nodeChanged}.
@@ -82,7 +93,7 @@ export interface TreeChangeEventsBeta<TNode extends TreeNode = TreeNode>
82
93
  * Extensions to {@link Tree} which are not yet stable.
83
94
  * @sealed @beta
84
95
  */
85
- export const TreeBeta = {
96
+ export const TreeBeta: {
86
97
  /**
87
98
  * Register an event listener on the given node.
88
99
  * @param node - The node whose events should be subscribed to.
@@ -91,6 +102,26 @@ export const TreeBeta = {
91
102
  * @returns A callback function which will deregister the event.
92
103
  * This callback should be called only once.
93
104
  */
105
+ on<K extends keyof TreeChangeEventsBeta<TNode>, TNode extends TreeNode>(
106
+ node: TNode,
107
+ eventName: K,
108
+ listener: NoInfer<TreeChangeEventsBeta<TNode>[K]>,
109
+ ): () => void;
110
+
111
+ /**
112
+ * Clones the persisted data associated with a node. Some key things to note:
113
+ * - Local state, such as properties added to customized schema classes, will not be cloned. However, they will be
114
+ * initialized to their default state just as if the node had been created via its constructor.
115
+ * - Value node types (i.e., numbers, strings, booleans, nulls and Fluid handles) will be returned as is.
116
+ * - The identifiers in the node's subtree will be preserved, i.e., they are not replaced with new values.
117
+ *
118
+ * @param node - The node to clone.
119
+ * @returns A new unhydrated node with the same persisted data as the original node.
120
+ */
121
+ clone<TSchema extends ImplicitFieldSchema>(
122
+ node: TreeFieldFromImplicitField<TSchema>,
123
+ ): TreeFieldFromImplicitField<TSchema>;
124
+ } = {
94
125
  on<K extends keyof TreeChangeEventsBeta<TNode>, TNode extends TreeNode>(
95
126
  node: TNode,
96
127
  eventName: K,
@@ -98,4 +129,35 @@ export const TreeBeta = {
98
129
  ): () => void {
99
130
  return treeNodeApi.on(node, eventName, listener);
100
131
  },
101
- } as const;
132
+ clone<TSchema extends ImplicitFieldSchema>(
133
+ node: TreeFieldFromImplicitField<TSchema>,
134
+ ): Unhydrated<TreeFieldFromImplicitField<TSchema>> {
135
+ /* The only non-TreeNode cases are {@link Value} (for an empty optional field) which can be returned as is. */
136
+ if (!isTreeNode(node)) {
137
+ return node;
138
+ }
139
+
140
+ const kernel = getKernel(node);
141
+ /*
142
+ * For unhydrated nodes, we can create a cursor by calling `cursorFromInsertable` because the node
143
+ * hasn't been inserted yet. We can then create a new node from the cursor.
144
+ */
145
+ if (!kernel.isHydrated()) {
146
+ return createFromCursor(
147
+ kernel.schema,
148
+ cursorFromInsertable(kernel.schema, node),
149
+ ) as Unhydrated<TreeFieldFromImplicitField<TSchema>>;
150
+ }
151
+
152
+ // For hydrated nodes, create a new cursor in the forest and then create a new node from the cursor.
153
+ const forest = kernel.context.flexContext.checkout.forest;
154
+ const cursor = forest.allocateCursor("tree.clone");
155
+ forest.moveCursorToPath(kernel.anchorNode, cursor);
156
+ const clonedNode = createFromCursor(
157
+ kernel.schema,
158
+ cursor as ITreeCursorSynchronous,
159
+ ) as Unhydrated<TreeFieldFromImplicitField<TSchema>>;
160
+ cursor.free();
161
+ return clonedNode;
162
+ },
163
+ };
@@ -6,24 +6,24 @@
6
6
  import type { RestrictiveStringRecord, _InlineTrick } from "../../util/index.js";
7
7
 
8
8
  import type {
9
+ AllowedTypes,
9
10
  ApplyKind,
10
11
  FieldKind,
11
12
  FieldSchema,
12
13
  ImplicitAllowedTypes,
13
14
  ImplicitFieldSchema,
14
- TreeLeafValue,
15
+ NodeFromSchema,
16
+ TreeNodeFromImplicitAllowedTypes,
15
17
  } from "../schemaTypes.js";
16
18
  import type {
17
19
  NodeKind,
20
+ TreeNodeSchema,
18
21
  WithType,
19
22
  TreeNode,
20
23
  Unhydrated,
21
- InternalTreeNode,
22
- TreeNodeSchema,
23
- TreeNodeSchemaCore,
24
24
  } from "../core/index.js";
25
- import type { TreeArrayNodeBase } from "../arrayNode.js";
26
- import type { FlexListToUnion, LazyItem } from "../flexList.js";
25
+ import type { TreeArrayNodeBase, TreeArrayNode } from "../arrayNode.js";
26
+ import type { FlexListToUnion } from "../flexList.js";
27
27
 
28
28
  /*
29
29
  * TODO:
@@ -59,65 +59,6 @@ export type ObjectFromSchemaRecordUnsafe<
59
59
  -readonly [Property in keyof T]: TreeFieldFromImplicitFieldUnsafe<T[Property]>;
60
60
  };
61
61
 
62
- /**
63
- * {@link Unenforced} version of {@link TreeNodeSchema}.
64
- * @remarks
65
- * Do note use this type directly: its only needed in the implementation of generic logic which define recursive schema, not when using recursive schema.
66
- * @system @public
67
- */
68
- export type TreeNodeSchemaUnsafe<
69
- Name extends string = string,
70
- Kind extends NodeKind = NodeKind,
71
- TNode extends Unenforced<TreeNode | TreeLeafValue> = unknown,
72
- TBuild = never,
73
- ImplicitlyConstructable extends boolean = boolean,
74
- Info = unknown,
75
- > =
76
- | TreeNodeSchemaClassUnsafe<Name, Kind, TNode, TBuild, ImplicitlyConstructable, Info>
77
- | TreeNodeSchemaNonClassUnsafe<Name, Kind, TNode, TBuild, ImplicitlyConstructable, Info>;
78
-
79
- /**
80
- * {@link Unenforced} version of {@link TreeNodeSchemaClass}.
81
- * @remarks
82
- * Do note use this type directly: its only needed in the implementation of generic logic which define recursive schema, not when using recursive schema.
83
- * @system @public
84
- */
85
- export interface TreeNodeSchemaClassUnsafe<
86
- out Name extends string,
87
- out Kind extends NodeKind,
88
- // TODO: maybe this can be more specific (exclude leaves)
89
- out TNode extends Unenforced<TreeNode | TreeLeafValue>,
90
- in TInsertable = never,
91
- out ImplicitlyConstructable extends boolean = boolean,
92
- out Info = unknown,
93
- > extends TreeNodeSchemaCore<Name, Kind, ImplicitlyConstructable, Info> {
94
- /**
95
- * Constructs an {@link Unhydrated} node with this schema.
96
- * @remarks
97
- * This constructor is also used internally to construct hydrated nodes with a different parameter type.
98
- * Therefore, overriding this constructor with different argument types is not type-safe and is not supported.
99
- * @sealed
100
- */
101
- new (data: TInsertable | InternalTreeNode): Unhydrated<TNode>;
102
- }
103
-
104
- /**
105
- * {@link Unenforced} version of {@link TreeNodeSchemaNonClass}.
106
- * @remarks
107
- * Do note use this type directly: its only needed in the implementation of generic logic which define recursive schema, not when using recursive schema.
108
- * @system @public
109
- */
110
- export interface TreeNodeSchemaNonClassUnsafe<
111
- out Name extends string,
112
- out Kind extends NodeKind,
113
- out TNode extends Unenforced<TreeNode | TreeLeafValue>,
114
- in TInsertable = never,
115
- out ImplicitlyConstructable extends boolean = boolean,
116
- out Info = unknown,
117
- > extends TreeNodeSchemaCore<Name, Kind, ImplicitlyConstructable, Info> {
118
- create(data: TInsertable): TNode;
119
- }
120
-
121
62
  /**
122
63
  * {@link Unenforced} version of {@link TreeObjectNode}.
123
64
  * @remarks
@@ -142,14 +83,6 @@ export type TreeFieldFromImplicitFieldUnsafe<TSchema extends Unenforced<Implicit
142
83
  ? TreeNodeFromImplicitAllowedTypesUnsafe<TSchema>
143
84
  : unknown;
144
85
 
145
- /**
146
- * {@link Unenforced} version of {@link AllowedTypes}.
147
- * @remarks
148
- * Do note use this type directly: its only needed in the implementation of generic logic which define recursive schema, not when using recursive schema.
149
- * @system @public
150
- */
151
- export type AllowedTypesUnsafe = readonly LazyItem<TreeNodeSchemaUnsafe>[];
152
-
153
86
  /**
154
87
  * {@link Unenforced} version of {@link TreeNodeFromImplicitAllowedTypes}.
155
88
  * @remarks
@@ -158,11 +91,13 @@ export type AllowedTypesUnsafe = readonly LazyItem<TreeNodeSchemaUnsafe>[];
158
91
  */
159
92
  export type TreeNodeFromImplicitAllowedTypesUnsafe<
160
93
  TSchema extends Unenforced<ImplicitAllowedTypes>,
161
- > = TSchema extends TreeNodeSchemaUnsafe
162
- ? NodeFromSchemaUnsafe<TSchema>
163
- : TSchema extends AllowedTypesUnsafe
164
- ? NodeFromSchemaUnsafe<FlexListToUnion<TSchema>>
165
- : unknown;
94
+ > = TSchema extends ImplicitAllowedTypes
95
+ ? TreeNodeFromImplicitAllowedTypes<TSchema>
96
+ : TSchema extends TreeNodeSchema
97
+ ? NodeFromSchema<TSchema>
98
+ : TSchema extends AllowedTypes
99
+ ? NodeFromSchema<FlexListToUnion<TSchema>>
100
+ : unknown;
166
101
 
167
102
  /**
168
103
  * {@link Unenforced} version of {@link InsertableTreeNodeFromImplicitAllowedTypes}.
@@ -172,7 +107,7 @@ export type TreeNodeFromImplicitAllowedTypesUnsafe<
172
107
  */
173
108
  export type InsertableTreeNodeFromImplicitAllowedTypesUnsafe<
174
109
  TSchema extends Unenforced<ImplicitAllowedTypes>,
175
- > = TSchema extends AllowedTypesUnsafe
110
+ > = TSchema extends AllowedTypes
176
111
  ? InsertableTypedNodeUnsafe<FlexListToUnion<TSchema>>
177
112
  : InsertableTypedNodeUnsafe<TSchema>;
178
113
 
@@ -194,7 +129,7 @@ export type InsertableTypedNodeUnsafe<T extends Unenforced<TreeNodeSchema>> = [
194
129
  * @system @public
195
130
  */
196
131
  export type NodeFromSchemaUnsafe<T extends Unenforced<TreeNodeSchema>> =
197
- T extends TreeNodeSchemaUnsafe<string, NodeKind, infer TNode> ? TNode : never;
132
+ T extends TreeNodeSchema<string, NodeKind, infer TNode> ? TNode : never;
198
133
 
199
134
  /**
200
135
  * {@link Unenforced} version of {@link InsertableTreeNodeFromImplicitAllowedTypes}.
@@ -203,7 +138,7 @@ export type NodeFromSchemaUnsafe<T extends Unenforced<TreeNodeSchema>> =
203
138
  * @system @public
204
139
  */
205
140
  export type NodeBuilderDataUnsafe<T extends Unenforced<TreeNodeSchema>> =
206
- T extends TreeNodeSchemaUnsafe<string, NodeKind, unknown, infer TBuild> ? TBuild : never;
141
+ T extends TreeNodeSchema<string, NodeKind, unknown, infer TBuild> ? TBuild : never;
207
142
 
208
143
  /**
209
144
  * {@link Unenforced} version of {@link (TreeArrayNode:interface)}.
@@ -214,7 +149,8 @@ export type NodeBuilderDataUnsafe<T extends Unenforced<TreeNodeSchema>> =
214
149
  export interface TreeArrayNodeUnsafe<TAllowedTypes extends Unenforced<ImplicitAllowedTypes>>
215
150
  extends TreeArrayNodeBase<
216
151
  TreeNodeFromImplicitAllowedTypesUnsafe<TAllowedTypes>,
217
- InsertableTreeNodeFromImplicitAllowedTypesUnsafe<TAllowedTypes>
152
+ InsertableTreeNodeFromImplicitAllowedTypesUnsafe<TAllowedTypes>,
153
+ TreeArrayNode
218
154
  > {}
219
155
 
220
156
  /**
@@ -18,7 +18,6 @@ import {
18
18
  normalizeAllowedTypes,
19
19
  type ImplicitAllowedTypes,
20
20
  type InsertableTreeNodeFromImplicitAllowedTypes,
21
- type TreeLeafValue,
22
21
  type TreeNodeFromImplicitAllowedTypes,
23
22
  } from "./schemaTypes.js";
24
23
  import {
@@ -35,7 +34,6 @@ import {
35
34
  type TreeNodeSchemaBoth,
36
35
  getSimpleNodeSchemaFromInnerNode,
37
36
  getOrCreateInnerNode,
38
- type TreeNodeSchemaClass,
39
37
  } from "./core/index.js";
40
38
  import { type InsertableContent, mapTreeFromNodeData } from "./toMapTree.js";
41
39
  import { fail } from "../util/index.js";
@@ -47,19 +45,6 @@ import {
47
45
  import { TreeNodeValid, type MostDerivedData } from "./treeNodeValid.js";
48
46
  import { getUnhydratedContext } from "./createContext.js";
49
47
 
50
- /**
51
- * A covariant base type for {@link (TreeArrayNode:interface)}.
52
- *
53
- * This provides the readonly subset of TreeArrayNode functionality, and is used as the source interface for moves since that needs to be covariant.
54
- * @privateRemarks
55
- * Ideally this would just include `TreeNode, WithType<string, NodeKind.Array>` in the extends list but https://github.com/microsoft/TypeScript/issues/16936 prevents that from compiling.
56
- * As a workaround around for this TypeScript limitation, the conflicting type intersection is wrapped in `Awaited` (which has no effect on the type in this case) which allows it to compile.
57
- * @system @sealed @public
58
- */
59
- export interface ReadonlyArrayNode<out T = TreeNode | TreeLeafValue>
60
- extends ReadonlyArray<T>,
61
- Awaited<TreeNode & WithType<string, NodeKind.Array>> {}
62
-
63
48
  /**
64
49
  * A generic array type, used to defined types like {@link (TreeArrayNode:interface)}.
65
50
  *
@@ -68,8 +53,9 @@ export interface ReadonlyArrayNode<out T = TreeNode | TreeLeafValue>
68
53
  *
69
54
  * @system @sealed @public
70
55
  */
71
- export interface TreeArrayNodeBase<out T, in TNew, in TMoveFrom = ReadonlyArrayNode>
72
- extends ReadonlyArrayNode<T> {
56
+ export interface TreeArrayNodeBase<out T, in TNew, in TMoveFrom>
57
+ extends ReadonlyArray<T>,
58
+ TreeNode {
73
59
  /**
74
60
  * Inserts new item(s) at a specified location.
75
61
  * @param index - The index at which to insert `value`.
@@ -380,7 +366,8 @@ export interface TreeArrayNode<
380
366
  TAllowedTypes extends ImplicitAllowedTypes = ImplicitAllowedTypes,
381
367
  > extends TreeArrayNodeBase<
382
368
  TreeNodeFromImplicitAllowedTypes<TAllowedTypes>,
383
- InsertableTreeNodeFromImplicitAllowedTypes<TAllowedTypes>
369
+ InsertableTreeNodeFromImplicitAllowedTypes<TAllowedTypes>,
370
+ TreeArrayNode
384
371
  > {}
385
372
 
386
373
  /**
@@ -430,7 +417,9 @@ export class IterableTreeArrayContent<T> implements Iterable<T> {
430
417
  /**
431
418
  * Given a array node proxy, returns its underlying LazySequence field.
432
419
  */
433
- function getSequenceField(arrayNode: ReadonlyArrayNode): FlexTreeSequenceField {
420
+ function getSequenceField<TSimpleType extends ImplicitAllowedTypes>(
421
+ arrayNode: TreeArrayNode<TSimpleType>,
422
+ ): FlexTreeSequenceField {
434
423
  return getOrCreateInnerNode(arrayNode).getBoxed(EmptyKey) as FlexTreeSequenceField;
435
424
  }
436
425
 
@@ -810,11 +799,6 @@ abstract class CustomArrayNodeBase<const T extends ImplicitAllowedTypes>
810
799
  protected abstract get simpleSchema(): T;
811
800
  protected abstract get allowedTypes(): ReadonlySet<TreeNodeSchema>;
812
801
 
813
- public abstract override get [typeSchemaSymbol](): TreeNodeSchemaClass<
814
- string,
815
- NodeKind.Array
816
- >;
817
-
818
802
  public constructor(
819
803
  input: Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>> | InternalTreeNode,
820
804
  ) {
@@ -917,13 +901,13 @@ abstract class CustomArrayNodeBase<const T extends ImplicitAllowedTypes>
917
901
  }
918
902
  field.editor.remove(removeStart, removeEnd - removeStart);
919
903
  }
920
- public moveToStart(sourceIndex: number, source?: ReadonlyArrayNode): void {
904
+ public moveToStart(sourceIndex: number, source?: TreeArrayNode): void {
921
905
  const sourceArray = source ?? this;
922
906
  const sourceField = getSequenceField(sourceArray);
923
907
  validateIndex(sourceIndex, sourceField, "moveToStart");
924
908
  this.moveRangeToIndex(0, sourceIndex, sourceIndex + 1, source);
925
909
  }
926
- public moveToEnd(sourceIndex: number, source?: ReadonlyArrayNode): void {
910
+ public moveToEnd(sourceIndex: number, source?: TreeArrayNode): void {
927
911
  const sourceArray = source ?? this;
928
912
  const sourceField = getSequenceField(sourceArray);
929
913
  validateIndex(sourceIndex, sourceField, "moveToEnd");
@@ -932,7 +916,7 @@ abstract class CustomArrayNodeBase<const T extends ImplicitAllowedTypes>
932
916
  public moveToIndex(
933
917
  destinationGap: number,
934
918
  sourceIndex: number,
935
- source?: ReadonlyArrayNode,
919
+ source?: TreeArrayNode,
936
920
  ): void {
937
921
  const sourceArray = source ?? this;
938
922
  const sourceField = getSequenceField(sourceArray);
@@ -944,7 +928,7 @@ abstract class CustomArrayNodeBase<const T extends ImplicitAllowedTypes>
944
928
  public moveRangeToStart(
945
929
  sourceStart: number,
946
930
  sourceEnd: number,
947
- source?: ReadonlyArrayNode,
931
+ source?: TreeArrayNode,
948
932
  ): void {
949
933
  validateIndexRange(
950
934
  sourceStart,
@@ -954,11 +938,7 @@ abstract class CustomArrayNodeBase<const T extends ImplicitAllowedTypes>
954
938
  );
955
939
  this.moveRangeToIndex(0, sourceStart, sourceEnd, source);
956
940
  }
957
- public moveRangeToEnd(
958
- sourceStart: number,
959
- sourceEnd: number,
960
- source?: ReadonlyArrayNode,
961
- ): void {
941
+ public moveRangeToEnd(sourceStart: number, sourceEnd: number, source?: TreeArrayNode): void {
962
942
  validateIndexRange(
963
943
  sourceStart,
964
944
  sourceEnd,
@@ -971,7 +951,7 @@ abstract class CustomArrayNodeBase<const T extends ImplicitAllowedTypes>
971
951
  destinationGap: number,
972
952
  sourceStart: number,
973
953
  sourceEnd: number,
974
- source?: ReadonlyArrayNode,
954
+ source?: TreeArrayNode,
975
955
  ): void {
976
956
  const destinationField = getSequenceField(this);
977
957
  const destinationSchema = this.allowedTypes;
@@ -29,7 +29,7 @@ export function getSimpleContextFromInnerNode(innerNode: InnerNode): Context {
29
29
  }
30
30
 
31
31
  const context = innerNode.anchorNode.anchorSet.slots.get(SimpleContextSlot);
32
- assert(context !== undefined, "missing simple tree context");
32
+ assert(context !== undefined, 0xa55 /* missing simple tree context */);
33
33
 
34
34
  return context;
35
35
  }
@@ -29,7 +29,7 @@ import { fail } from "../../util/index.js";
29
29
  // TODO: decide how to deal with dependencies on flex-tree implementation.
30
30
  // eslint-disable-next-line import/no-internal-modules
31
31
  import { makeTree } from "../../feature-libraries/flex-tree/lazyNode.js";
32
- import { SimpleContextSlot, type Context } from "./context.js";
32
+ import { SimpleContextSlot, type Context, type HydratedContext } from "./context.js";
33
33
  import { UnhydratedFlexTreeNode } from "./unhydratedFlexTree.js";
34
34
 
35
35
  const treeNodeToKernel = new WeakMap<TreeNode, TreeNodeKernel>();
@@ -267,6 +267,14 @@ export class TreeNodeKernel implements Listenable<KernelEvents> {
267
267
  // TODO: go to the context and remove myself from withAnchors
268
268
  }
269
269
 
270
+ public isHydrated(): this is { anchorNode: AnchorNode; context: HydratedContext } {
271
+ return isHydrated(this.#hydrationState);
272
+ }
273
+
274
+ public get anchorNode(): AnchorNode | undefined {
275
+ return isHydrated(this.#hydrationState) ? this.#hydrationState.anchorNode : undefined;
276
+ }
277
+
270
278
  /**
271
279
  * Retrieves the flex node associated with the given target via {@link setInnerNode}.
272
280
  * @remarks
@@ -421,7 +429,7 @@ export function tryDisposeTreeNode(anchorNode: AnchorNode): void {
421
429
  export function getTreeNodeSchemaFromHydratedFlexNode(flexNode: FlexTreeNode): TreeNodeSchema {
422
430
  assert(
423
431
  flexNode.context.isHydrated(),
424
- "getTreeNodeSchemaFromHydratedFlexNode only allows hydrated flex tree nodes",
432
+ 0xa56 /* getTreeNodeSchemaFromHydratedFlexNode only allows hydrated flex tree nodes */,
425
433
  );
426
434
 
427
435
  const context =