@fluid-experimental/tree 0.58.2002 → 0.59.1000

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 (817) hide show
  1. package/README.md +159 -46
  2. package/dist/ChangeCompression.d.ts +39 -0
  3. package/dist/ChangeCompression.d.ts.map +1 -0
  4. package/dist/ChangeCompression.js +117 -0
  5. package/dist/ChangeCompression.js.map +1 -0
  6. package/{lib/default-edits/PersistedTypes.d.ts → dist/ChangeTypes.d.ts} +58 -105
  7. package/dist/ChangeTypes.d.ts.map +1 -0
  8. package/dist/{default-edits/PersistedTypes.js → ChangeTypes.js} +21 -76
  9. package/dist/ChangeTypes.js.map +1 -0
  10. package/dist/Checkout.d.ts +39 -27
  11. package/dist/Checkout.d.ts.map +1 -1
  12. package/dist/Checkout.js +61 -32
  13. package/dist/Checkout.js.map +1 -1
  14. package/dist/Common.d.ts +175 -38
  15. package/dist/Common.d.ts.map +1 -1
  16. package/dist/Common.js +240 -103
  17. package/dist/Common.js.map +1 -1
  18. package/dist/EagerCheckout.d.ts +24 -0
  19. package/dist/EagerCheckout.d.ts.map +1 -0
  20. package/dist/{BasicCheckout.js → EagerCheckout.js} +9 -6
  21. package/dist/EagerCheckout.js.map +1 -0
  22. package/dist/EditLog.d.ts +77 -63
  23. package/dist/EditLog.d.ts.map +1 -1
  24. package/dist/EditLog.js +85 -48
  25. package/dist/EditLog.js.map +1 -1
  26. package/dist/EditUtilities.d.ts +168 -0
  27. package/dist/EditUtilities.d.ts.map +1 -0
  28. package/dist/EditUtilities.js +373 -0
  29. package/dist/EditUtilities.js.map +1 -0
  30. package/dist/EventTypes.d.ts +73 -0
  31. package/dist/EventTypes.d.ts.map +1 -0
  32. package/dist/EventTypes.js +78 -0
  33. package/dist/EventTypes.js.map +1 -0
  34. package/dist/Forest.d.ts +29 -7
  35. package/dist/Forest.d.ts.map +1 -1
  36. package/dist/Forest.js +60 -36
  37. package/dist/Forest.js.map +1 -1
  38. package/dist/HistoryEditFactory.d.ts +20 -0
  39. package/dist/HistoryEditFactory.d.ts.map +1 -0
  40. package/dist/HistoryEditFactory.js +226 -0
  41. package/dist/HistoryEditFactory.js.map +1 -0
  42. package/dist/IdConversion.d.ts +12 -0
  43. package/dist/IdConversion.d.ts.map +1 -0
  44. package/dist/IdConversion.js +98 -0
  45. package/dist/IdConversion.js.map +1 -0
  46. package/dist/Identifiers.d.ts +89 -2
  47. package/dist/Identifiers.d.ts.map +1 -1
  48. package/dist/Identifiers.js +10 -0
  49. package/dist/Identifiers.js.map +1 -1
  50. package/dist/InitialTree.d.ts +2 -2
  51. package/dist/InitialTree.d.ts.map +1 -1
  52. package/dist/InitialTree.js +2 -1
  53. package/dist/InitialTree.js.map +1 -1
  54. package/dist/LazyCheckout.d.ts +28 -0
  55. package/dist/LazyCheckout.d.ts.map +1 -0
  56. package/dist/LazyCheckout.js +44 -0
  57. package/dist/LazyCheckout.js.map +1 -0
  58. package/dist/LogViewer.d.ts +129 -85
  59. package/dist/LogViewer.d.ts.map +1 -1
  60. package/dist/LogViewer.js +111 -85
  61. package/dist/LogViewer.js.map +1 -1
  62. package/dist/MergeHealth.d.ts +221 -0
  63. package/dist/MergeHealth.d.ts.map +1 -0
  64. package/dist/MergeHealth.js +263 -0
  65. package/dist/MergeHealth.js.map +1 -0
  66. package/dist/NodeIdUtilities.d.ts +105 -0
  67. package/dist/NodeIdUtilities.d.ts.map +1 -0
  68. package/dist/NodeIdUtilities.js +60 -0
  69. package/dist/NodeIdUtilities.js.map +1 -0
  70. package/dist/PayloadUtilities.d.ts +42 -0
  71. package/dist/PayloadUtilities.d.ts.map +1 -0
  72. package/dist/PayloadUtilities.js +114 -0
  73. package/dist/PayloadUtilities.js.map +1 -0
  74. package/dist/ReconciliationPath.d.ts +18 -13
  75. package/dist/ReconciliationPath.d.ts.map +1 -1
  76. package/dist/ReconciliationPath.js.map +1 -1
  77. package/dist/RevisionValueCache.d.ts +11 -2
  78. package/dist/RevisionValueCache.d.ts.map +1 -1
  79. package/dist/RevisionValueCache.js +2 -3
  80. package/dist/RevisionValueCache.js.map +1 -1
  81. package/dist/RevisionView.d.ts +83 -0
  82. package/dist/RevisionView.d.ts.map +1 -0
  83. package/dist/RevisionView.js +182 -0
  84. package/dist/RevisionView.js.map +1 -0
  85. package/dist/SerializationUtilities.d.ts +36 -0
  86. package/dist/SerializationUtilities.d.ts.map +1 -0
  87. package/dist/SerializationUtilities.js +102 -0
  88. package/dist/SerializationUtilities.js.map +1 -0
  89. package/dist/SharedTree.d.ts +439 -0
  90. package/dist/SharedTree.d.ts.map +1 -0
  91. package/dist/SharedTree.js +1109 -0
  92. package/dist/SharedTree.js.map +1 -0
  93. package/dist/SharedTreeEncoder.d.ts +102 -0
  94. package/dist/SharedTreeEncoder.d.ts.map +1 -0
  95. package/dist/SharedTreeEncoder.js +313 -0
  96. package/dist/SharedTreeEncoder.js.map +1 -0
  97. package/dist/StringInterner.d.ts +46 -0
  98. package/dist/StringInterner.d.ts.map +1 -0
  99. package/dist/StringInterner.js +61 -0
  100. package/dist/StringInterner.js.map +1 -0
  101. package/dist/Summary.d.ts +40 -0
  102. package/dist/Summary.d.ts.map +1 -0
  103. package/dist/Summary.js +23 -0
  104. package/dist/Summary.js.map +1 -0
  105. package/dist/SummaryBackCompatibility.d.ts +22 -22
  106. package/dist/SummaryBackCompatibility.d.ts.map +1 -1
  107. package/dist/SummaryBackCompatibility.js +30 -33
  108. package/dist/SummaryBackCompatibility.js.map +1 -1
  109. package/dist/SummaryTestUtilities.d.ts +31 -0
  110. package/dist/SummaryTestUtilities.d.ts.map +1 -0
  111. package/dist/SummaryTestUtilities.js +37 -0
  112. package/dist/SummaryTestUtilities.js.map +1 -0
  113. package/dist/Transaction.d.ts +52 -0
  114. package/dist/Transaction.d.ts.map +1 -0
  115. package/dist/Transaction.js +72 -0
  116. package/dist/Transaction.js.map +1 -0
  117. package/dist/TransactionInternal.d.ts +540 -0
  118. package/dist/TransactionInternal.d.ts.map +1 -0
  119. package/dist/TransactionInternal.js +626 -0
  120. package/dist/TransactionInternal.js.map +1 -0
  121. package/dist/TreeCompressor.d.ts +36 -0
  122. package/dist/TreeCompressor.d.ts.map +1 -0
  123. package/dist/TreeCompressor.js +137 -0
  124. package/dist/TreeCompressor.js.map +1 -0
  125. package/dist/TreeNodeHandle.d.ts +12 -18
  126. package/dist/TreeNodeHandle.d.ts.map +1 -1
  127. package/dist/TreeNodeHandle.js +13 -23
  128. package/dist/TreeNodeHandle.js.map +1 -1
  129. package/dist/TreeView.d.ts +166 -0
  130. package/dist/TreeView.d.ts.map +1 -0
  131. package/dist/TreeView.js +218 -0
  132. package/dist/TreeView.js.map +1 -0
  133. package/dist/TreeViewUtilities.d.ts +21 -0
  134. package/dist/TreeViewUtilities.d.ts.map +1 -0
  135. package/dist/TreeViewUtilities.js +77 -0
  136. package/dist/TreeViewUtilities.js.map +1 -0
  137. package/dist/{default-edits/UndoRedoHandler.d.ts → UndoRedoHandler.d.ts} +2 -2
  138. package/dist/UndoRedoHandler.d.ts.map +1 -0
  139. package/dist/{default-edits/UndoRedoHandler.js → UndoRedoHandler.js} +5 -9
  140. package/dist/UndoRedoHandler.js.map +1 -0
  141. package/dist/id-compressor/AppendOnlySortedMap.d.ts +127 -0
  142. package/dist/id-compressor/AppendOnlySortedMap.d.ts.map +1 -0
  143. package/dist/id-compressor/AppendOnlySortedMap.js +283 -0
  144. package/dist/id-compressor/AppendOnlySortedMap.js.map +1 -0
  145. package/dist/id-compressor/IdCompressor.d.ts +389 -0
  146. package/dist/id-compressor/IdCompressor.d.ts.map +1 -0
  147. package/dist/id-compressor/IdCompressor.js +1353 -0
  148. package/dist/id-compressor/IdCompressor.js.map +1 -0
  149. package/dist/id-compressor/IdRange.d.ts +11 -0
  150. package/dist/id-compressor/IdRange.d.ts.map +1 -0
  151. package/dist/id-compressor/IdRange.js +29 -0
  152. package/dist/id-compressor/IdRange.js.map +1 -0
  153. package/dist/id-compressor/NumericUuid.d.ts +63 -0
  154. package/dist/id-compressor/NumericUuid.d.ts.map +1 -0
  155. package/dist/id-compressor/NumericUuid.js +377 -0
  156. package/dist/id-compressor/NumericUuid.js.map +1 -0
  157. package/dist/id-compressor/index.d.ts +12 -0
  158. package/dist/id-compressor/index.d.ts.map +1 -0
  159. package/dist/id-compressor/index.js +26 -0
  160. package/dist/id-compressor/index.js.map +1 -0
  161. package/dist/id-compressor/persisted-types/0.0.1.d.ts +156 -0
  162. package/dist/id-compressor/persisted-types/0.0.1.d.ts.map +1 -0
  163. package/dist/id-compressor/persisted-types/0.0.1.js +7 -0
  164. package/dist/id-compressor/persisted-types/0.0.1.js.map +1 -0
  165. package/dist/id-compressor/persisted-types/index.d.ts +6 -0
  166. package/dist/id-compressor/persisted-types/index.d.ts.map +1 -0
  167. package/dist/id-compressor/persisted-types/index.js +18 -0
  168. package/dist/id-compressor/persisted-types/index.js.map +1 -0
  169. package/dist/index.d.ts +29 -9
  170. package/dist/index.d.ts.map +1 -1
  171. package/dist/index.js +50 -35
  172. package/dist/index.js.map +1 -1
  173. package/dist/persisted-types/0.0.2.d.ts +385 -0
  174. package/dist/persisted-types/0.0.2.d.ts.map +1 -0
  175. package/dist/persisted-types/0.0.2.js +113 -0
  176. package/dist/persisted-types/0.0.2.js.map +1 -0
  177. package/dist/persisted-types/0.1.1.d.ts +314 -0
  178. package/dist/persisted-types/0.1.1.d.ts.map +1 -0
  179. package/dist/persisted-types/0.1.1.js +153 -0
  180. package/dist/persisted-types/0.1.1.js.map +1 -0
  181. package/dist/persisted-types/index.d.ts +7 -0
  182. package/dist/persisted-types/index.d.ts.map +1 -0
  183. package/dist/persisted-types/index.js +20 -0
  184. package/dist/persisted-types/index.js.map +1 -0
  185. package/docs/0-1-1-Compression.md +228 -0
  186. package/docs/Breaking-Change-Migration.md +52 -0
  187. package/docs/Compression.md +2 -2
  188. package/docs/Telemetry.md +43 -0
  189. package/docs/Write-Format.md +19 -0
  190. package/lib/ChangeCompression.d.ts +39 -0
  191. package/lib/ChangeCompression.d.ts.map +1 -0
  192. package/lib/ChangeCompression.js +111 -0
  193. package/lib/ChangeCompression.js.map +1 -0
  194. package/{dist/default-edits/PersistedTypes.d.ts → lib/ChangeTypes.d.ts} +58 -105
  195. package/lib/ChangeTypes.d.ts.map +1 -0
  196. package/lib/{default-edits/PersistedTypes.js → ChangeTypes.js} +15 -68
  197. package/lib/ChangeTypes.js.map +1 -0
  198. package/lib/Checkout.d.ts +39 -27
  199. package/lib/Checkout.d.ts.map +1 -1
  200. package/lib/Checkout.js +53 -24
  201. package/lib/Checkout.js.map +1 -1
  202. package/lib/Common.d.ts +175 -38
  203. package/lib/Common.d.ts.map +1 -1
  204. package/lib/Common.js +226 -101
  205. package/lib/Common.js.map +1 -1
  206. package/lib/EagerCheckout.d.ts +24 -0
  207. package/lib/EagerCheckout.d.ts.map +1 -0
  208. package/lib/{BasicCheckout.js → EagerCheckout.js} +7 -4
  209. package/lib/EagerCheckout.js.map +1 -0
  210. package/lib/EditLog.d.ts +77 -63
  211. package/lib/EditLog.d.ts.map +1 -1
  212. package/lib/EditLog.js +83 -47
  213. package/lib/EditLog.js.map +1 -1
  214. package/lib/EditUtilities.d.ts +168 -0
  215. package/lib/EditUtilities.d.ts.map +1 -0
  216. package/lib/EditUtilities.js +353 -0
  217. package/lib/EditUtilities.js.map +1 -0
  218. package/lib/EventTypes.d.ts +73 -0
  219. package/lib/EventTypes.d.ts.map +1 -0
  220. package/lib/EventTypes.js +75 -0
  221. package/lib/EventTypes.js.map +1 -0
  222. package/lib/Forest.d.ts +29 -7
  223. package/lib/Forest.d.ts.map +1 -1
  224. package/lib/Forest.js +58 -35
  225. package/lib/Forest.js.map +1 -1
  226. package/lib/HistoryEditFactory.d.ts +20 -0
  227. package/lib/HistoryEditFactory.d.ts.map +1 -0
  228. package/lib/{default-edits/HistoryEditFactory.js → HistoryEditFactory.js} +78 -39
  229. package/lib/HistoryEditFactory.js.map +1 -0
  230. package/lib/IdConversion.d.ts +12 -0
  231. package/lib/IdConversion.d.ts.map +1 -0
  232. package/lib/IdConversion.js +91 -0
  233. package/lib/IdConversion.js.map +1 -0
  234. package/lib/Identifiers.d.ts +89 -2
  235. package/lib/Identifiers.d.ts.map +1 -1
  236. package/lib/Identifiers.js +8 -1
  237. package/lib/Identifiers.js.map +1 -1
  238. package/lib/InitialTree.d.ts +2 -2
  239. package/lib/InitialTree.d.ts.map +1 -1
  240. package/lib/InitialTree.js +2 -1
  241. package/lib/InitialTree.js.map +1 -1
  242. package/lib/LazyCheckout.d.ts +28 -0
  243. package/lib/LazyCheckout.d.ts.map +1 -0
  244. package/lib/LazyCheckout.js +40 -0
  245. package/lib/LazyCheckout.js.map +1 -0
  246. package/lib/LogViewer.d.ts +129 -85
  247. package/lib/LogViewer.d.ts.map +1 -1
  248. package/lib/LogViewer.js +103 -77
  249. package/lib/LogViewer.js.map +1 -1
  250. package/lib/MergeHealth.d.ts +221 -0
  251. package/lib/MergeHealth.d.ts.map +1 -0
  252. package/lib/MergeHealth.js +258 -0
  253. package/lib/MergeHealth.js.map +1 -0
  254. package/lib/NodeIdUtilities.d.ts +105 -0
  255. package/lib/NodeIdUtilities.d.ts.map +1 -0
  256. package/lib/NodeIdUtilities.js +53 -0
  257. package/lib/NodeIdUtilities.js.map +1 -0
  258. package/lib/PayloadUtilities.d.ts +42 -0
  259. package/lib/PayloadUtilities.d.ts.map +1 -0
  260. package/lib/PayloadUtilities.js +110 -0
  261. package/lib/PayloadUtilities.js.map +1 -0
  262. package/lib/ReconciliationPath.d.ts +18 -13
  263. package/lib/ReconciliationPath.d.ts.map +1 -1
  264. package/lib/ReconciliationPath.js.map +1 -1
  265. package/lib/RevisionValueCache.d.ts +11 -2
  266. package/lib/RevisionValueCache.d.ts.map +1 -1
  267. package/lib/RevisionValueCache.js +2 -3
  268. package/lib/RevisionValueCache.js.map +1 -1
  269. package/lib/RevisionView.d.ts +83 -0
  270. package/lib/RevisionView.d.ts.map +1 -0
  271. package/lib/RevisionView.js +175 -0
  272. package/lib/RevisionView.js.map +1 -0
  273. package/lib/SerializationUtilities.d.ts +36 -0
  274. package/lib/SerializationUtilities.d.ts.map +1 -0
  275. package/lib/SerializationUtilities.js +95 -0
  276. package/lib/SerializationUtilities.js.map +1 -0
  277. package/lib/SharedTree.d.ts +439 -0
  278. package/lib/SharedTree.d.ts.map +1 -0
  279. package/lib/SharedTree.js +1104 -0
  280. package/lib/SharedTree.js.map +1 -0
  281. package/lib/SharedTreeEncoder.d.ts +102 -0
  282. package/lib/SharedTreeEncoder.d.ts.map +1 -0
  283. package/lib/SharedTreeEncoder.js +308 -0
  284. package/lib/SharedTreeEncoder.js.map +1 -0
  285. package/lib/StringInterner.d.ts +46 -0
  286. package/lib/StringInterner.d.ts.map +1 -0
  287. package/lib/StringInterner.js +57 -0
  288. package/lib/StringInterner.js.map +1 -0
  289. package/lib/Summary.d.ts +40 -0
  290. package/lib/Summary.d.ts.map +1 -0
  291. package/lib/Summary.js +19 -0
  292. package/lib/Summary.js.map +1 -0
  293. package/lib/SummaryBackCompatibility.d.ts +22 -22
  294. package/lib/SummaryBackCompatibility.d.ts.map +1 -1
  295. package/lib/SummaryBackCompatibility.js +29 -32
  296. package/lib/SummaryBackCompatibility.js.map +1 -1
  297. package/lib/SummaryTestUtilities.d.ts +31 -0
  298. package/lib/SummaryTestUtilities.d.ts.map +1 -0
  299. package/lib/SummaryTestUtilities.js +32 -0
  300. package/lib/SummaryTestUtilities.js.map +1 -0
  301. package/lib/Transaction.d.ts +52 -0
  302. package/lib/Transaction.d.ts.map +1 -0
  303. package/lib/Transaction.js +68 -0
  304. package/lib/Transaction.js.map +1 -0
  305. package/lib/TransactionInternal.d.ts +540 -0
  306. package/lib/TransactionInternal.d.ts.map +1 -0
  307. package/lib/TransactionInternal.js +622 -0
  308. package/lib/TransactionInternal.js.map +1 -0
  309. package/lib/TreeCompressor.d.ts +36 -0
  310. package/lib/TreeCompressor.d.ts.map +1 -0
  311. package/lib/TreeCompressor.js +133 -0
  312. package/lib/TreeCompressor.js.map +1 -0
  313. package/lib/TreeNodeHandle.d.ts +12 -18
  314. package/lib/TreeNodeHandle.d.ts.map +1 -1
  315. package/lib/TreeNodeHandle.js +14 -24
  316. package/lib/TreeNodeHandle.js.map +1 -1
  317. package/lib/TreeView.d.ts +166 -0
  318. package/lib/TreeView.d.ts.map +1 -0
  319. package/lib/TreeView.js +214 -0
  320. package/lib/TreeView.js.map +1 -0
  321. package/lib/TreeViewUtilities.d.ts +21 -0
  322. package/lib/TreeViewUtilities.d.ts.map +1 -0
  323. package/lib/TreeViewUtilities.js +71 -0
  324. package/lib/TreeViewUtilities.js.map +1 -0
  325. package/lib/{default-edits/UndoRedoHandler.d.ts → UndoRedoHandler.d.ts} +2 -2
  326. package/lib/UndoRedoHandler.d.ts.map +1 -0
  327. package/lib/{default-edits/UndoRedoHandler.js → UndoRedoHandler.js} +3 -7
  328. package/lib/UndoRedoHandler.js.map +1 -0
  329. package/lib/id-compressor/AppendOnlySortedMap.d.ts +127 -0
  330. package/lib/id-compressor/AppendOnlySortedMap.d.ts.map +1 -0
  331. package/lib/id-compressor/AppendOnlySortedMap.js +278 -0
  332. package/lib/id-compressor/AppendOnlySortedMap.js.map +1 -0
  333. package/lib/id-compressor/IdCompressor.d.ts +389 -0
  334. package/lib/id-compressor/IdCompressor.d.ts.map +1 -0
  335. package/lib/id-compressor/IdCompressor.js +1343 -0
  336. package/lib/id-compressor/IdCompressor.js.map +1 -0
  337. package/lib/id-compressor/IdRange.d.ts +11 -0
  338. package/lib/id-compressor/IdRange.d.ts.map +1 -0
  339. package/lib/id-compressor/IdRange.js +25 -0
  340. package/lib/id-compressor/IdRange.js.map +1 -0
  341. package/lib/id-compressor/NumericUuid.d.ts +63 -0
  342. package/lib/id-compressor/NumericUuid.d.ts.map +1 -0
  343. package/lib/id-compressor/NumericUuid.js +365 -0
  344. package/lib/id-compressor/NumericUuid.js.map +1 -0
  345. package/lib/id-compressor/index.d.ts +12 -0
  346. package/lib/id-compressor/index.d.ts.map +1 -0
  347. package/lib/id-compressor/index.js +12 -0
  348. package/lib/id-compressor/index.js.map +1 -0
  349. package/lib/id-compressor/persisted-types/0.0.1.d.ts +156 -0
  350. package/lib/id-compressor/persisted-types/0.0.1.d.ts.map +1 -0
  351. package/lib/{test/Snapshot.tests.d.ts → id-compressor/persisted-types/0.0.1.js} +1 -1
  352. package/lib/id-compressor/persisted-types/0.0.1.js.map +1 -0
  353. package/lib/id-compressor/persisted-types/index.d.ts +6 -0
  354. package/lib/id-compressor/persisted-types/index.d.ts.map +1 -0
  355. package/lib/id-compressor/persisted-types/index.js +6 -0
  356. package/lib/id-compressor/persisted-types/index.js.map +1 -0
  357. package/lib/index.d.ts +29 -9
  358. package/lib/index.d.ts.map +1 -1
  359. package/lib/index.js +23 -6
  360. package/lib/index.js.map +1 -1
  361. package/lib/persisted-types/0.0.2.d.ts +385 -0
  362. package/lib/persisted-types/0.0.2.d.ts.map +1 -0
  363. package/lib/persisted-types/0.0.2.js +110 -0
  364. package/lib/persisted-types/0.0.2.js.map +1 -0
  365. package/lib/persisted-types/0.1.1.d.ts +314 -0
  366. package/lib/persisted-types/0.1.1.d.ts.map +1 -0
  367. package/lib/persisted-types/0.1.1.js +150 -0
  368. package/lib/persisted-types/0.1.1.js.map +1 -0
  369. package/lib/persisted-types/index.d.ts +7 -0
  370. package/lib/persisted-types/index.d.ts.map +1 -0
  371. package/lib/persisted-types/index.js +8 -0
  372. package/lib/persisted-types/index.js.map +1 -0
  373. package/lib/test/AppendOnlySortedMap.tests.d.ts +6 -0
  374. package/lib/test/AppendOnlySortedMap.tests.d.ts.map +1 -0
  375. package/lib/test/AppendOnlySortedMap.tests.js +169 -0
  376. package/lib/test/AppendOnlySortedMap.tests.js.map +1 -0
  377. package/lib/test/{SnapshotUtilities.tests.d.ts → ChangeCompression.tests.d.ts} +1 -1
  378. package/lib/test/ChangeCompression.tests.d.ts.map +1 -0
  379. package/lib/test/ChangeCompression.tests.js +145 -0
  380. package/lib/test/ChangeCompression.tests.js.map +1 -0
  381. package/lib/test/Checkout.tests.d.ts +2 -3
  382. package/lib/test/Checkout.tests.d.ts.map +1 -1
  383. package/lib/test/Checkout.tests.js +126 -69
  384. package/lib/test/Checkout.tests.js.map +1 -1
  385. package/lib/test/Common.tests.js +60 -2
  386. package/lib/test/Common.tests.js.map +1 -1
  387. package/lib/test/{BasicCheckout.tests.d.ts → EagerCheckout.tests.d.ts} +1 -1
  388. package/lib/test/EagerCheckout.tests.d.ts.map +1 -0
  389. package/lib/test/EagerCheckout.tests.js +20 -0
  390. package/lib/test/EagerCheckout.tests.js.map +1 -0
  391. package/lib/test/Edit.tests.js +22 -14
  392. package/lib/test/Edit.tests.js.map +1 -1
  393. package/lib/test/{Anchors.glassBox.tests.d.ts → EditLog.perf.tests.d.ts} +1 -1
  394. package/lib/test/EditLog.perf.tests.d.ts.map +1 -0
  395. package/lib/test/EditLog.perf.tests.js +30 -0
  396. package/lib/test/EditLog.perf.tests.js.map +1 -0
  397. package/lib/test/EditLog.tests.js +10 -6
  398. package/lib/test/EditLog.tests.js.map +1 -1
  399. package/lib/test/EditUtilities.tests.d.ts +6 -0
  400. package/lib/test/EditUtilities.tests.d.ts.map +1 -0
  401. package/lib/test/EditUtilities.tests.js +503 -0
  402. package/lib/test/EditUtilities.tests.js.map +1 -0
  403. package/lib/test/Forest.perf.tests.d.ts +6 -0
  404. package/lib/test/Forest.perf.tests.d.ts.map +1 -0
  405. package/lib/test/Forest.perf.tests.js +133 -0
  406. package/lib/test/Forest.perf.tests.js.map +1 -0
  407. package/lib/test/Forest.tests.js +54 -27
  408. package/lib/test/Forest.tests.js.map +1 -1
  409. package/lib/test/GenericTransaction.tests.js +12 -3
  410. package/lib/test/GenericTransaction.tests.js.map +1 -1
  411. package/lib/test/HistoryEditFactory.tests.d.ts +6 -0
  412. package/lib/test/HistoryEditFactory.tests.d.ts.map +1 -0
  413. package/lib/test/HistoryEditFactory.tests.js +90 -0
  414. package/lib/test/HistoryEditFactory.tests.js.map +1 -0
  415. package/lib/test/IdCompressor.perf.tests.d.ts +6 -0
  416. package/lib/test/IdCompressor.perf.tests.d.ts.map +1 -0
  417. package/lib/test/IdCompressor.perf.tests.js +304 -0
  418. package/lib/test/IdCompressor.perf.tests.js.map +1 -0
  419. package/lib/test/IdCompressor.tests.d.ts +6 -0
  420. package/lib/test/IdCompressor.tests.d.ts.map +1 -0
  421. package/lib/test/IdCompressor.tests.js +1075 -0
  422. package/lib/test/IdCompressor.tests.js.map +1 -0
  423. package/lib/test/IdConversion.tests.d.ts +6 -0
  424. package/lib/test/IdConversion.tests.d.ts.map +1 -0
  425. package/lib/test/IdConversion.tests.js +36 -0
  426. package/lib/test/IdConversion.tests.js.map +1 -0
  427. package/lib/test/LazyCheckout.tests.d.ts +6 -0
  428. package/lib/test/LazyCheckout.tests.d.ts.map +1 -0
  429. package/lib/test/LazyCheckout.tests.js +22 -0
  430. package/lib/test/LazyCheckout.tests.js.map +1 -0
  431. package/lib/test/LogViewer.tests.js +276 -191
  432. package/lib/test/LogViewer.tests.js.map +1 -1
  433. package/lib/test/{SharedTreeWithAnchors.tests.d.ts → MergeHealthTelemetryHeartbeat.tests.d.ts} +1 -1
  434. package/lib/test/MergeHealthTelemetryHeartbeat.tests.d.ts.map +1 -0
  435. package/lib/test/MergeHealthTelemetryHeartbeat.tests.js +342 -0
  436. package/lib/test/MergeHealthTelemetryHeartbeat.tests.js.map +1 -0
  437. package/lib/test/NumericUuid.perf.tests.d.ts +6 -0
  438. package/lib/test/NumericUuid.perf.tests.d.ts.map +1 -0
  439. package/lib/test/NumericUuid.perf.tests.js +68 -0
  440. package/lib/test/NumericUuid.perf.tests.js.map +1 -0
  441. package/lib/test/NumericUuid.tests.d.ts +6 -0
  442. package/lib/test/NumericUuid.tests.d.ts.map +1 -0
  443. package/lib/test/NumericUuid.tests.js +191 -0
  444. package/lib/test/NumericUuid.tests.js.map +1 -0
  445. package/lib/test/RevisionView.tests.d.ts +6 -0
  446. package/lib/test/RevisionView.tests.d.ts.map +1 -0
  447. package/lib/test/RevisionView.tests.js +133 -0
  448. package/lib/test/RevisionView.tests.js.map +1 -0
  449. package/lib/test/SharedTree.perf.tests.d.ts +6 -0
  450. package/lib/test/SharedTree.perf.tests.d.ts.map +1 -0
  451. package/lib/test/SharedTree.perf.tests.js +39 -0
  452. package/lib/test/SharedTree.perf.tests.js.map +1 -0
  453. package/lib/test/SharedTree.tests.js +15 -3
  454. package/lib/test/SharedTree.tests.js.map +1 -1
  455. package/lib/test/StringInterner.tests.d.ts +6 -0
  456. package/lib/test/StringInterner.tests.d.ts.map +1 -0
  457. package/lib/test/StringInterner.tests.js +71 -0
  458. package/lib/test/StringInterner.tests.js.map +1 -0
  459. package/lib/test/Summary.tests.d.ts +8 -0
  460. package/lib/test/Summary.tests.d.ts.map +1 -0
  461. package/lib/test/Summary.tests.js +407 -0
  462. package/lib/test/Summary.tests.js.map +1 -0
  463. package/lib/test/Transaction.tests.js +76 -330
  464. package/lib/test/Transaction.tests.js.map +1 -1
  465. package/lib/test/TransactionInternal.tests.d.ts +6 -0
  466. package/lib/test/TransactionInternal.tests.d.ts.map +1 -0
  467. package/lib/test/TransactionInternal.tests.js +568 -0
  468. package/lib/test/TransactionInternal.tests.js.map +1 -0
  469. package/lib/test/TreeCompression.tests.d.ts +6 -0
  470. package/lib/test/TreeCompression.tests.d.ts.map +1 -0
  471. package/lib/test/TreeCompression.tests.js +292 -0
  472. package/lib/test/TreeCompression.tests.js.map +1 -0
  473. package/lib/test/TreeView.tests.d.ts +6 -0
  474. package/lib/test/TreeView.tests.d.ts.map +1 -0
  475. package/lib/test/TreeView.tests.js +176 -0
  476. package/lib/test/TreeView.tests.js.map +1 -0
  477. package/lib/test/UndoRedoHandler.tests.js +2 -2
  478. package/lib/test/UndoRedoHandler.tests.js.map +1 -1
  479. package/lib/test/Virtualization.tests.js +146 -62
  480. package/lib/test/Virtualization.tests.js.map +1 -1
  481. package/lib/test/fuzz/Generators.d.ts +19 -0
  482. package/lib/test/fuzz/Generators.d.ts.map +1 -0
  483. package/lib/test/fuzz/Generators.js +420 -0
  484. package/lib/test/fuzz/Generators.js.map +1 -0
  485. package/lib/test/fuzz/SharedTreeFuzzTests.d.ts +20 -0
  486. package/lib/test/fuzz/SharedTreeFuzzTests.d.ts.map +1 -0
  487. package/lib/test/fuzz/SharedTreeFuzzTests.js +217 -0
  488. package/lib/test/fuzz/SharedTreeFuzzTests.js.map +1 -0
  489. package/lib/test/fuzz/Types.d.ts +133 -0
  490. package/lib/test/fuzz/Types.d.ts.map +1 -0
  491. package/lib/test/{GenericTransactionWithAnchors.tests.d.ts → fuzz/Types.js} +2 -2
  492. package/lib/test/fuzz/Types.js.map +1 -0
  493. package/lib/test/utilities/IdCompressorTestUtilities.d.ts +180 -0
  494. package/lib/test/utilities/IdCompressorTestUtilities.d.ts.map +1 -0
  495. package/lib/test/utilities/IdCompressorTestUtilities.js +528 -0
  496. package/lib/test/utilities/IdCompressorTestUtilities.js.map +1 -0
  497. package/lib/test/utilities/MockTransaction.d.ts +26 -7
  498. package/lib/test/utilities/MockTransaction.d.ts.map +1 -1
  499. package/lib/test/utilities/MockTransaction.js +40 -11
  500. package/lib/test/utilities/MockTransaction.js.map +1 -1
  501. package/lib/test/utilities/PendingLocalStateTests.d.ts +12 -0
  502. package/lib/test/utilities/PendingLocalStateTests.d.ts.map +1 -0
  503. package/lib/test/utilities/PendingLocalStateTests.js +105 -0
  504. package/lib/test/utilities/PendingLocalStateTests.js.map +1 -0
  505. package/lib/test/utilities/SharedTreeTests.d.ts +3 -4
  506. package/lib/test/utilities/SharedTreeTests.d.ts.map +1 -1
  507. package/lib/test/utilities/SharedTreeTests.js +696 -439
  508. package/lib/test/utilities/SharedTreeTests.js.map +1 -1
  509. package/lib/test/utilities/SharedTreeVersioningTests.d.ts +11 -0
  510. package/lib/test/utilities/SharedTreeVersioningTests.d.ts.map +1 -0
  511. package/lib/test/utilities/SharedTreeVersioningTests.js +370 -0
  512. package/lib/test/utilities/SharedTreeVersioningTests.js.map +1 -0
  513. package/lib/test/utilities/SummaryLoadPerfTests.d.ts +10 -0
  514. package/lib/test/utilities/SummaryLoadPerfTests.d.ts.map +1 -0
  515. package/lib/test/utilities/SummaryLoadPerfTests.js +102 -0
  516. package/lib/test/utilities/SummaryLoadPerfTests.js.map +1 -0
  517. package/lib/test/utilities/SummarySizeTests.d.ts +11 -0
  518. package/lib/test/utilities/SummarySizeTests.d.ts.map +1 -0
  519. package/lib/test/utilities/SummarySizeTests.js +158 -0
  520. package/lib/test/utilities/SummarySizeTests.js.map +1 -0
  521. package/lib/test/utilities/TestCommon.d.ts +9 -0
  522. package/lib/test/utilities/TestCommon.d.ts.map +1 -0
  523. package/lib/test/utilities/TestCommon.js +13 -0
  524. package/lib/test/utilities/TestCommon.js.map +1 -0
  525. package/lib/test/utilities/TestNode.d.ts +140 -0
  526. package/lib/test/utilities/TestNode.d.ts.map +1 -0
  527. package/lib/test/utilities/TestNode.js +292 -0
  528. package/lib/test/utilities/TestNode.js.map +1 -0
  529. package/lib/test/utilities/TestUtilities.d.ts +84 -70
  530. package/lib/test/utilities/TestUtilities.d.ts.map +1 -1
  531. package/lib/test/utilities/TestUtilities.js +218 -143
  532. package/lib/test/utilities/TestUtilities.js.map +1 -1
  533. package/lib/test/utilities/UndoRedoTests.d.ts +4 -5
  534. package/lib/test/utilities/UndoRedoTests.d.ts.map +1 -1
  535. package/lib/test/utilities/UndoRedoTests.js +138 -149
  536. package/lib/test/utilities/UndoRedoTests.js.map +1 -1
  537. package/package.json +22 -17
  538. package/src/ChangeCompression.ts +159 -0
  539. package/src/{default-edits/PersistedTypes.ts → ChangeTypes.ts} +62 -125
  540. package/src/Checkout.ts +82 -53
  541. package/src/Common.ts +317 -117
  542. package/src/EagerCheckout.ts +38 -0
  543. package/src/EditLog.ts +153 -100
  544. package/src/EditUtilities.ts +559 -0
  545. package/src/EventTypes.ts +74 -0
  546. package/src/Forest.ts +81 -73
  547. package/src/{default-edits/HistoryEditFactory.ts → HistoryEditFactory.ts} +103 -53
  548. package/src/IdConversion.ts +125 -0
  549. package/src/Identifiers.ts +101 -1
  550. package/src/InitialTree.ts +5 -4
  551. package/src/LazyCheckout.ts +51 -0
  552. package/src/LogViewer.ts +242 -166
  553. package/src/MergeHealth.ts +447 -0
  554. package/src/NodeIdUtilities.ts +156 -0
  555. package/src/PayloadUtilities.ts +124 -0
  556. package/src/ReconciliationPath.ts +18 -13
  557. package/src/RevisionValueCache.ts +14 -5
  558. package/src/RevisionView.ts +252 -0
  559. package/src/SerializationUtilities.ts +130 -0
  560. package/src/SharedTree.ts +1501 -0
  561. package/src/SharedTreeEncoder.ts +493 -0
  562. package/src/StringInterner.ts +72 -0
  563. package/src/Summary.ts +48 -0
  564. package/src/SummaryBackCompatibility.ts +47 -57
  565. package/src/SummaryTestUtilities.ts +54 -0
  566. package/src/Transaction.ts +89 -0
  567. package/src/TransactionInternal.ts +1087 -0
  568. package/src/TreeCompressor.ts +213 -0
  569. package/src/TreeNodeHandle.ts +19 -32
  570. package/src/TreeView.ts +322 -0
  571. package/src/TreeViewUtilities.ts +77 -0
  572. package/src/{default-edits/UndoRedoHandler.ts → UndoRedoHandler.ts} +8 -13
  573. package/src/id-compressor/AppendOnlySortedMap.ts +325 -0
  574. package/src/id-compressor/IdCompressor.md +3 -0
  575. package/src/id-compressor/IdCompressor.ts +1848 -0
  576. package/src/id-compressor/IdRange.ts +33 -0
  577. package/src/id-compressor/NumericUuid.ts +414 -0
  578. package/src/id-compressor/index.ts +13 -0
  579. package/src/id-compressor/persisted-types/0.0.1.ts +179 -0
  580. package/src/id-compressor/persisted-types/README.md +3 -0
  581. package/src/id-compressor/persisted-types/index.ts +6 -0
  582. package/src/index.ts +118 -59
  583. package/src/persisted-types/0.0.2.ts +442 -0
  584. package/src/persisted-types/0.1.1.ts +476 -0
  585. package/src/persisted-types/README.md +22 -0
  586. package/src/persisted-types/index.ts +9 -0
  587. package/.mocharc.js +0 -41
  588. package/api/tree.api.md +0 -729
  589. package/dist/BasicCheckout.d.ts +0 -23
  590. package/dist/BasicCheckout.d.ts.map +0 -1
  591. package/dist/BasicCheckout.js.map +0 -1
  592. package/dist/Snapshot.d.ts +0 -198
  593. package/dist/Snapshot.d.ts.map +0 -1
  594. package/dist/Snapshot.js +0 -267
  595. package/dist/Snapshot.js.map +0 -1
  596. package/dist/SnapshotUtilities.d.ts +0 -29
  597. package/dist/SnapshotUtilities.d.ts.map +0 -1
  598. package/dist/SnapshotUtilities.js +0 -73
  599. package/dist/SnapshotUtilities.js.map +0 -1
  600. package/dist/anchored-edits/AnchorResolution.d.ts +0 -144
  601. package/dist/anchored-edits/AnchorResolution.d.ts.map +0 -1
  602. package/dist/anchored-edits/AnchorResolution.js +0 -162
  603. package/dist/anchored-edits/AnchorResolution.js.map +0 -1
  604. package/dist/anchored-edits/Factory.d.ts +0 -56
  605. package/dist/anchored-edits/Factory.d.ts.map +0 -1
  606. package/dist/anchored-edits/Factory.js +0 -79
  607. package/dist/anchored-edits/Factory.js.map +0 -1
  608. package/dist/anchored-edits/PersistedTypes.d.ts +0 -245
  609. package/dist/anchored-edits/PersistedTypes.d.ts.map +0 -1
  610. package/dist/anchored-edits/PersistedTypes.js +0 -131
  611. package/dist/anchored-edits/PersistedTypes.js.map +0 -1
  612. package/dist/anchored-edits/SharedTreeWithAnchors.d.ts +0 -120
  613. package/dist/anchored-edits/SharedTreeWithAnchors.d.ts.map +0 -1
  614. package/dist/anchored-edits/SharedTreeWithAnchors.js +0 -115
  615. package/dist/anchored-edits/SharedTreeWithAnchors.js.map +0 -1
  616. package/dist/anchored-edits/TransactionWithAnchors.d.ts +0 -28
  617. package/dist/anchored-edits/TransactionWithAnchors.d.ts.map +0 -1
  618. package/dist/anchored-edits/TransactionWithAnchors.js +0 -36
  619. package/dist/anchored-edits/TransactionWithAnchors.js.map +0 -1
  620. package/dist/anchored-edits/index.d.ts +0 -10
  621. package/dist/anchored-edits/index.d.ts.map +0 -1
  622. package/dist/anchored-edits/index.js +0 -34
  623. package/dist/anchored-edits/index.js.map +0 -1
  624. package/dist/default-edits/EditUtilities.d.ts +0 -57
  625. package/dist/default-edits/EditUtilities.d.ts.map +0 -1
  626. package/dist/default-edits/EditUtilities.js +0 -192
  627. package/dist/default-edits/EditUtilities.js.map +0 -1
  628. package/dist/default-edits/Factory.d.ts +0 -56
  629. package/dist/default-edits/Factory.d.ts.map +0 -1
  630. package/dist/default-edits/Factory.js +0 -79
  631. package/dist/default-edits/Factory.js.map +0 -1
  632. package/dist/default-edits/HistoryEditFactory.d.ts +0 -19
  633. package/dist/default-edits/HistoryEditFactory.d.ts.map +0 -1
  634. package/dist/default-edits/HistoryEditFactory.js +0 -187
  635. package/dist/default-edits/HistoryEditFactory.js.map +0 -1
  636. package/dist/default-edits/PersistedTypes.d.ts.map +0 -1
  637. package/dist/default-edits/PersistedTypes.js.map +0 -1
  638. package/dist/default-edits/SharedTree.d.ts +0 -111
  639. package/dist/default-edits/SharedTree.d.ts.map +0 -1
  640. package/dist/default-edits/SharedTree.js +0 -124
  641. package/dist/default-edits/SharedTree.js.map +0 -1
  642. package/dist/default-edits/Summary.d.ts +0 -15
  643. package/dist/default-edits/Summary.d.ts.map +0 -1
  644. package/dist/default-edits/Summary.js +0 -35
  645. package/dist/default-edits/Summary.js.map +0 -1
  646. package/dist/default-edits/Transaction.d.ts +0 -41
  647. package/dist/default-edits/Transaction.d.ts.map +0 -1
  648. package/dist/default-edits/Transaction.js +0 -225
  649. package/dist/default-edits/Transaction.js.map +0 -1
  650. package/dist/default-edits/UndoRedoHandler.d.ts.map +0 -1
  651. package/dist/default-edits/UndoRedoHandler.js.map +0 -1
  652. package/dist/default-edits/index.d.ts +0 -13
  653. package/dist/default-edits/index.d.ts.map +0 -1
  654. package/dist/default-edits/index.js +0 -41
  655. package/dist/default-edits/index.js.map +0 -1
  656. package/dist/generic/GenericEditUtilities.d.ts +0 -26
  657. package/dist/generic/GenericEditUtilities.d.ts.map +0 -1
  658. package/dist/generic/GenericEditUtilities.js +0 -45
  659. package/dist/generic/GenericEditUtilities.js.map +0 -1
  660. package/dist/generic/GenericSharedTree.d.ts +0 -221
  661. package/dist/generic/GenericSharedTree.d.ts.map +0 -1
  662. package/dist/generic/GenericSharedTree.js +0 -447
  663. package/dist/generic/GenericSharedTree.js.map +0 -1
  664. package/dist/generic/GenericTransaction.d.ts +0 -87
  665. package/dist/generic/GenericTransaction.d.ts.map +0 -1
  666. package/dist/generic/GenericTransaction.js +0 -144
  667. package/dist/generic/GenericTransaction.js.map +0 -1
  668. package/dist/generic/PersistedTypes.d.ts +0 -194
  669. package/dist/generic/PersistedTypes.d.ts.map +0 -1
  670. package/dist/generic/PersistedTypes.js +0 -42
  671. package/dist/generic/PersistedTypes.js.map +0 -1
  672. package/dist/generic/Summary.d.ts +0 -63
  673. package/dist/generic/Summary.d.ts.map +0 -1
  674. package/dist/generic/Summary.js +0 -64
  675. package/dist/generic/Summary.js.map +0 -1
  676. package/dist/generic/index.d.ts +0 -10
  677. package/dist/generic/index.d.ts.map +0 -1
  678. package/dist/generic/index.js +0 -26
  679. package/dist/generic/index.js.map +0 -1
  680. package/docs/Future.md +0 -155
  681. package/lib/BasicCheckout.d.ts +0 -23
  682. package/lib/BasicCheckout.d.ts.map +0 -1
  683. package/lib/BasicCheckout.js.map +0 -1
  684. package/lib/Snapshot.d.ts +0 -198
  685. package/lib/Snapshot.d.ts.map +0 -1
  686. package/lib/Snapshot.js +0 -263
  687. package/lib/Snapshot.js.map +0 -1
  688. package/lib/SnapshotUtilities.d.ts +0 -29
  689. package/lib/SnapshotUtilities.d.ts.map +0 -1
  690. package/lib/SnapshotUtilities.js +0 -67
  691. package/lib/SnapshotUtilities.js.map +0 -1
  692. package/lib/anchored-edits/AnchorResolution.d.ts +0 -144
  693. package/lib/anchored-edits/AnchorResolution.d.ts.map +0 -1
  694. package/lib/anchored-edits/AnchorResolution.js +0 -152
  695. package/lib/anchored-edits/AnchorResolution.js.map +0 -1
  696. package/lib/anchored-edits/Factory.d.ts +0 -56
  697. package/lib/anchored-edits/Factory.d.ts.map +0 -1
  698. package/lib/anchored-edits/Factory.js +0 -74
  699. package/lib/anchored-edits/Factory.js.map +0 -1
  700. package/lib/anchored-edits/PersistedTypes.d.ts +0 -245
  701. package/lib/anchored-edits/PersistedTypes.d.ts.map +0 -1
  702. package/lib/anchored-edits/PersistedTypes.js +0 -128
  703. package/lib/anchored-edits/PersistedTypes.js.map +0 -1
  704. package/lib/anchored-edits/SharedTreeWithAnchors.d.ts +0 -120
  705. package/lib/anchored-edits/SharedTreeWithAnchors.d.ts.map +0 -1
  706. package/lib/anchored-edits/SharedTreeWithAnchors.js +0 -110
  707. package/lib/anchored-edits/SharedTreeWithAnchors.js.map +0 -1
  708. package/lib/anchored-edits/TransactionWithAnchors.d.ts +0 -28
  709. package/lib/anchored-edits/TransactionWithAnchors.d.ts.map +0 -1
  710. package/lib/anchored-edits/TransactionWithAnchors.js +0 -32
  711. package/lib/anchored-edits/TransactionWithAnchors.js.map +0 -1
  712. package/lib/anchored-edits/index.d.ts +0 -10
  713. package/lib/anchored-edits/index.d.ts.map +0 -1
  714. package/lib/anchored-edits/index.js +0 -11
  715. package/lib/anchored-edits/index.js.map +0 -1
  716. package/lib/default-edits/EditUtilities.d.ts +0 -57
  717. package/lib/default-edits/EditUtilities.d.ts.map +0 -1
  718. package/lib/default-edits/EditUtilities.js +0 -181
  719. package/lib/default-edits/EditUtilities.js.map +0 -1
  720. package/lib/default-edits/Factory.d.ts +0 -56
  721. package/lib/default-edits/Factory.d.ts.map +0 -1
  722. package/lib/default-edits/Factory.js +0 -74
  723. package/lib/default-edits/Factory.js.map +0 -1
  724. package/lib/default-edits/HistoryEditFactory.d.ts +0 -19
  725. package/lib/default-edits/HistoryEditFactory.d.ts.map +0 -1
  726. package/lib/default-edits/HistoryEditFactory.js.map +0 -1
  727. package/lib/default-edits/PersistedTypes.d.ts.map +0 -1
  728. package/lib/default-edits/PersistedTypes.js.map +0 -1
  729. package/lib/default-edits/SharedTree.d.ts +0 -111
  730. package/lib/default-edits/SharedTree.d.ts.map +0 -1
  731. package/lib/default-edits/SharedTree.js +0 -100
  732. package/lib/default-edits/SharedTree.js.map +0 -1
  733. package/lib/default-edits/Summary.d.ts +0 -15
  734. package/lib/default-edits/Summary.d.ts.map +0 -1
  735. package/lib/default-edits/Summary.js +0 -31
  736. package/lib/default-edits/Summary.js.map +0 -1
  737. package/lib/default-edits/Transaction.d.ts +0 -41
  738. package/lib/default-edits/Transaction.d.ts.map +0 -1
  739. package/lib/default-edits/Transaction.js +0 -221
  740. package/lib/default-edits/Transaction.js.map +0 -1
  741. package/lib/default-edits/UndoRedoHandler.d.ts.map +0 -1
  742. package/lib/default-edits/UndoRedoHandler.js.map +0 -1
  743. package/lib/default-edits/index.d.ts +0 -13
  744. package/lib/default-edits/index.d.ts.map +0 -1
  745. package/lib/default-edits/index.js +0 -14
  746. package/lib/default-edits/index.js.map +0 -1
  747. package/lib/generic/GenericEditUtilities.d.ts +0 -26
  748. package/lib/generic/GenericEditUtilities.d.ts.map +0 -1
  749. package/lib/generic/GenericEditUtilities.js +0 -38
  750. package/lib/generic/GenericEditUtilities.js.map +0 -1
  751. package/lib/generic/GenericSharedTree.d.ts +0 -221
  752. package/lib/generic/GenericSharedTree.d.ts.map +0 -1
  753. package/lib/generic/GenericSharedTree.js +0 -443
  754. package/lib/generic/GenericSharedTree.js.map +0 -1
  755. package/lib/generic/GenericTransaction.d.ts +0 -87
  756. package/lib/generic/GenericTransaction.d.ts.map +0 -1
  757. package/lib/generic/GenericTransaction.js +0 -140
  758. package/lib/generic/GenericTransaction.js.map +0 -1
  759. package/lib/generic/PersistedTypes.d.ts +0 -194
  760. package/lib/generic/PersistedTypes.d.ts.map +0 -1
  761. package/lib/generic/PersistedTypes.js +0 -39
  762. package/lib/generic/PersistedTypes.js.map +0 -1
  763. package/lib/generic/Summary.d.ts +0 -63
  764. package/lib/generic/Summary.d.ts.map +0 -1
  765. package/lib/generic/Summary.js +0 -58
  766. package/lib/generic/Summary.js.map +0 -1
  767. package/lib/generic/index.d.ts +0 -10
  768. package/lib/generic/index.d.ts.map +0 -1
  769. package/lib/generic/index.js +0 -11
  770. package/lib/generic/index.js.map +0 -1
  771. package/lib/test/Anchors.glassBox.tests.d.ts.map +0 -1
  772. package/lib/test/Anchors.glassBox.tests.js +0 -410
  773. package/lib/test/Anchors.glassBox.tests.js.map +0 -1
  774. package/lib/test/BasicCheckout.tests.d.ts.map +0 -1
  775. package/lib/test/BasicCheckout.tests.js +0 -8
  776. package/lib/test/BasicCheckout.tests.js.map +0 -1
  777. package/lib/test/GenericTransactionWithAnchors.tests.d.ts.map +0 -1
  778. package/lib/test/GenericTransactionWithAnchors.tests.js +0 -25
  779. package/lib/test/GenericTransactionWithAnchors.tests.js.map +0 -1
  780. package/lib/test/SharedTreeWithAnchors.tests.d.ts.map +0 -1
  781. package/lib/test/SharedTreeWithAnchors.tests.js +0 -420
  782. package/lib/test/SharedTreeWithAnchors.tests.js.map +0 -1
  783. package/lib/test/Snapshot.tests.d.ts.map +0 -1
  784. package/lib/test/Snapshot.tests.js +0 -96
  785. package/lib/test/Snapshot.tests.js.map +0 -1
  786. package/lib/test/SnapshotUtilities.tests.d.ts.map +0 -1
  787. package/lib/test/SnapshotUtilities.tests.js +0 -168
  788. package/lib/test/SnapshotUtilities.tests.js.map +0 -1
  789. package/lib/test/undoRedoStackManager.d.ts +0 -26
  790. package/lib/test/undoRedoStackManager.d.ts.map +0 -1
  791. package/lib/test/undoRedoStackManager.js +0 -176
  792. package/lib/test/undoRedoStackManager.js.map +0 -1
  793. package/lib/test/utilities/SummaryFormatCompatibilityTests.d.ts +0 -13
  794. package/lib/test/utilities/SummaryFormatCompatibilityTests.d.ts.map +0 -1
  795. package/lib/test/utilities/SummaryFormatCompatibilityTests.js +0 -154
  796. package/lib/test/utilities/SummaryFormatCompatibilityTests.js.map +0 -1
  797. package/src/BasicCheckout.ts +0 -34
  798. package/src/Snapshot.ts +0 -363
  799. package/src/SnapshotUtilities.ts +0 -88
  800. package/src/anchored-edits/AnchorResolution.ts +0 -442
  801. package/src/anchored-edits/Factory.ts +0 -94
  802. package/src/anchored-edits/PersistedTypes.ts +0 -310
  803. package/src/anchored-edits/SharedTreeWithAnchors.ts +0 -200
  804. package/src/anchored-edits/TransactionWithAnchors.ts +0 -39
  805. package/src/anchored-edits/index.ts +0 -21
  806. package/src/default-edits/EditUtilities.ts +0 -220
  807. package/src/default-edits/Factory.ts +0 -94
  808. package/src/default-edits/SharedTree.ts +0 -174
  809. package/src/default-edits/Summary.ts +0 -44
  810. package/src/default-edits/Transaction.ts +0 -262
  811. package/src/default-edits/index.ts +0 -29
  812. package/src/generic/GenericEditUtilities.ts +0 -46
  813. package/src/generic/GenericSharedTree.ts +0 -593
  814. package/src/generic/GenericTransaction.ts +0 -194
  815. package/src/generic/PersistedTypes.ts +0 -221
  816. package/src/generic/Summary.ts +0 -113
  817. package/src/generic/index.ts +0 -41
