@fluidframework/tree 2.62.0-356644 → 2.62.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/CHANGELOG.md +162 -0
  2. package/api-report/tree.alpha.api.md +23 -21
  3. package/api-report/tree.beta.api.md +15 -0
  4. package/api-report/tree.legacy.beta.api.md +18 -0
  5. package/dist/alpha.d.ts +8 -8
  6. package/dist/api.d.ts +17 -0
  7. package/dist/api.d.ts.map +1 -0
  8. package/dist/api.js +24 -0
  9. package/dist/api.js.map +1 -0
  10. package/dist/beta.d.ts +5 -0
  11. package/dist/codec/codec.d.ts +3 -5
  12. package/dist/codec/codec.d.ts.map +1 -1
  13. package/dist/codec/codec.js +9 -2
  14. package/dist/codec/codec.js.map +1 -1
  15. package/dist/codec/index.d.ts +0 -1
  16. package/dist/codec/index.d.ts.map +1 -1
  17. package/dist/codec/index.js +1 -3
  18. package/dist/codec/index.js.map +1 -1
  19. package/dist/core/rebase/utils.js +1 -1
  20. package/dist/core/rebase/utils.js.map +1 -1
  21. package/dist/core/tree/detachedFieldIndex.js +1 -1
  22. package/dist/core/tree/detachedFieldIndex.js.map +1 -1
  23. package/dist/external-utilities/index.d.ts +1 -1
  24. package/dist/external-utilities/index.d.ts.map +1 -1
  25. package/dist/external-utilities/index.js +1 -2
  26. package/dist/external-utilities/index.js.map +1 -1
  27. package/dist/external-utilities/typeboxValidator.d.ts +0 -13
  28. package/dist/external-utilities/typeboxValidator.d.ts.map +1 -1
  29. package/dist/external-utilities/typeboxValidator.js +3 -5
  30. package/dist/external-utilities/typeboxValidator.js.map +1 -1
  31. package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts +2 -0
  32. package/dist/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
  33. package/dist/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
  34. package/dist/feature-libraries/flex-tree/index.d.ts +1 -0
  35. package/dist/feature-libraries/flex-tree/index.d.ts.map +1 -1
  36. package/dist/feature-libraries/flex-tree/index.js +4 -1
  37. package/dist/feature-libraries/flex-tree/index.js.map +1 -1
  38. package/dist/feature-libraries/flex-tree/lazyNode.d.ts.map +1 -1
  39. package/dist/feature-libraries/flex-tree/lazyNode.js +15 -8
  40. package/dist/feature-libraries/flex-tree/lazyNode.js.map +1 -1
  41. package/dist/feature-libraries/flex-tree/observer.d.ts +32 -0
  42. package/dist/feature-libraries/flex-tree/observer.d.ts.map +1 -0
  43. package/dist/feature-libraries/flex-tree/observer.js +33 -0
  44. package/dist/feature-libraries/flex-tree/observer.js.map +1 -0
  45. package/dist/feature-libraries/index.d.ts +1 -1
  46. package/dist/feature-libraries/index.d.ts.map +1 -1
  47. package/dist/feature-libraries/index.js +3 -1
  48. package/dist/feature-libraries/index.js.map +1 -1
  49. package/dist/index.d.ts +5 -5
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +9 -8
  52. package/dist/index.js.map +1 -1
  53. package/dist/legacy.d.ts +7 -1
  54. package/dist/packageVersion.d.ts +1 -1
  55. package/dist/packageVersion.d.ts.map +1 -1
  56. package/dist/packageVersion.js +1 -1
  57. package/dist/packageVersion.js.map +1 -1
  58. package/dist/shared-tree/index.d.ts +2 -2
  59. package/dist/shared-tree/index.d.ts.map +1 -1
  60. package/dist/shared-tree/index.js.map +1 -1
  61. package/dist/shared-tree/sharedTree.d.ts +9 -4
  62. package/dist/shared-tree/sharedTree.d.ts.map +1 -1
  63. package/dist/shared-tree/sharedTree.js +5 -4
  64. package/dist/shared-tree/sharedTree.js.map +1 -1
  65. package/dist/shared-tree/treeAlpha.d.ts +114 -1
  66. package/dist/shared-tree/treeAlpha.d.ts.map +1 -1
  67. package/dist/shared-tree/treeAlpha.js +140 -1
  68. package/dist/shared-tree/treeAlpha.js.map +1 -1
  69. package/dist/shared-tree/treeCheckout.d.ts.map +1 -1
  70. package/dist/shared-tree/treeCheckout.js +2 -2
  71. package/dist/shared-tree/treeCheckout.js.map +1 -1
  72. package/dist/shared-tree-core/editManager.d.ts +9 -4
  73. package/dist/shared-tree-core/editManager.d.ts.map +1 -1
  74. package/dist/shared-tree-core/editManager.js +41 -28
  75. package/dist/shared-tree-core/editManager.js.map +1 -1
  76. package/dist/shared-tree-core/editManagerCodecsCommons.d.ts.map +1 -1
  77. package/dist/shared-tree-core/editManagerCodecsCommons.js +3 -3
  78. package/dist/shared-tree-core/editManagerCodecsCommons.js.map +1 -1
  79. package/dist/shared-tree-core/editManagerCodecsV5.d.ts.map +1 -1
  80. package/dist/shared-tree-core/editManagerCodecsV5.js +3 -3
  81. package/dist/shared-tree-core/editManagerCodecsV5.js.map +1 -1
  82. package/dist/shared-tree-core/messageCodecV1ToV4.d.ts.map +1 -1
  83. package/dist/shared-tree-core/messageCodecV1ToV4.js +2 -2
  84. package/dist/shared-tree-core/messageCodecV1ToV4.js.map +1 -1
  85. package/dist/shared-tree-core/messageCodecV5.d.ts.map +1 -1
  86. package/dist/shared-tree-core/messageCodecV5.js +1 -1
  87. package/dist/shared-tree-core/messageCodecV5.js.map +1 -1
  88. package/dist/shared-tree-core/sharedTreeCore.d.ts +1 -0
  89. package/dist/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
  90. package/dist/shared-tree-core/sharedTreeCore.js +15 -10
  91. package/dist/shared-tree-core/sharedTreeCore.js.map +1 -1
  92. package/dist/simple-tree/api/tree.d.ts +7 -0
  93. package/dist/simple-tree/api/tree.d.ts.map +1 -1
  94. package/dist/simple-tree/api/tree.js +2 -0
  95. package/dist/simple-tree/api/tree.js.map +1 -1
  96. package/dist/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
  97. package/dist/simple-tree/core/unhydratedFlexTree.js +7 -1
  98. package/dist/simple-tree/core/unhydratedFlexTree.js.map +1 -1
  99. package/dist/treeFactory.d.ts +38 -9
  100. package/dist/treeFactory.d.ts.map +1 -1
  101. package/dist/treeFactory.js +44 -9
  102. package/dist/treeFactory.js.map +1 -1
  103. package/lib/alpha.d.ts +8 -8
  104. package/lib/api.d.ts +17 -0
  105. package/lib/api.d.ts.map +1 -0
  106. package/lib/api.js +22 -0
  107. package/lib/api.js.map +1 -0
  108. package/lib/beta.d.ts +5 -0
  109. package/lib/codec/codec.d.ts +3 -5
  110. package/lib/codec/codec.d.ts.map +1 -1
  111. package/lib/codec/codec.js +8 -1
  112. package/lib/codec/codec.js.map +1 -1
  113. package/lib/codec/index.d.ts +0 -1
  114. package/lib/codec/index.d.ts.map +1 -1
  115. package/lib/codec/index.js +0 -1
  116. package/lib/codec/index.js.map +1 -1
  117. package/lib/core/rebase/utils.js +1 -1
  118. package/lib/core/rebase/utils.js.map +1 -1
  119. package/lib/core/tree/detachedFieldIndex.js +2 -2
  120. package/lib/core/tree/detachedFieldIndex.js.map +1 -1
  121. package/lib/external-utilities/index.d.ts +1 -1
  122. package/lib/external-utilities/index.d.ts.map +1 -1
  123. package/lib/external-utilities/index.js +1 -1
  124. package/lib/external-utilities/index.js.map +1 -1
  125. package/lib/external-utilities/typeboxValidator.d.ts +0 -13
  126. package/lib/external-utilities/typeboxValidator.d.ts.map +1 -1
  127. package/lib/external-utilities/typeboxValidator.js +1 -3
  128. package/lib/external-utilities/typeboxValidator.js.map +1 -1
  129. package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts +2 -0
  130. package/lib/feature-libraries/flex-tree/flexTreeTypes.d.ts.map +1 -1
  131. package/lib/feature-libraries/flex-tree/flexTreeTypes.js.map +1 -1
  132. package/lib/feature-libraries/flex-tree/index.d.ts +1 -0
  133. package/lib/feature-libraries/flex-tree/index.d.ts.map +1 -1
  134. package/lib/feature-libraries/flex-tree/index.js +1 -0
  135. package/lib/feature-libraries/flex-tree/index.js.map +1 -1
  136. package/lib/feature-libraries/flex-tree/lazyNode.d.ts.map +1 -1
  137. package/lib/feature-libraries/flex-tree/lazyNode.js +15 -8
  138. package/lib/feature-libraries/flex-tree/lazyNode.js.map +1 -1
  139. package/lib/feature-libraries/flex-tree/observer.d.ts +32 -0
  140. package/lib/feature-libraries/flex-tree/observer.d.ts.map +1 -0
  141. package/lib/feature-libraries/flex-tree/observer.js +40 -0
  142. package/lib/feature-libraries/flex-tree/observer.js.map +1 -0
  143. package/lib/feature-libraries/index.d.ts +1 -1
  144. package/lib/feature-libraries/index.d.ts.map +1 -1
  145. package/lib/feature-libraries/index.js +1 -1
  146. package/lib/feature-libraries/index.js.map +1 -1
  147. package/lib/index.d.ts +5 -5
  148. package/lib/index.d.ts.map +1 -1
  149. package/lib/index.js +3 -3
  150. package/lib/index.js.map +1 -1
  151. package/lib/legacy.d.ts +7 -1
  152. package/lib/packageVersion.d.ts +1 -1
  153. package/lib/packageVersion.d.ts.map +1 -1
  154. package/lib/packageVersion.js +1 -1
  155. package/lib/packageVersion.js.map +1 -1
  156. package/lib/shared-tree/index.d.ts +2 -2
  157. package/lib/shared-tree/index.d.ts.map +1 -1
  158. package/lib/shared-tree/index.js.map +1 -1
  159. package/lib/shared-tree/sharedTree.d.ts +9 -4
  160. package/lib/shared-tree/sharedTree.d.ts.map +1 -1
  161. package/lib/shared-tree/sharedTree.js +6 -5
  162. package/lib/shared-tree/sharedTree.js.map +1 -1
  163. package/lib/shared-tree/treeAlpha.d.ts +114 -1
  164. package/lib/shared-tree/treeAlpha.d.ts.map +1 -1
  165. package/lib/shared-tree/treeAlpha.js +143 -4
  166. package/lib/shared-tree/treeAlpha.js.map +1 -1
  167. package/lib/shared-tree/treeCheckout.d.ts.map +1 -1
  168. package/lib/shared-tree/treeCheckout.js +3 -3
  169. package/lib/shared-tree/treeCheckout.js.map +1 -1
  170. package/lib/shared-tree-core/editManager.d.ts +9 -4
  171. package/lib/shared-tree-core/editManager.d.ts.map +1 -1
  172. package/lib/shared-tree-core/editManager.js +41 -28
  173. package/lib/shared-tree-core/editManager.js.map +1 -1
  174. package/lib/shared-tree-core/editManagerCodecsCommons.d.ts.map +1 -1
  175. package/lib/shared-tree-core/editManagerCodecsCommons.js +3 -3
  176. package/lib/shared-tree-core/editManagerCodecsCommons.js.map +1 -1
  177. package/lib/shared-tree-core/editManagerCodecsV5.d.ts.map +1 -1
  178. package/lib/shared-tree-core/editManagerCodecsV5.js +3 -3
  179. package/lib/shared-tree-core/editManagerCodecsV5.js.map +1 -1
  180. package/lib/shared-tree-core/messageCodecV1ToV4.d.ts.map +1 -1
  181. package/lib/shared-tree-core/messageCodecV1ToV4.js +2 -2
  182. package/lib/shared-tree-core/messageCodecV1ToV4.js.map +1 -1
  183. package/lib/shared-tree-core/messageCodecV5.d.ts.map +1 -1
  184. package/lib/shared-tree-core/messageCodecV5.js +1 -1
  185. package/lib/shared-tree-core/messageCodecV5.js.map +1 -1
  186. package/lib/shared-tree-core/sharedTreeCore.d.ts +1 -0
  187. package/lib/shared-tree-core/sharedTreeCore.d.ts.map +1 -1
  188. package/lib/shared-tree-core/sharedTreeCore.js +15 -10
  189. package/lib/shared-tree-core/sharedTreeCore.js.map +1 -1
  190. package/lib/simple-tree/api/tree.d.ts +7 -0
  191. package/lib/simple-tree/api/tree.d.ts.map +1 -1
  192. package/lib/simple-tree/api/tree.js +2 -0
  193. package/lib/simple-tree/api/tree.js.map +1 -1
  194. package/lib/simple-tree/core/unhydratedFlexTree.d.ts.map +1 -1
  195. package/lib/simple-tree/core/unhydratedFlexTree.js +8 -2
  196. package/lib/simple-tree/core/unhydratedFlexTree.js.map +1 -1
  197. package/lib/treeFactory.d.ts +38 -9
  198. package/lib/treeFactory.d.ts.map +1 -1
  199. package/lib/treeFactory.js +41 -8
  200. package/lib/treeFactory.js.map +1 -1
  201. package/package.json +25 -25
  202. package/src/api.ts +30 -0
  203. package/src/codec/codec.ts +12 -6
  204. package/src/codec/index.ts +0 -1
  205. package/src/core/rebase/utils.ts +1 -1
  206. package/src/core/tree/detachedFieldIndex.ts +2 -2
  207. package/src/external-utilities/index.ts +1 -1
  208. package/src/external-utilities/typeboxValidator.ts +1 -3
  209. package/src/feature-libraries/flex-tree/flexTreeTypes.ts +2 -0
  210. package/src/feature-libraries/flex-tree/index.ts +2 -0
  211. package/src/feature-libraries/flex-tree/lazyNode.ts +13 -3
  212. package/src/feature-libraries/flex-tree/observer.ts +64 -0
  213. package/src/feature-libraries/index.ts +3 -0
  214. package/src/index.ts +6 -4
  215. package/src/packageVersion.ts +1 -1
  216. package/src/shared-tree/index.ts +2 -0
  217. package/src/shared-tree/sharedTree.ts +13 -6
  218. package/src/shared-tree/treeAlpha.ts +309 -4
  219. package/src/shared-tree/treeCheckout.ts +6 -3
  220. package/src/shared-tree-core/editManager.ts +57 -30
  221. package/src/shared-tree-core/editManagerCodecsCommons.ts +12 -3
  222. package/src/shared-tree-core/editManagerCodecsV5.ts +9 -3
  223. package/src/shared-tree-core/messageCodecV1ToV4.ts +5 -2
  224. package/src/shared-tree-core/messageCodecV5.ts +4 -1
  225. package/src/shared-tree-core/sharedTreeCore.ts +20 -10
  226. package/src/simple-tree/api/tree.ts +8 -0
  227. package/src/simple-tree/core/unhydratedFlexTree.ts +11 -2
  228. package/src/treeFactory.ts +48 -8
  229. package/dist/codec/noopValidator.d.ts +0 -13
  230. package/dist/codec/noopValidator.d.ts.map +0 -1
  231. package/dist/codec/noopValidator.js +0 -17
  232. package/dist/codec/noopValidator.js.map +0 -1
  233. package/docs/user-facing/schema-evolution.md +0 -309
  234. package/lib/codec/noopValidator.d.ts +0 -13
  235. package/lib/codec/noopValidator.d.ts.map +0 -1
  236. package/lib/codec/noopValidator.js +0 -14
  237. package/lib/codec/noopValidator.js.map +0 -1
  238. package/src/codec/noopValidator.ts +0 -18
