@fluidframework/tree 2.53.1 → 2.60.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 (424) hide show
  1. package/.eslintrc.cjs +0 -19
  2. package/.mocharc.customBenchmarks.cjs +1 -9
  3. package/CHANGELOG.md +56 -0
  4. package/api-report/tree.alpha.api.md +50 -36
  5. package/api-report/tree.beta.api.md +15 -1
  6. package/api-report/{tree.legacy.alpha.api.md → tree.legacy.beta.api.md} +5 -5
  7. package/api-report/tree.legacy.public.api.md +1 -1
  8. package/api-report/tree.public.api.md +1 -1
  9. package/dist/alpha.d.ts +8 -2
  10. package/dist/beta.d.ts +3 -0
  11. package/dist/codec/codec.d.ts +43 -6
  12. package/dist/codec/codec.d.ts.map +1 -1
  13. package/dist/codec/codec.js +22 -2
  14. package/dist/codec/codec.js.map +1 -1
  15. package/dist/codec/index.d.ts +1 -1
  16. package/dist/codec/index.d.ts.map +1 -1
  17. package/dist/codec/index.js +4 -1
  18. package/dist/codec/index.js.map +1 -1
  19. package/dist/external-utilities/index.d.ts +1 -1
  20. package/dist/external-utilities/index.d.ts.map +1 -1
  21. package/dist/external-utilities/index.js +2 -1
  22. package/dist/external-utilities/index.js.map +1 -1
  23. package/dist/external-utilities/typeboxValidator.d.ts +6 -1
  24. package/dist/external-utilities/typeboxValidator.d.ts.map +1 -1
  25. package/dist/external-utilities/typeboxValidator.js +7 -1
  26. package/dist/external-utilities/typeboxValidator.js.map +1 -1
  27. package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts +10 -1
  28. package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts.map +1 -1
  29. package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.js +28 -5
  30. package/dist/feature-libraries/chunked-forest/codec/chunkDecoding.js.map +1 -1
  31. package/dist/feature-libraries/chunked-forest/codec/chunkDecodingGeneric.d.ts +19 -2
  32. package/dist/feature-libraries/chunked-forest/codec/chunkDecodingGeneric.d.ts.map +1 -1
  33. package/dist/feature-libraries/chunked-forest/codec/chunkDecodingGeneric.js +10 -2
  34. package/dist/feature-libraries/chunked-forest/codec/chunkDecodingGeneric.js.map +1 -1
  35. package/dist/feature-libraries/chunked-forest/codec/codecs.d.ts +59 -4
  36. package/dist/feature-libraries/chunked-forest/codec/codecs.d.ts.map +1 -1
  37. package/dist/feature-libraries/chunked-forest/codec/codecs.js +9 -2
  38. package/dist/feature-libraries/chunked-forest/codec/codecs.js.map +1 -1
  39. package/dist/feature-libraries/chunked-forest/codec/compressedEncode.d.ts +46 -8
  40. package/dist/feature-libraries/chunked-forest/codec/compressedEncode.d.ts.map +1 -1
  41. package/dist/feature-libraries/chunked-forest/codec/compressedEncode.js +91 -16
  42. package/dist/feature-libraries/chunked-forest/codec/compressedEncode.js.map +1 -1
  43. package/dist/feature-libraries/chunked-forest/codec/format.d.ts +14 -0
  44. package/dist/feature-libraries/chunked-forest/codec/format.d.ts.map +1 -1
  45. package/dist/feature-libraries/chunked-forest/codec/format.js +10 -1
  46. package/dist/feature-libraries/chunked-forest/codec/format.js.map +1 -1
  47. package/dist/feature-libraries/chunked-forest/codec/index.d.ts +1 -1
  48. package/dist/feature-libraries/chunked-forest/codec/index.d.ts.map +1 -1
  49. package/dist/feature-libraries/chunked-forest/codec/index.js.map +1 -1
  50. package/dist/feature-libraries/chunked-forest/codec/schemaBasedEncode.d.ts +8 -3
  51. package/dist/feature-libraries/chunked-forest/codec/schemaBasedEncode.d.ts.map +1 -1
  52. package/dist/feature-libraries/chunked-forest/codec/schemaBasedEncode.js +17 -6
  53. package/dist/feature-libraries/chunked-forest/codec/schemaBasedEncode.js.map +1 -1
  54. package/dist/feature-libraries/chunked-forest/index.d.ts +1 -1
  55. package/dist/feature-libraries/chunked-forest/index.d.ts.map +1 -1
  56. package/dist/feature-libraries/chunked-forest/index.js.map +1 -1
  57. package/dist/feature-libraries/forest-summary/codec.d.ts.map +1 -1
  58. package/dist/feature-libraries/forest-summary/codec.js +3 -0
  59. package/dist/feature-libraries/forest-summary/codec.js.map +1 -1
  60. package/dist/feature-libraries/forest-summary/forestSummarizer.d.ts +13 -8
  61. package/dist/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
  62. package/dist/feature-libraries/forest-summary/forestSummarizer.js +76 -38
  63. package/dist/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
  64. package/dist/feature-libraries/forest-summary/incrementalSummaryBuilder.d.ts +178 -0
  65. package/dist/feature-libraries/forest-summary/incrementalSummaryBuilder.d.ts.map +1 -0
  66. package/dist/feature-libraries/forest-summary/incrementalSummaryBuilder.js +322 -0
  67. package/dist/feature-libraries/forest-summary/incrementalSummaryBuilder.js.map +1 -0
  68. package/dist/feature-libraries/forest-summary/index.d.ts +1 -1
  69. package/dist/feature-libraries/forest-summary/index.d.ts.map +1 -1
  70. package/dist/feature-libraries/forest-summary/index.js +2 -1
  71. package/dist/feature-libraries/forest-summary/index.js.map +1 -1
  72. package/dist/feature-libraries/index.d.ts +1 -1
  73. package/dist/feature-libraries/index.d.ts.map +1 -1
  74. package/dist/feature-libraries/index.js +2 -1
  75. package/dist/feature-libraries/index.js.map +1 -1
  76. package/dist/feature-libraries/modular-schema/modularChangeCodecs.d.ts +2 -2
  77. package/dist/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
  78. package/dist/feature-libraries/modular-schema/modularChangeCodecs.js +1 -1
  79. package/dist/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
  80. package/dist/feature-libraries/modular-schema/modularChangeFormat.d.ts +6 -9
  81. package/dist/feature-libraries/modular-schema/modularChangeFormat.d.ts.map +1 -1
  82. package/dist/feature-libraries/treeCompressionUtils.d.ts +15 -0
  83. package/dist/feature-libraries/treeCompressionUtils.d.ts.map +1 -1
  84. package/dist/feature-libraries/treeCompressionUtils.js +16 -1
  85. package/dist/feature-libraries/treeCompressionUtils.js.map +1 -1
  86. package/dist/index.d.ts +3 -3
  87. package/dist/index.d.ts.map +1 -1
  88. package/dist/index.js +6 -2
  89. package/dist/index.js.map +1 -1
  90. package/dist/jsonDomainSchema.d.ts +1 -1
  91. package/dist/jsonDomainSchema.d.ts.map +1 -1
  92. package/dist/packageVersion.d.ts +1 -1
  93. package/dist/packageVersion.js +1 -1
  94. package/dist/packageVersion.js.map +1 -1
  95. package/dist/shared-tree/schematizingTreeView.d.ts +1 -1
  96. package/dist/shared-tree/schematizingTreeView.d.ts.map +1 -1
  97. package/dist/shared-tree/schematizingTreeView.js.map +1 -1
  98. package/dist/shared-tree/sharedTree.d.ts +23 -6
  99. package/dist/shared-tree/sharedTree.d.ts.map +1 -1
  100. package/dist/shared-tree/sharedTree.js +4 -1
  101. package/dist/shared-tree/sharedTree.js.map +1 -1
  102. package/dist/shared-tree/sharedTreeChangeFamily.d.ts +2 -2
  103. package/dist/shared-tree/sharedTreeChangeFamily.d.ts.map +1 -1
  104. package/dist/shared-tree/sharedTreeChangeFamily.js.map +1 -1
  105. package/dist/shared-tree/tree.d.ts.map +1 -1
  106. package/dist/shared-tree/tree.js +3 -0
  107. package/dist/shared-tree/tree.js.map +1 -1
  108. package/dist/shared-tree/treeAlpha.d.ts +9 -11
  109. package/dist/shared-tree/treeAlpha.d.ts.map +1 -1
  110. package/dist/shared-tree/treeAlpha.js.map +1 -1
  111. package/dist/shared-tree/treeCheckout.d.ts +2 -2
  112. package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
  113. package/dist/shared-tree/treeCheckout.js.map +1 -1
  114. package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
  115. package/dist/shared-tree-core/sharedTreeCore.js +13 -0
  116. package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
  117. package/dist/sharedTreeAttributes.d.ts +2 -2
  118. package/dist/sharedTreeAttributes.js +2 -2
  119. package/dist/sharedTreeAttributes.js.map +1 -1
  120. package/dist/simple-tree/api/conciseTree.d.ts.map +1 -1
  121. package/dist/simple-tree/api/conciseTree.js +1 -1
  122. package/dist/simple-tree/api/conciseTree.js.map +1 -1
  123. package/dist/simple-tree/api/customTree.d.ts +39 -11
  124. package/dist/simple-tree/api/customTree.d.ts.map +1 -1
  125. package/dist/simple-tree/api/customTree.js +79 -19
  126. package/dist/simple-tree/api/customTree.js.map +1 -1
  127. package/dist/simple-tree/api/getJsonSchema.d.ts +7 -2
  128. package/dist/simple-tree/api/getJsonSchema.d.ts.map +1 -1
  129. package/dist/simple-tree/api/getJsonSchema.js +1 -0
  130. package/dist/simple-tree/api/getJsonSchema.js.map +1 -1
  131. package/dist/simple-tree/api/index.d.ts +2 -1
  132. package/dist/simple-tree/api/index.d.ts.map +1 -1
  133. package/dist/simple-tree/api/index.js +4 -1
  134. package/dist/simple-tree/api/index.js.map +1 -1
  135. package/dist/simple-tree/api/schemaCreationUtilities.d.ts +1 -1
  136. package/dist/simple-tree/api/schemaCreationUtilities.js +1 -1
  137. package/dist/simple-tree/api/schemaCreationUtilities.js.map +1 -1
  138. package/dist/simple-tree/api/schemaFactory.d.ts +9 -6
  139. package/dist/simple-tree/api/schemaFactory.d.ts.map +1 -1
  140. package/dist/simple-tree/api/schemaFactory.js +8 -7
  141. package/dist/simple-tree/api/schemaFactory.js.map +1 -1
  142. package/dist/simple-tree/api/schemaFactoryAlpha.d.ts +13 -17
  143. package/dist/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -1
  144. package/dist/simple-tree/api/schemaFactoryAlpha.js +21 -25
  145. package/dist/simple-tree/api/schemaFactoryAlpha.js.map +1 -1
  146. package/dist/simple-tree/api/schemaFactoryBeta.d.ts +20 -0
  147. package/dist/simple-tree/api/schemaFactoryBeta.d.ts.map +1 -0
  148. package/dist/simple-tree/api/schemaFactoryBeta.js +26 -0
  149. package/dist/simple-tree/api/schemaFactoryBeta.js.map +1 -0
  150. package/dist/simple-tree/api/simpleSchemaToJsonSchema.d.ts +0 -2
  151. package/dist/simple-tree/api/simpleSchemaToJsonSchema.d.ts.map +1 -1
  152. package/dist/simple-tree/api/simpleSchemaToJsonSchema.js +6 -3
  153. package/dist/simple-tree/api/simpleSchemaToJsonSchema.js.map +1 -1
  154. package/dist/simple-tree/api/transactionTypes.d.ts +1 -0
  155. package/dist/simple-tree/api/transactionTypes.d.ts.map +1 -1
  156. package/dist/simple-tree/api/transactionTypes.js.map +1 -1
  157. package/dist/simple-tree/api/tree.d.ts +68 -74
  158. package/dist/simple-tree/api/tree.d.ts.map +1 -1
  159. package/dist/simple-tree/api/tree.js.map +1 -1
  160. package/dist/simple-tree/api/verboseTree.d.ts.map +1 -1
  161. package/dist/simple-tree/api/verboseTree.js +3 -3
  162. package/dist/simple-tree/api/verboseTree.js.map +1 -1
  163. package/dist/simple-tree/core/simpleNodeSchemaBase.d.ts +6 -0
  164. package/dist/simple-tree/core/simpleNodeSchemaBase.d.ts.map +1 -1
  165. package/dist/simple-tree/core/simpleNodeSchemaBase.js.map +1 -1
  166. package/dist/simple-tree/fieldSchema.d.ts +3 -4
  167. package/dist/simple-tree/fieldSchema.d.ts.map +1 -1
  168. package/dist/simple-tree/fieldSchema.js +0 -3
  169. package/dist/simple-tree/fieldSchema.js.map +1 -1
  170. package/dist/simple-tree/index.d.ts +1 -1
  171. package/dist/simple-tree/index.d.ts.map +1 -1
  172. package/dist/simple-tree/index.js +4 -2
  173. package/dist/simple-tree/index.js.map +1 -1
  174. package/dist/simple-tree/node-kinds/record/recordNode.d.ts.map +1 -1
  175. package/dist/simple-tree/node-kinds/record/recordNode.js +2 -3
  176. package/dist/simple-tree/node-kinds/record/recordNode.js.map +1 -1
  177. package/dist/simple-tree/simpleSchema.d.ts +12 -0
  178. package/dist/simple-tree/simpleSchema.d.ts.map +1 -1
  179. package/dist/simple-tree/simpleSchema.js.map +1 -1
  180. package/dist/simple-tree/toStoredSchema.d.ts +0 -3
  181. package/dist/simple-tree/toStoredSchema.d.ts.map +1 -1
  182. package/dist/simple-tree/toStoredSchema.js +0 -3
  183. package/dist/simple-tree/toStoredSchema.js.map +1 -1
  184. package/dist/tableSchema.d.ts +11 -80
  185. package/dist/tableSchema.d.ts.map +1 -1
  186. package/dist/tableSchema.js +200 -117
  187. package/dist/tableSchema.js.map +1 -1
  188. package/dist/treeFactory.d.ts +1 -2
  189. package/dist/treeFactory.d.ts.map +1 -1
  190. package/dist/treeFactory.js +1 -2
  191. package/dist/treeFactory.js.map +1 -1
  192. package/lib/alpha.d.ts +8 -2
  193. package/lib/beta.d.ts +3 -0
  194. package/lib/codec/codec.d.ts +43 -6
  195. package/lib/codec/codec.d.ts.map +1 -1
  196. package/lib/codec/codec.js +19 -1
  197. package/lib/codec/codec.js.map +1 -1
  198. package/lib/codec/index.d.ts +1 -1
  199. package/lib/codec/index.d.ts.map +1 -1
  200. package/lib/codec/index.js +1 -1
  201. package/lib/codec/index.js.map +1 -1
  202. package/lib/external-utilities/index.d.ts +1 -1
  203. package/lib/external-utilities/index.d.ts.map +1 -1
  204. package/lib/external-utilities/index.js +1 -1
  205. package/lib/external-utilities/index.js.map +1 -1
  206. package/lib/external-utilities/typeboxValidator.d.ts +6 -1
  207. package/lib/external-utilities/typeboxValidator.d.ts.map +1 -1
  208. package/lib/external-utilities/typeboxValidator.js +6 -0
  209. package/lib/external-utilities/typeboxValidator.js.map +1 -1
  210. package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts +10 -1
  211. package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.d.ts.map +1 -1
  212. package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.js +27 -5
  213. package/lib/feature-libraries/chunked-forest/codec/chunkDecoding.js.map +1 -1
  214. package/lib/feature-libraries/chunked-forest/codec/chunkDecodingGeneric.d.ts +19 -2
  215. package/lib/feature-libraries/chunked-forest/codec/chunkDecodingGeneric.d.ts.map +1 -1
  216. package/lib/feature-libraries/chunked-forest/codec/chunkDecodingGeneric.js +10 -2
  217. package/lib/feature-libraries/chunked-forest/codec/chunkDecodingGeneric.js.map +1 -1
  218. package/lib/feature-libraries/chunked-forest/codec/codecs.d.ts +59 -4
  219. package/lib/feature-libraries/chunked-forest/codec/codecs.d.ts.map +1 -1
  220. package/lib/feature-libraries/chunked-forest/codec/codecs.js +10 -3
  221. package/lib/feature-libraries/chunked-forest/codec/codecs.js.map +1 -1
  222. package/lib/feature-libraries/chunked-forest/codec/compressedEncode.d.ts +46 -8
  223. package/lib/feature-libraries/chunked-forest/codec/compressedEncode.d.ts.map +1 -1
  224. package/lib/feature-libraries/chunked-forest/codec/compressedEncode.js +87 -14
  225. package/lib/feature-libraries/chunked-forest/codec/compressedEncode.js.map +1 -1
  226. package/lib/feature-libraries/chunked-forest/codec/format.d.ts +14 -0
  227. package/lib/feature-libraries/chunked-forest/codec/format.d.ts.map +1 -1
  228. package/lib/feature-libraries/chunked-forest/codec/format.js +9 -0
  229. package/lib/feature-libraries/chunked-forest/codec/format.js.map +1 -1
  230. package/lib/feature-libraries/chunked-forest/codec/index.d.ts +1 -1
  231. package/lib/feature-libraries/chunked-forest/codec/index.d.ts.map +1 -1
  232. package/lib/feature-libraries/chunked-forest/codec/index.js.map +1 -1
  233. package/lib/feature-libraries/chunked-forest/codec/schemaBasedEncode.d.ts +8 -3
  234. package/lib/feature-libraries/chunked-forest/codec/schemaBasedEncode.d.ts.map +1 -1
  235. package/lib/feature-libraries/chunked-forest/codec/schemaBasedEncode.js +18 -7
  236. package/lib/feature-libraries/chunked-forest/codec/schemaBasedEncode.js.map +1 -1
  237. package/lib/feature-libraries/chunked-forest/index.d.ts +1 -1
  238. package/lib/feature-libraries/chunked-forest/index.d.ts.map +1 -1
  239. package/lib/feature-libraries/chunked-forest/index.js.map +1 -1
  240. package/lib/feature-libraries/forest-summary/codec.d.ts.map +1 -1
  241. package/lib/feature-libraries/forest-summary/codec.js +3 -0
  242. package/lib/feature-libraries/forest-summary/codec.js.map +1 -1
  243. package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts +13 -8
  244. package/lib/feature-libraries/forest-summary/forestSummarizer.d.ts.map +1 -1
  245. package/lib/feature-libraries/forest-summary/forestSummarizer.js +75 -37
  246. package/lib/feature-libraries/forest-summary/forestSummarizer.js.map +1 -1
  247. package/lib/feature-libraries/forest-summary/incrementalSummaryBuilder.d.ts +178 -0
  248. package/lib/feature-libraries/forest-summary/incrementalSummaryBuilder.d.ts.map +1 -0
  249. package/lib/feature-libraries/forest-summary/incrementalSummaryBuilder.js +318 -0
  250. package/lib/feature-libraries/forest-summary/incrementalSummaryBuilder.js.map +1 -0
  251. package/lib/feature-libraries/forest-summary/index.d.ts +1 -1
  252. package/lib/feature-libraries/forest-summary/index.d.ts.map +1 -1
  253. package/lib/feature-libraries/forest-summary/index.js +1 -1
  254. package/lib/feature-libraries/forest-summary/index.js.map +1 -1
  255. package/lib/feature-libraries/index.d.ts +1 -1
  256. package/lib/feature-libraries/index.d.ts.map +1 -1
  257. package/lib/feature-libraries/index.js +1 -1
  258. package/lib/feature-libraries/index.js.map +1 -1
  259. package/lib/feature-libraries/modular-schema/modularChangeCodecs.d.ts +2 -2
  260. package/lib/feature-libraries/modular-schema/modularChangeCodecs.d.ts.map +1 -1
  261. package/lib/feature-libraries/modular-schema/modularChangeCodecs.js +3 -3
  262. package/lib/feature-libraries/modular-schema/modularChangeCodecs.js.map +1 -1
  263. package/lib/feature-libraries/modular-schema/modularChangeFormat.d.ts +6 -9
  264. package/lib/feature-libraries/modular-schema/modularChangeFormat.d.ts.map +1 -1
  265. package/lib/feature-libraries/treeCompressionUtils.d.ts +15 -0
  266. package/lib/feature-libraries/treeCompressionUtils.d.ts.map +1 -1
  267. package/lib/feature-libraries/treeCompressionUtils.js +15 -0
  268. package/lib/feature-libraries/treeCompressionUtils.js.map +1 -1
  269. package/lib/index.d.ts +3 -3
  270. package/lib/index.d.ts.map +1 -1
  271. package/lib/index.js +4 -4
  272. package/lib/index.js.map +1 -1
  273. package/lib/jsonDomainSchema.d.ts +1 -1
  274. package/lib/jsonDomainSchema.d.ts.map +1 -1
  275. package/lib/packageVersion.d.ts +1 -1
  276. package/lib/packageVersion.js +1 -1
  277. package/lib/packageVersion.js.map +1 -1
  278. package/lib/shared-tree/schematizingTreeView.d.ts +1 -1
  279. package/lib/shared-tree/schematizingTreeView.d.ts.map +1 -1
  280. package/lib/shared-tree/schematizingTreeView.js.map +1 -1
  281. package/lib/shared-tree/sharedTree.d.ts +23 -6
  282. package/lib/shared-tree/sharedTree.d.ts.map +1 -1
  283. package/lib/shared-tree/sharedTree.js +4 -1
  284. package/lib/shared-tree/sharedTree.js.map +1 -1
  285. package/lib/shared-tree/sharedTreeChangeFamily.d.ts +2 -2
  286. package/lib/shared-tree/sharedTreeChangeFamily.d.ts.map +1 -1
  287. package/lib/shared-tree/sharedTreeChangeFamily.js.map +1 -1
  288. package/lib/shared-tree/tree.d.ts.map +1 -1
  289. package/lib/shared-tree/tree.js +3 -0
  290. package/lib/shared-tree/tree.js.map +1 -1
  291. package/lib/shared-tree/treeAlpha.d.ts +9 -11
  292. package/lib/shared-tree/treeAlpha.d.ts.map +1 -1
  293. package/lib/shared-tree/treeAlpha.js.map +1 -1
  294. package/lib/shared-tree/treeCheckout.d.ts +2 -2
  295. package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
  296. package/lib/shared-tree/treeCheckout.js.map +1 -1
  297. package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
  298. package/lib/shared-tree-core/sharedTreeCore.js +13 -0
  299. package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
  300. package/lib/sharedTreeAttributes.d.ts +2 -2
  301. package/lib/sharedTreeAttributes.js +2 -2
  302. package/lib/sharedTreeAttributes.js.map +1 -1
  303. package/lib/simple-tree/api/conciseTree.d.ts.map +1 -1
  304. package/lib/simple-tree/api/conciseTree.js +2 -2
  305. package/lib/simple-tree/api/conciseTree.js.map +1 -1
  306. package/lib/simple-tree/api/customTree.d.ts +39 -11
  307. package/lib/simple-tree/api/customTree.d.ts.map +1 -1
  308. package/lib/simple-tree/api/customTree.js +79 -19
  309. package/lib/simple-tree/api/customTree.js.map +1 -1
  310. package/lib/simple-tree/api/getJsonSchema.d.ts +7 -2
  311. package/lib/simple-tree/api/getJsonSchema.d.ts.map +1 -1
  312. package/lib/simple-tree/api/getJsonSchema.js +1 -0
  313. package/lib/simple-tree/api/getJsonSchema.js.map +1 -1
  314. package/lib/simple-tree/api/index.d.ts +2 -1
  315. package/lib/simple-tree/api/index.d.ts.map +1 -1
  316. package/lib/simple-tree/api/index.js +2 -1
  317. package/lib/simple-tree/api/index.js.map +1 -1
  318. package/lib/simple-tree/api/schemaCreationUtilities.d.ts +1 -1
  319. package/lib/simple-tree/api/schemaCreationUtilities.js +1 -1
  320. package/lib/simple-tree/api/schemaCreationUtilities.js.map +1 -1
  321. package/lib/simple-tree/api/schemaFactory.d.ts +9 -6
  322. package/lib/simple-tree/api/schemaFactory.d.ts.map +1 -1
  323. package/lib/simple-tree/api/schemaFactory.js +6 -6
  324. package/lib/simple-tree/api/schemaFactory.js.map +1 -1
  325. package/lib/simple-tree/api/schemaFactoryAlpha.d.ts +13 -17
  326. package/lib/simple-tree/api/schemaFactoryAlpha.d.ts.map +1 -1
  327. package/lib/simple-tree/api/schemaFactoryAlpha.js +22 -26
  328. package/lib/simple-tree/api/schemaFactoryAlpha.js.map +1 -1
  329. package/lib/simple-tree/api/schemaFactoryBeta.d.ts +20 -0
  330. package/lib/simple-tree/api/schemaFactoryBeta.d.ts.map +1 -0
  331. package/lib/simple-tree/api/schemaFactoryBeta.js +22 -0
  332. package/lib/simple-tree/api/schemaFactoryBeta.js.map +1 -0
  333. package/lib/simple-tree/api/simpleSchemaToJsonSchema.d.ts +0 -2
  334. package/lib/simple-tree/api/simpleSchemaToJsonSchema.d.ts.map +1 -1
  335. package/lib/simple-tree/api/simpleSchemaToJsonSchema.js +6 -3
  336. package/lib/simple-tree/api/simpleSchemaToJsonSchema.js.map +1 -1
  337. package/lib/simple-tree/api/transactionTypes.d.ts +1 -0
  338. package/lib/simple-tree/api/transactionTypes.d.ts.map +1 -1
  339. package/lib/simple-tree/api/transactionTypes.js.map +1 -1
  340. package/lib/simple-tree/api/tree.d.ts +68 -74
  341. package/lib/simple-tree/api/tree.d.ts.map +1 -1
  342. package/lib/simple-tree/api/tree.js.map +1 -1
  343. package/lib/simple-tree/api/verboseTree.d.ts.map +1 -1
  344. package/lib/simple-tree/api/verboseTree.js +4 -4
  345. package/lib/simple-tree/api/verboseTree.js.map +1 -1
  346. package/lib/simple-tree/core/simpleNodeSchemaBase.d.ts +6 -0
  347. package/lib/simple-tree/core/simpleNodeSchemaBase.d.ts.map +1 -1
  348. package/lib/simple-tree/core/simpleNodeSchemaBase.js.map +1 -1
  349. package/lib/simple-tree/fieldSchema.d.ts +3 -4
  350. package/lib/simple-tree/fieldSchema.d.ts.map +1 -1
  351. package/lib/simple-tree/fieldSchema.js +0 -3
  352. package/lib/simple-tree/fieldSchema.js.map +1 -1
  353. package/lib/simple-tree/index.d.ts +1 -1
  354. package/lib/simple-tree/index.d.ts.map +1 -1
  355. package/lib/simple-tree/index.js +1 -1
  356. package/lib/simple-tree/index.js.map +1 -1
  357. package/lib/simple-tree/node-kinds/record/recordNode.d.ts.map +1 -1
  358. package/lib/simple-tree/node-kinds/record/recordNode.js +2 -3
  359. package/lib/simple-tree/node-kinds/record/recordNode.js.map +1 -1
  360. package/lib/simple-tree/simpleSchema.d.ts +12 -0
  361. package/lib/simple-tree/simpleSchema.d.ts.map +1 -1
  362. package/lib/simple-tree/simpleSchema.js.map +1 -1
  363. package/lib/simple-tree/toStoredSchema.d.ts +0 -3
  364. package/lib/simple-tree/toStoredSchema.d.ts.map +1 -1
  365. package/lib/simple-tree/toStoredSchema.js +0 -3
  366. package/lib/simple-tree/toStoredSchema.js.map +1 -1
  367. package/lib/tableSchema.d.ts +11 -80
  368. package/lib/tableSchema.d.ts.map +1 -1
  369. package/lib/tableSchema.js +201 -118
  370. package/lib/tableSchema.js.map +1 -1
  371. package/lib/treeFactory.d.ts +1 -2
  372. package/lib/treeFactory.d.ts.map +1 -1
  373. package/lib/treeFactory.js +1 -2
  374. package/lib/treeFactory.js.map +1 -1
  375. package/package.json +21 -21
  376. package/src/codec/codec.ts +52 -7
  377. package/src/codec/index.ts +4 -0
  378. package/src/external-utilities/index.ts +1 -1
  379. package/src/external-utilities/typeboxValidator.ts +7 -1
  380. package/src/feature-libraries/chunked-forest/codec/chunkDecoding.ts +38 -4
  381. package/src/feature-libraries/chunked-forest/codec/chunkDecodingGeneric.ts +10 -3
  382. package/src/feature-libraries/chunked-forest/codec/codecs.ts +96 -8
  383. package/src/feature-libraries/chunked-forest/codec/compressedEncode.ts +123 -19
  384. package/src/feature-libraries/chunked-forest/codec/format.ts +11 -0
  385. package/src/feature-libraries/chunked-forest/codec/index.ts +4 -0
  386. package/src/feature-libraries/chunked-forest/codec/schemaBasedEncode.ts +28 -3
  387. package/src/feature-libraries/chunked-forest/index.ts +2 -0
  388. package/src/feature-libraries/forest-summary/codec.ts +3 -0
  389. package/src/feature-libraries/forest-summary/forestSummarizer.ts +118 -50
  390. package/src/feature-libraries/forest-summary/incrementalSummaryBuilder.ts +511 -0
  391. package/src/feature-libraries/forest-summary/index.ts +1 -1
  392. package/src/feature-libraries/index.ts +5 -1
  393. package/src/feature-libraries/modular-schema/modularChangeCodecs.ts +8 -4
  394. package/src/feature-libraries/treeCompressionUtils.ts +19 -0
  395. package/src/index.ts +6 -1
  396. package/src/packageVersion.ts +1 -1
  397. package/src/shared-tree/schematizingTreeView.ts +1 -1
  398. package/src/shared-tree/sharedTree.ts +37 -4
  399. package/src/shared-tree/sharedTreeChangeFamily.ts +2 -2
  400. package/src/shared-tree/tree.ts +3 -0
  401. package/src/shared-tree/treeAlpha.ts +10 -11
  402. package/src/shared-tree/treeCheckout.ts +2 -2
  403. package/src/shared-tree-core/sharedTreeCore.ts +17 -0
  404. package/src/sharedTreeAttributes.ts +2 -2
  405. package/src/simple-tree/api/conciseTree.ts +2 -1
  406. package/src/simple-tree/api/customTree.ts +102 -32
  407. package/src/simple-tree/api/getJsonSchema.ts +7 -2
  408. package/src/simple-tree/api/index.ts +3 -0
  409. package/src/simple-tree/api/schemaCreationUtilities.ts +1 -1
  410. package/src/simple-tree/api/schemaFactory.ts +21 -14
  411. package/src/simple-tree/api/schemaFactoryAlpha.ts +29 -30
  412. package/src/simple-tree/api/schemaFactoryBeta.ts +28 -0
  413. package/src/simple-tree/api/simpleSchemaToJsonSchema.ts +7 -3
  414. package/src/simple-tree/api/transactionTypes.ts +1 -0
  415. package/src/simple-tree/api/tree.ts +75 -81
  416. package/src/simple-tree/api/verboseTree.ts +42 -39
  417. package/src/simple-tree/core/simpleNodeSchemaBase.ts +6 -0
  418. package/src/simple-tree/fieldSchema.ts +3 -4
  419. package/src/simple-tree/index.ts +3 -0
  420. package/src/simple-tree/node-kinds/record/recordNode.ts +2 -3
  421. package/src/simple-tree/simpleSchema.ts +12 -0
  422. package/src/simple-tree/toStoredSchema.ts +0 -3
  423. package/src/tableSchema.ts +261 -243
  424. package/src/treeFactory.ts +1 -2
