@fluidframework/tree 2.70.0-360374 → 2.70.0-361092

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 (200) hide show
  1. package/.eslintrc.cjs +1 -0
  2. package/api-report/tree.alpha.api.md +31 -27
  3. package/api-report/tree.beta.api.md +36 -1
  4. package/api-report/tree.legacy.beta.api.md +36 -1
  5. package/dist/alpha.d.ts +4 -4
  6. package/dist/beta.d.ts +4 -0
  7. package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts +2 -2
  8. package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts.map +1 -1
  9. package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.js +9 -10
  10. package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.js.map +1 -1
  11. package/dist/feature-libraries/chunked-forest/codec/codecs.d.ts +5 -4
  12. package/dist/feature-libraries/chunked-forest/codec/codecs.d.ts.map +1 -1
  13. package/dist/feature-libraries/chunked-forest/codec/codecs.js.map +1 -1
  14. package/dist/feature-libraries/chunked-forest/codec/schemaBasedEncode.d.ts +0 -1
  15. package/dist/feature-libraries/chunked-forest/codec/schemaBasedEncode.d.ts.map +1 -1
  16. package/dist/feature-libraries/chunked-forest/codec/schemaBasedEncode.js +3 -14
  17. package/dist/feature-libraries/chunked-forest/codec/schemaBasedEncode.js.map +1 -1
  18. package/dist/feature-libraries/forest-summary/forestSummarizer.d.ts +1 -1
  19. package/dist/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
  20. package/dist/feature-libraries/forest-summary/forestSummarizer.js +2 -2
  21. package/dist/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
  22. package/dist/feature-libraries/forest-summary/incrementalSummaryBuilder.d.ts +9 -7
  23. package/dist/feature-libraries/forest-summary/incrementalSummaryBuilder.d.ts.map +1 -1
  24. package/dist/feature-libraries/forest-summary/incrementalSummaryBuilder.js +34 -11
  25. package/dist/feature-libraries/forest-summary/incrementalSummaryBuilder.js.map +1 -1
  26. package/dist/legacy.d.ts +4 -0
  27. package/dist/packageVersion.d.ts +1 -1
  28. package/dist/packageVersion.js +1 -1
  29. package/dist/packageVersion.js.map +1 -1
  30. package/dist/serializableDomainSchema.d.ts +12 -10
  31. package/dist/serializableDomainSchema.d.ts.map +1 -1
  32. package/dist/serializableDomainSchema.js +7 -7
  33. package/dist/serializableDomainSchema.js.map +1 -1
  34. package/dist/shared-tree/sharedTree.d.ts +1 -1
  35. package/dist/shared-tree/sharedTree.d.ts.map +1 -1
  36. package/dist/shared-tree/sharedTree.js +2 -2
  37. package/dist/shared-tree/sharedTree.js.map +1 -1
  38. package/dist/simple-tree/api/schemaFactory.d.ts +1 -1
  39. package/dist/simple-tree/api/schemaFactory.d.ts.map +1 -1
  40. package/dist/simple-tree/api/schemaFactory.js +17 -13
  41. package/dist/simple-tree/api/schemaFactory.js.map +1 -1
  42. package/dist/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -1
  43. package/dist/simple-tree/api/schemaFactoryAlpha.js +8 -8
  44. package/dist/simple-tree/api/schemaFactoryAlpha.js.map +1 -1
  45. package/dist/simple-tree/api/schemaFactoryBeta.d.ts +2 -1
  46. package/dist/simple-tree/api/schemaFactoryBeta.d.ts.map +1 -1
  47. package/dist/simple-tree/api/schemaFactoryBeta.js +8 -7
  48. package/dist/simple-tree/api/schemaFactoryBeta.js.map +1 -1
  49. package/dist/simple-tree/api/schemaFactoryRecursive.d.ts +1 -1
  50. package/dist/simple-tree/api/schemaFactoryRecursive.js.map +1 -1
  51. package/dist/simple-tree/core/allowedTypes.d.ts +6 -2
  52. package/dist/simple-tree/core/allowedTypes.d.ts.map +1 -1
  53. package/dist/simple-tree/core/allowedTypes.js +2 -2
  54. package/dist/simple-tree/core/allowedTypes.js.map +1 -1
  55. package/dist/simple-tree/node-kinds/array/arrayNode.d.ts +3 -4
  56. package/dist/simple-tree/node-kinds/array/arrayNode.d.ts.map +1 -1
  57. package/dist/simple-tree/node-kinds/array/arrayNode.js +3 -2
  58. package/dist/simple-tree/node-kinds/array/arrayNode.js.map +1 -1
  59. package/dist/simple-tree/node-kinds/map/mapNode.d.ts +4 -3
  60. package/dist/simple-tree/node-kinds/map/mapNode.d.ts.map +1 -1
  61. package/dist/simple-tree/node-kinds/map/mapNode.js +3 -2
  62. package/dist/simple-tree/node-kinds/map/mapNode.js.map +1 -1
  63. package/dist/simple-tree/node-kinds/object/objectNode.d.ts +4 -3
  64. package/dist/simple-tree/node-kinds/object/objectNode.d.ts.map +1 -1
  65. package/dist/simple-tree/node-kinds/object/objectNode.js +5 -5
  66. package/dist/simple-tree/node-kinds/object/objectNode.js.map +1 -1
  67. package/dist/simple-tree/node-kinds/record/recordNode.d.ts +3 -10
  68. package/dist/simple-tree/node-kinds/record/recordNode.d.ts.map +1 -1
  69. package/dist/simple-tree/node-kinds/record/recordNode.js +3 -2
  70. package/dist/simple-tree/node-kinds/record/recordNode.js.map +1 -1
  71. package/dist/simple-tree/node-kinds/record/recordNodeTypes.d.ts +2 -2
  72. package/dist/simple-tree/node-kinds/record/recordNodeTypes.d.ts.map +1 -1
  73. package/dist/simple-tree/node-kinds/record/recordNodeTypes.js.map +1 -1
  74. package/dist/tableSchema.d.ts +37 -24
  75. package/dist/tableSchema.d.ts.map +1 -1
  76. package/dist/tableSchema.js +81 -54
  77. package/dist/tableSchema.js.map +1 -1
  78. package/dist/treeFactory.d.ts.map +1 -1
  79. package/dist/treeFactory.js +1 -1
  80. package/dist/treeFactory.js.map +1 -1
  81. package/dist/util/breakable.js +3 -3
  82. package/dist/util/breakable.js.map +1 -1
  83. package/dist/util/index.d.ts +1 -1
  84. package/dist/util/index.d.ts.map +1 -1
  85. package/dist/util/index.js +2 -2
  86. package/dist/util/index.js.map +1 -1
  87. package/dist/util/utils.d.ts +18 -6
  88. package/dist/util/utils.d.ts.map +1 -1
  89. package/dist/util/utils.js +23 -16
  90. package/dist/util/utils.js.map +1 -1
  91. package/lib/alpha.d.ts +4 -4
  92. package/lib/beta.d.ts +4 -0
  93. package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts +2 -2
  94. package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts.map +1 -1
  95. package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.js +9 -10
  96. package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.js.map +1 -1
  97. package/lib/feature-libraries/chunked-forest/codec/codecs.d.ts +5 -4
  98. package/lib/feature-libraries/chunked-forest/codec/codecs.d.ts.map +1 -1
  99. package/lib/feature-libraries/chunked-forest/codec/codecs.js.map +1 -1
  100. package/lib/feature-libraries/chunked-forest/codec/schemaBasedEncode.d.ts +0 -1
  101. package/lib/feature-libraries/chunked-forest/codec/schemaBasedEncode.d.ts.map +1 -1
  102. package/lib/feature-libraries/chunked-forest/codec/schemaBasedEncode.js +2 -12
  103. package/lib/feature-libraries/chunked-forest/codec/schemaBasedEncode.js.map +1 -1
  104. package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts +1 -1
  105. package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
  106. package/lib/feature-libraries/forest-summary/forestSummarizer.js +2 -2
  107. package/lib/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
  108. package/lib/feature-libraries/forest-summary/incrementalSummaryBuilder.d.ts +9 -7
  109. package/lib/feature-libraries/forest-summary/incrementalSummaryBuilder.d.ts.map +1 -1
  110. package/lib/feature-libraries/forest-summary/incrementalSummaryBuilder.js +34 -11
  111. package/lib/feature-libraries/forest-summary/incrementalSummaryBuilder.js.map +1 -1
  112. package/lib/legacy.d.ts +4 -0
  113. package/lib/packageVersion.d.ts +1 -1
  114. package/lib/packageVersion.js +1 -1
  115. package/lib/packageVersion.js.map +1 -1
  116. package/lib/serializableDomainSchema.d.ts +12 -10
  117. package/lib/serializableDomainSchema.d.ts.map +1 -1
  118. package/lib/serializableDomainSchema.js +8 -8
  119. package/lib/serializableDomainSchema.js.map +1 -1
  120. package/lib/shared-tree/sharedTree.d.ts +1 -1
  121. package/lib/shared-tree/sharedTree.d.ts.map +1 -1
  122. package/lib/shared-tree/sharedTree.js +2 -2
  123. package/lib/shared-tree/sharedTree.js.map +1 -1
  124. package/lib/simple-tree/api/schemaFactory.d.ts +1 -1
  125. package/lib/simple-tree/api/schemaFactory.d.ts.map +1 -1
  126. package/lib/simple-tree/api/schemaFactory.js +18 -14
  127. package/lib/simple-tree/api/schemaFactory.js.map +1 -1
  128. package/lib/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -1
  129. package/lib/simple-tree/api/schemaFactoryAlpha.js +8 -8
  130. package/lib/simple-tree/api/schemaFactoryAlpha.js.map +1 -1
  131. package/lib/simple-tree/api/schemaFactoryBeta.d.ts +2 -1
  132. package/lib/simple-tree/api/schemaFactoryBeta.d.ts.map +1 -1
  133. package/lib/simple-tree/api/schemaFactoryBeta.js +8 -7
  134. package/lib/simple-tree/api/schemaFactoryBeta.js.map +1 -1
  135. package/lib/simple-tree/api/schemaFactoryRecursive.d.ts +1 -1
  136. package/lib/simple-tree/api/schemaFactoryRecursive.js.map +1 -1
  137. package/lib/simple-tree/core/allowedTypes.d.ts +6 -2
  138. package/lib/simple-tree/core/allowedTypes.d.ts.map +1 -1
  139. package/lib/simple-tree/core/allowedTypes.js +2 -2
  140. package/lib/simple-tree/core/allowedTypes.js.map +1 -1
  141. package/lib/simple-tree/node-kinds/array/arrayNode.d.ts +3 -4
  142. package/lib/simple-tree/node-kinds/array/arrayNode.d.ts.map +1 -1
  143. package/lib/simple-tree/node-kinds/array/arrayNode.js +3 -2
  144. package/lib/simple-tree/node-kinds/array/arrayNode.js.map +1 -1
  145. package/lib/simple-tree/node-kinds/map/mapNode.d.ts +4 -3
  146. package/lib/simple-tree/node-kinds/map/mapNode.d.ts.map +1 -1
  147. package/lib/simple-tree/node-kinds/map/mapNode.js +3 -2
  148. package/lib/simple-tree/node-kinds/map/mapNode.js.map +1 -1
  149. package/lib/simple-tree/node-kinds/object/objectNode.d.ts +4 -3
  150. package/lib/simple-tree/node-kinds/object/objectNode.d.ts.map +1 -1
  151. package/lib/simple-tree/node-kinds/object/objectNode.js +5 -5
  152. package/lib/simple-tree/node-kinds/object/objectNode.js.map +1 -1
  153. package/lib/simple-tree/node-kinds/record/recordNode.d.ts +3 -10
  154. package/lib/simple-tree/node-kinds/record/recordNode.d.ts.map +1 -1
  155. package/lib/simple-tree/node-kinds/record/recordNode.js +3 -2
  156. package/lib/simple-tree/node-kinds/record/recordNode.js.map +1 -1
  157. package/lib/simple-tree/node-kinds/record/recordNodeTypes.d.ts +2 -2
  158. package/lib/simple-tree/node-kinds/record/recordNodeTypes.d.ts.map +1 -1
  159. package/lib/simple-tree/node-kinds/record/recordNodeTypes.js.map +1 -1
  160. package/lib/tableSchema.d.ts +37 -24
  161. package/lib/tableSchema.d.ts.map +1 -1
  162. package/lib/tableSchema.js +81 -54
  163. package/lib/tableSchema.js.map +1 -1
  164. package/lib/treeFactory.d.ts.map +1 -1
  165. package/lib/treeFactory.js +1 -1
  166. package/lib/treeFactory.js.map +1 -1
  167. package/lib/util/breakable.js +3 -3
  168. package/lib/util/breakable.js.map +1 -1
  169. package/lib/util/index.d.ts +1 -1
  170. package/lib/util/index.d.ts.map +1 -1
  171. package/lib/util/index.js +1 -1
  172. package/lib/util/index.js.map +1 -1
  173. package/lib/util/utils.d.ts +18 -6
  174. package/lib/util/utils.d.ts.map +1 -1
  175. package/lib/util/utils.js +21 -14
  176. package/lib/util/utils.js.map +1 -1
  177. package/package.json +24 -24
  178. package/src/feature-libraries/chunked-forest/codec/chunkDecoding.ts +16 -14
  179. package/src/feature-libraries/chunked-forest/codec/codecs.ts +8 -4
  180. package/src/feature-libraries/chunked-forest/codec/schemaBasedEncode.ts +2 -13
  181. package/src/feature-libraries/forest-summary/forestSummarizer.ts +2 -0
  182. package/src/feature-libraries/forest-summary/incrementalSummaryBuilder.ts +65 -13
  183. package/src/packageVersion.ts +1 -1
  184. package/src/serializableDomainSchema.ts +11 -11
  185. package/src/shared-tree/sharedTree.ts +2 -0
  186. package/src/simple-tree/api/schemaFactory.ts +38 -22
  187. package/src/simple-tree/api/schemaFactoryAlpha.ts +8 -17
  188. package/src/simple-tree/api/schemaFactoryBeta.ts +17 -23
  189. package/src/simple-tree/api/schemaFactoryRecursive.ts +1 -1
  190. package/src/simple-tree/core/allowedTypes.ts +5 -17
  191. package/src/simple-tree/node-kinds/array/arrayNode.ts +5 -4
  192. package/src/simple-tree/node-kinds/map/mapNode.ts +5 -3
  193. package/src/simple-tree/node-kinds/object/objectNode.ts +9 -8
  194. package/src/simple-tree/node-kinds/record/recordNode.ts +6 -18
  195. package/src/simple-tree/node-kinds/record/recordNodeTypes.ts +2 -2
  196. package/src/tableSchema.ts +143 -81
  197. package/src/treeFactory.ts +1 -0
  198. package/src/util/breakable.ts +4 -4
  199. package/src/util/index.ts +1 -1
  200. package/src/util/utils.ts +33 -17