@@ -115,11 +115,14 @@ export class EditManager<
115
115
  /**
116
116
  * @param changeFamily - the change family of changes on the trunk and local branch
117
117
  * @param localSessionId - the id of the local session that will be used for local commits
118
+ * @param mintRevisionTag - a function which generates globally unique revision tags
119
+ * @param onSharedBranchCreated - called when a new shared branch is created. This is not called for the main branch.
118
120
  */
119
121
  public constructor(
120
122
  public readonly changeFamily: TChangeFamily,
121
123
  public readonly localSessionId: SessionId,
122
124
  private readonly mintRevisionTag: () => RevisionTag,
125
+ private readonly onSharedBranchCreated?: (branchId: BranchId) => void,
123
126
  logger?: ITelemetryLoggerExt,
124
127
  ) {
125
128
  this.trunkBase = {
@@ -146,12 +149,7 @@ export class EditManager<
146
149
  this.telemetryEventBatcher,
147
150
  );
148
151
 
149
- const mainBranch = this.createSharedBranch("main", undefined, undefined, mainTrunk);
150
-
151
- // Track all forks of the local branch for purposes of trunk eviction. Unlike the local branch, they have
152
- // an unknown lifetime and rebase frequency, so we can not make any assumptions about which trunk commits
153
- // they require and therefore we monitor them explicitly.
154
- onForkTransitive(mainBranch.localBranch, (fork) => this.registerBranch(fork));
152
+ this.createAndAddSharedBranch("main", undefined, undefined, mainTrunk);
155
153
  }