@@ -3,12 +3,14 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
+ import type { ErasedType } from "@fluidframework/core-interfaces/internal";
6
7
  import { IsoBuffer, bufferToString } from "@fluid-internal/client-utils";
7
8
  import { assert, fail } from "@fluidframework/core-utils/internal";
8
9
  import type { Static, TAnySchema, TSchema } from "@sinclair/typebox";
9
10
 
10
11
  import type { ChangeEncodingContext } from "../core/index.js";
11
12
  import type { JsonCompatibleReadOnly } from "../util/index.js";
13
+ import { noopValidator } from "./noopValidator.js";
12
14
 
13
15
  /**
14
16
  * Translates decoded data to encoded data.
@@ -44,6 +46,46 @@ export interface SchemaValidationFunction<Schema extends TSchema> {
44
46
  check(data: unknown): data is Static<Schema>;
45
47
  }
46
48
 
49
+ /**
50
+ * A kind of validator for SharedTree's internal data formats.
51
+ * @remarks
52
+ * Assuming no data corruption or type confusion, such validation should never fail.
53
+ * Any client version compatibility issues should instead be detected by the data format versioning which Shared Tree does internally independent of data format validation.
54
+ * However, persisted data can sometimes be corrupted, bugs can produce invalid data, or users can mix up which data is compatible with which APIs.
55
+ * In such cases, a format validator can help catch issues.
56
+ *
57
+ * Current options are {@link FormatValidatorNoOp} and {@link FormatValidatorBasic}.
58
+ * @privateRemarks
59
+ * Implement using {@link toFormatValidator}.
60
+ * Consume using {@link extractJsonValidator}.
61
+ *
62
+ * Exposing this as the stable API entry point (instead of {@link JsonValidator}) means that we avoid leaking the reference to TypeBox to the API surface.
63
+ * Additionally, if we adopt non JSON formats, we can just update the validators as needed without breaking the API.
64
+ * This also allows us to avoid stabilizing or documenting how handles interact with JSON validation since that is not exposed through this type.
65
+ * @sealed @alpha
66
+ */
67
+ export interface FormatValidator extends ErasedType<"FormatValidator"> {}
68
+
69
+ /**
70
+ * A {@link FormatValidator} which does no validation.
71
+ * @alpha
72
+ */
73
+ export const FormatValidatorNoOp = toFormatValidator(noopValidator);
74
+
75
+ /**
76
+ * Type erase a {@link JsonValidator} to a {@link FormatValidator}.
77
+ */
78
+ export function toFormatValidator(factory: JsonValidator): FormatValidator {
79
+ return factory as unknown as FormatValidator;
80
+ }
81
+
82
+ /**
83
+ * Un-type-erase the {@link FormatValidator}.
84
+ */
85
+ export function extractJsonValidator(input: FormatValidator | JsonValidator): JsonValidator {
86
+ return input as unknown as JsonValidator;
87
+ }
88
+
47
89
  /**
48
90
  * JSON schema validator compliant with draft 6 schema. See https://json-schema.org.
49
91
  * @alpha @input
@@ -69,19 +111,22 @@ export interface JsonValidator {
69
111
  */