@@ -0,0 +1,1075 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+ import { expect } from 'chai';
6
+ import { v4, v5 } from 'uuid';
7
+ import { IdCompressor, isFinalId, isLocalId, hasOngoingSession, legacySharedTreeInitialTreeId, } from '../id-compressor/IdCompressor';
8
+ import { assert, assertNotUndefined, fail } from '../Common';
9
+ import { assertIsStableId, createSessionId as createSessionId, incrementUuid, isStableId, numericUuidFromStableId, stableIdFromNumericUuid, } from '../id-compressor/NumericUuid';
10
+ import { getIds } from '../id-compressor/IdRange';
11
+ import { createCompressor, performFuzzActions, sessionIds, IdCompressorTestNetwork, Client, DestinationClient, MetaClient, expectSerializes, roundtrip, sessionNumericUuids, } from './utilities/IdCompressorTestUtilities';
12
+ import { expectDefined } from './utilities/TestCommon';
13
+ describe('IdCompressor', () => {
14
+ it('detects invalid cluster sizes', () => {
15
+ const compressor = createCompressor(Client.Client1, 1);
16
+ expect(() => (compressor.clusterCapacity = -1)).to.throw('Clusters must have a positive capacity');
17
+ expect(() => (compressor.clusterCapacity = 0)).to.throw('Clusters must have a positive capacity');
18
+ expect(() => (compressor.clusterCapacity = IdCompressor.maxClusterSize + 1)).to.throw('Clusters must not exceed max cluster size');
19
+ });
20
+ it('reports the proper session ID', () => {
21
+ const sessionId = createSessionId();
22
+ const compressor = new IdCompressor(sessionId, 0);
23
+ expect(compressor.localSessionId).to.equal(sessionId);
24
+ });
25
+ it('accepts different numbers of reserved IDs', () => {
26
+ for (const reservedIdCount of [0, 1, 5]) {
27
+ const compressor = new IdCompressor(createSessionId(), reservedIdCount);
28
+ if (reservedIdCount > 0) {
29
+ expect(compressor.decompress(compressor.getReservedId(0))).to.equal(legacySharedTreeInitialTreeId);
30
+ }
31
+ }
32
+ });
33
+ describe('ID Generation', () => {
34
+ it('can create a compressed ID with an override', () => {
35
+ const compressor = createCompressor(Client.Client1);
36
+ const override = 'override';
37
+ const id = compressor.generateCompressedId(override);
38
+ expect(compressor.decompress(id)).to.equal(override);
39
+ });
40
+ it('can create compressed IDs with v5 overrides', () => {
41
+ const compressor = createCompressor(Client.Client1);
42
+ const uuidA = v5('foo', '7834b437-6e8c-4936-a1a3-0130b1178f17');
43
+ const uuidB = uuidA.slice(0, uuidA.length - 1) + (uuidA.charAt(uuidA.length - 1) === 'a' ? 'b' : 'a');
44
+ const idA = compressor.generateCompressedId(uuidA);
45
+ const idB = compressor.generateCompressedId(uuidB);
46
+ expect(compressor.decompress(idA)).to.equal(uuidA);
47
+ expect(compressor.decompress(idB)).to.equal(uuidB);
48
+ });
49
+ it('can manually create a compressed ID', () => {
50
+ const compressor = createCompressor(Client.Client1);
51
+ const id = compressor.generateCompressedId();
52
+ const uuid = compressor.decompress(id);
53
+ expect(id).to.equal(compressor.recompress(uuid));
54
+ });
55
+ it('will not decompress IDs it did not compress', () => {
56
+ const errorMessage = 'Compressed ID was not generated by this compressor';
57
+ const compressor = createCompressor(Client.Client1);
58
+ expect(() => compressor.decompress(-1)).to.throw(errorMessage);
59
+ expect(() => compressor.decompress(compressor.reservedIdCount)).to.throw(errorMessage);
60
+ });
61
+ it('will not re-compress uuids it did not originally compress', () => {
62
+ const compressor = createCompressor(Client.Client1);
63
+ expect(compressor.tryRecompress('5fff846a-efd4-42fb-8b78-b32ce2672f99')).to.be.undefined;
64
+ });
65
+ it('unifies duplicate overrides originating from the same compressor', () => {
66
+ const override = 'override';
67
+ const compressor = createCompressor(Client.Client1, 3);
68
+ // Client1 compresses a uuid
69
+ const localId1 = compressor.generateCompressedId(override);
70
+ const localId2 = compressor.generateCompressedId(override);
71
+ expect(localId1).to.equal(localId2, 'only one local ID should be allocated for the same override');
72
+ expect(compressor.decompress(localId1)).to.equal(override, 'override incorrectly associated with local ID');
73
+ });
74
+ it('unifies overrides with sequential local IDs', () => {
75
+ const compressor = createCompressor(Client.Client1, 3);
76
+ // Client1 compresses a uuid
77
+ compressor.generateCompressedId();
78
+ const localId2 = compressor.generateCompressedId();
79
+ const stableId2 = assertIsStableId(compressor.decompress(localId2));
80
+ const localId3 = compressor.generateCompressedId(stableId2);
81
+ expect(localId3).to.equal(localId2, 'only one local ID should be allocated for the same sequential uuid');
82
+ });
83
+ it('unifies overrides with sequential local IDs that sort before the reserved session UUID', () => {
84
+ // This is a regression test for an issue where passing a sequential UUID that sorted before the reserved UUID
85
+ // as an override created duplicate overrides in the compressor.
86
+ const newSession = `0${legacySharedTreeInitialTreeId.slice(1)}`;
87
+ const compressor = new IdCompressor(newSession, 1 /* just needs to be > 0 */);
88
+ // Client1 compresses a uuid
89
+ compressor.generateCompressedId();
90
+ const localId2 = compressor.generateCompressedId();
91
+ const stableId2 = assertIsStableId(compressor.decompress(localId2));
92
+ const localId3 = compressor.generateCompressedId(stableId2);
93
+ expect(localId3).to.equal(localId2, 'only one local ID should be allocated for the same sequential uuid');
94
+ });
95
+ it('unifies overrides with sequential local IDs that sort after an existing override', () => {
96
+ // This is a regression test for an issue where passing a sequential UUID that sorted after an existing override
97
+ // as an override created duplicate overrides in the compressor.
98
+ const newSession = `b${v4().slice(1)}`;
99
+ const compressor = new IdCompressor(newSession, 0);
100
+ // Client1 compresses a uuid with some override that will sort before the session uuid
101
+ compressor.generateCompressedId(`a${v4().slice(1)}`);
102
+ const localId2 = compressor.generateCompressedId();
103
+ const stableId2 = assertIsStableId(compressor.decompress(localId2));
104
+ const localId3 = compressor.generateCompressedId(stableId2);
105
+ expect(localId3).to.equal(localId2, 'only one local ID should be allocated for the same sequential uuid');
106
+ });
107
+ it('unifies overrides with sequential local IDs that sort after an existing cluster', () => {
108
+ // This is a regression test for an issue where passing a sequential UUID that sorted after an existing cluster
109
+ // as an override created duplicate overrides in the compressor.
110
+ const newSession1 = `c${v4().slice(1)}`;
111
+ const newSession2 = `b${v4().slice(1)}`;
112
+ const compressor1 = new IdCompressor(newSession1, 0);
113
+ const compressor2 = new IdCompressor(newSession2, 0);
114
+ compressor1.clusterCapacity = 5;
115
+ compressor2.clusterCapacity = 5;
116
+ compressor2.generateCompressedId(); // one ID, enough to make a cluster
117
+ compressor1.finalizeCreationRange(compressor2.takeNextCreationRange());
118
+ const localId = compressor1.generateCompressedId();
119
+ const stableId2 = assertIsStableId(compressor1.decompress(localId));
120
+ const localId3 = compressor1.generateCompressedId(stableId2);
121
+ expect(localId3).to.equal(localId, 'only one local ID should be allocated for the same sequential uuid');
122
+ });
123
+ it('unifies unfinalized local overrides with final IDs from a remote session', () => {
124
+ const compressor1 = createCompressor(Client.Client1, 3);
125
+ const compressor2 = createCompressor(Client.Client2, 3);
126
+ const override = 'override';
127
+ const local1 = compressor1.generateCompressedId(override);
128
+ const local2 = compressor2.generateCompressedId(override);
129
+ const creationRange = compressor2.takeNextCreationRange();
130
+ compressor1.finalizeCreationRange(creationRange);
131
+ compressor2.finalizeCreationRange(creationRange);
132
+ expect(compressor1.decompress(local1)).to.equal(override);
133
+ const final1 = compressor1.normalizeToOpSpace(local1);
134
+ const final2 = compressor2.normalizeToOpSpace(local2);
135
+ expect(isFinalId(final1)).to.be.true;
136
+ expect(final1).to.equal(final2);
137
+ });
138
+ it('unifies overrides with sequential local IDs that have been finalized', () => {
139
+ const compressor = createCompressor(Client.Client1);
140
+ const id = compressor.generateCompressedId();
141
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
142
+ const stableId = assertIsStableId(compressor.decompress(id));
143
+ const localId2 = compressor.generateCompressedId(stableId);
144
+ expect(localId2).to.equal(id, 'only one local ID should be allocated for the same sequential uuid');
145
+ });
146
+ it('cannot create negative amounts of local IDs', () => {
147
+ expect(() => createCompressor(Client.Client1).generateCompressedIdRange(-1)).to.throw('Must generate a nonzero number of IDs.');
148
+ });
149
+ it('cannot create unacceptably large amounts of local IDs', () => {
150
+ expect(() => createCompressor(Client.Client1).generateCompressedIdRange(Number.MAX_SAFE_INTEGER + 2)).to.throw('The number of allocated local IDs must not exceed the JS maximum safe integer.');
151
+ });
152
+ });
153
+ describe('can enumerate all locally created IDs', () => {
154
+ const idCount = 10;
155
+ it('created without finalization', () => {
156
+ const compressor = createCompressor(Client.Client1);
157
+ const ids = [];
158
+ for (let i = 0; i < idCount; i++) {
159
+ ids.push(compressor.generateCompressedId());
160
+ }
161
+ const returnedIds = [...compressor.getAllIdsFromLocalSession()];
162
+ expect(returnedIds).to.deep.equal(ids);
163
+ });
164
+ it('created with finalization', () => {
165
+ const compressor = createCompressor(Client.Client1, 10);
166
+ const ids = [];
167
+ for (let i = 0; i < idCount; i++) {
168
+ if (i === Math.floor(idCount / 2)) {
169
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
170
+ }
171
+ ids.push(compressor.generateCompressedId());
172
+ }
173
+ const returnedIds = [...compressor.getAllIdsFromLocalSession()];
174
+ expect(returnedIds).to.deep.equal(ids);
175
+ });
176
+ });
177
+ it('only sends attribution info on the first range from each session', () => {
178
+ const compressor = createCompressor(Client.Client1, 5, 'attribution');
179
+ const range1 = compressor.takeNextCreationRange();
180
+ expectDefined(range1.attributionInfo);
181
+ const range2 = compressor.takeNextCreationRange();
182
+ expect(range2.attributionInfo).to.be.undefined;
183
+ });
184
+ describe('can produce a creation range', () => {
185
+ const tests = [
186
+ { title: 'that is empty', overrideIndices: [], idCount: 0 },
187
+ { title: 'with only sequential IDs', overrideIndices: [], idCount: 3 },
188
+ {
189
+ title: 'with an overriding ID',
190
+ overrideIndices: [0],
191
+ idCount: 1,
192
+ },
193
+ {
194
+ title: 'with a sequential ID before an overriding ID',
195
+ overrideIndices: [1],
196
+ idCount: 2,
197
+ },
198
+ {
199
+ title: 'with a sequential ID after an overriding ID',
200
+ overrideIndices: [0],
201
+ idCount: 2,
202
+ },
203
+ {
204
+ title: 'with an overriding ID between sequential IDs',
205
+ overrideIndices: [1],
206
+ idCount: 3,
207
+ },
208
+ {
209
+ title: 'with a sequential ID between override IDs',
210
+ overrideIndices: [0, 2],
211
+ idCount: 3,
212
+ },
213
+ ];
214
+ tests.forEach(({ title, overrideIndices, idCount }) => {
215
+ it(title, () => {
216
+ const compressor = createCompressor(Client.Client1);
217
+ validateIdCreationRange(compressor, idCount, new Set(overrideIndices));
218
+ });
219
+ tests.forEach(({ title: title2, overrideIndices: overrideIndices2, idCount: idCount2 }) => {
220
+ it(`${title2} after a range ${title}`, () => {
221
+ const compressor = createCompressor(Client.Client1);
222
+ const lastTaken = validateIdCreationRange(compressor, idCount, new Set(overrideIndices));
223
+ validateIdCreationRange(compressor, idCount2, new Set(overrideIndices2), lastTaken);
224
+ });
225
+ });
226
+ });
227
+ function validateIdCreationRange(compressor, idCount, overrideIndices, lastTakenId = 0) {
228
+ const overrides = [];
229
+ for (let i = 0; i < idCount; i++) {
230
+ const override = overrideIndices.has(i) ? v4() : undefined;
231
+ const id = compressor.generateCompressedId(override);
232
+ overrides.push([id, override]);
233
+ }
234
+ const range = compressor.takeNextCreationRange();
235
+ let newLastTakenId = lastTakenId;
236
+ let idsActual = getIds(range);
237
+ if (overrides.length === 0) {
238
+ expect(idsActual).to.be.undefined;
239
+ }
240
+ else {
241
+ idsActual = expectDefined(idsActual);
242
+ expect(overrides[0][0]).to.equal(idsActual.first);
243
+ expect(overrides[overrides.length - 1][0]).to.equal(idsActual.last);
244
+ for (const [id, uuid] of Object.entries(overrideIndices)) {
245
+ expect(overrides[id][1]).to.equal(uuid);
246
+ }
247
+ newLastTakenId = idsActual.last;
248
+ }
249
+ return newLastTakenId;
250
+ }
251
+ });
252
+ describe('Finalizing', () => {
253
+ it('can finalize multiple overrides into the same cluster using different ranges', () => {
254
+ const compressor = createCompressor(Client.Client1);
255
+ const override1 = 'override1';
256
+ const override2 = 'override2';
257
+ const id1 = compressor.generateCompressedId(override1);
258
+ compressor.generateCompressedId();
259
+ const range1 = compressor.takeNextCreationRange();
260
+ const id2 = compressor.generateCompressedId(override2);
261
+ const range2 = compressor.takeNextCreationRange();
262
+ compressor.finalizeCreationRange(range1);
263
+ compressor.finalizeCreationRange(range2);
264
+ const finalId1 = compressor.normalizeToOpSpace(id1);
265
+ const finalId2 = compressor.normalizeToOpSpace(id2);
266
+ expect(isFinalId(finalId1)).to.be.true;
267
+ expect(isFinalId(finalId2)).to.be.true;
268
+ expect(compressor.decompress(finalId1)).to.equal(override1);
269
+ expect(compressor.decompress(finalId2)).to.equal(override2);
270
+ });
271
+ it('prevents attempts to finalize ranges twice', () => {
272
+ const rangeCompressor = createCompressor(Client.Client1);
273
+ rangeCompressor.generateCompressedIdRange(3);
274
+ const batchRange = rangeCompressor.takeNextCreationRange();
275
+ rangeCompressor.finalizeCreationRange(batchRange);
276
+ expect(() => rangeCompressor.finalizeCreationRange(batchRange)).to.throw('Ranges finalized out of order.');
277
+ // Make a new compressor, as the first one will be left in a bad state
278
+ const explicitCompressor = createCompressor(Client.Client1);
279
+ explicitCompressor.generateCompressedId();
280
+ explicitCompressor.generateCompressedId('override');
281
+ const explicitRange = explicitCompressor.takeNextCreationRange();
282
+ explicitCompressor.finalizeCreationRange(explicitRange);
283
+ expect(() => explicitCompressor.finalizeCreationRange(explicitRange)).to.throw('Ranges finalized out of order.');
284
+ });
285
+ it('prevents attempts to finalize ranges out of order', () => {
286
+ const compressor = createCompressor(Client.Client1);
287
+ compressor.generateCompressedId();
288
+ compressor.takeNextCreationRange();
289
+ compressor.generateCompressedId();
290
+ const secondRange = compressor.takeNextCreationRange();
291
+ expect(() => compressor.finalizeCreationRange(secondRange)).to.throw('Ranges finalized out of order.');
292
+ });
293
+ it('prevents finalizing unacceptably enormous amounts of ID allocation', () => {
294
+ const compressor1 = createCompressor(Client.Client1);
295
+ const compressor2 = createCompressor(Client.Client2);
296
+ const integerLargerThanHalfMax = Math.round((Number.MAX_SAFE_INTEGER / 3) * 2);
297
+ compressor1.generateCompressedIdRange(integerLargerThanHalfMax);
298
+ compressor2.generateCompressedIdRange(integerLargerThanHalfMax);
299
+ const range1 = compressor1.takeNextCreationRange();
300
+ const range2 = compressor2.takeNextCreationRange();
301
+ compressor1.finalizeCreationRange(range1);
302
+ expect(() => compressor1.finalizeCreationRange(range2)).to.throw('The number of allocated final IDs must not exceed the JS maximum safe integer.');
303
+ });
304
+ });
305
+ describe('Compression', () => {
306
+ it('can re-compress a sequential uuid it generated', () => {
307
+ const compressor = createCompressor(Client.Client1);
308
+ const id = compressor.generateCompressedId();
309
+ const uuid = compressor.decompress(id);
310
+ expect(compressor.recompress(uuid)).to.equal(id);
311
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
312
+ expect(compressor.recompress(uuid)).to.equal(id);
313
+ });
314
+ it('can re-compress an override', () => {
315
+ const compressor = createCompressor(Client.Client1);
316
+ const override = 'override';
317
+ const id = compressor.generateCompressedId(override);
318
+ expect(compressor.recompress(override)).to.equal(id);
319
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
320
+ expect(compressor.recompress(override)).to.equal(id);
321
+ });
322
+ it('can re-compress overrides from a remote client it has finalized', () => {
323
+ const compressor = createCompressor(Client.Client1);
324
+ const id = compressor.generateCompressedId();
325
+ const override = 'override';
326
+ compressor.generateCompressedId(override);
327
+ const uuid = compressor.decompress(id);
328
+ const compressor2 = createCompressor(Client.Client2);
329
+ compressor2.finalizeCreationRange(compressor.takeNextCreationRange());
330
+ const finalId1 = compressor2.recompress(uuid);
331
+ const finalId2 = compressor2.recompress(override);
332
+ if (finalId1 === undefined || finalId2 === undefined) {
333
+ expect.fail();
334
+ }
335
+ expect(isFinalId(finalId1)).to.be.true;
336
+ expect(isFinalId(finalId2)).to.be.true;
337
+ });
338
+ it('will not compress an override it never compressed or finalized', () => {
339
+ const compressor = createCompressor(Client.Client1, 5);
340
+ // Leading zeroes to exploit calls to getOrNextLower on uuid maps, as it will be before test session uuids
341
+ const override = 'override';
342
+ expect(compressor.tryRecompress(override)).to.be.undefined;
343
+ expect(compressor.tryRecompress(stableIdFromNumericUuid(sessionNumericUuids.get(Client.Client1), 1))).to.be
344
+ .undefined;
345
+ compressor.generateCompressedId(override);
346
+ compressor.generateCompressedIdRange(2);
347
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
348
+ expect(compressor.tryRecompress(stableIdFromNumericUuid(sessionNumericUuids.get(Client.Client1), 4))).to.be
349
+ .undefined;
350
+ });
351
+ });
352
+ describe('Decompression', () => {
353
+ it('can decompress a local ID before and after finalizing', () => {
354
+ const compressor = createCompressor(Client.Client1);
355
+ const id = compressor.generateCompressedId();
356
+ const uuid = compressor.decompress(id);
357
+ expect(isStableId(uuid)).to.be.true;
358
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
359
+ expect(compressor.decompress(id)).to.equal(uuid);
360
+ });
361
+ it('can decompress reserved IDs', () => {
362
+ // This is a glass box test in that it increments UUIDs
363
+ const compressor = createCompressor(Client.Client1);
364
+ expect(compressor.decompress(compressor.getReservedId(0))).to.equal(legacySharedTreeInitialTreeId);
365
+ const reservedSessionUuid = numericUuidFromStableId(assertIsStableId(compressor.decompress(compressor.getReservedId(1))));
366
+ for (let i = 1; i < compressor.reservedIdCount; i++) {
367
+ const reservedId = compressor.getReservedId(i);
368
+ const stable = compressor.decompress(reservedId);
369
+ expect(stable).to.equal(stableIdFromNumericUuid(incrementUuid(reservedSessionUuid, i - 1)));
370
+ const finalIdForReserved = compressor.recompress(stable);
371
+ expect(isLocalId(finalIdForReserved)).to.be.false;
372
+ expect(finalIdForReserved).to.equal(reservedId);
373
+ }
374
+ const outOfBoundsError = 'Reserved Id index out of bounds';
375
+ expect(() => compressor.getReservedId(-1)).to.throw(outOfBoundsError);
376
+ expect(() => compressor.getReservedId(compressor.reservedIdCount)).to.throw(outOfBoundsError);
377
+ });
378
+ it('can decompress a final ID', () => {
379
+ const compressor = createCompressor(Client.Client1);
380
+ const range = compressor.generateCompressedIdRange(1);
381
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
382
+ const finalId = compressor.normalizeToOpSpace(compressor.getIdsFromRange(range, compressor.localSessionId).get(0));
383
+ if (isLocalId(finalId)) {
384
+ expect.fail('Op space ID was finalized but is local');
385
+ }
386
+ const uuid = compressor.decompress(finalId);
387
+ expect(isStableId(uuid)).to.be.true;
388
+ });
389
+ it('can decompress a final ID with an override', () => {
390
+ const compressor = createCompressor(Client.Client1);
391
+ const override = 'override';
392
+ const id = compressor.generateCompressedId(override);
393
+ const range = compressor.takeNextCreationRange();
394
+ compressor.finalizeCreationRange(range);
395
+ const finalId = compressor.normalizeToOpSpace(id);
396
+ if (isLocalId(finalId)) {
397
+ expect.fail('Op space ID was finalized but is local');
398
+ }
399
+ const uuid = compressor.decompress(finalId);
400
+ expect(uuid).to.equal(override);
401
+ });
402
+ it('can decompress an override that is an UUID', () => {
403
+ const compressor = createCompressor(Client.Client1, 5);
404
+ const uuid = 'd1302ab1-3c08-4e79-a49a-4c39ac369c16';
405
+ const id = compressor.generateCompressedId(uuid);
406
+ expect(compressor.decompress(id)).to.equal(uuid);
407
+ });
408
+ it('properly sorts UUID-like overrides separately from true UUIDs', () => {
409
+ // This is a glass box test that ensures overrides which would sort in between a cluster base UUID and an UUID higher up in the
410
+ // same cluster are not accidentally retrieved during cluster ID lookup.
411
+ const compressor = createCompressor(Client.Client1, 5);
412
+ const override = `${compressor.localSessionId}6`;
413
+ const id = compressor.generateCompressedId();
414
+ compressor.generateCompressedId(override);
415
+ const decompressedId = compressor.decompress(id);
416
+ expect(compressor.recompress(decompressedId)).to.equal(id);
417
+ });
418
+ it('can decompress an override that starts with the reserved prefix character', () => {
419
+ const compressor = createCompressor(Client.Client1, 5);
420
+ const override = `\ue15e${compressor.localSessionId}`;
421
+ const id = compressor.generateCompressedId(override);
422
+ expect(compressor.decompress(id)).to.equal(override);
423
+ });
424
+ });
425
+ describe('Normalization', () => {
426
+ it('can normalize a local ID to op space before finalizing', () => {
427
+ const compressor = createCompressor(Client.Client1);
428
+ const id = compressor.generateCompressedId();
429
+ const normalized = compressor.normalizeToOpSpace(id);
430
+ expect(isLocalId(id)).to.be.true;
431
+ expect(id).to.equal(normalized);
432
+ });
433
+ it('can normalize a local ID to op space after finalizing', () => {
434
+ const compressor = createCompressor(Client.Client1);
435
+ const id = compressor.generateCompressedId();
436
+ compressor.finalizeCreationRange(compressor.takeNextCreationRange());
437
+ const normalized = compressor.normalizeToOpSpace(id);
438
+ expect(isFinalId(normalized)).to.be.true;
439
+ expect(id).to.not.equal(normalized);
440
+ });
441
+ it('cannot normalize a remote ID to session space if it has not been finalized', () => {
442
+ const compressor1 = createCompressor(Client.Client1);
443
+ const compressor2 = createCompressor(Client.Client2);
444
+ const normalized = compressor1.normalizeToOpSpace(compressor1.generateCompressedId());
445
+ expect(() => compressor2.normalizeToSessionSpace(normalized, compressor1.localSessionId)).to.throw('No IDs have ever been finalized by the supplied session.');
446
+ });
447
+ it('can normalize local and final IDs from a remote session to session space', () => {
448
+ const compressor1 = createCompressor(Client.Client1);
449
+ const compressor2 = createCompressor(Client.Client2);
450
+ const id = compressor1.generateCompressedId();
451
+ const normalizedLocal = compressor1.normalizeToOpSpace(id);
452
+ const range = compressor1.takeNextCreationRange();
453
+ compressor1.finalizeCreationRange(range);
454
+ const normalizedFinal = compressor1.normalizeToOpSpace(id);
455
+ compressor2.finalizeCreationRange(range);
456
+ expect(isLocalId(normalizedLocal)).to.be.true;
457
+ expect(isFinalId(normalizedFinal)).to.be.true;
458
+ expect(compressor2.normalizeToSessionSpace(normalizedFinal, compressor1.localSessionId)).to.equal(normalizedFinal);
459
+ expect(compressor2.normalizeToSessionSpace(normalizedLocal, compressor1.localSessionId)).to.equal(normalizedFinal);
460
+ });
461
+ });
462
+ describe('Serialization', () => {
463
+ it('can serialize an empty compressor', () => {
464
+ const compressor = createCompressor(Client.Client1);
465
+ const [serializedNoSession, serializedWithSession] = expectSerializes(compressor);
466
+ expect(serializedWithSession.clusters.length).to.equal(0, 'reserved cluster should not be serialized');
467
+ expect(serializedNoSession.clusters.length).to.equal(0, 'reserved cluster should not be serialized');
468
+ });
469
+ it('correctly deserializes and resumes a session', () => {
470
+ const compressor1 = createCompressor(Client.Client1, undefined, Client.Client1);
471
+ const compressor2 = createCompressor(Client.Client2, undefined, Client.Client2);
472
+ compressor1.generateCompressedId();
473
+ const creationRange = compressor1.takeNextCreationRange();
474
+ compressor1.finalizeCreationRange(creationRange);
475
+ compressor2.finalizeCreationRange(creationRange);
476
+ const [_, serializedWithSession] = expectSerializes(compressor1);
477
+ const compressorResumed = IdCompressor.deserialize(serializedWithSession);
478
+ compressorResumed.generateCompressedId();
479
+ const range2 = compressorResumed.takeNextCreationRange();
480
+ compressor1.finalizeCreationRange(range2);
481
+ compressor2.finalizeCreationRange(range2);
482
+ expect(IdCompressor.deserialize(compressor1.serialize(false), createSessionId()).equals(IdCompressor.deserialize(compressor2.serialize(false), createSessionId()), false // don't compare local state
483
+ )).to.be.true;
484
+ });
485
+ });
486
+ // No validation, as these leave the network in a broken state
487
+ describeNetworkNoValidation('detects UUID collision', (itNetwork) => {
488
+ itNetwork('when a client requests an override that is an UUID reserved for later allocation by a cluster', 2, (network) => {
489
+ network.allocateAndSendIds(Client.Client2, 1);
490
+ network.deliverOperations(Client.Client1);
491
+ const compressor2 = network.getCompressor(Client.Client2);
492
+ const id = network.getIdLog(Client.Client2)[0].id;
493
+ const uuid = assertIsStableId(compressor2.decompress(id));
494
+ const nextUuid = stableIdFromNumericUuid(numericUuidFromStableId(uuid), 1);
495
+ expect(() => network.allocateAndSendIds(Client.Client1, 1, { 0: nextUuid })).to.throw(`Override '${nextUuid}' collides with another allocated UUID.`);
496
+ });
497
+ itNetwork('when a new cluster is allocated whose base UUID collides with an existing override', 2, (network) => {
498
+ network.allocateAndSendIds(Client.Client1, 1);
499
+ network.deliverOperations(DestinationClient.All);
500
+ const compressor1 = network.getCompressor(Client.Client1);
501
+ const id = network.getIdLog(Client.Client1)[0].id;
502
+ const uuid = assertIsStableId(compressor1.decompress(id));
503
+ const nextUuid = stableIdFromNumericUuid(numericUuidFromStableId(uuid), 2);
504
+ network.allocateAndSendIds(Client.Client1, 1, { 0: nextUuid });
505
+ network.allocateAndSendIds(Client.Client2, 1);
506
+ network.deliverOperations(DestinationClient.All);
507
+ network.allocateAndSendIds(Client.Client1, 1); // new cluster
508
+ expect(() => network.deliverOperations(Client.Client1)).to.throw(`Override '${nextUuid}' collides with another allocated UUID.`);
509
+ });
510
+ itNetwork('detects colliding override UUIDs when expanding a cluster', 1, (network) => {
511
+ // This is a glass box test in that it is testing cluster expansion
512
+ network.allocateAndSendIds(Client.Client1, 1);
513
+ network.deliverOperations(DestinationClient.All);
514
+ const compressor1 = network.getCompressor(Client.Client1);
515
+ const id = network.getIdLog(Client.Client1)[0].id;
516
+ const uuid = assertIsStableId(compressor1.decompress(id));
517
+ const expansion = 3;
518
+ const nextUuid = stableIdFromNumericUuid(numericUuidFromStableId(uuid), expansion);
519
+ network.allocateAndSendIds(Client.Client1, expansion, { 0: nextUuid });
520
+ expect(() => network.deliverOperations(DestinationClient.All)).to.throw(`Override '${nextUuid}' collides with another allocated UUID.`);
521
+ });
522
+ });
523
+ describeNetwork('Networked', (itNetwork) => {
524
+ describe('can attribute', () => {
525
+ itNetwork('local IDs before and after being finalized', (network) => {
526
+ const compressor = network.getCompressor(Client.Client1);
527
+ network.allocateAndSendIds(Client.Client1, 1);
528
+ const id = network.getIdLog(Client.Client1)[0].id;
529
+ expect(compressor.attributeId(id)).to.equal(Client.Client1);
530
+ network.deliverOperations(Client.Client1);
531
+ expect(compressor.attributeId(id)).to.equal(Client.Client1);
532
+ });
533
+ itNetwork('final IDs from a remote session', (network) => {
534
+ const compressor = network.getCompressor(Client.Client1);
535
+ network.allocateAndSendIds(Client.Client2, 1);
536
+ network.deliverOperations(DestinationClient.All);
537
+ const id = network.getSequencedIdLog(Client.Client1)[0].id;
538
+ expect(compressor.attributeId(id)).to.equal(Client.Client2);
539
+ });
540
+ itNetwork('final IDs from multiple remote sessions', 1, (network) => {
541
+ const compressor = network.getCompressor(Client.Client1);
542
+ // Ensure multiple clusters are made by each client. Cluster size === 1.
543
+ network.allocateAndSendIds(Client.Client1, compressor.clusterCapacity);
544
+ network.allocateAndSendIds(Client.Client2, compressor.clusterCapacity);
545
+ network.allocateAndSendIds(Client.Client3, compressor.clusterCapacity);
546
+ network.allocateAndSendIds(Client.Client1, compressor.clusterCapacity);
547
+ network.allocateAndSendIds(Client.Client2, compressor.clusterCapacity);
548
+ network.allocateAndSendIds(Client.Client3, compressor.clusterCapacity);
549
+ network.deliverOperations(DestinationClient.All);
550
+ const log = network.getSequencedIdLog(Client.Client1);
551
+ expect(compressor.attributeId(log[0].id)).to.equal(Client.Client1);
552
+ expect(compressor.attributeId(log[1].id)).to.equal(Client.Client2);
553
+ expect(compressor.attributeId(log[2].id)).to.equal(Client.Client3);
554
+ expect(compressor.attributeId(log[3].id)).to.equal(Client.Client1);
555
+ expect(compressor.attributeId(log[4].id)).to.equal(Client.Client2);
556
+ expect(compressor.attributeId(log[5].id)).to.equal(Client.Client3);
557
+ });
558
+ itNetwork('unified IDs', (network) => {
559
+ const override = 'override';
560
+ const allTargets = network.getTargetCompressors(DestinationClient.All);
561
+ for (const [client, compressor] of allTargets) {
562
+ network.allocateAndSendIds(client, 1, { 0: override });
563
+ for (const { id } of network.getIdLog(client)) {
564
+ expect(compressor.attributeId(id)).to.equal(client);
565
+ }
566
+ }
567
+ network.deliverOperations(DestinationClient.All);
568
+ const firstTarget = allTargets[0][0];
569
+ for (const [client, compressor] of allTargets) {
570
+ for (const { id } of network.getIdLog(client)) {
571
+ expect(compressor.attributeId(id)).to.equal(firstTarget);
572
+ }
573
+ }
574
+ });
575
+ });
576
+ itNetwork('upholds the invariant that IDs always decompress to the same UUID', 2, (network) => {
577
+ var _a;
578
+ network.allocateAndSendIds(Client.Client1, 5, {
579
+ 1: 'override1',
580
+ });
581
+ network.allocateAndSendIds(Client.Client2, 5, {
582
+ 2: 'override2',
583
+ });
584
+ network.allocateAndSendIds(Client.Client3, 5, {
585
+ 3: 'override3',
586
+ });
587
+ const preAckLocals = new Map();
588
+ for (const [client, compressor] of network.getTargetCompressors(MetaClient.All)) {
589
+ const locals = [];
590
+ for (const idData of network.getIdLog(client)) {
591
+ locals.push([idData.id, compressor.decompress(idData.id)]);
592
+ }
593
+ preAckLocals.set(client, locals);
594
+ }
595
+ // Ack all IDs
596
+ network.deliverOperations(DestinationClient.All);
597
+ for (const [client, compressor] of network.getTargetCompressors(MetaClient.All)) {
598
+ const preAckLocalIds = (_a = preAckLocals.get(client)) !== null && _a !== void 0 ? _a : fail();
599
+ let i = 0;
600
+ for (const idData of network.getIdLog(client)) {
601
+ if (idData.originatingClient === client) {
602
+ expect(isFinalId(idData.id)).to.be.false;
603
+ const currentUuid = compressor.decompress(idData.id);
604
+ expect(currentUuid).to.equal(preAckLocalIds[i % preAckLocalIds.length][1]);
605
+ i++;
606
+ }
607
+ }
608
+ }
609
+ });
610
+ itNetwork('can normalize session space IDs to op space', 5, (network) => {
611
+ const clusterCapacity = 5;
612
+ const idCount = clusterCapacity * 2;
613
+ for (let i = 0; i < idCount; i++) {
614
+ network.allocateAndSendIds(Client.Client1, 1);
615
+ network.allocateAndSendIds(Client.Client2, 1);
616
+ network.allocateAndSendIds(Client.Client3, 1);
617
+ }
618
+ for (const [client, compressor] of network.getTargetCompressors(MetaClient.All)) {
619
+ for (const idData of network.getIdLog(client)) {
620
+ expect(idData.originatingClient).to.equal(client);
621
+ expect(isLocalId(compressor.normalizeToOpSpace(idData.id))).to.be.true;
622
+ }
623
+ }
624
+ network.deliverOperations(DestinationClient.All);
625
+ for (const [client, compressor] of network.getTargetCompressors(MetaClient.All)) {
626
+ for (const idData of network.getIdLog(client)) {
627
+ expect(isFinalId(compressor.normalizeToOpSpace(idData.id))).to.be.true;
628
+ }
629
+ }
630
+ });
631
+ itNetwork('can normalize local op space IDs from a local session to session space IDs', (network) => {
632
+ const compressor = network.getCompressor(Client.Client1);
633
+ const { range, sessionId } = network.allocateAndSendIds(Client.Client1, 1);
634
+ network.deliverOperations(Client.Client1);
635
+ const id = compressor.normalizeToOpSpace(compressor.getIdsFromRange(range, sessionId).get(0));
636
+ expect(isFinalId(id)).to.be.true;
637
+ expect(isLocalId(compressor.normalizeToSessionSpace(id, compressor.localSessionId))).to.be.true;
638
+ });
639
+ itNetwork('can normalize local op space IDs from a remote session to session space IDs', (network) => {
640
+ const compressor1 = network.getCompressor(Client.Client1);
641
+ const compressor2 = network.getCompressor(Client.Client2);
642
+ const { range, sessionId } = network.allocateAndSendIds(Client.Client1, 1);
643
+ // Mimic sending a reference to an ID that hasn't been acked yet, such as in a slow network
644
+ const id = compressor1.normalizeToOpSpace(compressor1.getIdsFromRange(range, sessionId).get(0));
645
+ const getSessionNormalizedId = () => compressor2.normalizeToSessionSpace(id, compressor1.localSessionId);
646
+ expect(getSessionNormalizedId).to.throw('No IDs have ever been finalized by the supplied session.');
647
+ network.deliverOperations(Client.Client2);
648
+ expect(isFinalId(getSessionNormalizedId())).to.be.true;
649
+ });
650
+ itNetwork('unifies duplicate overrides', 3, (network) => {
651
+ var _a, _b;
652
+ const override = 'override';
653
+ const compressor1 = network.getCompressor(Client.Client1);
654
+ const compressor2 = network.getCompressor(Client.Client2);
655
+ const compressor3 = network.getCompressor(Client.Client3);
656
+ const clusterCapacity = compressor1.clusterCapacity;
657
+ // Ensure some clusters exist to avoid simple case of empty clusters
658
+ network.allocateAndSendIds(Client.Client1, clusterCapacity);
659
+ network.allocateAndSendIds(Client.Client2, clusterCapacity);
660
+ network.allocateAndSendIds(Client.Client3, clusterCapacity);
661
+ network.deliverOperations(DestinationClient.All);
662
+ const range1 = network.allocateAndSendIds(Client.Client1, 1, { 0: override });
663
+ const overrides1 = expectDefined((_a = getIds(range1)) === null || _a === void 0 ? void 0 : _a.overrides);
664
+ const id1 = compressor1.normalizeToSessionSpace(overrides1[0][0], compressor1.localSessionId);
665
+ const opNormalizedLocal1 = compressor1.normalizeToOpSpace(id1);
666
+ expect(isLocalId(opNormalizedLocal1)).to.be.true;
667
+ expect(isFinalId(id1)).to.be.false;
668
+ network.deliverOperations(DestinationClient.Client1);
669
+ const finalId1 = compressor1.normalizeToOpSpace(id1);
670
+ expect(isFinalId(finalId1)).to.be.true;
671
+ const range2 = network.allocateAndSendIds(Client.Client2, 2, { 1: override });
672
+ const overrides2 = expectDefined((_b = getIds(range2)) === null || _b === void 0 ? void 0 : _b.overrides);
673
+ const id2 = compressor2.normalizeToSessionSpace(overrides2[0][0], compressor2.localSessionId);
674
+ const opNormalizedLocal2 = compressor2.normalizeToOpSpace(id2);
675
+ expect(isLocalId(opNormalizedLocal2)).to.be.true;
676
+ expect(isFinalId(id2)).to.be.false;
677
+ network.allocateAndSendIds(Client.Client3, 1);
678
+ network.deliverOperations(DestinationClient.All);
679
+ const finalId2 = compressor2.normalizeToOpSpace(id2);
680
+ expect(isFinalId(finalId2)).to.be.true;
681
+ expect(finalId1).to.equal(finalId2);
682
+ expect(compressor1.normalizeToOpSpace(id1)).to.equal(finalId1);
683
+ expect(compressor1.normalizeToSessionSpace(finalId1, compressor1.localSessionId)).to.equal(id1);
684
+ expect(compressor1.normalizeToSessionSpace(opNormalizedLocal2, compressor2.localSessionId)).to.equal(id1);
685
+ expect(compressor1.decompress(id1)).to.equal(override);
686
+ expect(compressor1.decompress(finalId1)).to.equal(override);
687
+ expect(compressor1.recompress(override)).to.equal(id1);
688
+ expect(compressor2.normalizeToOpSpace(id2)).to.equal(finalId2);
689
+ expect(compressor2.normalizeToSessionSpace(finalId1, compressor1.localSessionId)).to.equal(id2);
690
+ expect(compressor2.normalizeToSessionSpace(opNormalizedLocal1, compressor1.localSessionId)).to.equal(id2);
691
+ expect(compressor2.decompress(id2)).to.equal(override);
692
+ expect(compressor2.decompress(finalId2)).to.equal(override);
693
+ expect(compressor2.tryRecompress(override)).to.equal(id2);
694
+ expect(compressor3.normalizeToSessionSpace(finalId1, compressor1.localSessionId)).to.equal(finalId1);
695
+ expect(compressor3.normalizeToSessionSpace(opNormalizedLocal1, compressor1.localSessionId)).to.equal(finalId1);
696
+ expect(compressor3.normalizeToSessionSpace(opNormalizedLocal2, compressor2.localSessionId)).to.equal(finalId1);
697
+ expect(compressor3.decompress(finalId1)).to.equal(override);
698
+ expect(compressor3.recompress(override)).to.equal(finalId1);
699
+ });
700
+ itNetwork('maintains alignment after unifying duplicate overrides', 3, (network) => {
701
+ const override = 'override';
702
+ network.allocateAndSendIds(Client.Client1, 1, { 0: override });
703
+ network.allocateAndSendIds(Client.Client2, 2, { 1: override });
704
+ network.allocateAndSendIds(Client.Client1, 5);
705
+ network.allocateAndSendIds(Client.Client2, 5);
706
+ expectSequencedLogsAlign(network, Client.Client1, Client.Client2, 1);
707
+ });
708
+ function expectSequencedLogsAlign(network, client1, client2, numUnifications = 0) {
709
+ network.deliverOperations(DestinationClient.All);
710
+ assert(client1 !== client2);
711
+ const log1 = network.getSequencedIdLog(client1);
712
+ const log2 = network.getSequencedIdLog(client2);
713
+ expect(log1.length).to.equal(log2.length);
714
+ const compressor1 = network.getCompressor(client1);
715
+ const compressor2 = network.getCompressor(client2);
716
+ const ids = new Set();
717
+ const uuidsOrOverrides = new Set();
718
+ for (let i = 0; i < log1.length; i++) {
719
+ const data1 = log1[i];
720
+ const id1 = compressor1.normalizeToOpSpace(data1.id);
721
+ const id2 = compressor2.normalizeToOpSpace(log2[i].id);
722
+ expect(isFinalId(id1)).to.be.true;
723
+ ids.add(id1);
724
+ expect(id1).to.equal(id2);
725
+ const uuidOrOverride1 = compressor1.decompress(id1);
726
+ uuidsOrOverrides.add(uuidOrOverride1);
727
+ if (data1.expectedOverride === undefined) {
728
+ expect(isStableId(uuidOrOverride1)).to.be.true;
729
+ }
730
+ expect(uuidOrOverride1).to.equal(compressor2.decompress(id2));
731
+ }
732
+ const expectedSize = log1.length - numUnifications;
733
+ expect(ids.size).to.equal(expectedSize);
734
+ expect(uuidsOrOverrides.size).to.equal(expectedSize);
735
+ }
736
+ itNetwork('produces ID spaces correctly', (network) => {
737
+ // This test asserts that IDs returned from IDCompressor APIs are correctly encoded as either local or final.
738
+ // This is a glass box test in that it assumes the negative/positive encoding of CompressedIds (negative = local, positive = final).
739
+ const compressor1 = network.getCompressor(Client.Client1);
740
+ // Client 1 makes two IDs, two explicit (one with an override) and one sequential
741
+ network.allocateAndSendIds(Client.Client1, 3, {
742
+ 1: 'override1',
743
+ });
744
+ network.getIdLog(Client.Client1).forEach((id) => expect(id.id).to.be.lessThan(0));
745
+ // Client 1's IDs have not been acked so have no op space equivalent
746
+ network
747
+ .getIdLog(Client.Client1)
748
+ .forEach((idData) => expect(compressor1.normalizeToOpSpace(idData.id)).to.be.lessThan(0));
749
+ // Client 1's IDs are acked
750
+ network.deliverOperations(Client.Client1);
751
+ network.getIdLog(Client.Client1).forEach((id) => expect(id.id).to.be.lessThan(0));
752
+ // Client 3 makes two IDs, two explicit (one with an override) and one sequential
753
+ network.allocateAndSendIds(Client.Client2, 3, {
754
+ 1: 'override2',
755
+ });
756
+ network.getIdLog(Client.Client2).forEach((id) => expect(id.id).to.be.lessThan(0));
757
+ // Client 1 receives Client 2's IDs
758
+ network.deliverOperations(Client.Client1);
759
+ network
760
+ .getIdLog(Client.Client1)
761
+ .slice(-3)
762
+ .forEach((id) => expect(id.id).to.be.greaterThan(0));
763
+ // All IDs have been acked or are from another client, and therefore have a final form in op space
764
+ network
765
+ .getIdLog(Client.Client1)
766
+ .forEach((idData) => expect(compressor1.normalizeToOpSpace(idData.id)).to.be.greaterThan(0));
767
+ // Compression should preserve ID space correctness
768
+ network.getIdLog(Client.Client1).forEach((idData) => {
769
+ const roundtripped = compressor1.recompress(compressor1.decompress(idData.id));
770
+ expect(Math.sign(roundtripped)).to.equal(Math.sign(idData.id));
771
+ });
772
+ network.getIdLog(Client.Client1).forEach((idData) => {
773
+ const opNormalized = compressor1.normalizeToOpSpace(idData.id);
774
+ expect(Math.sign(compressor1.normalizeToSessionSpace(opNormalized, idData.sessionId))).to.equal(Math.sign(idData.id));
775
+ });
776
+ });
777
+ itNetwork('produces consistent IDs with large fuzz input', (network) => {
778
+ performFuzzActions(network, 1984, true, undefined, true, 1000, 25, (network) => network.assertNetworkState());
779
+ network.deliverOperations(DestinationClient.All);
780
+ });
781
+ itNetwork('can set the cluster size via constructor', 2, (network) => {
782
+ const compressor = network.getCompressor(Client.Client1);
783
+ network.allocateAndSendIds(Client.Client1, 1);
784
+ const { range, sessionId } = network.allocateAndSendIds(Client.Client2, 2);
785
+ network.deliverOperations(DestinationClient.All);
786
+ const id = compressor.getIdsFromRange(range, sessionId).get(0);
787
+ // Glass box test, as it knows the order of final IDs
788
+ expect(id).to.equal(compressor.reservedIdCount + compressor.clusterCapacity);
789
+ });
790
+ itNetwork('can set the cluster size via API', 2, (network) => {
791
+ const compressor = network.getCompressor(Client.Client1);
792
+ const initialClusterCapacity = compressor.clusterCapacity;
793
+ network.allocateAndSendIds(Client.Client1, initialClusterCapacity);
794
+ network.allocateAndSendIds(Client.Client2, initialClusterCapacity);
795
+ network.enqueueCapacityChange(5);
796
+ network.allocateAndSendIds(Client.Client1, 1);
797
+ const { range, sessionId } = network.allocateAndSendIds(Client.Client2, 1);
798
+ network.deliverOperations(DestinationClient.All);
799
+ const id = compressor.getIdsFromRange(range, sessionId).get(0);
800
+ // Glass box test, as it knows the order of final IDs
801
+ expect(id).to.equal(compressor.reservedIdCount + initialClusterCapacity * 2 + compressor.clusterCapacity);
802
+ });
803
+ describe('can get IDs from ranges', () => {
804
+ itNetwork('unless they are unfinalized and from a remote session', (network) => {
805
+ const compressor = network.getCompressor(Client.Client1);
806
+ const { range: unackedRemoteRange, sessionId } = network.allocateAndSendIds(Client.Client2, 5);
807
+ expect(() => compressor.getIdsFromRange(unackedRemoteRange, sessionId)).to.throw('Unknown session, range may not be finalized.');
808
+ network.deliverOperations(Client.Client1);
809
+ const { range: unackedRemoteRange2, sessionId: sessionId2 } = network.allocateAndSendIds(Client.Client2, 5);
810
+ expect(() => compressor.getIdsFromRange(unackedRemoteRange2, sessionId2)).to.throw('Remote range must be finalized before getting IDs.');
811
+ });
812
+ itNetwork('that are unacked', (network) => {
813
+ const compressor = network.getCompressor(Client.Client1);
814
+ const { range: rangeDescriptor1, sessionId: sessionId1 } = network.allocateAndSendIds(Client.Client1, 5);
815
+ const range1 = compressor.getIdsFromRange(rangeDescriptor1, sessionId1);
816
+ for (let i = 0; i < range1.length; i++) {
817
+ expect(range1.get(i)).to.equal(-(i + 1));
818
+ }
819
+ const { range: rangeDescriptor2, sessionId: sessionId2 } = network.allocateAndSendIds(Client.Client1, 7);
820
+ const range2 = compressor.getIdsFromRange(rangeDescriptor2, sessionId2);
821
+ for (let i = 0; i < range2.length; i++) {
822
+ expect(range2.get(i)).to.equal(-(i + 1 + range1.length));
823
+ }
824
+ });
825
+ itNetwork('from the local session that are acked', (network) => {
826
+ const compressor = network.getCompressor(Client.Client1);
827
+ const { range, sessionId } = network.allocateAndSendIds(Client.Client1, 5);
828
+ const range1 = compressor.getIdsFromRange(range, sessionId);
829
+ network.deliverOperations(Client.Client1);
830
+ for (let i = 0; i < range1.length; i++) {
831
+ expect(range1.get(i)).to.equal(-(i + 1));
832
+ }
833
+ });
834
+ itNetwork('from a remote session that are in a single cluster', 5, (network) => {
835
+ const compressor = network.getCompressor(Client.Client1);
836
+ const clusterCapacity = compressor.clusterCapacity;
837
+ network.allocateAndSendIds(Client.Client1, 1);
838
+ // Spans an entire cluster
839
+ const { range: rangeFullCluster, sessionId: sessionId2 } = network.allocateAndSendIds(Client.Client2, clusterCapacity);
840
+ network.allocateAndSendIds(Client.Client1, 1);
841
+ network.allocateAndSendIds(Client.Client2, 1);
842
+ // Spans the middle 3 IDs in a cluster of size 5
843
+ const { range: rangeMiddleCluster } = network.allocateAndSendIds(Client.Client2, clusterCapacity - 2);
844
+ network.deliverOperations(Client.Client1);
845
+ const idsFullCluster = compressor.getIdsFromRange(rangeFullCluster, sessionId2);
846
+ for (let i = 0; i < idsFullCluster.length; i++) {
847
+ expect(idsFullCluster.get(i)).to.equal(compressor.reservedIdCount + clusterCapacity + i);
848
+ }
849
+ const idsMiddleCluster = compressor.getIdsFromRange(rangeMiddleCluster, sessionId2);
850
+ for (let i = 0; i < idsMiddleCluster.length; i++) {
851
+ expect(idsMiddleCluster.get(i)).to.equal(compressor.reservedIdCount + clusterCapacity * 2 + 1 + i);
852
+ }
853
+ });
854
+ itNetwork('from a remote session that span multiple clusters', 5, (network) => {
855
+ const compressor = network.getCompressor(Client.Client1);
856
+ const clusterCapacity = compressor.clusterCapacity;
857
+ network.allocateAndSendIds(Client.Client1, clusterCapacity);
858
+ network.allocateAndSendIds(Client.Client2, clusterCapacity - 2);
859
+ network.allocateAndSendIds(Client.Client1, 1);
860
+ const { range: rangeSpanningClusters, sessionId } = network.allocateAndSendIds(Client.Client2, clusterCapacity);
861
+ network.deliverOperations(Client.Client1);
862
+ const idsSpanningClusters = compressor.getIdsFromRange(rangeSpanningClusters, sessionId);
863
+ for (let i = 0; i < 2; i++) {
864
+ expect(idsSpanningClusters.get(i)).to.equal(compressor.reservedIdCount + clusterCapacity + 3 + i);
865
+ }
866
+ for (let i = 2; i < idsSpanningClusters.length; i++) {
867
+ expect(idsSpanningClusters.get(i)).to.equal(compressor.reservedIdCount + clusterCapacity * 2 + 3 + i);
868
+ }
869
+ });
870
+ });
871
+ itNetwork('does not decompress ids for empty parts of clusters', 2, (network) => {
872
+ // This is a glass box test in that it creates a final ID outside of the ID compressor
873
+ network.allocateAndSendIds(Client.Client1, 1);
874
+ network.deliverOperations(DestinationClient.All);
875
+ const id = network.getSequencedIdLog(Client.Client2)[0].id;
876
+ expect(isFinalId(id)).to.be.true;
877
+ // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
878
+ const emptyId = (id + 1);
879
+ expect(() => network.getCompressor(Client.Client2).decompress(emptyId)).to.throw('Compressed ID was not generated by this compressor');
880
+ });
881
+ describe('Finalizing', () => {
882
+ itNetwork('can finalize IDs from multiple clients', (network) => {
883
+ network.allocateAndSendIds(Client.Client1, 3, {
884
+ 1: 'override1',
885
+ });
886
+ network.allocateAndSendIds(Client.Client2, 3, {
887
+ 1: 'override2',
888
+ });
889
+ expectSequencedLogsAlign(network, Client.Client1, Client.Client2);
890
+ });
891
+ itNetwork('can finalize a range when the current cluster is full', 5, (network) => {
892
+ const clusterCapacity = network.getCompressor(Client.Client1).clusterCapacity;
893
+ network.allocateAndSendIds(Client.Client1, clusterCapacity);
894
+ network.allocateAndSendIds(Client.Client2, clusterCapacity);
895
+ network.allocateAndSendIds(Client.Client1, clusterCapacity, {
896
+ 0: 'override1',
897
+ 1: 'override2',
898
+ 2: 'override3',
899
+ });
900
+ expectSequencedLogsAlign(network, Client.Client1, Client.Client2);
901
+ });
902
+ itNetwork('can finalize a range that spans multiple clusters', 5, (network) => {
903
+ const clusterCapacity = network.getCompressor(Client.Client1).clusterCapacity;
904
+ network.allocateAndSendIds(Client.Client1, clusterCapacity - 2, {
905
+ 0: 'override1',
906
+ 1: 'override2',
907
+ });
908
+ network.allocateAndSendIds(Client.Client2, 1);
909
+ network.allocateAndSendIds(Client.Client1, clusterCapacity, {
910
+ 0: 'override3',
911
+ 1: 'override4',
912
+ 2: 'override5',
913
+ });
914
+ expectSequencedLogsAlign(network, Client.Client1, Client.Client2);
915
+ });
916
+ });
917
+ describe('Serialization', () => {
918
+ itNetwork('prevents attempts to resume a session from a serialized compressor with no session', (network) => {
919
+ const compressor = network.getCompressor(Client.Client1);
920
+ network.allocateAndSendIds(Client.Client2, 1);
921
+ network.allocateAndSendIds(Client.Client3, 1);
922
+ network.deliverOperations(Client.Client1);
923
+ const serializedWithoutLocalState = compressor.serialize(false);
924
+ expect(() => IdCompressor.deserialize(serializedWithoutLocalState, sessionIds.get(Client.Client2))).to.throw('Cannot resume existing session.');
925
+ });
926
+ itNetwork('round-trips local state', 3, (network) => {
927
+ network.allocateAndSendIds(Client.Client1, 2);
928
+ network.allocateAndSendIds(Client.Client2, 3);
929
+ network.allocateAndSendIds(Client.Client1, 5);
930
+ network.allocateAndSendIds(Client.Client1, 5);
931
+ network.allocateAndSendIds(Client.Client3, 3);
932
+ network.allocateAndSendIds(Client.Client2, 3);
933
+ network.deliverOperations(Client.Client1);
934
+ // Some un-acked locals at the end
935
+ network.allocateAndSendIds(Client.Client1, 4);
936
+ const [serializedNoSession, serializedWithSession] = expectSerializes(network.getCompressor(Client.Client1));
937
+ expect(hasOngoingSession(serializedWithSession)).to.be.true;
938
+ expect(hasOngoingSession(serializedNoSession)).to.be.false;
939
+ });
940
+ itNetwork('can serialize a partially empty cluster', 5, (network) => {
941
+ network.allocateAndSendIds(Client.Client1, 2);
942
+ network.deliverOperations(DestinationClient.All);
943
+ expectSerializes(network.getCompressor(Client.Client1));
944
+ expectSerializes(network.getCompressor(Client.Client3));
945
+ });
946
+ itNetwork('can serialize a full cluster', 2, (network) => {
947
+ network.allocateAndSendIds(Client.Client1, 2);
948
+ network.deliverOperations(DestinationClient.All);
949
+ expectSerializes(network.getCompressor(Client.Client1));
950
+ expectSerializes(network.getCompressor(Client.Client3));
951
+ });
952
+ itNetwork('can serialize full clusters from different clients', 2, (network) => {
953
+ network.allocateAndSendIds(Client.Client1, 2);
954
+ network.allocateAndSendIds(Client.Client2, 2);
955
+ network.deliverOperations(DestinationClient.All);
956
+ expectSerializes(network.getCompressor(Client.Client1));
957
+ expectSerializes(network.getCompressor(Client.Client3));
958
+ });
959
+ itNetwork('can serialize clusters of different sizes and clients', 3, (network) => {
960
+ network.allocateAndSendIds(Client.Client1, 2);
961
+ network.allocateAndSendIds(Client.Client2, 3);
962
+ network.allocateAndSendIds(Client.Client1, 5);
963
+ network.allocateAndSendIds(Client.Client1, 5);
964
+ network.allocateAndSendIds(Client.Client2, 3);
965
+ network.deliverOperations(DestinationClient.All);
966
+ expectSerializes(network.getCompressor(Client.Client1));
967
+ expectSerializes(network.getCompressor(Client.Client3));
968
+ });
969
+ itNetwork('can serialize clusters with overrides', 3, (network) => {
970
+ network.allocateAndSendIds(Client.Client1, 2, {
971
+ 1: 'override',
972
+ });
973
+ network.allocateAndSendIds(Client.Client2, 3, {
974
+ 0: 'override1',
975
+ 2: 'override2',
976
+ });
977
+ network.deliverOperations(DestinationClient.All);
978
+ expectSerializes(network.getCompressor(Client.Client1));
979
+ expectSerializes(network.getCompressor(Client.Client3));
980
+ });
981
+ itNetwork('packs IDs into a single cluster when a single client generates non-overridden ids', 3, (network) => {
982
+ network.allocateAndSendIds(Client.Client1, 20);
983
+ network.deliverOperations(DestinationClient.All);
984
+ const [serialized1WithNoSession, serialized1WithSession] = expectSerializes(network.getCompressor(Client.Client1));
985
+ expect(serialized1WithNoSession.clusters.length).to.equal(1);
986
+ expect(serialized1WithSession.clusters.length).to.equal(1);
987
+ const [serialized3WithNoSession, serialized3WithSession] = expectSerializes(network.getCompressor(Client.Client3));
988
+ expect(serialized3WithNoSession.clusters.length).to.equal(1);
989
+ expect(serialized3WithSession.clusters.length).to.equal(1);
990
+ });
991
+ itNetwork('serializes correctly after unifying duplicate overrides', 3, (network) => {
992
+ const override = 'override';
993
+ network.allocateAndSendIds(Client.Client1, 1, { 0: override });
994
+ network.allocateAndSendIds(Client.Client2, 2, { 1: override });
995
+ network.allocateAndSendIds(Client.Client1, 5);
996
+ network.allocateAndSendIds(Client.Client2, 5);
997
+ network.deliverOperations(DestinationClient.All);
998
+ expectSerializes(network.getCompressor(Client.Client1));
999
+ expectSerializes(network.getCompressor(Client.Client2));
1000
+ expectSerializes(network.getCompressor(Client.Client3));
1001
+ });
1002
+ itNetwork('can resume a session and interact with multiple other clients', 3, (network) => {
1003
+ const clusterSize = network.getCompressor(Client.Client1).clusterCapacity;
1004
+ network.allocateAndSendIds(Client.Client1, clusterSize);
1005
+ network.allocateAndSendIds(Client.Client2, clusterSize);
1006
+ network.allocateAndSendIds(Client.Client3, clusterSize);
1007
+ network.allocateAndSendIds(Client.Client1, clusterSize);
1008
+ network.allocateAndSendIds(Client.Client2, clusterSize);
1009
+ network.allocateAndSendIds(Client.Client3, clusterSize);
1010
+ network.deliverOperations(DestinationClient.All);
1011
+ network.goOfflineThenResume(Client.Client1);
1012
+ network.allocateAndSendIds(Client.Client1, 2);
1013
+ network.allocateAndSendIds(Client.Client2, 2);
1014
+ network.allocateAndSendIds(Client.Client3, 2);
1015
+ expectSequencedLogsAlign(network, Client.Client1, Client.Client2);
1016
+ });
1017
+ itNetwork('can serialize after a large fuzz input', 3, (network) => {
1018
+ performFuzzActions(network, Math.PI, true, undefined, true, 1000, 25, (network) => {
1019
+ // Periodically check that everyone in the network has the same serialized state
1020
+ network.deliverOperations(DestinationClient.All);
1021
+ const compressors = network.getTargetCompressors(DestinationClient.All);
1022
+ let deserializedPrev = roundtrip(compressors[0][1], false)[1];
1023
+ for (let i = 1; i < compressors.length; i++) {
1024
+ const deserializedCur = roundtrip(compressors[i][1], false)[1];
1025
+ expect(deserializedPrev.equals(deserializedCur, false)).to.be.true;
1026
+ deserializedPrev = deserializedCur;
1027
+ }
1028
+ });
1029
+ expectSerializes(network.getCompressor(Client.Client1));
1030
+ expectSerializes(network.getCompressor(Client.Client2));
1031
+ expectSerializes(network.getCompressor(Client.Client3));
1032
+ });
1033
+ itNetwork('stores override indices relative to their clusters', 3, (network) => {
1034
+ var _a, _b;
1035
+ network.allocateAndSendIds(Client.Client1, 3, { 0: 'cluster1' });
1036
+ network.allocateAndSendIds(Client.Client2, 3, { 0: 'cluster2' });
1037
+ network.deliverOperations(Client.Client1);
1038
+ const serialized = network.getCompressor(Client.Client1).serialize(false);
1039
+ expect(serialized.clusters.length).to.equal(2);
1040
+ expect((_a = serialized.clusters[0][2]) === null || _a === void 0 ? void 0 : _a[0][0]).to.equal(0);
1041
+ expect((_b = serialized.clusters[1][2]) === null || _b === void 0 ? void 0 : _b[0][0]).to.equal(0);
1042
+ });
1043
+ });
1044
+ });
1045
+ });
1046
+ function createNetworkTestFunction(validateAfter) {
1047
+ return (title, testOrCapacity, test) => {
1048
+ it(title, () => {
1049
+ const hasCapacity = typeof testOrCapacity === 'number';
1050
+ const capacity = hasCapacity ? testOrCapacity : undefined;
1051
+ // TODO: This cast can be removed on typescript 4.6
1052
+ const network = new IdCompressorTestNetwork(capacity);
1053
+ // TODO: This cast can be removed on typescript 4.6
1054
+ (hasCapacity ? assertNotUndefined(test) : testOrCapacity)(network);
1055
+ if (validateAfter) {
1056
+ network.deliverOperations(DestinationClient.All);
1057
+ network.assertNetworkState();
1058
+ }
1059
+ });
1060
+ };
1061
+ }
1062
+ function describeNetwork(title, its) {
1063
+ describe(title, () => {
1064
+ its(createNetworkTestFunction(false));
1065
+ });
1066
+ describe(`${title} (with validation)`, () => {
1067
+ its(createNetworkTestFunction(true));
1068
+ });
1069
+ }
1070
+ function describeNetworkNoValidation(title, its) {
1071
+ describe(title, () => {
1072
+ its(createNetworkTestFunction(false));
1073
+ });
1074
+ }
1075
+ //# sourceMappingURL=IdCompressor.tests.js.map