156
154
 
157
155
  public getLocalBranch(branchId: BranchId): SharedTreeBranch<TEditor, TChangeset> {
@@ -159,7 +157,7 @@ export class EditManager<
159
157
  }
160
158
 
161
159
  private getSharedBranch(branchId: BranchId): SharedBranch<TEditor, TChangeset> {
162
- return this.sharedBranches.get(branchId) ?? fail("Branch does not exist");
160
+ return this.sharedBranches.get(branchId) ?? fail(0xc56 /* Branch does not exist */);
163
161
  }
164
162
 
165
163
  /**
@@ -374,7 +372,7 @@ export class EditManager<
374
372
  this.trunkBase.revision,
375
373
  );
376
374
  branches.set(branchId, branchSummary);
377
- assert(branchSummary.base !== undefined, "Branch summary must have a base");
375
+ assert(branchSummary.base !== undefined, 0xc57 /* Branch summary must have a base */);
378
376
  const baseSequenceId = mainBranch.getCommitSequenceId(branchSummary.base);
379
377
  minBaseSeqId = minSequenceId(minBaseSeqId, baseSequenceId);
380
378
  }
@@ -392,7 +390,8 @@ export class EditManager<
392
390
  // when hydrating the peer branches below
393
391
  const trunkRevisionCache = new Map<RevisionTag, GraphCommit<TChangeset>>();
