@fluidframework/tree 2.10.0-305357 → 2.10.0-306579

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 (234) hide show
  1. package/.eslintrc.cjs +56 -25
  2. package/api-report/tree.alpha.api.md +3 -2
  3. package/api-report/tree.beta.api.md +3 -2
  4. package/api-report/tree.legacy.alpha.api.md +3 -2
  5. package/api-report/tree.legacy.public.api.md +3 -2
  6. package/api-report/tree.public.api.md +3 -2
  7. package/dist/core/forest/forest.d.ts +5 -1
  8. package/dist/core/forest/forest.d.ts.map +1 -1
  9. package/dist/core/forest/forest.js.map +1 -1
  10. package/dist/core/index.d.ts +1 -1
  11. package/dist/core/index.d.ts.map +1 -1
  12. package/dist/core/index.js.map +1 -1
  13. package/dist/core/schema-stored/storedSchemaRepository.d.ts +7 -3
  14. package/dist/core/schema-stored/storedSchemaRepository.d.ts.map +1 -1
  15. package/dist/core/schema-stored/storedSchemaRepository.js +4 -6
  16. package/dist/core/schema-stored/storedSchemaRepository.js.map +1 -1
  17. package/dist/core/tree/anchorSet.d.ts +8 -5
  18. package/dist/core/tree/anchorSet.d.ts.map +1 -1
  19. package/dist/core/tree/anchorSet.js +12 -11
  20. package/dist/core/tree/anchorSet.js.map +1 -1
  21. package/dist/events/emitter.d.ts +21 -9
  22. package/dist/events/emitter.d.ts.map +1 -1
  23. package/dist/events/emitter.js +36 -21
  24. package/dist/events/emitter.js.map +1 -1
  25. package/dist/events/listeners.d.ts +16 -5
  26. package/dist/events/listeners.d.ts.map +1 -1
  27. package/dist/events/listeners.js.map +1 -1
  28. package/dist/feature-libraries/chunked-forest/chunkTree.js +1 -1
  29. package/dist/feature-libraries/chunked-forest/chunkTree.js.map +1 -1
  30. package/dist/feature-libraries/chunked-forest/chunkedForest.d.ts +3 -2
  31. package/dist/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
  32. package/dist/feature-libraries/chunked-forest/chunkedForest.js +14 -9
  33. package/dist/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
  34. package/dist/feature-libraries/flex-tree/context.d.ts +3 -2
  35. package/dist/feature-libraries/flex-tree/context.d.ts.map +1 -1
  36. package/dist/feature-libraries/flex-tree/context.js +3 -3
  37. package/dist/feature-libraries/flex-tree/context.js.map +1 -1
  38. package/dist/feature-libraries/flex-tree/lazyField.js +1 -1
  39. package/dist/feature-libraries/flex-tree/lazyField.js.map +1 -1
  40. package/dist/feature-libraries/flex-tree/lazyNode.js +1 -1
  41. package/dist/feature-libraries/flex-tree/lazyNode.js.map +1 -1
  42. package/dist/feature-libraries/flex-tree/utilities.js +1 -1
  43. package/dist/feature-libraries/flex-tree/utilities.js.map +1 -1
  44. package/dist/feature-libraries/modular-schema/comparison.d.ts.map +1 -1
  45. package/dist/feature-libraries/modular-schema/comparison.js +3 -0
  46. package/dist/feature-libraries/modular-schema/comparison.js.map +1 -1
  47. package/dist/feature-libraries/modular-schema/discrepancies.d.ts +2 -2
  48. package/dist/feature-libraries/modular-schema/discrepancies.d.ts.map +1 -1
  49. package/dist/feature-libraries/modular-schema/discrepancies.js +90 -44
  50. package/dist/feature-libraries/modular-schema/discrepancies.js.map +1 -1
  51. package/dist/feature-libraries/modular-schema/genericFieldKind.js +2 -2
  52. package/dist/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
  53. package/dist/feature-libraries/modular-schema/modularChangeFamily.js +1 -1
  54. package/dist/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
  55. package/dist/feature-libraries/object-forest/objectForest.d.ts +2 -2
  56. package/dist/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
  57. package/dist/feature-libraries/object-forest/objectForest.js +6 -8
  58. package/dist/feature-libraries/object-forest/objectForest.js.map +1 -1
  59. package/dist/feature-libraries/schema-index/schemaSummarizer.js +1 -1
  60. package/dist/feature-libraries/schema-index/schemaSummarizer.js.map +1 -1
  61. package/dist/feature-libraries/sequence-field/compose.js +2 -2
  62. package/dist/feature-libraries/sequence-field/compose.js.map +1 -1
  63. package/dist/feature-libraries/sequence-field/markListFactory.js +1 -1
  64. package/dist/feature-libraries/sequence-field/markListFactory.js.map +1 -1
  65. package/dist/packageVersion.d.ts +1 -1
  66. package/dist/packageVersion.js +1 -1
  67. package/dist/packageVersion.js.map +1 -1
  68. package/dist/shared-tree/schematizingTreeView.js +2 -2
  69. package/dist/shared-tree/schematizingTreeView.js.map +1 -1
  70. package/dist/shared-tree/treeApi.js +2 -2
  71. package/dist/shared-tree/treeApi.js.map +1 -1
  72. package/dist/shared-tree/treeCheckout.js +7 -7
  73. package/dist/shared-tree/treeCheckout.js.map +1 -1
  74. package/dist/shared-tree-core/branch.d.ts +7 -7
  75. package/dist/shared-tree-core/branch.d.ts.map +1 -1
  76. package/dist/shared-tree-core/branch.js +35 -25
  77. package/dist/shared-tree-core/branch.js.map +1 -1
  78. package/dist/shared-tree-core/editManager.js +4 -4
  79. package/dist/shared-tree-core/editManager.js.map +1 -1
  80. package/dist/shared-tree-core/sharedTreeCore.js +5 -5
  81. package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
  82. package/dist/simple-tree/api/schemaFactory.d.ts +66 -10
  83. package/dist/simple-tree/api/schemaFactory.d.ts.map +1 -1
  84. package/dist/simple-tree/api/schemaFactory.js +34 -9
  85. package/dist/simple-tree/api/schemaFactory.js.map +1 -1
  86. package/dist/simple-tree/api/treeNodeApi.js +4 -4
  87. package/dist/simple-tree/api/treeNodeApi.js.map +1 -1
  88. package/dist/simple-tree/arrayNode.js +1 -1
  89. package/dist/simple-tree/arrayNode.js.map +1 -1
  90. package/dist/simple-tree/core/treeNodeKernel.d.ts +3 -3
  91. package/dist/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
  92. package/dist/simple-tree/core/treeNodeKernel.js +7 -8
  93. package/dist/simple-tree/core/treeNodeKernel.js.map +1 -1
  94. package/dist/simple-tree/proxies.js +1 -1
  95. package/dist/simple-tree/proxies.js.map +1 -1
  96. package/dist/simple-tree/schemaTypes.d.ts +26 -1
  97. package/dist/simple-tree/schemaTypes.d.ts.map +1 -1
  98. package/dist/simple-tree/schemaTypes.js.map +1 -1
  99. package/dist/simple-tree/treeNodeValid.js +2 -2
  100. package/dist/simple-tree/treeNodeValid.js.map +1 -1
  101. package/dist/util/nestedMap.d.ts.map +1 -1
  102. package/dist/util/nestedMap.js.map +1 -1
  103. package/lib/core/forest/forest.d.ts +5 -1
  104. package/lib/core/forest/forest.d.ts.map +1 -1
  105. package/lib/core/forest/forest.js.map +1 -1
  106. package/lib/core/index.d.ts +1 -1
  107. package/lib/core/index.d.ts.map +1 -1
  108. package/lib/core/index.js.map +1 -1
  109. package/lib/core/schema-stored/storedSchemaRepository.d.ts +7 -3
  110. package/lib/core/schema-stored/storedSchemaRepository.d.ts.map +1 -1
  111. package/lib/core/schema-stored/storedSchemaRepository.js +4 -6
  112. package/lib/core/schema-stored/storedSchemaRepository.js.map +1 -1
  113. package/lib/core/tree/anchorSet.d.ts +8 -5
  114. package/lib/core/tree/anchorSet.d.ts.map +1 -1
  115. package/lib/core/tree/anchorSet.js +12 -11
  116. package/lib/core/tree/anchorSet.js.map +1 -1
  117. package/lib/events/emitter.d.ts +21 -9
  118. package/lib/events/emitter.d.ts.map +1 -1
  119. package/lib/events/emitter.js +37 -22
  120. package/lib/events/emitter.js.map +1 -1
  121. package/lib/events/listeners.d.ts +16 -5
  122. package/lib/events/listeners.d.ts.map +1 -1
  123. package/lib/events/listeners.js.map +1 -1
  124. package/lib/feature-libraries/chunked-forest/chunkTree.js +1 -1
  125. package/lib/feature-libraries/chunked-forest/chunkTree.js.map +1 -1
  126. package/lib/feature-libraries/chunked-forest/chunkedForest.d.ts +3 -2
  127. package/lib/feature-libraries/chunked-forest/chunkedForest.d.ts.map +1 -1
  128. package/lib/feature-libraries/chunked-forest/chunkedForest.js +14 -9
  129. package/lib/feature-libraries/chunked-forest/chunkedForest.js.map +1 -1
  130. package/lib/feature-libraries/flex-tree/context.d.ts +3 -2
  131. package/lib/feature-libraries/flex-tree/context.d.ts.map +1 -1
  132. package/lib/feature-libraries/flex-tree/context.js +3 -3
  133. package/lib/feature-libraries/flex-tree/context.js.map +1 -1
  134. package/lib/feature-libraries/flex-tree/lazyField.js +1 -1
  135. package/lib/feature-libraries/flex-tree/lazyField.js.map +1 -1
  136. package/lib/feature-libraries/flex-tree/lazyNode.js +1 -1
  137. package/lib/feature-libraries/flex-tree/lazyNode.js.map +1 -1
  138. package/lib/feature-libraries/flex-tree/utilities.js +1 -1
  139. package/lib/feature-libraries/flex-tree/utilities.js.map +1 -1
  140. package/lib/feature-libraries/modular-schema/comparison.d.ts.map +1 -1
  141. package/lib/feature-libraries/modular-schema/comparison.js +3 -0
  142. package/lib/feature-libraries/modular-schema/comparison.js.map +1 -1
  143. package/lib/feature-libraries/modular-schema/discrepancies.d.ts +2 -2
  144. package/lib/feature-libraries/modular-schema/discrepancies.d.ts.map +1 -1
  145. package/lib/feature-libraries/modular-schema/discrepancies.js +91 -45
  146. package/lib/feature-libraries/modular-schema/discrepancies.js.map +1 -1
  147. package/lib/feature-libraries/modular-schema/genericFieldKind.js +2 -2
  148. package/lib/feature-libraries/modular-schema/genericFieldKind.js.map +1 -1
  149. package/lib/feature-libraries/modular-schema/modularChangeFamily.js +1 -1
  150. package/lib/feature-libraries/modular-schema/modularChangeFamily.js.map +1 -1
  151. package/lib/feature-libraries/object-forest/objectForest.d.ts +2 -2
  152. package/lib/feature-libraries/object-forest/objectForest.d.ts.map +1 -1
  153. package/lib/feature-libraries/object-forest/objectForest.js +6 -8
  154. package/lib/feature-libraries/object-forest/objectForest.js.map +1 -1
  155. package/lib/feature-libraries/schema-index/schemaSummarizer.js +1 -1
  156. package/lib/feature-libraries/schema-index/schemaSummarizer.js.map +1 -1
  157. package/lib/feature-libraries/sequence-field/compose.js +2 -2
  158. package/lib/feature-libraries/sequence-field/compose.js.map +1 -1
  159. package/lib/feature-libraries/sequence-field/markListFactory.js +1 -1
  160. package/lib/feature-libraries/sequence-field/markListFactory.js.map +1 -1
  161. package/lib/packageVersion.d.ts +1 -1
  162. package/lib/packageVersion.js +1 -1
  163. package/lib/packageVersion.js.map +1 -1
  164. package/lib/shared-tree/schematizingTreeView.js +2 -2
  165. package/lib/shared-tree/schematizingTreeView.js.map +1 -1
  166. package/lib/shared-tree/treeApi.js +2 -2
  167. package/lib/shared-tree/treeApi.js.map +1 -1
  168. package/lib/shared-tree/treeCheckout.js +7 -7
  169. package/lib/shared-tree/treeCheckout.js.map +1 -1
  170. package/lib/shared-tree-core/branch.d.ts +7 -7
  171. package/lib/shared-tree-core/branch.d.ts.map +1 -1
  172. package/lib/shared-tree-core/branch.js +36 -26
  173. package/lib/shared-tree-core/branch.js.map +1 -1
  174. package/lib/shared-tree-core/editManager.js +4 -4
  175. package/lib/shared-tree-core/editManager.js.map +1 -1
  176. package/lib/shared-tree-core/sharedTreeCore.js +5 -5
  177. package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
  178. package/lib/simple-tree/api/schemaFactory.d.ts +66 -10
  179. package/lib/simple-tree/api/schemaFactory.d.ts.map +1 -1
  180. package/lib/simple-tree/api/schemaFactory.js +34 -9
  181. package/lib/simple-tree/api/schemaFactory.js.map +1 -1
  182. package/lib/simple-tree/api/treeNodeApi.js +4 -4
  183. package/lib/simple-tree/api/treeNodeApi.js.map +1 -1
  184. package/lib/simple-tree/arrayNode.js +1 -1
  185. package/lib/simple-tree/arrayNode.js.map +1 -1
  186. package/lib/simple-tree/core/treeNodeKernel.d.ts +3 -3
  187. package/lib/simple-tree/core/treeNodeKernel.d.ts.map +1 -1
  188. package/lib/simple-tree/core/treeNodeKernel.js +7 -8
  189. package/lib/simple-tree/core/treeNodeKernel.js.map +1 -1
  190. package/lib/simple-tree/proxies.js +1 -1
  191. package/lib/simple-tree/proxies.js.map +1 -1
  192. package/lib/simple-tree/schemaTypes.d.ts +26 -1
  193. package/lib/simple-tree/schemaTypes.d.ts.map +1 -1
  194. package/lib/simple-tree/schemaTypes.js.map +1 -1
  195. package/lib/simple-tree/treeNodeValid.js +2 -2
  196. package/lib/simple-tree/treeNodeValid.js.map +1 -1
  197. package/lib/util/nestedMap.d.ts.map +1 -1
  198. package/lib/util/nestedMap.js.map +1 -1
  199. package/package.json +20 -20
  200. package/src/core/forest/forest.ts +6 -1
  201. package/src/core/index.ts +1 -1
  202. package/src/core/schema-stored/storedSchemaRepository.ts +10 -13
  203. package/src/core/tree/anchorSet.ts +13 -20
  204. package/src/events/emitter.ts +45 -24
  205. package/src/events/listeners.ts +17 -5
  206. package/src/feature-libraries/chunked-forest/chunkTree.ts +1 -1
  207. package/src/feature-libraries/chunked-forest/chunkedForest.ts +8 -14
  208. package/src/feature-libraries/flex-tree/context.ts +5 -7
  209. package/src/feature-libraries/flex-tree/lazyField.ts +1 -1
  210. package/src/feature-libraries/flex-tree/lazyNode.ts +1 -1
  211. package/src/feature-libraries/flex-tree/utilities.ts +1 -1
  212. package/src/feature-libraries/modular-schema/comparison.ts +4 -0
  213. package/src/feature-libraries/modular-schema/discrepancies.ts +116 -50
  214. package/src/feature-libraries/modular-schema/genericFieldKind.ts +2 -2
  215. package/src/feature-libraries/modular-schema/modularChangeFamily.ts +1 -1
  216. package/src/feature-libraries/object-forest/objectForest.ts +5 -11
  217. package/src/feature-libraries/schema-index/schemaSummarizer.ts +1 -1
  218. package/src/feature-libraries/sequence-field/compose.ts +2 -2
  219. package/src/feature-libraries/sequence-field/markListFactory.ts +1 -1
  220. package/src/packageVersion.ts +1 -1
  221. package/src/shared-tree/schematizingTreeView.ts +2 -2
  222. package/src/shared-tree/treeApi.ts +2 -2
  223. package/src/shared-tree/treeCheckout.ts +7 -7
  224. package/src/shared-tree-core/branch.ts +30 -30
  225. package/src/shared-tree-core/editManager.ts +4 -4
  226. package/src/shared-tree-core/sharedTreeCore.ts +5 -5
  227. package/src/simple-tree/api/schemaFactory.ts +37 -11
  228. package/src/simple-tree/api/treeNodeApi.ts +4 -4
  229. package/src/simple-tree/arrayNode.ts +1 -1
  230. package/src/simple-tree/core/treeNodeKernel.ts +8 -10
  231. package/src/simple-tree/proxies.ts +1 -1
  232. package/src/simple-tree/schemaTypes.ts +26 -1
  233. package/src/simple-tree/treeNodeValid.ts +2 -2
  234. package/src/util/nestedMap.ts +1 -0