70
112
  export interface ICodecOptions {
71
113
  /**
72
- * {@link JsonValidator} which SharedTree uses to validate persisted data it reads & writes
114
+ * {@link FormatValidator} which SharedTree uses to validate persisted data it reads & writes
73
115
  * matches the expected encoded format (i.e. the wire format for ops and summaries).
74
- *
75
- * See {@link noopValidator} and {@link typeboxValidator} for out-of-the-box implementations.
116
+ * @remarks
117
+ * See {@link FormatValidatorNoOp} and {@link FormatValidatorBasic} for out-of-the-box implementations.
76
118
  *
77
119
  * This option is not "on-by-default" because JSON schema validation comes with a small but noticeable
78
120
  * runtime performance cost, and popular schema validation libraries have relatively large bundle size.
79
121
  *
80
- * SharedTree users are still encouraged to use a non-trivial validator (i.e. not `noopValidator`)
122
+ * SharedTree users are still encouraged to use a non-trivial validator (i.e. not `FormatValidatorNoOp`)
81
123
  * whenever reasonable: it gives better fail-fast behavior when unexpected encoded data is found,
82
124
  * which reduces the risk of unrecoverable data corruption.
125
+ *
126
+ * Use of {@link JsonValidator} here is deprecated and will be removed:
127
+ * it is recommended to use {@link FormatValidator} instead.
83
128
  */
84
- readonly jsonValidator: JsonValidator;
129
+ readonly jsonValidator: JsonValidator | FormatValidator;
85
130
  }