394
392
  trunkRevisionCache.set(this.trunkBase.revision, this.trunkBase);
395
- const mainBranch = this.sharedBranches.get("main") ?? fail("Main branch must exist");
393
+ const mainBranch =
394
+ this.sharedBranches.get("main") ?? fail(0xc58 /* Main branch must exist */);
396
395
  mainBranch.loadSummaryData(data.main, trunkRevisionCache);
397
396
  if (data.branches !== undefined) {
398
397
  for (const [branchId, branchData] of data.branches) {
@@ -403,6 +402,7 @@ export class EditManager<
403
402
  mainBranch.trunk.fork(),
404
403
  );
405
404
  branch.loadSummaryData(branchData, trunkRevisionCache);
405
+ this.addSharedBranch(branchId, branch);
406
406
  }
407
407
  }
408
408
  }
@@ -419,10 +419,6 @@ export class EditManager<
419
419
  return getPathFromBase(this.getTrunkHead(branchId), this.trunkBase);
420
420
  }
421
421
 
422
- public getLocalChanges(branchId: BranchId): readonly TChangeset[] {
423
- return this.getLocalCommits(branchId).map((c) => c.change);
424
- }
425
-
426
422
  public getLocalCommits(branchId: BranchId): readonly GraphCommit<TChangeset>[] {
427
423
  const branch = this.getSharedBranch(branchId);
428
424
  return branch.getLocalCommits();
@@ -450,21 +446,18 @@ export class EditManager<
450
446
  branchId: BranchId,
451
447
  ): void {
452
448
  if (sessionId === this.localSessionId) {
453
- assert(this.sharedBranches.has(branchId), "Expected branch to already exist");
449
+ assert(this.sharedBranches.has(branchId), 0xc59 /* Expected branch to already exist */);
454
450
  return;
455
451
  }
456
452
 
457
453
  const mainBranch = this.getSharedBranch("main");
458
454
  const branchTrunk = mainBranch.rebasePeer(sessionId, referenceSequenceNumber).fork();
459
-
460
- const sharedBranch = this.createSharedBranch(branchId, sessionId, mainBranch, branchTrunk);
461
- this.registerBranch(sharedBranch.localBranch);
462
- onForkTransitive(sharedBranch.localBranch, (fork) => this.registerBranch(fork));
455
+ this.createAndAddSharedBranch(branchId, sessionId, mainBranch, branchTrunk);
463
456
  }
464
457
 