@@ -183,16 +183,16 @@ export class SharedTreeCore<TEditor extends ChangeFamilyEditor, TChange>
183
183
  this.mintRevisionTag,
184
184
  rebaseLogger,
185
185
  );
186
- this.editManager.localBranch.on("transactionStarted", () => {
186
+ this.editManager.localBranch.events.on("transactionStarted", () => {
187
187
  this.commitEnricher.startNewTransaction();
188
188
  });
189
- this.editManager.localBranch.on("transactionAborted", () => {
189
+ this.editManager.localBranch.events.on("transactionAborted", () => {
190
190
  this.commitEnricher.abortCurrentTransaction();
191
191
  });
192
- this.editManager.localBranch.on("transactionCommitted", () => {
192
+ this.editManager.localBranch.events.on("transactionCommitted", () => {
193
193
  this.commitEnricher.commitCurrentTransaction();
194
194
  });
195
- this.editManager.localBranch.on("beforeChange", (change) => {
195
+ this.editManager.localBranch.events.on("beforeChange", (change) => {
196
196
  // Ensure that any previously prepared commits that have not been sent are purged.
197
197
  this.commitEnricher.purgePreparedCommits();
198
198
  if (this.detachedRevision !== undefined) {
@@ -219,7 +219,7 @@ export class SharedTreeCore<TEditor extends ChangeFamilyEditor, TChange>
219
219
  this.commitEnricher.prepareCommit(change.newCommits[0] ?? oob(), true);
220
220
  }
221
221
  });
222
- this.editManager.localBranch.on("afterChange", (change) => {
222
+ this.editManager.localBranch.events.on("afterChange", (change) => {
223
223
  if (this.getLocalBranch().isTransacting()) {
224
224
  // We do not submit ops for changes that are part of a transaction.
225
225
  return;
@@ -216,19 +216,45 @@ export class SchemaFactory<
216
216
  private readonly structuralTypes: Map<string, TreeNodeSchema> = new Map();
217
217
 
218
218
  /**
219
- * Construct a SchemaFactory with a given scope.
219
+ * Construct a SchemaFactory with a given {@link SchemaFactory.scope|scope}.
220
220
  * @remarks
221
- * There are no restrictions on mixing schema from different schema factories:
222
- * this is encouraged when a single schema references schema from different libraries.
223
- * If each library exporting schema picks its own globally unique scope for its SchemaFactory,
224
- * then all schema an application might depend on, directly or transitively,
225
- * will end up with a unique fully qualified name which is required to refer to it in persisted data and errors.
226
- *
227
- * @param scope - Prefix appended to the identifiers of all {@link TreeNodeSchema} produced by this builder.
228
- * Use of [Reverse domain name notation](https://en.wikipedia.org/wiki/Reverse_domain_name_notation) or a UUIDv4 is recommended to avoid collisions.
229
- * You may opt out of using a scope by passing `undefined`, but note that this increases the risk of collisions.
221
+ * There are no restrictions on mixing schema from different schema factories.
222
+ * Typically each library will create one or more SchemaFactories and use them to define its schema.
230
223
  */
231
- public constructor(public readonly scope: TScope) {}
224
+ public constructor(
225
+ /**
226
+ * Prefix appended to the identifiers of all {@link TreeNodeSchema} produced by this builder.
227
+ *
228
+ * @remarks
229
+ * Generally each independently developed library
230
+ * (possibly a package, but could also be part of a package or multiple packages developed together)
231
+ * should get its own unique `scope`.
232
+ * Then each schema in the library get a name which is unique within the library.
233
+ * The scope and name are joined (with a period) to form the {@link TreeNodeSchemaCore.identifier|schema identifier}.
234
+ * Following this pattern allows a single application to depend on multiple libraries which define their own schema, and use them together in a single tree without risk of collisions.
235
+ * If a library logically contains sub-libraries with their own schema, they can be given a scope nested inside the parent scope, such as "ParentScope.ChildScope".
236
+ *
237
+ * To avoid collisions between the scopes of libraries
238
+ * it is recommended that the libraries use {@link https://en.wikipedia.org/wiki/Reverse_domain_name_notation | Reverse domain name notation} or a UUIDv4 for their scope.
239
+ * If this pattern is followed, application can safely use third party libraries without risk of the schema in them colliding.
240
+ *
241
+ * You may opt out of using a scope by passing `undefined`, but note that this increases the risk of collisions.
242
+ *
243
+ * @example
244
+ * Fluid Framework follows this pattern, placing the schema for the built in leaf types in the `com.fluidframework.leaf` scope.
245
+ * If Fluid Framework publishes more schema in the future, they would be under some other `com.fluidframework` scope.
246
+ * This ensures that any schema defined by any other library will not conflict with Fluid Framework's schema
247
+ * as long as the library uses the recommended patterns for how to scope its schema..
248
+ *
249
+ * @example
250
+ * A library could generate a random UUIDv4, like `242c4397-49ed-47e6-8dd0-d5c3bc31778b` and use that as the scope.
251
+ * Note: do not use this UUID: a new one must be randomly generated when needed to ensure collision resistance.
252
+ * ```typescript
253
+ * const factory = new SchemaFactory("242c4397-49ed-47e6-8dd0-d5c3bc31778b");
254
+ * ```
255
+ */
256
+ public readonly scope: TScope,
257
+ ) {}
232
258
 
233
259
  private scoped<Name extends TName | string>(name: Name): ScopedSchemaName<TScope, Name> {
234
260
  return (
@@ -168,7 +168,7 @@ export const treeNodeApi: TreeNodeApi = {
168
168
  case "nodeChanged": {
169
169
  const nodeSchema = kernel.schema;
170
170
  if (isObjectNodeSchema(nodeSchema)) {
171
- return kernel.on("childrenChangedAfterBatch", ({ changedFields }) => {
171
+ return kernel.events.on("childrenChangedAfterBatch", ({ changedFields }) => {
172
172
  const changedProperties = new Set(
173
173
  Array.from(
174
174
  changedFields,
@@ -180,17 +180,17 @@ export const treeNodeApi: TreeNodeApi = {
180
180
  listener({ changedProperties });
181
181
  });
182
182
  } else if (nodeSchema.kind === NodeKind.Array) {
183
- return kernel.on("childrenChangedAfterBatch", () => {
183
+ return kernel.events.on("childrenChangedAfterBatch", () => {
184
184
  listener({ changedProperties: undefined });
185
185
  });
186
186
  } else {
187
- return kernel.on("childrenChangedAfterBatch", ({ changedFields }) => {
187
+ return kernel.events.on("childrenChangedAfterBatch", ({ changedFields }) => {
188
188
  listener({ changedProperties: changedFields });
189
189
  });
190
190
  }
191
191
  }
192
192
  case "treeChanged": {
193
- return kernel.on("subtreeChangedAfterBatch", () => listener({}));
193
+ return kernel.events.on("subtreeChangedAfterBatch", () => listener({}));
194
194
  }
195
195
  default:
196
196
  throw new UsageError(`No event named ${JSON.stringify(eventName)}.`);
@@ -1096,7 +1096,7 @@ export function arraySchema<
1096
1096
  // Since proxy reports this as a "non-configurable" property, it must exist on the underlying object used as the proxy target, not as an inherited property.
1097
1097
  // This should not get used as the proxy should intercept all use.
1098
1098
  Object.defineProperty(instance, "length", {
1099
- value: NaN,
1099
+ value: Number.NaN,
1100
1100
  writable: true,
1101
1101
  enumerable: false,
1102
1102
  configurable: false,
@@ -95,7 +95,7 @@ function isHydrated(state: HydrationState): state is HydratedState {
95
95
  * The kernel has the same lifetime as the node and spans both its unhydrated and hydrated states.
96
96
  * When hydration occurs, the kernel is notified via the {@link TreeNodeKernel.hydrate | hydrate} method.
97
97
  */
98
- export class TreeNodeKernel implements Listenable<KernelEvents> {
98
+ export class TreeNodeKernel {
99
99
  private disposed = false;
100
100
 
101
101
  /**
@@ -205,9 +205,9 @@ export class TreeNodeKernel implements Listenable<KernelEvents> {
205
205
  this.#hydrationState = {
206
206
  anchorNode,
207
207
  offAnchorNode: new Set([
208
- anchorNode.on("afterDestroy", () => this.dispose()),
208
+ anchorNode.events.on("afterDestroy", () => this.dispose()),
209
209
  // TODO: this should be triggered on change even for unhydrated nodes.
210
- anchorNode.on("childrenChanging", () => {
210
+ anchorNode.events.on("childrenChanging", () => {
211
211
  this.generationNumber += 1;
212
212
  }),
213
213
  ]),
@@ -221,7 +221,7 @@ export class TreeNodeKernel implements Listenable<KernelEvents> {
221
221
  this.#hydrationState.offAnchorNode.add(
222
222
  // Argument is forwarded between matching events, so the type should be correct.
223
223
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
224
- anchorNode.on(eventName, (arg: any) => events.emit(eventName, arg)),
224
+ anchorNode.events.on(eventName, (arg: any) => events.emit(eventName, arg)),
225
225
  );
226
226
  }
227
227
  }
@@ -248,13 +248,11 @@ export class TreeNodeKernel implements Listenable<KernelEvents> {
248
248
  return treeStatusFromAnchorCache(this.#hydrationState.anchorNode);
249
249
  }
250
250
 
251
- public on<K extends keyof KernelEvents>(eventName: K, listener: KernelEvents[K]): Off {
251
+ public get events(): Listenable<KernelEvents> {
252
252
  // Retrieve the correct events object based on whether this node is pre or post hydration.
253
- const events: Listenable<KernelEvents> = isHydrated(this.#hydrationState)
254
- ? this.#hydrationState.anchorNode
253
+ return isHydrated(this.#hydrationState)
254
+ ? this.#hydrationState.anchorNode.events
255
255
  : this.#unhydratedEvents.value;
256
-
257
- return events.on(eventName, listener);
258
256
  }
259
257
 
260
258
  public dispose(): void {
@@ -339,7 +337,7 @@ export class TreeNodeKernel implements Listenable<KernelEvents> {
339
337
  off();
340
338
  };
341
339
  anchorForgetters.set(this.node, forget);
342
- const off = anchorNode.on("afterDestroy", forget);
340
+ const off = anchorNode.events.on("afterDestroy", forget);
343
341
  return anchorNode;
344
342
  }
345
343
 
@@ -172,7 +172,7 @@ function bindProxies(proxies: RootedProxyPaths[], forest: IForestSubscription):
172
172
  if (proxies.length > 0) {
173
173
  // Creating a new array emits one event per element in the array, so listen to the event once for each element
174
174
  let i = 0;
175
- const off = forest.on("afterRootFieldCreated", (fieldKey) => {
175
+ const off = forest.events.on("afterRootFieldCreated", (fieldKey) => {
176
176
  // Non null asserting here because of the length check above
177
177
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
178
178
  (proxies[i]!.rootPath as Mutable<UpPath>).parentField = fieldKey;
@@ -476,9 +476,34 @@ function evaluateLazySchema(value: LazyItem<TreeNodeSchema>): TreeNodeSchema {
476
476
  }
477
477
 
478
478
  /**
479
- * Types allowed in a field.
479
+ * Types of {@link TreeNode|TreeNodes} or {@link TreeLeafValue|TreeLeafValues} allowed at a location in a tree.
480
480
  * @remarks
481
+ * Used by {@link TreeViewConfiguration} for the root and various kinds of {@link TreeNodeSchema} to specify their allowed child types.
482
+ *
483
+ * Use {@link SchemaFactory} to access leaf schema or declare new composite schema.
484
+ *
481
485
  * Implicitly treats a single type as an array of one type.
486
+ *
487
+ * Arrays of schema can be used to specify multiple types are allowed, which result in unions of those types in the Tree APIs.
488
+ *
489
+ * When saved into variables, avoid type-erasing the details, as doing so loses the compile time schema awareness of APIs derived from the types.
490
+ *
491
+ * When referring to types that are declared after the definition of the `ImplicitAllowedTypes`, the schema can be wrapped in a lambda to allow the forward reference.
492
+ * See {@link ValidateRecursiveSchema} for details on how to structure the `ImplicitAllowedTypes` instances when constructing recursive schema.
493
+ *
494
+ * @example Explicit use with strong typing
495
+ * ```typescript
496
+ * const sf = new SchemaFactory("myScope");
497
+ * const childTypes = [sf.number, sf.string] as const satisfies ImplicitAllowedTypes;
498
+ * const config = new TreeViewConfiguration({ schema: childTypes });
499
+ * ```
500
+ *
501
+ * @example Forward reference
502
+ * ```typescript
503
+ * const sf = new SchemaFactory("myScope");
504
+ * class A extends sf.array("example", [() => B]) {}
505
+ * class B extends sf.array("Inner", sf.number) {}
506
+ * ```
482
507
  * @public
483
508
  */
484
509
  export type ImplicitAllowedTypes = AllowedTypes | TreeNodeSchema;
@@ -103,7 +103,7 @@ export abstract class TreeNodeValid<TInput> extends TreeNode {
103
103
  // would not see the stored `constructorCached`, and the validation above against multiple derived classes would not work.
104
104
 
105
105
  // This is not just an alias of `this`, but a reference to the item in the prototype chain being walked, which happens to start at `this`.
106
- // eslint-disable-next-line @typescript-eslint/no-this-alias
106
+ // eslint-disable-next-line @typescript-eslint/no-this-alias, unicorn/no-this-assignment
107
107
  let schemaBase: typeof TreeNodeValid = this;
108
108
  while (!Object.prototype.hasOwnProperty.call(schemaBase, "constructorCached")) {
109
109
  schemaBase = Reflect.getPrototypeOf(schemaBase) as typeof TreeNodeValid;
@@ -300,7 +300,7 @@ function formattedReference(
300
300
  object: unknown,
301
301
  config?: DevtoolsFormatter.ObjectConfig,
302
302
  ): DevtoolsFormatter.Item {
303
- if (typeof object === "undefined") {
303
+ if (object === undefined) {
304
304
  return ["span", "undefined"];
305
305
  } else if (object === "null") {
306
306
  return ["span", "null"];
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import { oob } from "@fluidframework/core-utils/internal";
7
+
7
8
  import type { MapGetSet } from "./utils.js";
8
9
 
9
10
  /**