86
131
 
87
132
  /**
@@ -326,12 +371,12 @@ export function withSchemaValidation<
326
371
  >(
327
372
  schema: EncodedSchema,
328
373
  codec: IJsonCodec<TInMemoryFormat, TEncodedFormat, TValidate, TContext>,
329
- validator?: JsonValidator,
374
+ validator?: JsonValidator | FormatValidator,
330
375
  ): IJsonCodec<TInMemoryFormat, TEncodedFormat, TValidate, TContext> {
331
376
  if (!validator) {
332
377
  return codec;
333
378
  }
334
- const compiledFormat = validator.compile(schema);
379
+ const compiledFormat = extractJsonValidator(validator).compile(schema);
335
380
  return {
336
381
  encode: (obj: TInMemoryFormat, context: TContext): TEncodedFormat => {
337
382
  const encoded = codec.encode(obj, context);
@@ -21,6 +21,10 @@ export {
21
21
  withSchemaValidation,
22
22
  FluidClientVersion,
23
23
  currentVersion,
24
+ toFormatValidator,
25
+ FormatValidatorNoOp,
26
+ type FormatValidator,
27
+ extractJsonValidator,
24
28
  } from "./codec.js";
25
29
  export {
26
30
  DiscriminatedUnionDispatcher,
@@ -3,4 +3,4 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- export { typeboxValidator } from "./typeboxValidator.js";
6
+ export { typeboxValidator, FormatValidatorBasic } from "./typeboxValidator.js";
@@ -8,7 +8,7 @@ import type { Static, TSchema } from "@sinclair/typebox";
8
8
  // eslint-disable-next-line import/no-internal-modules
9
9
  import { TypeCompiler } from "@sinclair/typebox/compiler";
10
10
 
11
- import type { JsonValidator } from "../codec/index.js";
11
+ import { toFormatValidator, type JsonValidator } from "../codec/index.js";
12
12
 
13
13
  /**
14
14
  * A {@link JsonValidator} implementation which uses TypeBox's JSON schema validator.
@@ -29,3 +29,9 @@ export const typeboxValidator: JsonValidator = {
29
29
  };
30
30
  },
31
31
  };
32
+
33
+ /**
34
+ * A {@link FormatValidator} implementation which uses TypeBox's JSON schema validator.
35
+ * @alpha
36
+ */
37
+ export const FormatValidatorBasic = toFormatValidator(typeboxValidator);
@@ -17,7 +17,7 @@ import type {
17
17
  Value,
18
18
  TreeChunk,
19
19
  } from "../../../core/index.js";