@@ -58,6 +58,31 @@ export const ForestSummaryTrackingState = {
58
58
  export type ForestSummaryTrackingState =
59
59
  (typeof ForestSummaryTrackingState)[keyof typeof ForestSummaryTrackingState];
60
60
 
61
+ /**
62
+ * The properties of a chunk tracked during the loading process.
63
+ * These are used to identify a chunk when it is decoded and recreate the tracking state
64
+ * as it was when the summary that the client is loading from was generated.
65
+ *
66
+ * An encoded chunk, paired with a location it can be reused / reloaded from.
67
+ * @remarks
68
+ * This identifies a location in a specific summary where `encodedContents` was loaded from.
69
+ *
70
+ * When summarizing, Fluid always ensures the summary that the summary client is allowed to reuse content from
71
+ * is the one it loaded from, so tracking this on load is sufficient for now:
72
+ * there is no need to track the equivalent data when summarizing.
73
+ */
74
+ interface ChunkLoadProperties {
75
+ /**
76
+ * The encoded contents of the chunk.
77
+ */
78
+ readonly encodedContents: EncodedFieldBatch;
79
+ /**
80
+ * The path for this chunk's contents in the summary tree relative to the forest's summary tree.
81
+ * This path is used to generate a summary handle for the chunk if it doesn't change between summaries.
82
+ */
83
+ readonly summaryPath: string;
84
+ }
85
+
61
86
  /**
62
87
  * The properties of a chunk that is tracked for every summary.
63
88
  * If a chunk doesn't change between summaries,
@@ -255,12 +280,17 @@ export class ForestIncrementalSummaryBuilder implements IncrementalEncoderDecode
255
280
  * A map of chunk reference IDs to their encoded contents. This is typically used during the loading of the
256
281
  * forest to retrieve the contents of the chunks that were summarized incrementally.
257
282
  */
258
- private readonly encodedChunkContentsMap: Map<string, EncodedFieldBatch> = new Map();
283
+ /**
284
+ * A map of chunk reference IDs to their {@link ChunkLoadProperties}.
285
+ * This is used during the loading of the forest to track each chunk that is retrieved and decoded.
286
+ */
287
+ private readonly loadedChunksMap: Map<string, ChunkLoadProperties> = new Map();
259
288
 
260
289
  public constructor(
261
290
  private readonly enableIncrementalSummary: boolean,
262
291
  private readonly getChunkAtCursor: (cursor: ITreeCursorSynchronous) => TreeChunk,
263
292
  public readonly shouldEncodeIncrementally: IncrementalEncodingPolicy,
293
+ private readonly initialSequenceNumber: number,
264
294
  ) {}
265
295
 
266
296
  /**
@@ -297,7 +327,15 @@ export class ForestIncrementalSummaryBuilder implements IncrementalEncoderDecode
297
327
  );
298
328
  }
299
329
  const chunkContents = await readAndParseChunk<EncodedFieldBatch>(chunkContentsPath);
300
- this.encodedChunkContentsMap.set(chunkReferenceId, chunkContents);
330
+ this.loadedChunksMap.set(chunkReferenceId, {
331
+ encodedContents: chunkContents,
332
+ summaryPath: chunkSubTreePath,
333
+ });
334
+
335
+ const chunkReferenceIdNumber = Number(chunkReferenceId);
336
+ this.nextReferenceId = brand(
337
+ Math.max(this.nextReferenceId, chunkReferenceIdNumber + 1),
338
+ );
301
339
 
302
340
  // Recursively download the contents of chunks in this chunk's sub tree.
303
341
  await downloadChunkContentsInTree(chunkSnapshotTree, `${chunkSubTreePath}/`);
@@ -361,6 +399,10 @@ export class ForestIncrementalSummaryBuilder implements IncrementalEncoderDecode
361
399
  let chunkReferenceId: ChunkReferenceId;
362
400
  let chunkProperties: ChunkSummaryProperties;
363
401
 
402
+ // An additional ref-count must be added to these chunks representing a reference from the summary tree to the chunk.
403
+ // This will ensure that the blob's content never change and thus the reference stays accurate: instead of modifying it,
404
+ // a copy will be created without the blob reference.
405
+ // The "getChunkAtCursor" adds this additional ref-count.
364
406
  const chunk = this.getChunkAtCursor(cursor);
365
407
 
366
408
  // Try and get the properties of the chunk from the latest successful summary.
@@ -486,17 +528,27 @@ export class ForestIncrementalSummaryBuilder implements IncrementalEncoderDecode
486
528
  }
487
529
 
488
530
  /**
489
- * Called to get the encoded contents of an incremental chunk with the given reference ID.
490
- * This is typically used when loading the forest to retrieve the contents of incremental chunks.
491
- * @param referenceId - The reference ID of the chunk to retrieve.
492
- * @returns The encoded contents of the chunk.
531
+ * {@link IncrementalEncoder.decodeIncrementalChunk}
493
532
  */
494
- public getEncodedIncrementalChunk(referenceId: ChunkReferenceId): EncodedFieldBatch {
495
- const chunkEncodedContents = this.encodedChunkContentsMap.get(`${referenceId}`);
496
- assert(
497
- chunkEncodedContents !== undefined,
498
- 0xc26 /* Incremental chunk contents not found */,
499
- );
500
- return chunkEncodedContents;
533
+ public decodeIncrementalChunk(
534
+ referenceId: ChunkReferenceId,
535
+ chunkDecoder: (encoded: EncodedFieldBatch) => TreeChunk,
536
+ ): TreeChunk {
537
+ const ChunkLoadProperties = this.loadedChunksMap.get(`${referenceId}`);
538
+ assert(ChunkLoadProperties !== undefined, "Encoded incremental chunk not found");
539
+ const chunk = chunkDecoder(ChunkLoadProperties.encodedContents);
540
+
541
+ // Account for the reference about to be added in `chunkTrackingPropertiesMap`
542
+ // to ensure that no other users of this chunk think they have unique ownership.
543
+ // This prevents prevent whoever this chunk is returned to from modifying it in-place.
544
+ chunk.referenceAdded();
545
+ // Track the decoded chunk. This will recreate the tracking state when the summary that this client
546
+ // is loaded from was generated. This is needed to ensure that incremental summaries work correctly
547
+ // when a new client starts to summarize.
548
+ setInNestedMap(this.chunkTrackingPropertiesMap, this.initialSequenceNumber, chunk, {
549
+ referenceId,
550
+ summaryPath: ChunkLoadProperties.summaryPath,
551
+ });
552
+ return chunk;
501
553
  }
502
554
  }
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/tree";
9
- export const pkgVersion = "2.70.0-360374";
9
+ export const pkgVersion = "2.70.0-361092";
@@ -7,14 +7,14 @@ import type { IFluidHandle } from "@fluidframework/core-interfaces";
7
7
 
8
8
  import {
9
9
  SchemaFactory,
10
- SchemaFactoryAlpha,
10
+ SchemaFactoryBeta,
11
11
  type FixRecursiveArraySchema,
12
12
  type TreeNodeFromImplicitAllowedTypes,
13
13
  type ValidateRecursiveSchema,
14
14
  } from "./simple-tree/index.js";
15
15
  import type { JsonCompatible } from "./util/index.js";
16
16
 
17
- const sf = new SchemaFactoryAlpha("com.fluidframework.serializable");
17
+ const sf = new SchemaFactoryBeta("com.fluidframework.serializable");
18
18
 
19
19
  /**
20
20
  * Utilities for storing {@link FluidSerializableAsTree.Data|Fluid Serializable data} in {@link TreeNode}s.
@@ -24,14 +24,14 @@ const sf = new SchemaFactoryAlpha("com.fluidframework.serializable");
24
24
  * Schema which replicate the Fluid Serializable data model with {@link TreeNode}s.
25
25
  *
26
26
  * Fluid Serializable data can be imported from the {@link FluidSerializableAsTree.Data|Fluid Serializable format} into this format using {@link (TreeBeta:interface).importConcise} with the {@link FluidSerializableAsTree.(Tree:variable)} schema.
27
- * @alpha
27
+ * @beta
28
28
  */
29
29
  export namespace FluidSerializableAsTree {
30
30
  /**
31
31
  * Data which can be serialized by Fluid.
32
32
  * @remarks
33
33
  * Can be encoded as a {@link FluidSerializableAsTree.(Tree:type)} using {@link (TreeBeta:interface).importConcise}.
34
- * @alpha
34
+ * @beta
35
35
  */
36
36
  export type Data = JsonCompatible<IFluidHandle>;
37
37
 
@@ -41,7 +41,7 @@ export namespace FluidSerializableAsTree {
41
41
  * ```typescript
42
42
  * const tree = TreeBeta.importConcise(FluidSerializableAsTree.Tree, { example: { nested: true }, value: 5 });
43
43
  * ```
44
- * @alpha
44
+ * @beta
45
45
  */
46
46
  export const Tree = [
47
47
  () => FluidSerializableObject,
@@ -50,13 +50,13 @@ export namespace FluidSerializableAsTree {
50
50
  ] as const;
51
51
 
52
52
  /**
53
- * @alpha
53
+ * @beta
54
54
  */
55
55
  export type Tree = TreeNodeFromImplicitAllowedTypes<typeof Tree>;
56
56
 
57
57
  /**
58
58
  * Do not use. Exists only as a workaround for {@link https://github.com/microsoft/TypeScript/issues/59550} and {@link https://github.com/microsoft/rushstack/issues/4429}.
59
- * @system @alpha
59
+ * @system @beta
60
60
  */
61
61
  export const _APIExtractorWorkaroundObjectBase = sf.recordRecursive("object", Tree);
62
62
 
@@ -75,7 +75,7 @@ export namespace FluidSerializableAsTree {
75
75
  * ```
76
76
  * @privateRemarks
77
77
  * Due to https://github.com/microsoft/TypeScript/issues/61270 this can't be named `Object`.
78
- * @sealed @alpha
78
+ * @sealed @beta
79
79
  */
80
80
  export class FluidSerializableObject extends _APIExtractorWorkaroundObjectBase {}
81
81
  {
@@ -87,7 +87,7 @@ export namespace FluidSerializableAsTree {
87
87
  * @privateRemarks
88
88
  * In the past this this had to reference the base type (_APIExtractorWorkaroundArrayBase).
89
89
  * Testing for this in examples/utils/import-testing now shows it has to reference FluidSerializableAsTree.Array instead.
90
- * @system @alpha
90
+ * @system @beta
91
91
  */
92
92
  export declare type _RecursiveArrayWorkaroundJsonArray = FixRecursiveArraySchema<
93
93
  typeof Array
@@ -95,7 +95,7 @@ export namespace FluidSerializableAsTree {
95
95
 
96
96
  /**
97
97
  * Do not use. Exists only as a workaround for {@link https://github.com/microsoft/TypeScript/issues/59550} and {@link https://github.com/microsoft/rushstack/issues/4429}.
98
- * @system @alpha
98
+ * @system @beta
99
99
  */
100
100
  export const _APIExtractorWorkaroundArrayBase = sf.arrayRecursive("array", Tree);
101
101
 
@@ -114,7 +114,7 @@ export namespace FluidSerializableAsTree {
114
114
  * assert(Tree.is(inner, FluidSerializableAsTree.Array));
115
115
  * const leaf = inner[0];
116
116
  * ```
117
- * @sealed @alpha
117
+ * @sealed @beta
118
118
  */
119
119
  export class Array extends _APIExtractorWorkaroundArrayBase {}
120
120
  {
@@ -299,6 +299,7 @@ export class SharedTreeKernel
299
299
  serializer: IFluidSerializer,
300
300
  submitLocalMessage: (content: unknown, localOpMetadata?: unknown) => void,
301
301
  lastSequenceNumber: () => number | undefined,
302
+ initialSequenceNumber: number,
302
303
  private readonly logger: ITelemetryLoggerExt | undefined,
303
304
  idCompressor: IIdCompressor,
304
305
  optionsParam: SharedTreeOptionsInternal,
@@ -346,6 +347,7 @@ export class SharedTreeKernel
346
347
  encoderContext,
347
348
  options,
348
349
  idCompressor,
350
+ initialSequenceNumber,
349
351
  options.shouldEncodeIncrementally,
350
352
  );
351
353
  const removedRootsSummarizer = new DetachedFieldIndexSummarizer(removedRoots);
@@ -3,7 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { assert, unreachableCase } from "@fluidframework/core-utils/internal";
6
+ import { assert, debugAssert, unreachableCase } from "@fluidframework/core-utils/internal";
7
7
  import { isFluidHandle } from "@fluidframework/runtime-utils/internal";
8
8
  import { UsageError } from "@fluidframework/telemetry-utils/internal";
9
9
 
@@ -164,7 +164,7 @@ export interface ObjectSchemaOptionsAlpha<TCustomMetadata = unknown>
164
164
  * @remarks Omits parameters that are not relevant for common use cases.
165
165
  */
166
166
  export const defaultSchemaFactoryObjectOptions: Required<
167
- Omit<ObjectSchemaOptionsAlpha, "metadata" | "persistedMetadata">
167
+ Pick<ObjectSchemaOptions, "allowUnknownOptionalFields">
168
168
  > = {
169
169
  allowUnknownOptionalFields: false,
170
170
  };
@@ -397,12 +397,9 @@ export class SchemaFactory<
397
397
  true,
398
398
  T
399
399
  > {
400
- return objectSchema(
401
- scoped(this, name),
402
- fields,
403
- true,
404
- defaultSchemaFactoryObjectOptions.allowUnknownOptionalFields,
405
- );
400
+ return objectSchema(scoped(this, name), fields, true, {
401
+ ...defaultSchemaFactoryObjectOptions,
402
+ });
406
403
  }
407
404
 
408
405
  /**
@@ -474,15 +471,17 @@ export class SchemaFactory<
474
471
  * This seems like a TypeScript bug getting variance backwards for overload return types since it's erroring when the relation between the overload
475
472
  * and the implementation is type safe, and forcing an unsafe typing instead.
476
473
  */
477
- public map<const T extends ImplicitAllowedTypes>(
474
+ public map<const T extends ImplicitAllowedTypes, const TCustomMetadata = unknown>(
478
475
  nameOrAllowedTypes: TName | ((T & TreeNodeSchema) | readonly TreeNodeSchema[]),
479
476
  allowedTypes?: T,
477
+ options?: NodeSchemaOptions<TCustomMetadata>,
480
478
  ): TreeNodeSchema<string, NodeKind.Map, TreeMapNode<T>, MapNodeInsertableData<T>, true, T> {
481
479
  if (allowedTypes === undefined) {
482
480
  const types = nameOrAllowedTypes as (T & TreeNodeSchema) | readonly TreeNodeSchema[];
483
481
  const fullName = structuralName("Map", types);
482
+ debugAssert(() => options === undefined || "No options for structural types");
484
483
  return this.getStructuralType(fullName, types, () =>
485
- this.namedMap(fullName, nameOrAllowedTypes as T, false, true),
484
+ this.namedMap(fullName, nameOrAllowedTypes as T, false, true, {}),
486
485
  ) as TreeNodeSchemaBoth<
487
486
  string,
488
487
  NodeKind.Map,
@@ -490,7 +489,8 @@ export class SchemaFactory<
490
489
  MapNodeInsertableData<T>,
491
490
  true,
492
491
  T,
493
- undefined
492
+ undefined,
493
+ TCustomMetadata
494
494
  >;
495
495
  }
496
496
  // To actually have type safety, assign to the type this method should return before implicitly up-casting when returning.
@@ -501,8 +501,9 @@ export class SchemaFactory<
501
501
  MapNodeInsertableData<T>,
502
502
  true,
503
503
  T,
504
- undefined
505
- > = this.namedMap(nameOrAllowedTypes as TName, allowedTypes, true, true);
504
+ undefined,
505
+ TCustomMetadata
506
+ > = this.namedMap(nameOrAllowedTypes as TName, allowedTypes, true, true, options ?? {});
506
507
  return out;
507
508
  }
508
509
 
@@ -515,11 +516,13 @@ export class SchemaFactory<
515
516
  Name extends TName | string,
516
517
  const T extends ImplicitAllowedTypes,
517
518
  const ImplicitlyConstructable extends boolean,
519
+ const TCustomMetadata = unknown,
518
520
  >(
519
521
  name: Name,
520
522
  allowedTypes: T,
521
523
  customizable: boolean,
522
524
  implicitlyConstructable: ImplicitlyConstructable,
525
+ options: NodeSchemaOptionsAlpha<TCustomMetadata>,
523
526
  ): TreeNodeSchemaBoth<
524
527
  ScopedSchemaName<TScope, Name>,
525
528
  NodeKind.Map,
@@ -527,7 +530,8 @@ export class SchemaFactory<
527
530
  MapNodeInsertableData<T>,
528
531
  ImplicitlyConstructable,
529
532
  T,
530
- undefined
533
+ undefined,
534
+ TCustomMetadata
531
535
  > {
532
536
  return mapSchema(
533
537
  scoped(this, name),
@@ -535,7 +539,7 @@ export class SchemaFactory<
535
539
  implicitlyConstructable,
536
540
  // The current policy is customizable nodes don't get fake prototypes.
537
541
  !customizable,
538
- undefined,
542
+ options ?? {},
539
543
  );
540
544
  }
541
545
 
@@ -618,22 +622,25 @@ export class SchemaFactory<
618
622
  * @privateRemarks
619
623
  * This should return TreeNodeSchemaBoth: see note on "map" implementation for details.
620
624
  */
621
- public array<const T extends ImplicitAllowedTypes>(
625
+ public array<const T extends ImplicitAllowedTypes, const TCustomMetadata = unknown>(
622
626
  nameOrAllowedTypes: TName | ((T & TreeNodeSchema) | readonly TreeNodeSchema[]),
623
627
  allowedTypes?: T,
628
+ options?: NodeSchemaOptions<TCustomMetadata>,
624
629
  ): TreeNodeSchema<
625
630
  ScopedSchemaName<TScope, string>,
626
631
  NodeKind.Array,
627
632
  TreeArrayNode<T>,
628
633
  Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>,
629
634
  true,
630
- T
635
+ T,
636
+ TCustomMetadata
631
637
  > {
632
638
  if (allowedTypes === undefined) {
633
639
  const types = nameOrAllowedTypes as (T & TreeNodeSchema) | readonly TreeNodeSchema[];
634
640
  const fullName = structuralName("Array", types);
641
+ debugAssert(() => options === undefined || "No options for structural types");
635
642
  return this.getStructuralType(fullName, types, () =>
636
- this.namedArray(fullName, nameOrAllowedTypes as T, false, true),
643
+ this.namedArray(fullName, nameOrAllowedTypes as T, false, true, {}),
637
644
  ) as TreeNodeSchemaClass<
638
645
  ScopedSchemaName<TScope, string>,
639
646
  NodeKind.Array,
@@ -641,9 +648,11 @@ export class SchemaFactory<
641
648
  Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>,
642
649
  true,
643
650
  T,
644
- undefined
651
+ undefined,
652
+ TCustomMetadata
645
653
  >;
646
654
  }
655
+
647
656
  const out: TreeNodeSchemaBoth<
648
657
  ScopedSchemaName<TScope, string>,
649
658
  NodeKind.Array,
@@ -651,8 +660,9 @@ export class SchemaFactory<
651
660
  Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>,
652
661
  true,
653
662
  T,
654
- undefined
655
- > = this.namedArray(nameOrAllowedTypes as TName, allowedTypes, true, true);
663
+ undefined,
664
+ TCustomMetadata
665
+ > = this.namedArray(nameOrAllowedTypes as TName, allowedTypes, true, true, options ?? {});
656
666
  return out;
657
667
  }
658
668
 
@@ -698,11 +708,13 @@ export class SchemaFactory<
698
708
  Name extends TName | string,
699
709
  const T extends ImplicitAllowedTypes,
700
710
  const ImplicitlyConstructable extends boolean,
711
+ const TCustomMetadata = unknown,
701
712
  >(
702
713
  name: Name,
703
714
  allowedTypes: T,
704
715
  customizable: boolean,
705
716
  implicitlyConstructable: ImplicitlyConstructable,
717
+ options: NodeSchemaOptionsAlpha<TCustomMetadata>,
706
718
  ): TreeNodeSchemaBoth<
707
719
  ScopedSchemaName<TScope, Name>,
708
720
  NodeKind.Array,
@@ -710,13 +722,15 @@ export class SchemaFactory<
710
722
  Iterable<InsertableTreeNodeFromImplicitAllowedTypes<T>>,
711
723
  ImplicitlyConstructable,
712
724
  T,
713
- undefined
725
+ undefined,
726
+ TCustomMetadata
714
727
  > {
715
728
  return arraySchema(
716
729
  scoped(this, name),
717
730
  allowedTypes,
718
731
  implicitlyConstructable,
719
732
  customizable,
733
+ options,
720
734
  );
721
735
  }
722
736
 
@@ -822,6 +836,7 @@ export class SchemaFactory<
822
836
  allowedTypes as T & ImplicitAllowedTypes,
823
837
  true,
824
838
  false,
839
+ {},
825
840
  );
826
841
 
827
842
  return RecursiveArray as TreeNodeSchemaClass<
@@ -870,6 +885,7 @@ export class SchemaFactory<
870
885
  // Setting this (implicitlyConstructable) to true seems to work ok currently, but not for other node kinds.
871
886
  // Supporting this could be fragile and might break other future changes, so it's being kept as false for now.
872
887
  false,
888
+ {},
873
889
  );
874
890
 
875
891
  return MapSchema as TreeNodeSchemaClass<
@@ -218,15 +218,10 @@ export class SchemaFactoryAlpha<
218
218
  */
219
219
  readonly createFromInsertable: unknown;
220
220
  } {
221
- return objectSchema(
222
- scoped<TScope, TName, Name>(this, name),
223
- fields,
224
- true,
225
- options?.allowUnknownOptionalFields ??
226
- defaultSchemaFactoryObjectOptions.allowUnknownOptionalFields,
227
- options?.metadata,
228
- options?.persistedMetadata,
229
- );
221
+ return objectSchema(scoped<TScope, TName, Name>(this, name), fields, true, {
222
+ ...defaultSchemaFactoryObjectOptions,
223
+ ...(options ?? {}),
224
+ });
230
225
  }
231
226
 
232
227
  /**
@@ -408,8 +403,7 @@ export class SchemaFactoryAlpha<
408
403
  allowedTypes,
409
404
  true,
410
405
  true,
411
- options?.metadata,
412
- options?.persistedMetadata,
406
+ options,
413
407
  );
414
408
  }
415
409
 
@@ -459,8 +453,7 @@ export class SchemaFactoryAlpha<
459
453
  allowedTypes,
460
454
  true,
461
455
  true,
462
- options?.metadata,
463
- options?.persistedMetadata,
456
+ options ?? {},
464
457
  );
465
458
  }
466
459
 
@@ -510,8 +503,7 @@ export class SchemaFactoryAlpha<
510
503
  info: allowedTypes,
511
504
  customizable: true,
512
505
  implicitlyConstructable: true,
513
- metadata: options?.metadata,
514
- persistedMetadata: options?.persistedMetadata,
506
+ nodeOptions: options,
515
507
  });
516
508
  }
517
509
 
@@ -535,8 +527,7 @@ export class SchemaFactoryAlpha<
535
527
  // Setting this to true seems to work ok currently, but not for other node kinds.
536
528
  // Supporting this could be fragile and might break other future changes, so it's being kept as false for now.
537
529
  implicitlyConstructable: false,
538
- metadata: options?.metadata,
539
- persistedMetadata: options?.persistedMetadata,
530
+ nodeOptions: options,
540
531
  });
541
532
 
542
533
  return RecordSchema as TreeNodeSchemaClass<
@@ -90,14 +90,10 @@ export class SchemaFactoryBeta<
90
90
  true,
91
91
  T
92
92
  > {
93
- return objectSchema(
94
- scoped<TScope, TName, Name>(this, name),
95
- fields,
96
- true,
97
- options?.allowUnknownOptionalFields ??
98
- defaultSchemaFactoryObjectOptions.allowUnknownOptionalFields,
99
- options?.metadata,
100
- );
93
+ return objectSchema(scoped<TScope, TName, Name>(this, name), fields, true, {
94
+ ...defaultSchemaFactoryObjectOptions,
95
+ ...(options ?? {}),
96
+ });
101
97
  }
102
98
 
103
99
  public override objectRecursive<
@@ -192,6 +188,7 @@ export class SchemaFactoryBeta<
192
188
  *
193
189
  * @param name - Unique identifier for this schema within this factory's scope.
194
190
  * @param allowedTypes - The types that may appear in the record.
191
+ * @param options - Additional options for the schema.
195
192
  *
196
193
  * @remarks
197
194
  * The underlying data format for `Record` nodes is the same as that for `Map` nodes.
@@ -211,9 +208,14 @@ export class SchemaFactoryBeta<
211
208
  *
212
209
  * {@label NAMED}
213
210
  */
214
- public record<const Name extends TName, const T extends ImplicitAllowedTypes>(
211
+ public record<
212
+ const Name extends TName,
213
+ const T extends ImplicitAllowedTypes,
214
+ const TCustomMetadata = unknown,
215
+ >(
215
216
  name: Name,
216
217
  allowedTypes: T,
218
+ options?: NodeSchemaOptions<TCustomMetadata>,
217
219
  ): TreeNodeSchemaClass<
218
220
  /* Name */ ScopedSchemaName<TScope, Name>,
219
221
  /* Kind */ NodeKind.Record,
@@ -221,7 +223,8 @@ export class SchemaFactoryBeta<
221
223
  /* TInsertable */ RecordNodeInsertableData<T>,
222
224
  /* ImplicitlyConstructable */ true,
223
225
  /* Info */ T,
224
- /* TConstructorExtra */ undefined
226
+ /* TConstructorExtra */ undefined,
227
+ /* TCustomMetadata */ TCustomMetadata
225
228
  >;
226
229
 
227
230
  /**
@@ -233,6 +236,7 @@ export class SchemaFactoryBeta<
233
236
  public record<const T extends ImplicitAllowedTypes>(
234
237
  nameOrAllowedTypes: TName | ((T & TreeNodeSchema) | readonly TreeNodeSchema[]),
235
238
  maybeAllowedTypes?: T,
239
+ options?: NodeSchemaOptions,
236
240
  ): TreeNodeSchema<
237
241
  /* Name */ ScopedSchemaName<TScope, string>,
238
242
  /* Kind */ NodeKind.Record,
@@ -274,6 +278,7 @@ export class SchemaFactoryBeta<
274
278
  maybeAllowedTypes,
275
279
  /* customizable */ true,
276
280
  /* implicitlyConstructable */ true,
281
+ options,
277
282
  );
278
283
  return out;
279
284
  }
@@ -307,24 +312,13 @@ export class SchemaFactoryBeta<
307
312
  /* Info */ T,
308
313
  /* TConstructorExtra */ undefined
309
314
  > {
310
- const record = recordSchema({
315
+ return recordSchema({
311
316
  identifier: scoped<TScope, TName, Name>(this, name),
312
317
  info: allowedTypes,
313
318
  customizable,
314
319
  implicitlyConstructable,
315
- metadata: options?.metadata,
320
+ nodeOptions: options,
316
321
  });
317
-
318
- return record as TreeNodeSchemaBoth<
319
- /* Name */ ScopedSchemaName<TScope, Name>,
320
- /* Kind */ NodeKind.Record,
321
- /* TNode */ TreeRecordNode<T> &
322
- WithType<ScopedSchemaName<TScope, string>, NodeKind.Record>,
323
- /* TInsertable */ RecordNodeInsertableData<T>,
324
- /* ImplicitlyConstructable */ ImplicitlyConstructable,
325
- /* Info */ T,
326
- /* TConstructorExtra */ undefined
327
- >;
328
322
  }
329
323
 
330
324
  /**
@@ -283,6 +283,6 @@ export function allowUnused<T>(t?: T): void {}
283
283
  * }
284
284
  * ```
285
285
  *
286
- * @alpha
286
+ * @beta
287
287
  */
288
288
  export type FixRecursiveArraySchema<T> = T extends TreeNodeSchema ? undefined : undefined;
@@ -253,32 +253,20 @@ export class AnnotatedAllowedTypesInternal<
253
253
  return this.lazyEvaluate.value.identifiers;
254
254
  }
255
255
 
256
- public static override [Symbol.hasInstance]<
257
- TThis extends
258
- | (abstract new (
259
- ...args: unknown[]
260
- ) => object)
261
- | typeof AnnotatedAllowedTypesInternal,
262
- >(
256
+ public static override [Symbol.hasInstance]<TThis extends { prototype: object }>(
263
257
  this: TThis,
264
- value: ErasedBaseType | InstanceTypeRelaxed<TThis> | ImplicitAllowedTypes,
258
+ value: unknown,
265
259
  ): value is InstanceTypeRelaxed<TThis> & AnnotatedAllowedTypesInternal & AllowedTypesFull {
266
- return Object.prototype.isPrototypeOf.call(this.prototype, value);
260
+ return ErasedTypeImplementation[Symbol.hasInstance].call(this, value);
267
261
  }
268
262
 
269
- public static override narrow<
270
- TThis extends
271
- | (abstract new (
272
- ...args: unknown[]
273
- ) => object)
274
- | typeof AnnotatedAllowedTypesInternal,
275
- >(
263
+ public static override narrow<TThis extends { prototype: object }>(
276
264
  this: TThis,
277
265
  value: ErasedBaseType | InstanceTypeRelaxed<TThis> | ImplicitAllowedTypes,
278
266
  ): asserts value is InstanceTypeRelaxed<TThis> &
279
267
  AnnotatedAllowedTypesInternal &
280
268
  AllowedTypesFull {
281
- if (!Object.prototype.isPrototypeOf.call(this.prototype, value)) {
269
+ if (!ErasedTypeImplementation[Symbol.hasInstance].call(this, value)) {
282
270
  throw new TypeError("Invalid AnnotatedAllowedTypes instance");
283
271
  }
284
272
  }
@@ -59,7 +59,7 @@ import {
59
59
  getTreeNodeSchemaInitializedData,
60
60
  getUnhydratedContext,
61
61
  } from "../../createContext.js";
62
- import type { System_Unsafe } from "../../api/index.js";
62
+ import type { NodeSchemaOptionsAlpha, System_Unsafe } from "../../api/index.js";
63
63
  import type {
64
64
  ArrayNodeCustomizableSchema,
65
65
  ArrayNodePojoEmulationSchema,
@@ -1152,8 +1152,7 @@ export function arraySchema<
1152
1152
  info: T,
1153
1153
  implicitlyConstructable: ImplicitlyConstructable,
1154
1154
  customizable: boolean,
1155
- metadata?: NodeSchemaMetadata<TCustomMetadata>,
1156
- persistedMetadata?: JsonCompatibleReadOnlyObject | undefined,
1155
+ nodeOptions: NodeSchemaOptionsAlpha<TCustomMetadata>,
1157
1156
  ) {
1158
1157
  type Output = ArrayNodeCustomizableSchema<
1159
1158
  TName,
@@ -1164,6 +1163,7 @@ export function arraySchema<
1164
1163
  ArrayNodePojoEmulationSchema<TName, T, ImplicitlyConstructable, TCustomMetadata> &
1165
1164
  TreeNodeSchemaCorePrivate;
1166
1165
 
1166
+ const persistedMetadata = nodeOptions?.persistedMetadata;
1167
1167
  const normalizedTypes = normalizeAllowedTypes(info);
1168
1168
  const lazyAllowedTypesIdentifiers = new Lazy(
1169
1169
  () => new Set(normalizedTypes.evaluate().map((type) => type.identifier)),
@@ -1252,7 +1252,8 @@ export function arraySchema<
1252
1252
  public static get childTypes(): ReadonlySet<TreeNodeSchema> {
1253
1253
  return normalizedTypes.evaluateSet();
1254
1254
  }
1255
- public static readonly metadata: NodeSchemaMetadata<TCustomMetadata> = metadata ?? {};
1255
+ public static readonly metadata: NodeSchemaMetadata<TCustomMetadata> =
1256
+ nodeOptions.metadata ?? {};
1256
1257
  public static readonly persistedMetadata: JsonCompatibleReadOnlyObject | undefined =
1257
1258
  persistedMetadata;
1258
1259