465
- public addBranch(branchId: BranchId): void {
466
- const main = this.getSharedBranch("main") ?? fail("Main branch must exist");
467
- this.createSharedBranch(
458
+ public addNewBranch(branchId: BranchId): void {
459
+ const main = this.getSharedBranch("main") ?? fail(0xc5a /* Main branch must exist */);
460
+ this.createAndAddSharedBranch(
468
461
  branchId,
469
462
  this.localSessionId,
470
463
  main,
@@ -472,10 +465,46 @@ export class EditManager<
472
465
  );
473
466
  }
474
467
 
468
+ public getSharedBranchIds(): BranchId[] {
469
+ return Array.from(this.sharedBranches.keys());
470
+ }
471
+
475
472
  public removeBranch(branchId: BranchId): void {
476
- assert(branchId !== "main", "Cannot remove main branch");
473
+ assert(branchId !== "main", 0xc5b /* Cannot remove main branch */);
477
474
  const hadBranch = this.sharedBranches.delete(branchId);
478
- assert(hadBranch, "Expected branch to exist");
475
+ assert(hadBranch, 0xc5c /* Expected branch to exist */);
476
+ }
477
+
478
+ private createAndAddSharedBranch(
479
+ branchId: BranchId,
480
+ sessionId: SessionId | undefined,
481
+ parent: SharedBranch<TEditor, TChangeset> | undefined,
482
+ branch: SharedTreeBranch<TEditor, TChangeset>,
483
+ ): SharedBranch<TEditor, TChangeset> {
484
+ const sharedBranch = this.createSharedBranch(branchId, sessionId, parent, branch);
485
+ this.addSharedBranch(branchId, sharedBranch);
486
+ return sharedBranch;
487
+ }
488
+
489
+ private addSharedBranch(
490
+ branchId: BranchId,
491
+ branch: SharedBranch<TEditor, TChangeset>,
492
+ ): void {
493
+ assert(
494
+ !this.sharedBranches.has(branchId),
495
+ 0xc5d /* A branch with this ID already exists */,
496
+ );
497
+ this.sharedBranches.set(branchId, branch);
498
+
499
+ // Track all forks of the local branch for purposes of trunk eviction. Unlike the local branch, they have
500
+ // an unknown lifetime and rebase frequency, so we can not make any assumptions about which trunk commits
501
+ // they require and therefore we monitor them explicitly.
502
+ onForkTransitive(branch.localBranch, (fork) => this.registerBranch(fork));
503
+
504
+ if (branchId !== "main") {
505
+ this.registerBranch(branch.localBranch);
506
+ this.onSharedBranchCreated?.(branchId);
507
+ }
479
508
  }
480
509
 
481
510
  private createSharedBranch(
@@ -496,8 +525,6 @@ export class EditManager<
496
525
  this.telemetryEventBatcher,
497
526
  );
498
527
 
499
- assert(!this.sharedBranches.has(branchId), "A branch with this ID already exists");
500
- this.sharedBranches.set(branchId, sharedBranch);
501
528
  return sharedBranch;
502
529
  }
503
530
 
@@ -517,7 +544,7 @@ export class EditManager<
517
544
  sessionId: SessionId,
518
545
  sequenceNumber: SeqNumber,
519
546
  referenceSequenceNumber: SeqNumber,
520
- branchId: BranchId = "main",
547
+ branchId: BranchId,
521
548
  ): void {
522
549
  assert(newCommits.length > 0, 0xad8 /* Expected at least one sequenced change */);
523
550
  assert(
@@ -976,7 +1003,7 @@ class SharedBranch<TEditor extends ChangeFamilyEditor, TChangeset> {
976
1003
  // rebasing trunk changes over the inverse of trunk changes.
977
1004
  assert(
978
1005
  this.localBranch.getHead() === this.trunk.getHead(),
979
- "Clients with local changes cannot be used to generate summaries",
1006
+ 0xc5e /* Clients with local changes cannot be used to generate summaries */,
980
1007
  );
981
1008
 
982
1009
  let parentHead: GraphCommit<TChangeset>;
@@ -996,7 +1023,7 @@ class SharedBranch<TEditor extends ChangeFamilyEditor, TChangeset> {
996
1023
  );
997
1024
  assert(
998
1025
  forkPointFromMainTrunk !== undefined,
999
- "Expected child branch to be based on main branch",
1026
+ 0xc5f /* Expected child branch to be based on main branch */,
1000
1027
  );
1001
1028
 
1002
1029
  const trunk = childBranchTrunkCommits.map((c) => {
@@ -1052,11 +1079,11 @@ class SharedBranch<TEditor extends ChangeFamilyEditor, TChangeset> {
1052
1079
  ): void {
1053
1080
  assert(
1054
1081
  (this.parentBranch === undefined) === (data.base === undefined),
1055
- "Expected branch base to match presence of parent branch",
1082
+ 0xc60 /* Expected branch base to match presence of parent branch */,
1056
1083
  );
1057
1084
  const parentTrunkBase =
1058
1085
  trunkRevisionCache.get(data.base ?? rootRevision) ??
1059
- fail("Expected base revision to be in trunk cache");
1086
+ fail(0xc61 /* Expected base revision to be in trunk cache */);
1060
1087
  this.trunk.setHead(
1061
1088
  data.trunk.reduce((base, c) => {
1062
1089
  const sequenceId: SequenceId =
@@ -144,7 +144,10 @@ export function encodeSharedBranch<TChangeset>(
144
144
  json.author = data.author;
145
145
  }
146
146
  if (data.base !== undefined) {
147
- assert(originatorId !== undefined, "Cannot encode branch base without originatorId");
147
+ assert(
148
+ originatorId !== undefined,
149
+ 0xc62 /* Cannot encode branch base without originatorId */,
150
+ );
148
151
  json.base = revisionTagCodec.encode(data.base, {
149
152
  originatorId,
150
153
  idCompressor: context.idCompressor,
@@ -221,11 +224,17 @@ export function decodeSharedBranch<TChangeset>(
221
224
  data.author = json.author;
222
225
  }
223
226
  if (json.id !== undefined) {
224
- assert(originatorId !== undefined, "Cannot decode branch id without originatorId");
227
+ assert(
228
+ originatorId !== undefined,
229
+ 0xc63 /* Cannot decode branch id without originatorId */,
230
+ );
225
231
  data.id = decodeBranchId(context.idCompressor, json.id, { originatorId });
226
232
  }
227
233
  if (json.base !== undefined) {
228
- assert(originatorId !== undefined, "Cannot decode branch base without originatorId");
234
+ assert(
235
+ originatorId !== undefined,
236
+ 0xc64 /* Cannot decode branch base without originatorId */,
237
+ );
229
238
  data.base = revisionTagCodec.decode(json.base, {
230
239
  originatorId,
231
240
  idCompressor: context.idCompressor,
@@ -76,7 +76,10 @@ export function makeV5CodecWithVersion<TChangeset>(
76
76
  context,
77
77
  data.originator,
78
78
  );
79
- assert(data.originator !== undefined, "Cannot encode V5 summary without originator");
79
+ assert(
80
+ data.originator !== undefined,
81
+ 0xc65 /* Cannot encode V5 summary without originator */,
82
+ );
80
83
  const json: Mutable<EncodedEditManager<TChangeset>> = {
81
84
  main: mainBranch,
82
85
  originator: data.originator,
@@ -126,8 +129,11 @@ export function makeV5CodecWithVersion<TChangeset>(
126
129
  context,
127
130
  json.originator,
128
131
  );
129
- assert(decodedBranch.id !== undefined, "Shared branches must have an id");
130
- assert(!branches.has(decodedBranch.id), "Duplicate shared branch id");
132
+ assert(
133
+ decodedBranch.id !== undefined,
134
+ 0xc66 /* Shared branches must have an id */,
135
+ );
136
+ assert(!branches.has(decodedBranch.id), 0xc67 /* Duplicate shared branch id */);
131
137
  branches.set(decodedBranch.id, decodedBranch);
132
138
  }
133
139
 
@@ -45,8 +45,11 @@ export function makeV1ToV4CodecWithVersion<TChangeset>(
45
45
  Message(changeCodec.encodedSchema ?? Type.Any()),
46
46
  {
47
47
  encode: (decoded: DecodedMessage<TChangeset>, context: MessageEncodingContext) => {
48
- assert(decoded.type === "commit", "Only commit messages are supported");
49
- assert(decoded.branchId === "main", "Only commit messages to main are supported");
48
+ assert(decoded.type === "commit", 0xc68 /* Only commit messages are supported */);
49
+ assert(
50
+ decoded.branchId === "main",
51
+ 0xc69 /* Only commit messages to main are supported */,
52
+ );
50
53
  const { commit, sessionId: originatorId } = decoded;
51
54
  const message: Message = {
52
55
  revision: revisionTagCodec.encode(commit.revision, {
@@ -105,7 +105,10 @@ export function makeV5CodecWithVersion<TChangeset>(
105
105
  return { type: "branch", sessionId: originatorId, branchId };
106
106
  }
107
107
 
108
- assert(encodedRevision !== undefined, "Commit messages must have a revision");
108
+ assert(
109
+ encodedRevision !== undefined,
110
+ 0xc6a /* Commit messages must have a revision */,
111
+ );
109
112
  const revision = revisionTagCodec.decode(encodedRevision, changeContext);
110
113
 
111
114
  return {
@@ -7,7 +7,11 @@ import type { IFluidLoadable, ITelemetryBaseLogger } from "@fluidframework/core-
7
7
  import { assert, fail, unreachableCase } from "@fluidframework/core-utils/internal";
8
8
  import type { IChannelStorageService } from "@fluidframework/datastore-definitions/internal";
9
9
  import type { ISnapshotTree } from "@fluidframework/driver-definitions/internal";
10
- import type { IIdCompressor, SessionId } from "@fluidframework/id-compressor";
10
+ import type {
11
+ IIdCompressor,
12
+ SessionId,
13
+ SessionSpaceCompressedId,
14
+ } from "@fluidframework/id-compressor";
11
15
  import type {
12
16
  IExperimentalIncrementalSummaryContext,
13
17
  IRuntimeMessageCollection,
@@ -150,6 +154,7 @@ export class SharedTreeCore<TEditor extends ChangeFamilyEditor, TChange>
150
154
  changeFamily,
151
155
  localSessionId,
152
156
  this.mintRevisionTag,
157
+ (branchId) => this.registerSharedBranch(branchId),
153
158
  rebaseLogger,
154
159
  );
155
160
 
@@ -315,6 +320,7 @@ export class SharedTreeCore<TEditor extends ChangeFamilyEditor, TChange>
315
320
  this.editManager.localSessionId,
316
321
  newRevision,
317
322
  this.detachedRevision,
323
+ branchId,
318
324
  );
319
325
  this.editManager.advanceMinimumSequenceNumber(newRevision, false);
320
326
  return undefined;
@@ -376,6 +382,7 @@ export class SharedTreeCore<TEditor extends ChangeFamilyEditor, TChange>
376
382
  );
377
383
 
378
384
  commits.length = 0;
385
+ branchId = undefined;
379
386
  };
380
387
 
381
388
  // Get a list of all the commits from the messages.
@@ -413,8 +420,6 @@ export class SharedTreeCore<TEditor extends ChangeFamilyEditor, TChange>
413
420
  brand(envelope.referenceSequenceNumber),
414
421
  message.branchId,
415
422
  );
416
-
417
- this.registerSharedBranch(message.branchId);
418
423
  break;
419
424
  }
420
425
  default:
@@ -455,6 +460,12 @@ export class SharedTreeCore<TEditor extends ChangeFamilyEditor, TChange>
455
460
  return this.editManager.getLocalBranch("main");
456
461
  }
457
462
 
463
+ public getSharedBranchIds(): string[] {
464
+ return this.editManager
465
+ .getSharedBranchIds()
466
+ .filter((id): id is SessionSpaceCompressedId => id !== "main")
467
+ .map((id) => this.idCompressor.decompress(id));
468
+ }
458
469
  public createSharedBranch(): string {
459
470
  const branchId = this.idCompressor.generateCompressedId();
460
471
  this.addBranch(branchId);
@@ -463,8 +474,7 @@ export class SharedTreeCore<TEditor extends ChangeFamilyEditor, TChange>
463
474
  }
464
475
 
465
476
  protected addBranch(branchId: BranchId): void {
466
- this.editManager.addBranch(branchId);
467
- this.registerSharedBranch(branchId);
477
+ this.editManager.addNewBranch(branchId);
468
478
  }
469
479
 
470
480
  public getSharedBranch(branchId: BranchId): SharedTreeBranch<TEditor, TChange> {
@@ -534,8 +544,8 @@ export class SharedTreeCore<TEditor extends ChangeFamilyEditor, TChange>
534
544
  } = message;
535
545
  const branch = this.editManager.getLocalBranch(branchId);
536
546
  const head = branch.getHead();
537
- assert(head.revision === revision, "Can only rollback latest commit");
538
- const newHead = head.parent ?? fail("must have parent");
547
+ assert(head.revision === revision, 0xc6b /* Can only rollback latest commit */);
548
+ const newHead = head.parent ?? fail(0xc6c /* must have parent */);
539
549
  branch.removeAfter(newHead);
540
550
  this.getResubmitMachine(branchId).onCommitRollback(head);
541
551
  break;
@@ -566,7 +576,7 @@ export class SharedTreeCore<TEditor extends ChangeFamilyEditor, TChange>
566
576
  break;
567
577
  }
568
578
  case "branch": {
569
- this.editManager.addBranch(message.branchId);
579
+ this.editManager.addNewBranch(message.branchId);
570
580
  break;
571
581
  }
572
582
  default:
@@ -581,7 +591,7 @@ export class SharedTreeCore<TEditor extends ChangeFamilyEditor, TChange>
581
591
  ): void {
582
592
  const changeEnricher = enricher ?? new NoOpChangeEnricher();
583
593
  const commitEnricher = new BranchCommitEnricher(this.changeFamily.rebaser, changeEnricher);
584
- assert(!this.enrichers.has(branchId), "Branch already registered");
594
+ assert(!this.enrichers.has(branchId), 0xc6d /* Branch already registered */);
585
595
  this.enrichers.set(branchId, {
586
596
  enricher: commitEnricher,
587
597
  resubmitMachine:
@@ -609,7 +619,7 @@ export class SharedTreeCore<TEditor extends ChangeFamilyEditor, TChange>
609
619
  private getEnricherState(branchId: BranchId): EnricherState<TChange> {
610
620
  return (
611
621
  this.tryGetEnricherState(branchId) ??
612
- fail("Expected to have a resubmit machine for this branch")
622
+ fail(0xc6e /* Expected to have a resubmit machine for this branch */)
613
623
  );
614
624
  }
615
625
 
@@ -106,6 +106,12 @@ export interface ITreeAlpha extends ITree {
106
106
  */
107
107
  createSharedBranch(): string;
108
108
 
109
+ /**
110
+ * Returns a list of all shared branches that currently exist on this tree.
111
+ * Any one of them can be checked out using {@link ITreeAlpha.viewSharedBranchWith}.
112
+ */
113
+ getSharedBranchIds(): string[];
114
+
109
115
  /**
110
116
  * Returns a view of the tree on the specified shared branch, using the provided schema.
111
117
  * See {@link ViewableTree.viewWith}.
@@ -532,6 +538,8 @@ export interface TreeViewEvents {
532
538
  /**
533
539
  * Retrieve the {@link TreeViewAlpha | alpha API} for a {@link TreeView}.
534
540
  * @alpha
541
+ * @deprecated Use {@link asAlpha} instead.
542
+ * @privateRemarks Despite being deprecated, this function should be used within the tree package (outside of tests) rather than `asAlpha` in order to avoid circular import dependencies.
535
543
  */
536
544
  export function asTreeViewAlpha<TSchema extends ImplicitFieldSchema>(
537
545
  view: TreeView<TSchema>,
@@ -50,6 +50,7 @@ import {
50
50
  type HydratedFlexTreeNode,
51
51
  cursorForMapTreeField,
52
52
  type MinimalFieldMap,
53
+ currentObserver,
53
54
  } from "../../feature-libraries/index.js";
54
55
  import { brand, filterIterable, getOrCreate, mapIterable } from "../../util/index.js";
55
56
 
@@ -144,8 +145,10 @@ export class UnhydratedFlexTreeNode
144
145
  */
145
146
  public readonly fields: MinimalFieldMap<UnhydratedFlexTreeField> = {
146
147
  get: (key: FieldKey): UnhydratedFlexTreeField | undefined => this.tryGetField(key),
147
- [Symbol.iterator]: (): IterableIterator<[FieldKey, UnhydratedFlexTreeField]> =>
148
- filterIterable(this.fieldsAll, ([, field]) => field.length > 0),
148
+ [Symbol.iterator]: (): IterableIterator<[FieldKey, UnhydratedFlexTreeField]> => {
149
+ currentObserver?.observeNodeFields(this);
150
+ return filterIterable(this.fieldsAll, ([, field]) => field.length > 0);
151
+ },
149
152
  };
150
153
 
151
154
  public [Symbol.iterator](): IterableIterator<UnhydratedFlexTreeField> {
@@ -218,6 +221,7 @@ export class UnhydratedFlexTreeNode
218
221
  * @remarks If this node is unparented, this method will return the special {@link unparentedLocation} as the parent.
219
222
  */
220
223
  public get parentField(): LocationInField {
224
+ currentObserver?.observeParentOf(this);
221
225
  return this.location;
222
226
  }
223
227
 
@@ -226,6 +230,8 @@ export class UnhydratedFlexTreeNode
226
230
  }
227
231
 
228
232
  public tryGetField(key: FieldKey): UnhydratedFlexTreeField | undefined {
233
+ currentObserver?.observeNodeField(this, key);
234
+
229
235
  const field = this.fieldsAll.get(key);
230
236
  // Only return the field if it is not empty, in order to fulfill the contract of `tryGetField`.
231
237
  if (field !== undefined && field.length > 0) {
@@ -235,6 +241,9 @@ export class UnhydratedFlexTreeNode
235
241
 
236
242
  public getBoxed(key: string): UnhydratedFlexTreeField {
237
243
  const fieldKey: FieldKey = brand(key);
244
+
245
+ currentObserver?.observeNodeField(this, fieldKey);
246
+
238
247
  return this.getOrCreateField(fieldKey);
239
248
  }
240
249
 
@@ -20,6 +20,7 @@ import {
20
20
  SharedTreeKernel,
21
21
  type ITreePrivate,
22
22
  type SharedTreeOptions,
23
+ type SharedTreeOptionsBeta,
23
24
  type SharedTreeOptionsInternal,
24
25
  type SharedTreeKernelView,
25
26
  } from "./shared-tree/index.js";
@@ -91,26 +92,65 @@ export const SharedTree = configuredSharedTree({});
91
92
  /**
92
93
  * {@link SharedTree} but allowing a non-default configuration.
93
94
  * @remarks
94
- * This is useful for debugging and testing to opt into extra validation or see if opting out of some optimizations fixes an issue.
95
+ * This is useful for debugging and testing.
96
+ * For example it can be used to opt into extra validation or see if opting out of some optimizations fixes an issue.
97
+ *
98
+ * With great care, and knowledge of the support and stability of the options exposed here,
99
+ * this can also be used to opt into some features early or for performance tuning.
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * import {
104
+ * configuredSharedTreeBeta,
105
+ * ForestTypeReference,
106
+ * } from "fluid-framework/beta";
107
+ * const SharedTree = configuredSharedTree({
108
+ * forest: ForestTypeReference,
109
+ * });
110
+ * ```
111
+ * @privateRemarks
112
+ * The Legacy `ISharedObjectKind<ITree>` type is omitted here for simplicity.
113
+ * @beta
114
+ */
115
+ export function configuredSharedTreeBeta(
116
+ options: SharedTreeOptionsBeta,
117
+ ): SharedObjectKind<ITree> {
118
+ return configuredSharedTree(options);
119
+ }
120
+
121
+ /**
122
+ * {@link configuredSharedTreeBeta} including the legacy `ISharedObjectKind` type.
123
+ * @privateRemarks
124
+ * This is given a different export name (with legacy appended) to avoid the need to do the special reexport with different types from the fluid-framework package.
125
+ * @legacy @beta
126
+ */
127
+ export function configuredSharedTreeBetaLegacy(
128
+ options: SharedTreeOptionsBeta,
129
+ ): ISharedObjectKind<ITree> & SharedObjectKind<ITree> {
130
+ return configuredSharedTree(options);
131
+ }
132
+
133
+ /**
134
+ * {@link configuredSharedTreeBetaLegacy} but including `@alpha` options.
135
+ *
95
136
  * @example
96
137
  * ```typescript
97
138
  * import {
98
- * ForestType,
99
139
  * TreeCompressionStrategy,
100
140
  * configuredSharedTree,
101
- * typeboxValidator,
141
+ * FormatValidatorBasic,
142
+ * ForestTypeReference,
102
143
  * } from "@fluidframework/tree/internal";
103
144
  * const SharedTree = configuredSharedTree({
104
145
  * forest: ForestTypeReference,
105
- * jsonValidator: typeboxValidator,
146
+ * jsonValidator: FormatValidatorBasic,
106
147
  * treeEncodeType: TreeCompressionStrategy.Uncompressed,
107
148
  * });
108
149
  * ```
109
150
  * @privateRemarks
110
- * This should be legacy, but has to be internal due to limitations of API tagging preventing it from being both alpha and alpha+legacy.
111
- * TODO:
112
- * Expose Ajv validator for better error message quality somehow.
113
- * Maybe as part of a test utils or dev-tool package?
151
+ * This should be legacy, but has to be internal due to no alpha+legacy being setup yet.
152
+ *
153
+ * This should be renamed to `configuredSharedTreeAlpha` to avoid colliding with the eventual public version which will have less options.
114
154
  * @internal
115
155
  */
116
156
  export function configuredSharedTree(
@@ -1,13 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- import type { JsonValidator } from "./codec.js";
6
- /**
7
- * A {@link JsonValidator} implementation which performs no validation and accepts all data as valid.
8
- * @privateRemarks Having this as an option unifies opting out of validation with selection of
9
- * validators, simplifying code performing validation.
10
- * @alpha
11
- */
12
- export declare const noopValidator: JsonValidator;
13
- //# sourceMappingURL=noopValidator.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"noopValidator.d.ts","sourceRoot":"","sources":["../../src/codec/noopValidator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,EAAE,aAE3B,CAAC"}
@@ -1,17 +0,0 @@
1
- "use strict";
2
- /*!
3
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
4
- * Licensed under the MIT License.
5
- */
6
- Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.noopValidator = void 0;
8
- /**
9
- * A {@link JsonValidator} implementation which performs no validation and accepts all data as valid.
10
- * @privateRemarks Having this as an option unifies opting out of validation with selection of
11
- * validators, simplifying code performing validation.
12
- * @alpha
13
- */
14
- exports.noopValidator = {
15
- compile: () => ({ check: (data) => true }),
16
- };
17
- //# sourceMappingURL=noopValidator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"noopValidator.js","sourceRoot":"","sources":["../../src/codec/noopValidator.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAMH;;;;;GAKG;AACU,QAAA,aAAa,GAAkB;IAC3C,OAAO,EAAE,GAA2B,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,IAAI,EAA0B,EAAE,CAAC,IAAI,EAAE,CAAC;CAC1F,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { Static, TSchema } from \"@sinclair/typebox\";\n\nimport type { JsonValidator } from \"./codec.js\";\n\n/**\n * A {@link JsonValidator} implementation which performs no validation and accepts all data as valid.\n * @privateRemarks Having this as an option unifies opting out of validation with selection of\n * validators, simplifying code performing validation.\n * @alpha\n */\nexport const noopValidator: JsonValidator = {\n\tcompile: <Schema extends TSchema>() => ({ check: (data): data is Static<Schema> => true }),\n};\n"]}