20
- import { assertValidIndex } from "../../../util/index.js";
20
+ import { assertValidIndex, brand } from "../../../util/index.js";
21
21
  import { BasicChunk } from "../basicChunk.js";
22
22
  import { emptyChunk } from "../emptyChunk.js";
23
23
  import { SequenceChunk } from "../sequenceChunk.js";
@@ -41,12 +41,14 @@ import {
41
41
  type EncodedAnyShape,
42
42
  type EncodedChunkShape,
43
43
  type EncodedFieldBatch,
44
+ type EncodedIncrementalChunkShape,
44
45
  type EncodedInlineArrayShape,
45
46
  type EncodedNestedArrayShape,
46
47
  type EncodedNodeShape,
47
48
  type EncodedValueShape,
48
49
  SpecialField,
49
50
  } from "./format.js";
51
+ import type { IncrementalDecoder } from "./codecs.js";
50
52
 
51
53
  export interface IdDecodingContext {
52
54
  idCompressor: IIdCompressor;
@@ -61,10 +63,11 @@ export interface IdDecodingContext {
61
63
  export function decode(
62
64
  chunk: EncodedFieldBatch,
63
65
  idDecodingContext: { idCompressor: IIdCompressor; originatorId: SessionId },
66
+ incrementalDecoder?: IncrementalDecoder,
64
67
  ): TreeChunk[] {
65
68
  return genericDecode(
66
69
  decoderLibrary,
67
- new DecoderContext(chunk.identifiers, chunk.shapes, idDecodingContext),
70
+ new DecoderContext(chunk.identifiers, chunk.shapes, idDecodingContext, incrementalDecoder),
68
71
  chunk,
69
72
  anyDecoder,
70
73
  );
@@ -87,6 +90,9 @@ const decoderLibrary = new DiscriminatedUnionDispatcher<
87
90
  d(shape: EncodedAnyShape): ChunkDecoder {
88
91
  return anyDecoder;
89
92
  },
93
+ e(shape: EncodedIncrementalChunkShape, cache): ChunkDecoder {
94
+ return new IncrementalChunkDecoder(cache);
95
+ },
90
96
  });
91
97
 
92
98
  /**
@@ -228,6 +234,34 @@ export class InlineArrayDecoder implements ChunkDecoder {
228
234
  }
229
235
  }
230
236
 
237
+ /**
238
+ * Decoder for {@link EncodedIncrementalChunkShape}s.
239
+ */
240
+ export class IncrementalChunkDecoder implements ChunkDecoder {
241
+ public constructor(private readonly cache: DecoderContext<EncodedChunkShape>) {}
242
+ public decode(_: readonly ChunkDecoder[], stream: StreamCursor): TreeChunk {
243
+ assert(
244
+ this.cache.incrementalDecoder !== undefined,
245
+ 0xc27 /* incremental decoder not available for incremental field decoding */,
246
+ );
247
+ const chunkReferenceId = readStreamNumber(stream);
248
+ const batch = this.cache.incrementalDecoder.getEncodedIncrementalChunk(
249
+ brand(chunkReferenceId),
250
+ );
251
+ assert(batch !== undefined, 0xc28 /* Incremental chunk data missing */);
252
+ // The incremental chunk data is self-describing, i.e., it contain its own shapes list and identifier table.
253
+ // Use these to create a new decoder context to be used to decode the incremental chunk's data.
254
+ const context = new DecoderContext(
255
+ batch.identifiers,
256
+ batch.shapes,
257
+ this.cache.idDecodingContext,
258
+ this.cache.incrementalDecoder,
259
+ );
260
+ const chunks = genericDecode(decoderLibrary, context, batch, anyDecoder);
261
+ return aggregateChunks(chunks);
262
+ }
263
+ }
264
+
231
265
  /**
232
266
  * Decoder for {@link EncodedAnyShape}s.
233
267
  */
@@ -300,8 +334,8 @@ export class NodeDecoder implements ChunkDecoder {
300
334
  }
301
335
  }
302
336
 
303
- for (const field of this.fieldDecoders) {
304
- const [key, content] = field(decoders, stream);
337
+ for (const decoder of this.fieldDecoders) {
338
+ const [key, content] = decoder(decoders, stream);
305
339
  addField(key, content);
306
340
  }
307
341
 
@@ -17,6 +17,7 @@ import {
17
17
  } from "./chunkCodecUtilities.js";
18
18
  import type { IdDecodingContext } from "./chunkDecoding.js";
19
19
  import type { EncodedFieldBatchGeneric, IdentifierOrIndex } from "./formatGeneric.js";
20
+ import type { IncrementalDecoder } from "./codecs.js";
20
21
 
21
22
  /**
22
23
  * General purpose shape based tree decoder which gets its support for specific shapes from the caller.
@@ -50,13 +51,19 @@ export function decode<TEncodedShape extends object, TContext>(
50
51
  * Shared data for use in constructing decoders.
51
52
  */
52
53
  export class DecoderContext<TEncodedShape = unknown> {
53
- /**
54
- * @param identifiers - identifier substitution table (use to replace numeric identifier indexes with the actual identifiers from this table).
55
- */
56
54
  public constructor(
55
+ /**
56
+ * Identifier substitution table (use to replace numeric identifier indexes with the actual identifiers from this table).
57
+ */
57
58
  public readonly identifiers: readonly string[],
58
59
  public readonly shapes: readonly TEncodedShape[],
59
60
  public readonly idDecodingContext: IdDecodingContext,
61
+ /**
62
+ * To be used to decode incremental chunks, if any.
63
+ * @remarks
64
+ * See {@link IncrementalDecoder} for more information.
65
+ */
66
+ public readonly incrementalDecoder: IncrementalDecoder | undefined,
60
67
  ) {}
61
68
 
62
69
  public identifier<T extends string & BrandedType<string, string>>(
@@ -12,9 +12,24 @@ import {
12
12
  type IJsonCodec,
13
13
  makeVersionedValidatedCodec,
14
14
  } from "../../../codec/index.js";
15
- import { CursorLocationType, type SchemaAndPolicy } from "../../../core/index.js";
16
- import type { JsonCompatibleReadOnly } from "../../../util/index.js";
17
- import { TreeCompressionStrategy } from "../../treeCompressionUtils.js";
15
+ import {
16
+ CursorLocationType,
17
+ type FieldKey,
18
+ type ITreeCursorSynchronous,
19
+ type SchemaAndPolicy,
20
+ type TreeChunk,
21
+ type TreeNodeSchemaIdentifier,
22
+ } from "../../../core/index.js";
23
+ import {
24
+ brandedNumberType,
25
+ type Brand,
26
+ type JsonCompatibleReadOnly,
27
+ } from "../../../util/index.js";
28
+ import {
29
+ TreeCompressionStrategy,
30
+ TreeCompressionStrategyExtended,
31
+ type TreeCompressionStrategyPrivate,
32
+ } from "../../treeCompressionUtils.js";
18
33
 
19
34
  import { decode } from "./chunkDecoding.js";
20
35
  import type { FieldBatch } from "./fieldBatch.js";
@@ -22,11 +37,75 @@ import { EncodedFieldBatch, validVersions } from "./format.js";
22
37
  import { schemaCompressedEncode } from "./schemaBasedEncode.js";
23
38
  import { uncompressedEncode } from "./uncompressedEncode.js";
24
39
 
40
+ /**
41
+ * Reference ID for a chunk that is incrementally encoded.
42
+ */
43
+ export type ChunkReferenceId = Brand<number, "forest.ChunkReferenceId">;
44
+ const ChunkReferenceId = brandedNumberType<ChunkReferenceId>({ multipleOf: 1, minimum: 0 });
45
+
46
+ /**
47
+ * Properties for incremental encoding.
48
+ * Fields that support incremental encoding will encode their chunks separately by calling `encodeIncrementalField`.
49
+ * @remarks
50
+ * This supports features like incremental summarization where the summary from these fields can be re-used if
51
+ * unchanged between summaries.
52
+ * Note that each of these chunks that are incrementally encoded is fully self-describing (contain its own shapes
53
+ * list and identifier table) and does not rely on context from its parent.
54
+ */
55
+ export interface IncrementalEncoder {
56
+ /**
57
+ * Returns whether a field should be incrementally encoded.
58
+ * @param nodeIdentifier - The identifier of the node containing the field.
59
+ * @param fieldKey - The key of the field to check.
60
+ */
61
+ shouldEncodeFieldIncrementally(
62
+ nodeIdentifier: TreeNodeSchemaIdentifier,
63
+ fieldKey: FieldKey,
64
+ ): boolean;
65
+ /**
66
+ * Called to encode an incremental field at the cursor.
67
+ * The chunks for this field are encoded separately from the main buffer.
68
+ * @param cursor - The cursor pointing to the field to encode.
69
+ * @param chunkEncoder - A function that encodes the contents of the passed chunk in the field.
70
+ * @returns The reference IDs of the encoded chunks in the field.
71
+ * This is used to retrieve the encoded chunks later.
72
+ */
73
+ encodeIncrementalField(
74
+ cursor: ITreeCursorSynchronous,
75
+ chunkEncoder: (chunk: TreeChunk) => EncodedFieldBatch,
76
+ ): ChunkReferenceId[];
77
+ }
78
+
79
+ /**
80
+ * Properties for incremental decoding.
81
+ *
82
+ * Fields that had their chunks incrementally encoded will retrieve them by calling `getEncodedIncrementalChunk`.
83
+ * @remarks
84
+ * See {@link IncrementalEncoder} for more details.
85
+ */
86
+ export interface IncrementalDecoder {
87
+ /**
88
+ * Called to get the encoded contents of an chunk in an incremental field with the given reference ID.
89
+ * @param referenceId - The reference ID of the chunk to retrieve.
90
+ * @returns The encoded contents of the chunk.
91
+ */
92
+ getEncodedIncrementalChunk: (referenceId: ChunkReferenceId) => EncodedFieldBatch;
93
+ }
94
+ /**
95
+ * Combines the properties of {@link IncrementalEncoder} and {@link IncrementalDecoder}.
96
+ */
97
+ export interface IncrementalEncoderDecoder extends IncrementalEncoder, IncrementalDecoder {}
98
+
25
99
  export interface FieldBatchEncodingContext {
26
- readonly encodeType: TreeCompressionStrategy;
100
+ readonly encodeType: TreeCompressionStrategyPrivate;
27
101
  readonly idCompressor: IIdCompressor;
28
102
  readonly originatorId: SessionId;
29
103
  readonly schema?: SchemaAndPolicy;
104
+ /**
105
+ * An encoder / decoder for encoding and decoding of incremental fields.
106
+ * This will be defined if incremental encoding is supported and enabled.
107
+ */
108
+ readonly incrementalEncoderDecoder?: IncrementalEncoderDecoder;
30
109
  }
31
110
  /**
32
111
  * @remarks
@@ -78,6 +157,7 @@ export function makeFieldBatchCodec(
78
157
  case TreeCompressionStrategy.Uncompressed:
79
158
  encoded = uncompressedEncode(data);
80
159
  break;
160
+ case TreeCompressionStrategyExtended.CompressedIncremental:
81
161
  case TreeCompressionStrategy.Compressed:
82
162
  // eslint-disable-next-line unicorn/prefer-ternary
83
163
  if (context.schema !== undefined) {
@@ -86,6 +166,10 @@ export function makeFieldBatchCodec(
86
166
  context.schema.policy,
87
167
  data,
88
168
  context.idCompressor,
169
+ // Incremental encoding is only supported for CompressedIncremental.
170
+ context.encodeType === TreeCompressionStrategyExtended.CompressedIncremental
171
+ ? context.incrementalEncoderDecoder
172
+ : undefined,
89
173
  );
90
174
  } else {
91
175
  // TODO: consider enabling a somewhat compressed but not schema accelerated encode.
@@ -102,10 +186,14 @@ export function makeFieldBatchCodec(
102
186
  },
103
187
  decode: (data: EncodedFieldBatch, context: FieldBatchEncodingContext): FieldBatch => {
104
188
  // TODO: consider checking data is in schema.
105
- return decode(data, {
106
- idCompressor: context.idCompressor,
107
- originatorId: context.originatorId,
108
- }).map((chunk) => chunk.cursor());
189
+ return decode(
190
+ data,
191
+ {
192
+ idCompressor: context.idCompressor,
193
+ originatorId: context.originatorId,
194
+ },
195
+ context.incrementalEncoderDecoder,
196
+ ).map((chunk) => chunk.cursor());
109
197
  },
110
198
  });
111
199
  }
@@ -11,6 +11,7 @@ import {
11
11
  type FieldKey,
12
12
  type FieldKindIdentifier,
13
13
  type ITreeCursorSynchronous,
14
+ type TreeChunk,
14
15
  type TreeFieldStoredSchema,
15
16
  type TreeNodeSchemaIdentifier,
16
17
  type Value,
@@ -35,9 +36,10 @@ import {
35
36
  SpecialField,
36
37
  version,
37
38
  } from "./format.js";
39
+ import type { ChunkReferenceId, IncrementalEncoder } from "./codecs.js";
38
40
 
39
41
  /**
40
- * Encode data from `FieldBatch` into an `EncodedChunk`.
42
+ * Encode data from `FieldBatch` into an `EncodedFieldBatch`.
41
43
  *
42
44
  * Optimized for encoded size and encoding performance.
43
45
  *
@@ -347,22 +349,48 @@ export class InlineArrayEncoder
347
349
  }
348
350
  }
349
351
 
352
+ /**
353
+ * Encodes the shape for a nested array as {@link EncodedNestedArray} shape.
354
+ */
355
+ export class NestedArrayShape extends ShapeGeneric<EncodedChunkShape> {
356
+ /**
357
+ * @param innerShape - The shape of each item in this nested array.
358
+ */
359
+ public constructor(public readonly innerShape: Shape) {
360
+ super();
361
+ }
362
+
363
+ public encodeShape(
364
+ identifiers: DeduplicationTable<string>,
365
+ shapes: DeduplicationTable<Shape>,
366
+ ): EncodedChunkShape {
367
+ const shape: EncodedNestedArrayShape =
368
+ shapes.valueToIndex.get(this.innerShape) ??
369
+ fail(0xb4f /* index for shape not found in table */);
370
+ return {
371
+ a: shape,
372
+ };
373
+ }
374
+
375
+ public countReferencedShapesAndIdentifiers(
376
+ identifiers: Counter<string>,
377
+ shapeDiscovered: (shape: Shape) => void,
378
+ ): void {
379
+ shapeDiscovered(this.innerShape);
380
+ }
381
+ }
382
+
350
383
  /**
351
384
  * Encodes a field as a nested array with the {@link EncodedNestedArrayShape} shape.
352
385
  * @remarks
353
- * The fact this is also a Shape is an implementation detail of the encoder: that allows the shape it uses to be itself,
386
+ * The fact this is also exposes a Shape is an implementation detail: it allows the shape it uses to be itself
354
387
  * which is an easy way to keep all the related code together without extra objects.
355
388
  */
356
- export class NestedArrayEncoder
357
- extends ShapeGeneric<EncodedChunkShape>
358
- implements FieldEncoder
359
- {
360
- public readonly shape: Shape;
361
-
362
- public constructor(public readonly inner: NodeEncoder) {
363
- super();
364
- this.shape = this;
365
- }
389
+ export class NestedArrayEncoder implements FieldEncoder {
390
+ public constructor(
391
+ public readonly innerEncoder: NodeEncoder,
392
+ public readonly shape: NestedArrayShape = new NestedArrayShape(innerEncoder.shape),
393
+ ) {}
366
394
 
367
395
  public encodeField(
368
396
  cursor: ITreeCursorSynchronous,
@@ -374,7 +402,7 @@ export class NestedArrayEncoder
374
402
  const length = cursor.getFieldLength();
375
403
  forEachNode(cursor, () => {
376
404
  const before = buffer.length;
377
- this.inner.encodeNode(cursor, context, buffer);
405
+ this.innerEncoder.encodeNode(cursor, context, buffer);
378
406
  allNonZeroSize &&= buffer.length - before !== 0;
379
407
  });
380
408
  if (buffer.length === 0) {
@@ -389,27 +417,77 @@ export class NestedArrayEncoder
389
417
  outputBuffer.push(buffer);
390
418
  }
391
419
  }
420
+ }
421
+
422
+ /**
423
+ * Encodes a chunk with the {@link EncodedIncrementalChunkShape} shape.
424
+ * This chunks will be encoded separately, i.e., the contents of the chunk will not be part of the main buffer.
425
+ * A reference to the chunk will be stored in the main buffer as an {@link ChunkReferenceId}.
426
+ */
427
+ export class IncrementalChunkShape extends ShapeGeneric<EncodedChunkShape> {
428
+ /**
429
+ * Encodes all the nodes in the chunk at the cursor position using `InlineArrayShape`.
430
+ */
431
+ public static encodeChunk(chunk: TreeChunk, context: EncoderContext): BufferFormat {
432
+ const chunkOutputBuffer: BufferFormat = [];
433
+ const nodesEncoder = asNodesEncoder(anyNodeEncoder);
434
+ const chunkCursor = chunk.cursor();
435
+ chunkCursor.firstNode();
436
+ const chunkLength = chunkCursor.chunkLength;
437
+ for (let index = 0; index < chunkLength; index++) {
438
+ nodesEncoder.encodeNodes(chunkCursor, context, chunkOutputBuffer);
439
+ }
440
+ assert(
441
+ chunkCursor.mode === CursorLocationType.Fields,
442
+ 0xc29 /* should return to fields mode when finished encoding */,
443
+ );
444
+ return chunkOutputBuffer;
445
+ }
392
446
 
393
447
  public encodeShape(
394
448
  identifiers: DeduplicationTable<string>,
395
449
  shapes: DeduplicationTable<Shape>,
396
450
  ): EncodedChunkShape {
397
- const shape: EncodedNestedArrayShape =
398
- shapes.valueToIndex.get(this.inner.shape) ??
399
- fail(0xb4f /* index for shape not found in table */);
400
451
  return {
401
- a: shape,
452
+ e: 0 /* EncodedIncrementalChunkShape */,
402
453
  };
403
454
  }
404
455
 
405
456
  public countReferencedShapesAndIdentifiers(
406
457
  identifiers: Counter<string>,
407
458
  shapeDiscovered: (shape: Shape) => void,
408
- ): void {
409
- shapeDiscovered(this.inner.shape);
459
+ ): void {}
460
+
461
+ public get shape(): this {
462
+ return this;
410
463
  }
411
464
  }
412
465
 
466
+ /**
467
+ * Encodes an incremental field whose chunks are encoded separately and referenced by their {@link ChunkReferenceId}.
468
+ * The shape of the content of this field is {@link NestedShape} where the items in the array are
469
+ * the {@link ChunkReferenceId}s of the encoded chunks.
470
+ */
471
+ export const incrementalFieldEncoder: FieldEncoder = {
472
+ encodeField(
473
+ cursor: ITreeCursorSynchronous,
474
+ context: EncoderContext,
475
+ outputBuffer: BufferFormat,
476
+ ): void {
477
+ assert(
478
+ context.shouldEncodeIncrementally,
479
+ 0xc2a /* incremental encoding must be enabled to use IncrementalFieldShape */,
480
+ );
481
+
482
+ const chunkReferenceIds = context.encodeIncrementalField(cursor, (chunk: TreeChunk) =>
483
+ IncrementalChunkShape.encodeChunk(chunk, context),
484
+ );
485
+ outputBuffer.push(chunkReferenceIds);
486
+ },
487
+
488
+ shape: new NestedArrayShape(new IncrementalChunkShape() /* innerShape */),
489
+ };
490
+
413
491
  /**
414
492
  * Encode `value` with `shape` into `outputBuffer`.
415
493
  *
@@ -448,6 +526,7 @@ export function encodeValue(
448
526
  /**
449
527
  * Provides common contextual information during encoding, like schema and policy settings.
450
528
  * Also, provides a cache to avoid duplicating equivalent shapes during a batch of encode operations.
529
+ * @remarks
451
530
  * To avoid Shape duplication, any Shapes used in the encoding should either be:
452
531
  * - Singletons defined in a static scope.
453
532
  * - Cached in this object for future reuse such that all equivalent Shapes are deduplicated.
@@ -461,6 +540,7 @@ export class EncoderContext implements NodeEncodeBuilder, FieldEncodeBuilder {
461
540
  private readonly fieldEncoderFromPolicy: FieldEncoderPolicy,
462
541
  public readonly fieldShapes: ReadonlyMap<FieldKindIdentifier, FlexFieldKind>,
463
542
  public readonly idCompressor: IIdCompressor,
543
+ private readonly incrementalEncoder: IncrementalEncoder | undefined,
464
544
  ) {}
465
545
 
466
546
  public nodeEncoderFromSchema(schemaName: TreeNodeSchemaIdentifier): NodeEncoder {
@@ -476,6 +556,30 @@ export class EncoderContext implements NodeEncodeBuilder, FieldEncodeBuilder {
476
556
  public nestedArrayEncoder(inner: NodeEncoder): NestedArrayEncoder {
477
557
  return getOrCreate(this.nestedArrayEncoders, inner, () => new NestedArrayEncoder(inner));
478
558
  }
559
+
560
+ public get shouldEncodeIncrementally(): boolean {
561
+ return this.incrementalEncoder !== undefined;
562
+ }
563
+
564
+ /**
565
+ * {@link IncrementalEncoder.encodeIncrementalField}
566
+ */
567
+ public encodeIncrementalField(
568
+ cursor: ITreeCursorSynchronous,
569
+ encoder: (chunk: TreeChunk) => BufferFormat,
570
+ ): ChunkReferenceId[] {
571
+ assert(
572
+ this.incrementalEncoder !== undefined,
573
+ 0xc2b /* incremental encoding must be enabled */,
574
+ );
575
+ // Encoder for the chunk that encodes its data using the provided encoder function and
576
+ // updates the encoded data for shapes and identifiers.
577
+ const chunkEncoder = (chunk: TreeChunk): EncodedFieldBatch => {
578
+ const chunkOutputBuffer = encoder(chunk);
579
+ return updateShapesAndIdentifiersEncoding(version, [chunkOutputBuffer]);
580
+ };
581
+ return this.incrementalEncoder.encodeIncrementalField(cursor, chunkEncoder);
582
+ }
479
583
  }
480
584
 
481
585
  export interface NodeEncodeBuilder {
@@ -47,6 +47,12 @@ export const EncodedInlineArrayShape = Type.Object(
47
47
  */
48
48
  export const EncodedAnyShape = Type.Literal(0);
49
49
 
50
+ /**
51
+ * Encoded content is a {@link ChunkReferenceId}.
52
+ * This represents the shape of a chunk that is encoded separately and is referenced by its {@link ChunkReferenceId}.
53
+ */
54
+ export const EncodedIncrementalChunkShape = Type.Literal(0);
55
+
50
56
  /**
51
57
  * Content of the encoded field is specified by the Shape referenced by the ShapeIndex.
52
58
  * This is a tuple for conciseness.
@@ -185,6 +191,10 @@ export const EncodedChunkShape = Type.Object(
185
191
  * {@link EncodedAnyShape} union member.
186
192
  */
187
193
  d: Type.Optional(EncodedAnyShape),
194
+ /**
195
+ * {@link EncodedIncrementalChunkShape} union member.
196
+ */
197
+ e: Type.Optional(EncodedIncrementalChunkShape),
188
198
  },
189
199
  unionOptions,
190
200
  );
@@ -195,6 +205,7 @@ export type EncodedNestedArrayShape = Static<typeof EncodedNestedArrayShape>;
195
205
  export type EncodedInlineArrayShape = Static<typeof EncodedInlineArrayShape>;
196
206
  export type EncodedNodeShape = Static<typeof EncodedNodeShape>;
197
207
  export type EncodedAnyShape = Static<typeof EncodedAnyShape>;
208
+ export type EncodedIncrementalChunkShape = Static<typeof EncodedIncrementalChunkShape>;
198
209
 
199
210
  export const EncodedFieldBatch = EncodedFieldBatchGeneric(version, EncodedChunkShape);
200
211
  export type EncodedFieldBatch = Static<typeof EncodedFieldBatch>;
@@ -10,4 +10,8 @@ export {
10
10
  makeFieldBatchCodec,
11
11
  type FieldBatchEncodingContext,
12
12
  fluidVersionToFieldBatchCodecWriteVersion,
13
+ type IncrementalEncoderDecoder,
14
+ type IncrementalEncoder,
15
+ type IncrementalDecoder,
16
+ type ChunkReferenceId,
13
17
  } from "./codecs.js";