@fluidframework/container-loader 2.118.1 → 3.0.1

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 (213) hide show
  1. package/CHANGELOG.md +74 -4
  2. package/README.md +53 -50
  3. package/{api-extractor.json → api-extractor/api-extractor-model.json} +1 -1
  4. package/api-report/container-loader.legacy.alpha.api.md +4 -3
  5. package/dist/attachment.d.ts.map +1 -1
  6. package/dist/audience.js +3 -2
  7. package/dist/audience.js.map +1 -1
  8. package/dist/captureReferencedContents.js +9 -9
  9. package/dist/captureReferencedContents.js.map +1 -1
  10. package/dist/catchUpMonitor.js +11 -8
  11. package/dist/catchUpMonitor.js.map +1 -1
  12. package/dist/connectionManager.d.ts.map +1 -1
  13. package/dist/connectionManager.js +86 -51
  14. package/dist/connectionManager.js.map +1 -1
  15. package/dist/connectionStateHandler.js +40 -14
  16. package/dist/connectionStateHandler.js.map +1 -1
  17. package/dist/container.d.ts +1 -1
  18. package/dist/container.d.ts.map +1 -1
  19. package/dist/container.js +193 -143
  20. package/dist/container.js.map +1 -1
  21. package/dist/containerContext.js +48 -11
  22. package/dist/containerContext.js.map +1 -1
  23. package/dist/containerStorageAdapter.js +25 -17
  24. package/dist/containerStorageAdapter.js.map +1 -1
  25. package/dist/contracts.d.ts.map +1 -1
  26. package/dist/createAndLoadContainerUtils.d.ts +34 -13
  27. package/dist/createAndLoadContainerUtils.d.ts.map +1 -1
  28. package/dist/createAndLoadContainerUtils.js +97 -37
  29. package/dist/createAndLoadContainerUtils.js.map +1 -1
  30. package/dist/debugLogger.d.ts +7 -22
  31. package/dist/debugLogger.d.ts.map +1 -1
  32. package/dist/debugLogger.js +34 -34
  33. package/dist/debugLogger.js.map +1 -1
  34. package/dist/deltaManager.d.ts +16 -4
  35. package/dist/deltaManager.d.ts.map +1 -1
  36. package/dist/deltaManager.js +73 -48
  37. package/dist/deltaManager.js.map +1 -1
  38. package/dist/deltaManagerFactory.d.ts +23 -0
  39. package/dist/deltaManagerFactory.d.ts.map +1 -0
  40. package/dist/deltaManagerFactory.js +17 -0
  41. package/dist/deltaManagerFactory.js.map +1 -0
  42. package/dist/deltaQueue.js +14 -7
  43. package/dist/deltaQueue.js.map +1 -1
  44. package/dist/disposal.js +1 -2
  45. package/dist/disposal.js.map +1 -1
  46. package/dist/error.js +5 -4
  47. package/dist/error.js.map +1 -1
  48. package/dist/frozenServices.d.ts +2 -2
  49. package/dist/frozenServices.d.ts.map +1 -1
  50. package/dist/frozenServices.js +52 -34
  51. package/dist/frozenServices.js.map +1 -1
  52. package/dist/index.d.ts +1 -1
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +2 -1
  55. package/dist/index.js.map +1 -1
  56. package/dist/loadContainerToSequenceNumber.js +1 -2
  57. package/dist/loadContainerToSequenceNumber.js.map +1 -1
  58. package/dist/loadPaused.js +1 -2
  59. package/dist/loadPaused.js.map +1 -1
  60. package/dist/loader.js +5 -1
  61. package/dist/loader.js.map +1 -1
  62. package/dist/loaderLayerCompatState.d.ts +25 -1
  63. package/dist/loaderLayerCompatState.d.ts.map +1 -1
  64. package/dist/loaderLayerCompatState.js +79 -11
  65. package/dist/loaderLayerCompatState.js.map +1 -1
  66. package/dist/location-redirection-utilities/resolveWithLocationRedirection.js +2 -3
  67. package/dist/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -1
  68. package/dist/memoryBlobStorage.js +2 -3
  69. package/dist/memoryBlobStorage.js.map +1 -1
  70. package/dist/noopHeuristic.js +3 -1
  71. package/dist/noopHeuristic.js.map +1 -1
  72. package/dist/packageVersion.d.ts +1 -1
  73. package/dist/packageVersion.d.ts.map +1 -1
  74. package/dist/packageVersion.js +1 -1
  75. package/dist/packageVersion.js.map +1 -1
  76. package/dist/pendingLocalStateStore.d.ts +4 -3
  77. package/dist/pendingLocalStateStore.d.ts.map +1 -1
  78. package/dist/pendingLocalStateStore.js +26 -37
  79. package/dist/pendingLocalStateStore.js.map +1 -1
  80. package/dist/pointInTimeServices.js +4 -2
  81. package/dist/pointInTimeServices.js.map +1 -1
  82. package/dist/protocol/protocol.js +3 -0
  83. package/dist/protocol/protocol.js.map +1 -1
  84. package/dist/protocol/quorum.js +26 -5
  85. package/dist/protocol/quorum.js.map +1 -1
  86. package/dist/protocol.js +5 -3
  87. package/dist/protocol.js.map +1 -1
  88. package/dist/protocolTreeDocumentStorageService.js +10 -0
  89. package/dist/protocolTreeDocumentStorageService.js.map +1 -1
  90. package/dist/quorum.js +1 -2
  91. package/dist/quorum.js.map +1 -1
  92. package/dist/retriableDocumentStorageService.d.ts.map +1 -1
  93. package/dist/retriableDocumentStorageService.js +5 -1
  94. package/dist/retriableDocumentStorageService.js.map +1 -1
  95. package/dist/serializedStateManager.d.ts +6 -0
  96. package/dist/serializedStateManager.d.ts.map +1 -1
  97. package/dist/serializedStateManager.js +19 -24
  98. package/dist/serializedStateManager.js.map +1 -1
  99. package/dist/snapshotRefresher.js +31 -36
  100. package/dist/snapshotRefresher.js.map +1 -1
  101. package/dist/utils.d.ts +1 -1
  102. package/dist/utils.d.ts.map +1 -1
  103. package/dist/utils.js +13 -13
  104. package/dist/utils.js.map +1 -1
  105. package/lib/attachment.d.ts.map +1 -1
  106. package/lib/audience.js +3 -2
  107. package/lib/audience.js.map +1 -1
  108. package/lib/catchUpMonitor.js +11 -8
  109. package/lib/catchUpMonitor.js.map +1 -1
  110. package/lib/connectionManager.d.ts.map +1 -1
  111. package/lib/connectionManager.js +86 -51
  112. package/lib/connectionManager.js.map +1 -1
  113. package/lib/connectionStateHandler.js +37 -11
  114. package/lib/connectionStateHandler.js.map +1 -1
  115. package/lib/container.d.ts +1 -1
  116. package/lib/container.d.ts.map +1 -1
  117. package/lib/container.js +191 -141
  118. package/lib/container.js.map +1 -1
  119. package/lib/containerContext.js +48 -11
  120. package/lib/containerContext.js.map +1 -1
  121. package/lib/containerStorageAdapter.js +22 -14
  122. package/lib/containerStorageAdapter.js.map +1 -1
  123. package/lib/contracts.d.ts.map +1 -1
  124. package/lib/createAndLoadContainerUtils.d.ts +34 -13
  125. package/lib/createAndLoadContainerUtils.d.ts.map +1 -1
  126. package/lib/createAndLoadContainerUtils.js +93 -32
  127. package/lib/createAndLoadContainerUtils.js.map +1 -1
  128. package/lib/debugLogger.d.ts +7 -22
  129. package/lib/debugLogger.d.ts.map +1 -1
  130. package/lib/debugLogger.js +34 -33
  131. package/lib/debugLogger.js.map +1 -1
  132. package/lib/deltaManager.d.ts +16 -4
  133. package/lib/deltaManager.d.ts.map +1 -1
  134. package/lib/deltaManager.js +73 -48
  135. package/lib/deltaManager.js.map +1 -1
  136. package/lib/deltaManagerFactory.d.ts +23 -0
  137. package/lib/deltaManagerFactory.d.ts.map +1 -0
  138. package/lib/deltaManagerFactory.js +14 -0
  139. package/lib/deltaManagerFactory.js.map +1 -0
  140. package/lib/deltaQueue.js +14 -7
  141. package/lib/deltaQueue.js.map +1 -1
  142. package/lib/error.js +5 -4
  143. package/lib/error.js.map +1 -1
  144. package/lib/frozenServices.d.ts +2 -2
  145. package/lib/frozenServices.d.ts.map +1 -1
  146. package/lib/frozenServices.js +48 -30
  147. package/lib/frozenServices.js.map +1 -1
  148. package/lib/index.d.ts +1 -1
  149. package/lib/index.d.ts.map +1 -1
  150. package/lib/index.js +1 -1
  151. package/lib/index.js.map +1 -1
  152. package/lib/legacy.d.ts +1 -1
  153. package/lib/legacyAlpha.d.ts +1 -1
  154. package/lib/loader.js +6 -2
  155. package/lib/loader.js.map +1 -1
  156. package/lib/loaderLayerCompatState.d.ts +25 -1
  157. package/lib/loaderLayerCompatState.d.ts.map +1 -1
  158. package/lib/loaderLayerCompatState.js +76 -9
  159. package/lib/loaderLayerCompatState.js.map +1 -1
  160. package/lib/noopHeuristic.js +3 -1
  161. package/lib/noopHeuristic.js.map +1 -1
  162. package/lib/packageVersion.d.ts +1 -1
  163. package/lib/packageVersion.d.ts.map +1 -1
  164. package/lib/packageVersion.js +1 -1
  165. package/lib/packageVersion.js.map +1 -1
  166. package/lib/pendingLocalStateStore.d.ts +4 -3
  167. package/lib/pendingLocalStateStore.d.ts.map +1 -1
  168. package/lib/pendingLocalStateStore.js +26 -37
  169. package/lib/pendingLocalStateStore.js.map +1 -1
  170. package/lib/pointInTimeServices.js +2 -0
  171. package/lib/pointInTimeServices.js.map +1 -1
  172. package/lib/protocol/protocol.js +3 -0
  173. package/lib/protocol/protocol.js.map +1 -1
  174. package/lib/protocol/quorum.js +26 -5
  175. package/lib/protocol/quorum.js.map +1 -1
  176. package/lib/protocol.js +2 -0
  177. package/lib/protocol.js.map +1 -1
  178. package/lib/protocolTreeDocumentStorageService.js +10 -0
  179. package/lib/protocolTreeDocumentStorageService.js.map +1 -1
  180. package/lib/public.d.ts +1 -1
  181. package/lib/retriableDocumentStorageService.d.ts.map +1 -1
  182. package/lib/retriableDocumentStorageService.js +5 -1
  183. package/lib/retriableDocumentStorageService.js.map +1 -1
  184. package/lib/serializedStateManager.d.ts +6 -0
  185. package/lib/serializedStateManager.d.ts.map +1 -1
  186. package/lib/serializedStateManager.js +15 -20
  187. package/lib/serializedStateManager.js.map +1 -1
  188. package/lib/snapshotRefresher.js +31 -36
  189. package/lib/snapshotRefresher.js.map +1 -1
  190. package/lib/utils.d.ts +1 -1
  191. package/lib/utils.d.ts.map +1 -1
  192. package/lib/utils.js +3 -3
  193. package/lib/utils.js.map +1 -1
  194. package/package.json +44 -106
  195. package/src/container.ts +35 -22
  196. package/src/createAndLoadContainerUtils.ts +131 -46
  197. package/src/debugLogger.ts +39 -40
  198. package/src/deltaManager.ts +16 -4
  199. package/src/deltaManagerFactory.ts +53 -0
  200. package/src/frozenServices.ts +6 -7
  201. package/src/index.ts +1 -0
  202. package/src/loader.ts +2 -2
  203. package/src/loaderLayerCompatState.ts +85 -20
  204. package/src/packageVersion.ts +1 -1
  205. package/src/pendingLocalStateStore.ts +7 -3
  206. package/src/serializedStateManager.ts +6 -0
  207. package/src/utils.ts +3 -3
  208. package/tsconfig.json +1 -1
  209. package/internal.d.ts +0 -11
  210. package/legacy/alpha.d.ts +0 -11
  211. package/legacy.d.ts +0 -11
  212. /package/api-extractor/{api-extractor.current.json → api-extractor-report.current.json} +0 -0
  213. /package/api-extractor/{api-extractor.legacy.json → api-extractor-report.legacy.json} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"frozenServices.d.ts","sourceRoot":"","sources":["../src/frozenServices.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAEnE,OAAO,EAEN,KAAK,cAAc,EAEnB,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,8BAA8B,EAEnC,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EAErB,KAAK,uBAAuB,EAG5B,KAAK,YAAY,EACjB,KAAK,yBAAyB,EAC9B,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,MAAM,6CAA6C,CAAC;AAIrD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,kCAAkC,CACjD,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,uBAAuB,CAAC,EACpE,QAAQ,GAAE,OAAc,GACtB,uBAAuB,CAUzB;AAED,qBAAa,4BAA6B,YAAW,uBAAuB;aAE1D,QAAQ,EAAE,OAAO;aACjB,KAAK,CAAC;gBADN,QAAQ,EAAE,OAAO,EACjB,KAAK,CAAC,wEAA4D;IAG7E,qBAAqB,CAAC,WAAW,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAQ3E,eAAe,IAAI,OAAO,CAAC,gBAAgB,CAAC;CAGlD;AAiMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,uBAAe,qBACd,SAAQ,iBAAiB,CAAC,8BAA8B,CACxD,YAAW,wBAAwB,EAAE,WAAW;IAEhD,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,MAAM,EAAE,YAAY,CAAC;IACrC,SAAgB,cAAc,EAAE,aAAa,EAAE,CAAC;IAChD,SAAgB,IAAI,EAAE,cAAc,CAAU;IAC9C,SAAgB,QAAQ,EAAE,OAAO,CAAQ;IACzC,SAAgB,cAAc,EAAE,MAAM,CAAK;IAC3C,SAAgB,OAAO,EAAE,MAAM,CAAM;IACrC,SAAgB,eAAe,EAAE,yBAAyB,EAAE,CAAM;IAClE,SAAgB,cAAc,EAAE,cAAc,EAAE,CAAM;IACtD,SAAgB,oBAAoB,EAAE,oBAAoB,CAGxD;IACF,SAAgB,wBAAwB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAa;gBAE9D,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY;IASlD,MAAM,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,IAAI;IAa1C,YAAY,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAIrC,OAAO,CAAC,SAAS,CAAS;IAC1B,IAAW,QAAQ,IAAI,OAAO,CAE7B;IACM,OAAO,IAAI,IAAI;CAGtB;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,iBAAkB,SAAQ,qBAAqB;IAC3D,SAAgB,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtD,SAAgB,wBAAwB,EAAE,4BAA4B,GAAG,SAAS,CAAC;gBAEvE,OAAO,CAAC,EAAE;QACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,wBAAwB,CAAC,EAAE,4BAA4B,CAAC;KACxD;CASD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,yBAA0B,SAAQ,qBAAqB;;CAInE;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC5C,UAAU,EAAE,OAAO,GACjB,UAAU,IAAI,iBAAiB,CAEjC;AAED;;;;;;GAMG;AACH,wBAAgB,qCAAqC,CACpD,UAAU,EAAE,OAAO,GACjB,UAAU,IAAI,yBAAyB,CAEzC"}
1
+ {"version":3,"file":"frozenServices.d.ts","sourceRoot":"","sources":["../src/frozenServices.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAEnE,OAAO,EAEN,KAAK,cAAc,EAEnB,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,8BAA8B,EAEnC,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EAErB,KAAK,uBAAuB,EAG5B,KAAK,YAAY,EACjB,KAAK,yBAAyB,EAC9B,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,MAAM,6CAA6C,CAAC;AAIrD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,kCAAkC,CACjD,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,uBAAuB,CAAC,EACpE,QAAQ,GAAE,OAAc,GACtB,uBAAuB,CAUzB;AAED,qBAAa,4BAA6B,YAAW,uBAAuB;aAE1D,QAAQ,EAAE,OAAO;aACjB,KAAK,CAAC,GAAE,uBAAuB,GAAG,OAAO,CAAC,uBAAuB,CAAC;gBADlE,QAAQ,EAAE,OAAO,EACjB,KAAK,CAAC,GAAE,uBAAuB,GAAG,OAAO,CAAC,uBAAuB,CAAC,aAAA;IAG7E,qBAAqB,CAAC,WAAW,EAAE,YAAY,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAQ3E,eAAe,IAAI,OAAO,CAAC,gBAAgB,CAAC;CAGlD;AAgMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,uBAAe,qBACd,SAAQ,iBAAiB,CAAC,8BAA8B,CACxD,YAAW,wBAAwB,EAAE,WAAW;IAEhD,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,SAAgB,MAAM,EAAE,YAAY,CAAC;IACrC,SAAgB,cAAc,EAAE,aAAa,EAAE,CAAC;IAChD,SAAgB,IAAI,EAAE,cAAc,CAAU;IAC9C,SAAgB,QAAQ,EAAE,OAAO,CAAQ;IACzC,SAAgB,cAAc,EAAE,MAAM,CAAK;IAC3C,SAAgB,OAAO,EAAE,MAAM,CAAM;IACrC,SAAgB,eAAe,EAAE,yBAAyB,EAAE,CAAM;IAClE,SAAgB,cAAc,EAAE,cAAc,EAAE,CAAM;IACtD,SAAgB,oBAAoB,EAAE,oBAAoB,CAGxD;IACF,SAAgB,wBAAwB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAa;gBAE9D,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY;IASlD,MAAM,CAAC,QAAQ,EAAE,gBAAgB,EAAE,GAAG,IAAI;IAa1C,YAAY,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAIrC,OAAO,CAAC,SAAS,CAAS;IAC1B,IAAW,QAAQ,IAAI,OAAO,CAE7B;IACM,OAAO,IAAI,IAAI;CAGtB;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,iBAAkB,SAAQ,qBAAqB;IAC3D,SAAgB,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IACtD,SAAgB,wBAAwB,EAAE,4BAA4B,GAAG,SAAS,CAAC;gBAEvE,OAAO,CAAC,EAAE;QACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,wBAAwB,CAAC,EAAE,4BAA4B,CAAC;KACxD;CASD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,yBAA0B,SAAQ,qBAAqB;;CAInE;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC5C,UAAU,EAAE,OAAO,GACjB,UAAU,IAAI,iBAAiB,CAEjC;AAED;;;;;;GAMG;AACH,wBAAgB,qCAAqC,CACpD,UAAU,EAAE,OAAO,GACjB,UAAU,IAAI,yBAAyB,CAEzC"}
@@ -4,7 +4,10 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.isWritableFrozenDeltaStreamConnection = exports.isFrozenDeltaStreamConnection = exports.WritableFrozenDeltaStream = exports.FrozenDeltaStream = exports.FrozenDocumentServiceFactory = exports.createFrozenDocumentServiceFactory = void 0;
7
+ exports.WritableFrozenDeltaStream = exports.FrozenDeltaStream = exports.FrozenDocumentServiceFactory = void 0;
8
+ exports.createFrozenDocumentServiceFactory = createFrozenDocumentServiceFactory;
9
+ exports.isFrozenDeltaStreamConnection = isFrozenDeltaStreamConnection;
10
+ exports.isWritableFrozenDeltaStreamConnection = isWritableFrozenDeltaStreamConnection;
8
11
  const client_utils_1 = require("@fluid-internal/client-utils");
9
12
  const internal_1 = require("@fluidframework/core-utils/internal");
10
13
  const internal_2 = require("@fluidframework/driver-definitions/internal");
@@ -43,8 +46,9 @@ function createFrozenDocumentServiceFactory(factory, readOnly = true) {
43
46
  }
44
47
  return new FrozenDocumentServiceFactory(readOnly, factory);
45
48
  }
46
- exports.createFrozenDocumentServiceFactory = createFrozenDocumentServiceFactory;
47
49
  class FrozenDocumentServiceFactory {
50
+ readOnly;
51
+ inner;
48
52
  constructor(readOnly, inner) {
49
53
  this.readOnly = readOnly;
50
54
  this.inner = inner;
@@ -59,16 +63,19 @@ class FrozenDocumentServiceFactory {
59
63
  }
60
64
  exports.FrozenDocumentServiceFactory = FrozenDocumentServiceFactory;
61
65
  class FrozenDocumentService extends client_utils_1.TypedEventEmitter {
66
+ resolvedUrl;
67
+ readOnly;
68
+ documentService;
69
+ // Tracks every storage instance handed out by `connectToStorage` so `dispose()` can cascade
70
+ // disposal to each one (rejecting their hanging `createBlob` deferreds). A Set rather than
71
+ // a single field because `IDocumentService.connectToStorage` is a public API that can be
72
+ // called more than once — we cannot assume the Container holds a single instance.
73
+ storageServices = new Set();
62
74
  constructor(resolvedUrl, readOnly, documentService) {
63
75
  super();
64
76
  this.resolvedUrl = resolvedUrl;
65
77
  this.readOnly = readOnly;
66
78
  this.documentService = documentService;
67
- // Tracks every storage instance handed out by `connectToStorage` so `dispose()` can cascade
68
- // disposal to each one (rejecting their hanging `createBlob` deferreds). A Set rather than
69
- // a single field because `IDocumentService.connectToStorage` is a public API that can be
70
- // called more than once — we cannot assume the Container holds a single instance.
71
- this.storageServices = new Set();
72
79
  // When readOnly, advertise the storageOnly policy. The connectionManager short-circuits
73
80
  // on it: it synthesizes a FrozenDeltaStream itself and never calls
74
81
  // connectToDeltaStream, and the readOnlyInfo getter forces the container to read-only
@@ -83,6 +90,7 @@ class FrozenDocumentService extends client_utils_1.TypedEventEmitter {
83
90
  // flows through the live `WritableFrozenDeltaStream` instead.
84
91
  this.policies = readOnly ? { storageOnly: true } : {};
85
92
  }
93
+ policies;
86
94
  async connectToStorage() {
87
95
  const storage = new FrozenDocumentStorageService(this.readOnly, await this.documentService?.connectToStorage());
88
96
  this.storageServices.add(storage);
@@ -128,27 +136,27 @@ const frozenDocumentStorageServiceHandler = () => {
128
136
  };
129
137
  /**
130
138
  * Distinct from {@link frozenDocumentStorageServiceHandler} because callers
131
- * that hit this path are almost always exercising a fully-offline frozen load
132
- * whose pending state was produced by {@link getPendingLocalState} (which omits
133
- * inlined attachment blobs) rather than {@link captureFullContainerState}. A
134
- * generic "operation not supported" is technically true but unhelpful; this
135
- * message names the missing precondition and the API that produces it.
139
+ * that hit this path are exercising a fully-offline frozen load whose pending
140
+ * state omits a required structural or attachment blob. A generic "operation
141
+ * not supported" is technically true but unhelpful; this message names the
142
+ * missing precondition and the API mode that satisfies it.
136
143
  */
137
144
  const frozenReadBlobOfflineHandler = async () => {
138
- throw new internal_3.UsageError("Attempted to read an attachment blob from a frozen-loaded container without a live storage service. " +
139
- "Fully-offline frozen loads must use pending state produced by `captureFullContainerState`, which inlines all referenced attachment blobs.");
145
+ throw new internal_3.UsageError("Attempted to read a blob from a frozen-loaded container without a live storage service. " +
146
+ "Fully-offline frozen loads must use pending state produced by `captureFullContainerState` with the default inline blob capture mode.");
140
147
  };
141
148
  class FrozenDocumentStorageService {
149
+ // Single deferred shared by every in-flight `createBlob` call. The writable-frozen
150
+ // `createBlob` returns this promise so the BlobManager keeps the blob in `uploading`
151
+ // state (see comment in the constructor). Rejecting the deferred on disposal fans the
152
+ // rejection out to every awaiter at once — and to any future `createBlob` calls too,
153
+ // since they receive the already-rejected promise.
154
+ disposalDeferred;
155
+ _disposed = false;
142
156
  get disposed() {
143
157
  return this._disposed;
144
158
  }
145
159
  constructor(readOnly, documentStorageService) {
146
- this._disposed = false;
147
- this.getSnapshotTree = frozenDocumentStorageServiceHandler;
148
- this.getSnapshot = frozenDocumentStorageServiceHandler;
149
- this.getVersions = frozenDocumentStorageServiceHandler;
150
- this.uploadSummaryWithContext = frozenDocumentStorageServiceHandler;
151
- this.downloadSummary = frozenDocumentStorageServiceHandler;
152
160
  let rejectFn;
153
161
  const promise = new Promise((_, reject) => {
154
162
  rejectFn = reject;
@@ -173,6 +181,13 @@ class FrozenDocumentStorageService {
173
181
  documentStorageService?.readBlob.bind(documentStorageService) ??
174
182
  frozenReadBlobOfflineHandler;
175
183
  }
184
+ getSnapshotTree = frozenDocumentStorageServiceHandler;
185
+ getSnapshot = frozenDocumentStorageServiceHandler;
186
+ getVersions = frozenDocumentStorageServiceHandler;
187
+ createBlob;
188
+ readBlob;
189
+ uploadSummaryWithContext = frozenDocumentStorageServiceHandler;
190
+ downloadSummary = frozenDocumentStorageServiceHandler;
176
191
  dispose() {
177
192
  if (this._disposed) {
178
193
  return;
@@ -234,20 +249,22 @@ const writableClaims = {
234
249
  * triggering a reconnect on a stray signal would be strictly worse than dropping it.
235
250
  */
236
251
  class FrozenDeltaStreamBase extends client_utils_1.TypedEventEmitter {
252
+ clientId;
253
+ claims;
254
+ initialClients;
255
+ mode = "read";
256
+ existing = true;
257
+ maxMessageSize = 0;
258
+ version = "";
259
+ initialMessages = [];
260
+ initialSignals = [];
261
+ serviceConfiguration = {
262
+ maxMessageSize: 0,
263
+ blockSize: 0,
264
+ };
265
+ checkpointSequenceNumber = undefined;
237
266
  constructor(clientId, claims) {
238
267
  super();
239
- this.mode = "read";
240
- this.existing = true;
241
- this.maxMessageSize = 0;
242
- this.version = "";
243
- this.initialMessages = [];
244
- this.initialSignals = [];
245
- this.serviceConfiguration = {
246
- maxMessageSize: 0,
247
- blockSize: 0,
248
- };
249
- this.checkpointSequenceNumber = undefined;
250
- this._disposed = false;
251
268
  this.clientId = clientId;
252
269
  this.claims = claims;
253
270
  // initialClients mirrors clientId so the audience handler observes "self" and
@@ -265,6 +282,7 @@ class FrozenDeltaStreamBase extends client_utils_1.TypedEventEmitter {
265
282
  submitSignal(_message) {
266
283
  // Intentional no-op. See class JSDoc for rationale.
267
284
  }
285
+ _disposed = false;
268
286
  get disposed() {
269
287
  return this._disposed;
270
288
  }
@@ -285,6 +303,8 @@ class FrozenDeltaStreamBase extends client_utils_1.TypedEventEmitter {
285
303
  * `outOfStorageError`).
286
304
  */
287
305
  class FrozenDeltaStream extends FrozenDeltaStreamBase {
306
+ storageOnlyReason;
307
+ readonlyConnectionReason;
288
308
  constructor(options) {
289
309
  // Constant clientId: preserves the pre-PR `"storage-only client"` identity for any
290
310
  // consumer that keys off it. The 0x173 replay-assert risk that motivates per-instance
@@ -330,7 +350,6 @@ exports.WritableFrozenDeltaStream = WritableFrozenDeltaStream;
330
350
  function isFrozenDeltaStreamConnection(connection) {
331
351
  return connection instanceof FrozenDeltaStream;
332
352
  }
333
- exports.isFrozenDeltaStreamConnection = isFrozenDeltaStreamConnection;
334
353
  /**
335
354
  * Recognizes the writable variant of {@link FrozenDeltaStreamBase}. Drives the
336
355
  * `ConnectionManager.sendMessages` short-circuit: writable-frozen submits must be dropped at
@@ -341,5 +360,4 @@ exports.isFrozenDeltaStreamConnection = isFrozenDeltaStreamConnection;
341
360
  function isWritableFrozenDeltaStreamConnection(connection) {
342
361
  return connection instanceof WritableFrozenDeltaStream;
343
362
  }
344
- exports.isWritableFrozenDeltaStreamConnection = isWritableFrozenDeltaStreamConnection;
345
363
  //# sourceMappingURL=frozenServices.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"frozenServices.js","sourceRoot":"","sources":["../src/frozenServices.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { IDisposable } from \"@fluidframework/core-interfaces\";\nimport { isPromiseLike } from \"@fluidframework/core-utils/internal\";\nimport {\n\tScopeType,\n\ttype ConnectionMode,\n\ttype IClient,\n\ttype IClientConfiguration,\n\ttype IDocumentDeltaConnection,\n\ttype IDocumentDeltaConnectionEvents,\n\ttype IDocumentDeltaStorageService,\n\ttype IDocumentMessage,\n\ttype IDocumentService,\n\ttype IDocumentServiceEvents,\n\ttype IDocumentServiceFactory,\n\ttype IDocumentServicePolicies,\n\ttype IDocumentStorageService,\n\ttype IResolvedUrl,\n\ttype ISequencedDocumentMessage,\n\ttype ISignalClient,\n\ttype ISignalMessage,\n\ttype ITokenClaims,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { UsageError } from \"@fluidframework/telemetry-utils/internal\";\nimport { v4 as uuid } from \"uuid\";\n\nimport type { IConnectionStateChangeReason } from \"./contracts.js\";\n\n/**\n * Creates an `IDocumentServiceFactory` that produces a \"frozen\" document service: one whose\n * delta stream never sends or receives ops, and whose storage service only supports\n * `IDocumentStorageService.readBlob`. Used to load a container from pending local state\n * without re-establishing a live connection.\n *\n * @param factory - The underlying factory to wrap. Its storage backs blob reads; all other\n * storage operations throw. May be omitted when blob fetches are not required.\n * @param readOnly - When `true` (the default), the document service advertises the\n * `IDocumentServicePolicies.storageOnly` policy, which causes the loader to surface the\n * container as read-only (see `IContainer.readOnlyInfo`).\n *\n * When `false`, the container is loaded as writable so the runtime will accept DDS submissions.\n * The connection itself stays `Connected`: `ConnectionManager.sendMessages` recognizes the\n * `WritableFrozenDeltaStream` as the live connection and short-circuits — the message is dropped\n * at the network layer rather than triggering a read→write reconnect. Local DDS state continues\n * to update via optimistic apply, and submitted ops accumulate in the runtime's pending-state\n * manager, which is exactly the state needed to capture pending local state. Use `false` when\n * callers want to accrue and capture pending state without publishing it.\n * @returns A factory that produces frozen document services.\n * @legacy @alpha\n */\nexport function createFrozenDocumentServiceFactory(\n\tfactory?: IDocumentServiceFactory | Promise<IDocumentServiceFactory>,\n\treadOnly: boolean = true,\n): IDocumentServiceFactory {\n\tif (factory instanceof FrozenDocumentServiceFactory) {\n\t\t// Already wrapped. Reuse if readOnly matches; otherwise unwrap and rewrap so the caller's\n\t\t// most recent readOnly intent wins (silently honoring caller intent rather than dropping\n\t\t// the new argument).\n\t\treturn factory.readOnly === readOnly\n\t\t\t? factory\n\t\t\t: new FrozenDocumentServiceFactory(readOnly, factory.inner);\n\t}\n\treturn new FrozenDocumentServiceFactory(readOnly, factory);\n}\n\nexport class FrozenDocumentServiceFactory implements IDocumentServiceFactory {\n\tconstructor(\n\t\tpublic readonly readOnly: boolean,\n\t\tpublic readonly inner?: IDocumentServiceFactory | Promise<IDocumentServiceFactory>,\n\t) {}\n\n\tasync createDocumentService(resolvedUrl: IResolvedUrl): Promise<IDocumentService> {\n\t\tconst factory = isPromiseLike(this.inner) ? await this.inner : this.inner;\n\t\treturn new FrozenDocumentService(\n\t\t\tresolvedUrl,\n\t\t\tthis.readOnly,\n\t\t\tawait factory?.createDocumentService(resolvedUrl),\n\t\t);\n\t}\n\tasync createContainer(): Promise<IDocumentService> {\n\t\tthrow new Error(\"The FrozenDocumentServiceFactory cannot be used to create containers.\");\n\t}\n}\n\nclass FrozenDocumentService\n\textends TypedEventEmitter<IDocumentServiceEvents>\n\timplements IDocumentService\n{\n\t// Tracks every storage instance handed out by `connectToStorage` so `dispose()` can cascade\n\t// disposal to each one (rejecting their hanging `createBlob` deferreds). A Set rather than\n\t// a single field because `IDocumentService.connectToStorage` is a public API that can be\n\t// called more than once — we cannot assume the Container holds a single instance.\n\tprivate readonly storageServices = new Set<FrozenDocumentStorageService>();\n\n\tconstructor(\n\t\tpublic readonly resolvedUrl: IResolvedUrl,\n\t\tprivate readonly readOnly: boolean,\n\t\tprivate readonly documentService?: IDocumentService,\n\t) {\n\t\tsuper();\n\t\t// When readOnly, advertise the storageOnly policy. The connectionManager short-circuits\n\t\t// on it: it synthesizes a FrozenDeltaStream itself and never calls\n\t\t// connectToDeltaStream, and the readOnlyInfo getter forces the container to read-only\n\t\t// because the live connection is a FrozenDeltaStream.\n\t\t//\n\t\t// Audit (2026-05-05): the only consumer of `policies.storageOnly` as a frozen-container\n\t\t// signal is `ConnectionManager` (synthesizing a `FrozenDeltaStream` when set). All other\n\t\t// matches in the loader/runtime/driver layers are either drivers reading their own\n\t\t// policies (e.g. local-driver) or `IReadOnlyInfo.storageOnly`, which is derived from the\n\t\t// live connection — not the policy. So the writable-frozen container is intentionally\n\t\t// indistinguishable from a normal container at the policies layer; downstream behavior\n\t\t// flows through the live `WritableFrozenDeltaStream` instead.\n\t\tthis.policies = readOnly ? { storageOnly: true } : {};\n\t}\n\n\tpublic readonly policies: IDocumentServicePolicies;\n\tasync connectToStorage(): Promise<IDocumentStorageService> {\n\t\tconst storage = new FrozenDocumentStorageService(\n\t\t\tthis.readOnly,\n\t\t\tawait this.documentService?.connectToStorage(),\n\t\t);\n\t\tthis.storageServices.add(storage);\n\t\treturn storage;\n\t}\n\tasync connectToDeltaStorage(): Promise<IDocumentDeltaStorageService> {\n\t\treturn frozenDocumentDeltaStorageService;\n\t}\n\tasync connectToDeltaStream(_client: IClient): Promise<IDocumentDeltaConnection> {\n\t\tif (this.readOnly) {\n\t\t\t// connectionManager short-circuits via policies.storageOnly before reaching here\n\t\t\t// in the read-only path; reaching this branch indicates a non-connectionManager\n\t\t\t// consumer or a regression of the short-circuit. Throw to surface the misuse\n\t\t\t// rather than silently produce a working stream.\n\t\t\tthrow new Error(\n\t\t\t\t\"FrozenDocumentService is read-only; connectToDeltaStream should not be called (connectionManager short-circuits via policies.storageOnly)\",\n\t\t\t);\n\t\t}\n\t\t// Writable path: hand out a fresh WritableFrozenDeltaStream regardless of client.mode\n\t\t// or whether this is the initial connect or a reconnect. The stream's own mode is\n\t\t// \"read\" (advertising \"write\" would imply quorum membership we cannot honor), and\n\t\t// `ConnectionManager.sendMessages` short-circuits on WritableFrozenDeltaStream so\n\t\t// outbound writes never reach a real network. The per-instance clientId minted in\n\t\t// FrozenDeltaStreamBase prevents pendingStateManager 0x173 on replay across reconnects.\n\t\treturn new WritableFrozenDeltaStream();\n\t}\n\tdispose(error?: unknown): void {\n\t\t// Cascade disposal to each storage instance so any hanging `createBlob` promises (the\n\t\t// writable-frozen pending-blob mechanism) reject and the BlobManager can release its\n\t\t// references. Without this, hung promises remain held by BlobManager closures for the\n\t\t// lifetime of the process.\n\t\tfor (const storage of this.storageServices) {\n\t\t\tstorage.dispose();\n\t\t}\n\t\tthis.storageServices.clear();\n\t\t// Forward disposal to the wrapped service. We own its lifetime (it was created for us\n\t\t// by the wrapping factory and is never exposed to callers), so the contract from\n\t\t// `IDocumentService.dispose` (\"called by storage consumer when done with storage\")\n\t\t// applies here.\n\t\tthis.documentService?.dispose(error);\n\t}\n}\n\nconst frozenDocumentStorageServiceHandler = (): never => {\n\tthrow new UsageError(\"Operations are not supported on the FrozenDocumentStorageService.\");\n};\n\n/**\n * Distinct from {@link frozenDocumentStorageServiceHandler} because callers\n * that hit this path are almost always exercising a fully-offline frozen load\n * whose pending state was produced by {@link getPendingLocalState} (which omits\n * inlined attachment blobs) rather than {@link captureFullContainerState}. A\n * generic \"operation not supported\" is technically true but unhelpful; this\n * message names the missing precondition and the API that produces it.\n */\nconst frozenReadBlobOfflineHandler = async (): Promise<never> => {\n\tthrow new UsageError(\n\t\t\"Attempted to read an attachment blob from a frozen-loaded container without a live storage service. \" +\n\t\t\t\"Fully-offline frozen loads must use pending state produced by `captureFullContainerState`, which inlines all referenced attachment blobs.\",\n\t);\n};\n\nclass FrozenDocumentStorageService implements IDocumentStorageService, IDisposable {\n\t// Single deferred shared by every in-flight `createBlob` call. The writable-frozen\n\t// `createBlob` returns this promise so the BlobManager keeps the blob in `uploading`\n\t// state (see comment in the constructor). Rejecting the deferred on disposal fans the\n\t// rejection out to every awaiter at once — and to any future `createBlob` calls too,\n\t// since they receive the already-rejected promise.\n\tprivate readonly disposalDeferred: {\n\t\treadonly promise: Promise<never>;\n\t\treadonly reject: (error: Error) => void;\n\t};\n\n\tprivate _disposed = false;\n\tpublic get disposed(): boolean {\n\t\treturn this._disposed;\n\t}\n\n\tconstructor(readOnly: boolean, documentStorageService?: IDocumentStorageService) {\n\t\tlet rejectFn!: (error: Error) => void;\n\t\tconst promise = new Promise<never>((_, reject) => {\n\t\t\trejectFn = reject;\n\t\t});\n\t\t// Attach a no-op catch so node doesn't log an unhandled-rejection warning when\n\t\t// dispose runs before any caller has awaited the promise. Callers awaiting the\n\t\t// original promise still observe the rejection.\n\t\tpromise.catch(() => {});\n\t\tthis.disposalDeferred = { promise, reject: rejectFn };\n\n\t\t// In the writable-frozen path, `createBlob` returns a never-resolving promise instead\n\t\t// of throwing. This keeps the BlobManager's `localBlobCache` entry in the `uploading`\n\t\t// state: `getPendingBlobs` downgrades `uploading` blobs to `localOnly` in pending\n\t\t// state, so the blob survives `getPendingLocalState`. A subsequent live load runs\n\t\t// `sharePendingBlobs`, which re-enters `uploadAndAttach` against the real storage to\n\t\t// complete the upload. Throwing here would instead delete the cache entry (in\n\t\t// `uploadAndAttach`'s catch handler) and lose the blob — defeating the whole point of\n\t\t// accruing pending state.\n\t\tthis.createBlob = readOnly\n\t\t\t? frozenDocumentStorageServiceHandler\n\t\t\t: async () => this.disposalDeferred.promise;\n\t\tthis.readBlob =\n\t\t\tdocumentStorageService?.readBlob.bind(documentStorageService) ??\n\t\t\tfrozenReadBlobOfflineHandler;\n\t}\n\n\tgetSnapshotTree = frozenDocumentStorageServiceHandler;\n\tgetSnapshot = frozenDocumentStorageServiceHandler;\n\tgetVersions = frozenDocumentStorageServiceHandler;\n\tcreateBlob: IDocumentStorageService[\"createBlob\"];\n\treadBlob: IDocumentStorageService[\"readBlob\"];\n\tuploadSummaryWithContext = frozenDocumentStorageServiceHandler;\n\tdownloadSummary = frozenDocumentStorageServiceHandler;\n\n\tpublic dispose(): void {\n\t\tif (this._disposed) {\n\t\t\treturn;\n\t\t}\n\t\tthis._disposed = true;\n\t\t// Don't propagate any caller-supplied error here. `IDocumentService.dispose` already\n\t\t// logs the Container's error path; the createBlob deferred's consumer (BlobManager)\n\t\t// only needs the \"this storage is going away\" signal — not a chain of error causes.\n\t\tthis.disposalDeferred.reject(new Error(\"FrozenDocumentStorageService is disposed\"));\n\t}\n}\n\nconst frozenDocumentDeltaStorageService: IDocumentDeltaStorageService = {\n\tfetchMessages: () => ({\n\t\tread: async () => ({\n\t\t\tdone: true,\n\t\t}),\n\t}),\n};\n\nconst clientFrozenDeltaStream: IClient = {\n\tmode: \"read\",\n\tdetails: { capabilities: { interactive: true } },\n\tpermission: [],\n\tuser: { id: \"storage-only client\" }, // we need some \"fake\" ID here.\n\tscopes: [],\n};\n\nconst clientIdFrozenDeltaStream: string = \"storage-only client\";\n\n// Cast rationale: ITokenClaims requires tenantId/documentId/user/iat/exp/ver, but a frozen\n// delta stream has no tenant or session to draw real values from — it's a synthetic\n// in-process connection that never reaches a service. Inventing sentinel values would imply\n// quorum membership we cannot honor; only `scopes` actually drives behavior here (DocRead vs\n// DocWrite gates readOnlyInfo). The cast is the honest representation of \"this connection\n// has no claims worth populating.\"\n/* eslint-disable @typescript-eslint/consistent-type-assertions */\nconst readOnlyClaims: ITokenClaims = { scopes: [ScopeType.DocRead] } as ITokenClaims;\nconst writableClaims: ITokenClaims = {\n\tscopes: [ScopeType.DocRead, ScopeType.DocWrite],\n} as ITokenClaims;\n/* eslint-enable @typescript-eslint/consistent-type-assertions */\n\n/**\n * Inert `IDocumentDeltaConnection` for frozen container loads. Has no server upstream:\n * op and signal streams are empty, and `initialClients` contains only its own synthetic\n * read-only client — which lets the connection state handler observe \"self\" in the audience\n * and transition the container to Connected without waiting for a real join op or signal.\n *\n * Two concrete variants share this base — see their JSDoc for variant-specific details:\n *\n * - {@link FrozenDeltaStream} — read-only.\n * - {@link WritableFrozenDeltaStream} — writable.\n *\n * Both variants nack any incoming `submit`: this connection has no upstream and\n * `ConnectionManager.sendMessages` recognizes `WritableFrozenDeltaStream` and drops messages\n * before they reach `submit`, so under normal flow it should never fire. A nack reaching the\n * connectionManager surfaces the misuse — and may close the container — which is the right\n * defensive signal that something has bypassed the expected flow.\n *\n * `submitSignal` is a silent no-op for both variants. Signals are ephemeral and best-effort —\n * runtime/presence subsystems may submit them at any point in the writable-frozen lifetime, and\n * dropping them is the correct behavior here (we have no upstream). Closing the container or\n * triggering a reconnect on a stray signal would be strictly worse than dropping it.\n */\nabstract class FrozenDeltaStreamBase\n\textends TypedEventEmitter<IDocumentDeltaConnectionEvents>\n\timplements IDocumentDeltaConnection, IDisposable\n{\n\tpublic readonly clientId: string;\n\tpublic readonly claims: ITokenClaims;\n\tpublic readonly initialClients: ISignalClient[];\n\tpublic readonly mode: ConnectionMode = \"read\";\n\tpublic readonly existing: boolean = true;\n\tpublic readonly maxMessageSize: number = 0;\n\tpublic readonly version: string = \"\";\n\tpublic readonly initialMessages: ISequencedDocumentMessage[] = [];\n\tpublic readonly initialSignals: ISignalMessage[] = [];\n\tpublic readonly serviceConfiguration: IClientConfiguration = {\n\t\tmaxMessageSize: 0,\n\t\tblockSize: 0,\n\t};\n\tpublic readonly checkpointSequenceNumber?: number | undefined = undefined;\n\n\tconstructor(clientId: string, claims: ITokenClaims) {\n\t\tsuper();\n\t\tthis.clientId = clientId;\n\t\tthis.claims = claims;\n\t\t// initialClients mirrors clientId so the audience handler observes \"self\" and\n\t\t// transitions the container to Connected without waiting for a real join op or signal.\n\t\tthis.initialClients = [{ client: clientFrozenDeltaStream, clientId }];\n\t}\n\n\tsubmit(messages: IDocumentMessage[]): void {\n\t\t// Defensive nack: nothing should send on a frozen delta stream. If this fires, an\n\t\t// invariant in connectionManager has changed and we want it to surface loudly.\n\t\tthis.emit(\n\t\t\t\"nack\",\n\t\t\tthis.clientId,\n\t\t\tmessages.map((operation) => ({\n\t\t\t\toperation,\n\t\t\t\tcontent: { message: \"Cannot submit on a frozen delta stream\", code: 403 },\n\t\t\t})),\n\t\t);\n\t}\n\n\tsubmitSignal(_message: unknown): void {\n\t\t// Intentional no-op. See class JSDoc for rationale.\n\t}\n\n\tprivate _disposed = false;\n\tpublic get disposed(): boolean {\n\t\treturn this._disposed;\n\t}\n\tpublic dispose(): void {\n\t\tthis._disposed = true;\n\t}\n}\n\n/**\n * Read-only variant of {@link FrozenDeltaStreamBase}. Claims show only `DocRead`. Used by\n * storage-only loads (where `connectionManager` synthesizes one directly via\n * `policies.storageOnly`) and by the forbidden / out-of-storage fallback paths.\n * {@link isFrozenDeltaStreamConnection} matches this variant and drives the read-only forcing\n * in `ConnectionManager.readOnlyInfo`. Uses the historical `\"storage-only client\"` constant\n * `clientId`, preserving existing behavior for any consumer that keys off it.\n *\n * `storageOnlyReason` and `readonlyConnectionReason` are surfaced through `IContainer.readOnlyInfo`\n * for diagnostics on the fallback paths (`isDeltaStreamConnectionForbiddenError`,\n * `outOfStorageError`).\n */\nexport class FrozenDeltaStream extends FrozenDeltaStreamBase {\n\tpublic readonly storageOnlyReason: string | undefined;\n\tpublic readonly readonlyConnectionReason: IConnectionStateChangeReason | undefined;\n\n\tconstructor(options?: {\n\t\tstorageOnlyReason?: string;\n\t\treadonlyConnectionReason?: IConnectionStateChangeReason;\n\t}) {\n\t\t// Constant clientId: preserves the pre-PR `\"storage-only client\"` identity for any\n\t\t// consumer that keys off it. The 0x173 replay-assert risk that motivates per-instance\n\t\t// clientIds applies only to the writable variant, where the runtime accumulates dirty\n\t\t// pending ops across reconnects; the read-only variant does not.\n\t\tsuper(clientIdFrozenDeltaStream, readOnlyClaims);\n\t\tthis.storageOnlyReason = options?.storageOnlyReason;\n\t\tthis.readonlyConnectionReason = options?.readonlyConnectionReason;\n\t}\n}\n\n/**\n * Variant of {@link FrozenDeltaStreamBase} that appears to support writing but remains\n * \"frozen\" — no messages are actually sent or received. The stream itself does not enforce\n * the no-send guarantee; that lives in `ConnectionManager.sendMessages`, which recognizes\n * any `WritableFrozenDeltaStream` (via {@link isWritableFrozenDeltaStreamConnection}) and\n * short-circuits before its read-mode upgrade branch. Submitted ops are dropped at the\n * connection-manager layer, so the container stays `Connected` and the runtime accumulates\n * them in `pendingStateManager`.\n *\n * \"Appears writable\" mechanics: claims include `DocWrite` so the container surfaces as\n * writable; not matched by {@link isFrozenDeltaStreamConnection}, so `readOnlyInfo` reports\n * `readonly: false`. Connection mode stays `\"read\"` (advertising `\"write\"` would imply quorum\n * membership we cannot honor).\n *\n * Each instance mints a fresh `frozen-delta-stream/<uuid>` `clientId` to avoid\n * `pendingStateManager` `0x173` (`replayPendingStates called twice for same clientId!`) on\n * reconnect with dirty pending ops. Sibling (not subclass) of `FrozenDeltaStream` so\n * `instanceof` cleanly distinguishes the two for `ConnectionManager`'s short-circuits.\n */\nexport class WritableFrozenDeltaStream extends FrozenDeltaStreamBase {\n\tconstructor() {\n\t\tsuper(`frozen-delta-stream/${uuid()}`, writableClaims);\n\t}\n}\n\n/**\n * Recognizes the read-only variant of {@link FrozenDeltaStreamBase}. Drives the storage-only\n * forcing in `ConnectionManager.readOnlyInfo`: only the read-only variant should make the\n * container surface as read-only. {@link WritableFrozenDeltaStream} is a sibling class, not\n * a subclass, so `instanceof FrozenDeltaStream` already excludes it.\n */\nexport function isFrozenDeltaStreamConnection(\n\tconnection: unknown,\n): connection is FrozenDeltaStream {\n\treturn connection instanceof FrozenDeltaStream;\n}\n\n/**\n * Recognizes the writable variant of {@link FrozenDeltaStreamBase}. Drives the\n * `ConnectionManager.sendMessages` short-circuit: writable-frozen submits must be dropped at\n * the network layer instead of triggering a read→write reconnect. Sibling (not subclass) of\n * {@link FrozenDeltaStream}, so `instanceof WritableFrozenDeltaStream` excludes the read-only\n * variant.\n */\nexport function isWritableFrozenDeltaStreamConnection(\n\tconnection: unknown,\n): connection is WritableFrozenDeltaStream {\n\treturn connection instanceof WritableFrozenDeltaStream;\n}\n"]}
1
+ {"version":3,"file":"frozenServices.js","sourceRoot":"","sources":["../src/frozenServices.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAoDH,gFAaC;AA4VD,sEAIC;AASD,sFAIC;AA5aD,+DAAiE;AAEjE,kEAAoE;AACpE,0EAmBqD;AACrD,uEAAsE;AACtE,+BAAkC;AAIlC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,SAAgB,kCAAkC,CACjD,OAAoE,EACpE,WAAoB,IAAI;IAExB,IAAI,OAAO,YAAY,4BAA4B,EAAE,CAAC;QACrD,0FAA0F;QAC1F,yFAAyF;QACzF,qBAAqB;QACrB,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ;YACnC,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,IAAI,4BAA4B,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,IAAI,4BAA4B,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC5D,CAAC;AAED,MAAa,4BAA4B;IAEvB;IACA;IAFjB,YACiB,QAAiB,EACjB,KAAkE;QADlE,aAAQ,GAAR,QAAQ,CAAS;QACjB,UAAK,GAAL,KAAK,CAA6D;IAChF,CAAC;IAEJ,KAAK,CAAC,qBAAqB,CAAC,WAAyB;QACpD,MAAM,OAAO,GAAG,IAAA,wBAAa,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;QAC1E,OAAO,IAAI,qBAAqB,CAC/B,WAAW,EACX,IAAI,CAAC,QAAQ,EACb,MAAM,OAAO,EAAE,qBAAqB,CAAC,WAAW,CAAC,CACjD,CAAC;IACH,CAAC;IACD,KAAK,CAAC,eAAe;QACpB,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;IAC1F,CAAC;CACD;AAjBD,oEAiBC;AAED,MAAM,qBACL,SAAQ,gCAAyC;IAUhC;IACC;IACA;IATlB,4FAA4F;IAC5F,2FAA2F;IAC3F,yFAAyF;IACzF,kFAAkF;IACjE,eAAe,GAAG,IAAI,GAAG,EAAgC,CAAC;IAE3E,YACiB,WAAyB,EACxB,QAAiB,EACjB,eAAkC;QAEnD,KAAK,EAAE,CAAC;QAJQ,gBAAW,GAAX,WAAW,CAAc;QACxB,aAAQ,GAAR,QAAQ,CAAS;QACjB,oBAAe,GAAf,eAAe,CAAmB;QAGnD,wFAAwF;QACxF,mEAAmE;QACnE,sFAAsF;QACtF,sDAAsD;QACtD,EAAE;QACF,wFAAwF;QACxF,yFAAyF;QACzF,mFAAmF;QACnF,yFAAyF;QACzF,sFAAsF;QACtF,uFAAuF;QACvF,8DAA8D;QAC9D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACvD,CAAC;IAEe,QAAQ,CAA2B;IACnD,KAAK,CAAC,gBAAgB;QACrB,MAAM,OAAO,GAAG,IAAI,4BAA4B,CAC/C,IAAI,CAAC,QAAQ,EACb,MAAM,IAAI,CAAC,eAAe,EAAE,gBAAgB,EAAE,CAC9C,CAAC;QACF,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAClC,OAAO,OAAO,CAAC;IAChB,CAAC;IACD,KAAK,CAAC,qBAAqB;QAC1B,OAAO,iCAAiC,CAAC;IAC1C,CAAC;IACD,KAAK,CAAC,oBAAoB,CAAC,OAAgB;QAC1C,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,iFAAiF;YACjF,gFAAgF;YAChF,6EAA6E;YAC7E,iDAAiD;YACjD,MAAM,IAAI,KAAK,CACd,2IAA2I,CAC3I,CAAC;QACH,CAAC;QACD,sFAAsF;QACtF,kFAAkF;QAClF,kFAAkF;QAClF,kFAAkF;QAClF,kFAAkF;QAClF,wFAAwF;QACxF,OAAO,IAAI,yBAAyB,EAAE,CAAC;IACxC,CAAC;IACD,OAAO,CAAC,KAAe;QACtB,sFAAsF;QACtF,qFAAqF;QACrF,sFAAsF;QACtF,2BAA2B;QAC3B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YAC5C,OAAO,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;QACD,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QAC7B,sFAAsF;QACtF,iFAAiF;QACjF,mFAAmF;QACnF,gBAAgB;QAChB,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACtC,CAAC;CACD;AAED,MAAM,mCAAmC,GAAG,GAAU,EAAE;IACvD,MAAM,IAAI,qBAAU,CAAC,mEAAmE,CAAC,CAAC;AAC3F,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,4BAA4B,GAAG,KAAK,IAAoB,EAAE;IAC/D,MAAM,IAAI,qBAAU,CACnB,0FAA0F;QACzF,sIAAsI,CACvI,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,4BAA4B;IACjC,mFAAmF;IACnF,qFAAqF;IACrF,sFAAsF;IACtF,qFAAqF;IACrF,mDAAmD;IAClC,gBAAgB,CAG/B;IAEM,SAAS,GAAG,KAAK,CAAC;IAC1B,IAAW,QAAQ;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IAED,YAAY,QAAiB,EAAE,sBAAgD;QAC9E,IAAI,QAAiC,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;YAChD,QAAQ,GAAG,MAAM,CAAC;QACnB,CAAC,CAAC,CAAC;QACH,+EAA+E;QAC/E,+EAA+E;QAC/E,gDAAgD;QAChD,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,gBAAgB,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QAEtD,sFAAsF;QACtF,sFAAsF;QACtF,kFAAkF;QAClF,kFAAkF;QAClF,qFAAqF;QACrF,8EAA8E;QAC9E,sFAAsF;QACtF,0BAA0B;QAC1B,IAAI,CAAC,UAAU,GAAG,QAAQ;YACzB,CAAC,CAAC,mCAAmC;YACrC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;QAC7C,IAAI,CAAC,QAAQ;YACZ,sBAAsB,EAAE,QAAQ,CAAC,IAAI,CAAC,sBAAsB,CAAC;gBAC7D,4BAA4B,CAAC;IAC/B,CAAC;IAED,eAAe,GAAG,mCAAmC,CAAC;IACtD,WAAW,GAAG,mCAAmC,CAAC;IAClD,WAAW,GAAG,mCAAmC,CAAC;IAClD,UAAU,CAAwC;IAClD,QAAQ,CAAsC;IAC9C,wBAAwB,GAAG,mCAAmC,CAAC;IAC/D,eAAe,GAAG,mCAAmC,CAAC;IAE/C,OAAO;QACb,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO;QACR,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,qFAAqF;QACrF,oFAAoF;QACpF,oFAAoF;QACpF,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC,CAAC;IACrF,CAAC;CACD;AAED,MAAM,iCAAiC,GAAiC;IACvE,aAAa,EAAE,GAAG,EAAE,CAAC,CAAC;QACrB,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;YAClB,IAAI,EAAE,IAAI;SACV,CAAC;KACF,CAAC;CACF,CAAC;AAEF,MAAM,uBAAuB,GAAY;IACxC,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,EAAE,YAAY,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE;IAChD,UAAU,EAAE,EAAE;IACd,IAAI,EAAE,EAAE,EAAE,EAAE,qBAAqB,EAAE,EAAE,+BAA+B;IACpE,MAAM,EAAE,EAAE;CACV,CAAC;AAEF,MAAM,yBAAyB,GAAW,qBAAqB,CAAC;AAEhE,2FAA2F;AAC3F,oFAAoF;AACpF,4FAA4F;AAC5F,6FAA6F;AAC7F,0FAA0F;AAC1F,mCAAmC;AACnC,kEAAkE;AAClE,MAAM,cAAc,GAAiB,EAAE,MAAM,EAAE,CAAC,oBAAS,CAAC,OAAO,CAAC,EAAkB,CAAC;AACrF,MAAM,cAAc,GAAiB;IACpC,MAAM,EAAE,CAAC,oBAAS,CAAC,OAAO,EAAE,oBAAS,CAAC,QAAQ,CAAC;CAC/B,CAAC;AAClB,iEAAiE;AAEjE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAe,qBACd,SAAQ,gCAAiD;IAGzC,QAAQ,CAAS;IACjB,MAAM,CAAe;IACrB,cAAc,CAAkB;IAChC,IAAI,GAAmB,MAAM,CAAC;IAC9B,QAAQ,GAAY,IAAI,CAAC;IACzB,cAAc,GAAW,CAAC,CAAC;IAC3B,OAAO,GAAW,EAAE,CAAC;IACrB,eAAe,GAAgC,EAAE,CAAC;IAClD,cAAc,GAAqB,EAAE,CAAC;IACtC,oBAAoB,GAAyB;QAC5D,cAAc,EAAE,CAAC;QACjB,SAAS,EAAE,CAAC;KACZ,CAAC;IACc,wBAAwB,GAAwB,SAAS,CAAC;IAE1E,YAAY,QAAgB,EAAE,MAAoB;QACjD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,8EAA8E;QAC9E,uFAAuF;QACvF,IAAI,CAAC,cAAc,GAAG,CAAC,EAAE,MAAM,EAAE,uBAAuB,EAAE,QAAQ,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,CAAC,QAA4B;QAClC,kFAAkF;QAClF,+EAA+E;QAC/E,IAAI,CAAC,IAAI,CACR,MAAM,EACN,IAAI,CAAC,QAAQ,EACb,QAAQ,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YAC5B,SAAS;YACT,OAAO,EAAE,EAAE,OAAO,EAAE,wCAAwC,EAAE,IAAI,EAAE,GAAG,EAAE;SACzE,CAAC,CAAC,CACH,CAAC;IACH,CAAC;IAED,YAAY,CAAC,QAAiB;QAC7B,oDAAoD;IACrD,CAAC;IAEO,SAAS,GAAG,KAAK,CAAC;IAC1B,IAAW,QAAQ;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IACM,OAAO;QACb,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACvB,CAAC;CACD;AAED;;;;;;;;;;;GAWG;AACH,MAAa,iBAAkB,SAAQ,qBAAqB;IAC3C,iBAAiB,CAAqB;IACtC,wBAAwB,CAA2C;IAEnF,YAAY,OAGX;QACA,mFAAmF;QACnF,sFAAsF;QACtF,sFAAsF;QACtF,iEAAiE;QACjE,KAAK,CAAC,yBAAyB,EAAE,cAAc,CAAC,CAAC;QACjD,IAAI,CAAC,iBAAiB,GAAG,OAAO,EAAE,iBAAiB,CAAC;QACpD,IAAI,CAAC,wBAAwB,GAAG,OAAO,EAAE,wBAAwB,CAAC;IACnE,CAAC;CACD;AAhBD,8CAgBC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAa,yBAA0B,SAAQ,qBAAqB;IACnE;QACC,KAAK,CAAC,uBAAuB,IAAA,SAAI,GAAE,EAAE,EAAE,cAAc,CAAC,CAAC;IACxD,CAAC;CACD;AAJD,8DAIC;AAED;;;;;GAKG;AACH,SAAgB,6BAA6B,CAC5C,UAAmB;IAEnB,OAAO,UAAU,YAAY,iBAAiB,CAAC;AAChD,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,qCAAqC,CACpD,UAAmB;IAEnB,OAAO,UAAU,YAAY,yBAAyB,CAAC;AACxD,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport type { IDisposable } from \"@fluidframework/core-interfaces\";\nimport { isPromiseLike } from \"@fluidframework/core-utils/internal\";\nimport {\n\tScopeType,\n\ttype ConnectionMode,\n\ttype IClient,\n\ttype IClientConfiguration,\n\ttype IDocumentDeltaConnection,\n\ttype IDocumentDeltaConnectionEvents,\n\ttype IDocumentDeltaStorageService,\n\ttype IDocumentMessage,\n\ttype IDocumentService,\n\ttype IDocumentServiceEvents,\n\ttype IDocumentServiceFactory,\n\ttype IDocumentServicePolicies,\n\ttype IDocumentStorageService,\n\ttype IResolvedUrl,\n\ttype ISequencedDocumentMessage,\n\ttype ISignalClient,\n\ttype ISignalMessage,\n\ttype ITokenClaims,\n} from \"@fluidframework/driver-definitions/internal\";\nimport { UsageError } from \"@fluidframework/telemetry-utils/internal\";\nimport { v4 as uuid } from \"uuid\";\n\nimport type { IConnectionStateChangeReason } from \"./contracts.js\";\n\n/**\n * Creates an `IDocumentServiceFactory` that produces a \"frozen\" document service: one whose\n * delta stream never sends or receives ops, and whose storage service only supports\n * `IDocumentStorageService.readBlob`. Used to load a container from pending local state\n * without re-establishing a live connection.\n *\n * @param factory - The underlying factory to wrap. Its storage backs blob reads; all other\n * storage operations throw. May be omitted when blob fetches are not required.\n * @param readOnly - When `true` (the default), the document service advertises the\n * `IDocumentServicePolicies.storageOnly` policy, which causes the loader to surface the\n * container as read-only (see `IContainer.readOnlyInfo`).\n *\n * When `false`, the container is loaded as writable so the runtime will accept DDS submissions.\n * The connection itself stays `Connected`: `ConnectionManager.sendMessages` recognizes the\n * `WritableFrozenDeltaStream` as the live connection and short-circuits — the message is dropped\n * at the network layer rather than triggering a read→write reconnect. Local DDS state continues\n * to update via optimistic apply, and submitted ops accumulate in the runtime's pending-state\n * manager, which is exactly the state needed to capture pending local state. Use `false` when\n * callers want to accrue and capture pending state without publishing it.\n * @returns A factory that produces frozen document services.\n * @legacy @alpha\n */\nexport function createFrozenDocumentServiceFactory(\n\tfactory?: IDocumentServiceFactory | Promise<IDocumentServiceFactory>,\n\treadOnly: boolean = true,\n): IDocumentServiceFactory {\n\tif (factory instanceof FrozenDocumentServiceFactory) {\n\t\t// Already wrapped. Reuse if readOnly matches; otherwise unwrap and rewrap so the caller's\n\t\t// most recent readOnly intent wins (silently honoring caller intent rather than dropping\n\t\t// the new argument).\n\t\treturn factory.readOnly === readOnly\n\t\t\t? factory\n\t\t\t: new FrozenDocumentServiceFactory(readOnly, factory.inner);\n\t}\n\treturn new FrozenDocumentServiceFactory(readOnly, factory);\n}\n\nexport class FrozenDocumentServiceFactory implements IDocumentServiceFactory {\n\tconstructor(\n\t\tpublic readonly readOnly: boolean,\n\t\tpublic readonly inner?: IDocumentServiceFactory | Promise<IDocumentServiceFactory>,\n\t) {}\n\n\tasync createDocumentService(resolvedUrl: IResolvedUrl): Promise<IDocumentService> {\n\t\tconst factory = isPromiseLike(this.inner) ? await this.inner : this.inner;\n\t\treturn new FrozenDocumentService(\n\t\t\tresolvedUrl,\n\t\t\tthis.readOnly,\n\t\t\tawait factory?.createDocumentService(resolvedUrl),\n\t\t);\n\t}\n\tasync createContainer(): Promise<IDocumentService> {\n\t\tthrow new Error(\"The FrozenDocumentServiceFactory cannot be used to create containers.\");\n\t}\n}\n\nclass FrozenDocumentService\n\textends TypedEventEmitter<IDocumentServiceEvents>\n\timplements IDocumentService\n{\n\t// Tracks every storage instance handed out by `connectToStorage` so `dispose()` can cascade\n\t// disposal to each one (rejecting their hanging `createBlob` deferreds). A Set rather than\n\t// a single field because `IDocumentService.connectToStorage` is a public API that can be\n\t// called more than once — we cannot assume the Container holds a single instance.\n\tprivate readonly storageServices = new Set<FrozenDocumentStorageService>();\n\n\tconstructor(\n\t\tpublic readonly resolvedUrl: IResolvedUrl,\n\t\tprivate readonly readOnly: boolean,\n\t\tprivate readonly documentService?: IDocumentService,\n\t) {\n\t\tsuper();\n\t\t// When readOnly, advertise the storageOnly policy. The connectionManager short-circuits\n\t\t// on it: it synthesizes a FrozenDeltaStream itself and never calls\n\t\t// connectToDeltaStream, and the readOnlyInfo getter forces the container to read-only\n\t\t// because the live connection is a FrozenDeltaStream.\n\t\t//\n\t\t// Audit (2026-05-05): the only consumer of `policies.storageOnly` as a frozen-container\n\t\t// signal is `ConnectionManager` (synthesizing a `FrozenDeltaStream` when set). All other\n\t\t// matches in the loader/runtime/driver layers are either drivers reading their own\n\t\t// policies (e.g. local-driver) or `IReadOnlyInfo.storageOnly`, which is derived from the\n\t\t// live connection — not the policy. So the writable-frozen container is intentionally\n\t\t// indistinguishable from a normal container at the policies layer; downstream behavior\n\t\t// flows through the live `WritableFrozenDeltaStream` instead.\n\t\tthis.policies = readOnly ? { storageOnly: true } : {};\n\t}\n\n\tpublic readonly policies: IDocumentServicePolicies;\n\tasync connectToStorage(): Promise<IDocumentStorageService> {\n\t\tconst storage = new FrozenDocumentStorageService(\n\t\t\tthis.readOnly,\n\t\t\tawait this.documentService?.connectToStorage(),\n\t\t);\n\t\tthis.storageServices.add(storage);\n\t\treturn storage;\n\t}\n\tasync connectToDeltaStorage(): Promise<IDocumentDeltaStorageService> {\n\t\treturn frozenDocumentDeltaStorageService;\n\t}\n\tasync connectToDeltaStream(_client: IClient): Promise<IDocumentDeltaConnection> {\n\t\tif (this.readOnly) {\n\t\t\t// connectionManager short-circuits via policies.storageOnly before reaching here\n\t\t\t// in the read-only path; reaching this branch indicates a non-connectionManager\n\t\t\t// consumer or a regression of the short-circuit. Throw to surface the misuse\n\t\t\t// rather than silently produce a working stream.\n\t\t\tthrow new Error(\n\t\t\t\t\"FrozenDocumentService is read-only; connectToDeltaStream should not be called (connectionManager short-circuits via policies.storageOnly)\",\n\t\t\t);\n\t\t}\n\t\t// Writable path: hand out a fresh WritableFrozenDeltaStream regardless of client.mode\n\t\t// or whether this is the initial connect or a reconnect. The stream's own mode is\n\t\t// \"read\" (advertising \"write\" would imply quorum membership we cannot honor), and\n\t\t// `ConnectionManager.sendMessages` short-circuits on WritableFrozenDeltaStream so\n\t\t// outbound writes never reach a real network. The per-instance clientId minted in\n\t\t// FrozenDeltaStreamBase prevents pendingStateManager 0x173 on replay across reconnects.\n\t\treturn new WritableFrozenDeltaStream();\n\t}\n\tdispose(error?: unknown): void {\n\t\t// Cascade disposal to each storage instance so any hanging `createBlob` promises (the\n\t\t// writable-frozen pending-blob mechanism) reject and the BlobManager can release its\n\t\t// references. Without this, hung promises remain held by BlobManager closures for the\n\t\t// lifetime of the process.\n\t\tfor (const storage of this.storageServices) {\n\t\t\tstorage.dispose();\n\t\t}\n\t\tthis.storageServices.clear();\n\t\t// Forward disposal to the wrapped service. We own its lifetime (it was created for us\n\t\t// by the wrapping factory and is never exposed to callers), so the contract from\n\t\t// `IDocumentService.dispose` (\"called by storage consumer when done with storage\")\n\t\t// applies here.\n\t\tthis.documentService?.dispose(error);\n\t}\n}\n\nconst frozenDocumentStorageServiceHandler = (): never => {\n\tthrow new UsageError(\"Operations are not supported on the FrozenDocumentStorageService.\");\n};\n\n/**\n * Distinct from {@link frozenDocumentStorageServiceHandler} because callers\n * that hit this path are exercising a fully-offline frozen load whose pending\n * state omits a required structural or attachment blob. A generic \"operation\n * not supported\" is technically true but unhelpful; this message names the\n * missing precondition and the API mode that satisfies it.\n */\nconst frozenReadBlobOfflineHandler = async (): Promise<never> => {\n\tthrow new UsageError(\n\t\t\"Attempted to read a blob from a frozen-loaded container without a live storage service. \" +\n\t\t\t\"Fully-offline frozen loads must use pending state produced by `captureFullContainerState` with the default inline blob capture mode.\",\n\t);\n};\n\nclass FrozenDocumentStorageService implements IDocumentStorageService, IDisposable {\n\t// Single deferred shared by every in-flight `createBlob` call. The writable-frozen\n\t// `createBlob` returns this promise so the BlobManager keeps the blob in `uploading`\n\t// state (see comment in the constructor). Rejecting the deferred on disposal fans the\n\t// rejection out to every awaiter at once — and to any future `createBlob` calls too,\n\t// since they receive the already-rejected promise.\n\tprivate readonly disposalDeferred: {\n\t\treadonly promise: Promise<never>;\n\t\treadonly reject: (error: Error) => void;\n\t};\n\n\tprivate _disposed = false;\n\tpublic get disposed(): boolean {\n\t\treturn this._disposed;\n\t}\n\n\tconstructor(readOnly: boolean, documentStorageService?: IDocumentStorageService) {\n\t\tlet rejectFn!: (error: Error) => void;\n\t\tconst promise = new Promise<never>((_, reject) => {\n\t\t\trejectFn = reject;\n\t\t});\n\t\t// Attach a no-op catch so node doesn't log an unhandled-rejection warning when\n\t\t// dispose runs before any caller has awaited the promise. Callers awaiting the\n\t\t// original promise still observe the rejection.\n\t\tpromise.catch(() => {});\n\t\tthis.disposalDeferred = { promise, reject: rejectFn };\n\n\t\t// In the writable-frozen path, `createBlob` returns a never-resolving promise instead\n\t\t// of throwing. This keeps the BlobManager's `localBlobCache` entry in the `uploading`\n\t\t// state: `getPendingBlobs` downgrades `uploading` blobs to `localOnly` in pending\n\t\t// state, so the blob survives `getPendingLocalState`. A subsequent live load runs\n\t\t// `sharePendingBlobs`, which re-enters `uploadAndAttach` against the real storage to\n\t\t// complete the upload. Throwing here would instead delete the cache entry (in\n\t\t// `uploadAndAttach`'s catch handler) and lose the blob — defeating the whole point of\n\t\t// accruing pending state.\n\t\tthis.createBlob = readOnly\n\t\t\t? frozenDocumentStorageServiceHandler\n\t\t\t: async () => this.disposalDeferred.promise;\n\t\tthis.readBlob =\n\t\t\tdocumentStorageService?.readBlob.bind(documentStorageService) ??\n\t\t\tfrozenReadBlobOfflineHandler;\n\t}\n\n\tgetSnapshotTree = frozenDocumentStorageServiceHandler;\n\tgetSnapshot = frozenDocumentStorageServiceHandler;\n\tgetVersions = frozenDocumentStorageServiceHandler;\n\tcreateBlob: IDocumentStorageService[\"createBlob\"];\n\treadBlob: IDocumentStorageService[\"readBlob\"];\n\tuploadSummaryWithContext = frozenDocumentStorageServiceHandler;\n\tdownloadSummary = frozenDocumentStorageServiceHandler;\n\n\tpublic dispose(): void {\n\t\tif (this._disposed) {\n\t\t\treturn;\n\t\t}\n\t\tthis._disposed = true;\n\t\t// Don't propagate any caller-supplied error here. `IDocumentService.dispose` already\n\t\t// logs the Container's error path; the createBlob deferred's consumer (BlobManager)\n\t\t// only needs the \"this storage is going away\" signal — not a chain of error causes.\n\t\tthis.disposalDeferred.reject(new Error(\"FrozenDocumentStorageService is disposed\"));\n\t}\n}\n\nconst frozenDocumentDeltaStorageService: IDocumentDeltaStorageService = {\n\tfetchMessages: () => ({\n\t\tread: async () => ({\n\t\t\tdone: true,\n\t\t}),\n\t}),\n};\n\nconst clientFrozenDeltaStream: IClient = {\n\tmode: \"read\",\n\tdetails: { capabilities: { interactive: true } },\n\tpermission: [],\n\tuser: { id: \"storage-only client\" }, // we need some \"fake\" ID here.\n\tscopes: [],\n};\n\nconst clientIdFrozenDeltaStream: string = \"storage-only client\";\n\n// Cast rationale: ITokenClaims requires tenantId/documentId/user/iat/exp/ver, but a frozen\n// delta stream has no tenant or session to draw real values from — it's a synthetic\n// in-process connection that never reaches a service. Inventing sentinel values would imply\n// quorum membership we cannot honor; only `scopes` actually drives behavior here (DocRead vs\n// DocWrite gates readOnlyInfo). The cast is the honest representation of \"this connection\n// has no claims worth populating.\"\n/* eslint-disable @typescript-eslint/consistent-type-assertions */\nconst readOnlyClaims: ITokenClaims = { scopes: [ScopeType.DocRead] } as ITokenClaims;\nconst writableClaims: ITokenClaims = {\n\tscopes: [ScopeType.DocRead, ScopeType.DocWrite],\n} as ITokenClaims;\n/* eslint-enable @typescript-eslint/consistent-type-assertions */\n\n/**\n * Inert `IDocumentDeltaConnection` for frozen container loads. Has no server upstream:\n * op and signal streams are empty, and `initialClients` contains only its own synthetic\n * read-only client — which lets the connection state handler observe \"self\" in the audience\n * and transition the container to Connected without waiting for a real join op or signal.\n *\n * Two concrete variants share this base — see their JSDoc for variant-specific details:\n *\n * - {@link FrozenDeltaStream} — read-only.\n * - {@link WritableFrozenDeltaStream} — writable.\n *\n * Both variants nack any incoming `submit`: this connection has no upstream and\n * `ConnectionManager.sendMessages` recognizes `WritableFrozenDeltaStream` and drops messages\n * before they reach `submit`, so under normal flow it should never fire. A nack reaching the\n * connectionManager surfaces the misuse — and may close the container — which is the right\n * defensive signal that something has bypassed the expected flow.\n *\n * `submitSignal` is a silent no-op for both variants. Signals are ephemeral and best-effort —\n * runtime/presence subsystems may submit them at any point in the writable-frozen lifetime, and\n * dropping them is the correct behavior here (we have no upstream). Closing the container or\n * triggering a reconnect on a stray signal would be strictly worse than dropping it.\n */\nabstract class FrozenDeltaStreamBase\n\textends TypedEventEmitter<IDocumentDeltaConnectionEvents>\n\timplements IDocumentDeltaConnection, IDisposable\n{\n\tpublic readonly clientId: string;\n\tpublic readonly claims: ITokenClaims;\n\tpublic readonly initialClients: ISignalClient[];\n\tpublic readonly mode: ConnectionMode = \"read\";\n\tpublic readonly existing: boolean = true;\n\tpublic readonly maxMessageSize: number = 0;\n\tpublic readonly version: string = \"\";\n\tpublic readonly initialMessages: ISequencedDocumentMessage[] = [];\n\tpublic readonly initialSignals: ISignalMessage[] = [];\n\tpublic readonly serviceConfiguration: IClientConfiguration = {\n\t\tmaxMessageSize: 0,\n\t\tblockSize: 0,\n\t};\n\tpublic readonly checkpointSequenceNumber?: number | undefined = undefined;\n\n\tconstructor(clientId: string, claims: ITokenClaims) {\n\t\tsuper();\n\t\tthis.clientId = clientId;\n\t\tthis.claims = claims;\n\t\t// initialClients mirrors clientId so the audience handler observes \"self\" and\n\t\t// transitions the container to Connected without waiting for a real join op or signal.\n\t\tthis.initialClients = [{ client: clientFrozenDeltaStream, clientId }];\n\t}\n\n\tsubmit(messages: IDocumentMessage[]): void {\n\t\t// Defensive nack: nothing should send on a frozen delta stream. If this fires, an\n\t\t// invariant in connectionManager has changed and we want it to surface loudly.\n\t\tthis.emit(\n\t\t\t\"nack\",\n\t\t\tthis.clientId,\n\t\t\tmessages.map((operation) => ({\n\t\t\t\toperation,\n\t\t\t\tcontent: { message: \"Cannot submit on a frozen delta stream\", code: 403 },\n\t\t\t})),\n\t\t);\n\t}\n\n\tsubmitSignal(_message: unknown): void {\n\t\t// Intentional no-op. See class JSDoc for rationale.\n\t}\n\n\tprivate _disposed = false;\n\tpublic get disposed(): boolean {\n\t\treturn this._disposed;\n\t}\n\tpublic dispose(): void {\n\t\tthis._disposed = true;\n\t}\n}\n\n/**\n * Read-only variant of {@link FrozenDeltaStreamBase}. Claims show only `DocRead`. Used by\n * storage-only loads (where `connectionManager` synthesizes one directly via\n * `policies.storageOnly`) and by the forbidden / out-of-storage fallback paths.\n * {@link isFrozenDeltaStreamConnection} matches this variant and drives the read-only forcing\n * in `ConnectionManager.readOnlyInfo`. Uses the historical `\"storage-only client\"` constant\n * `clientId`, preserving existing behavior for any consumer that keys off it.\n *\n * `storageOnlyReason` and `readonlyConnectionReason` are surfaced through `IContainer.readOnlyInfo`\n * for diagnostics on the fallback paths (`isDeltaStreamConnectionForbiddenError`,\n * `outOfStorageError`).\n */\nexport class FrozenDeltaStream extends FrozenDeltaStreamBase {\n\tpublic readonly storageOnlyReason: string | undefined;\n\tpublic readonly readonlyConnectionReason: IConnectionStateChangeReason | undefined;\n\n\tconstructor(options?: {\n\t\tstorageOnlyReason?: string;\n\t\treadonlyConnectionReason?: IConnectionStateChangeReason;\n\t}) {\n\t\t// Constant clientId: preserves the pre-PR `\"storage-only client\"` identity for any\n\t\t// consumer that keys off it. The 0x173 replay-assert risk that motivates per-instance\n\t\t// clientIds applies only to the writable variant, where the runtime accumulates dirty\n\t\t// pending ops across reconnects; the read-only variant does not.\n\t\tsuper(clientIdFrozenDeltaStream, readOnlyClaims);\n\t\tthis.storageOnlyReason = options?.storageOnlyReason;\n\t\tthis.readonlyConnectionReason = options?.readonlyConnectionReason;\n\t}\n}\n\n/**\n * Variant of {@link FrozenDeltaStreamBase} that appears to support writing but remains\n * \"frozen\" — no messages are actually sent or received. The stream itself does not enforce\n * the no-send guarantee; that lives in `ConnectionManager.sendMessages`, which recognizes\n * any `WritableFrozenDeltaStream` (via {@link isWritableFrozenDeltaStreamConnection}) and\n * short-circuits before its read-mode upgrade branch. Submitted ops are dropped at the\n * connection-manager layer, so the container stays `Connected` and the runtime accumulates\n * them in `pendingStateManager`.\n *\n * \"Appears writable\" mechanics: claims include `DocWrite` so the container surfaces as\n * writable; not matched by {@link isFrozenDeltaStreamConnection}, so `readOnlyInfo` reports\n * `readonly: false`. Connection mode stays `\"read\"` (advertising `\"write\"` would imply quorum\n * membership we cannot honor).\n *\n * Each instance mints a fresh `frozen-delta-stream/<uuid>` `clientId` to avoid\n * `pendingStateManager` `0x173` (`replayPendingStates called twice for same clientId!`) on\n * reconnect with dirty pending ops. Sibling (not subclass) of `FrozenDeltaStream` so\n * `instanceof` cleanly distinguishes the two for `ConnectionManager`'s short-circuits.\n */\nexport class WritableFrozenDeltaStream extends FrozenDeltaStreamBase {\n\tconstructor() {\n\t\tsuper(`frozen-delta-stream/${uuid()}`, writableClaims);\n\t}\n}\n\n/**\n * Recognizes the read-only variant of {@link FrozenDeltaStreamBase}. Drives the storage-only\n * forcing in `ConnectionManager.readOnlyInfo`: only the read-only variant should make the\n * container surface as read-only. {@link WritableFrozenDeltaStream} is a sibling class, not\n * a subclass, so `instanceof FrozenDeltaStream` already excludes it.\n */\nexport function isFrozenDeltaStreamConnection(\n\tconnection: unknown,\n): connection is FrozenDeltaStream {\n\treturn connection instanceof FrozenDeltaStream;\n}\n\n/**\n * Recognizes the writable variant of {@link FrozenDeltaStreamBase}. Drives the\n * `ConnectionManager.sendMessages` short-circuit: writable-frozen submits must be dropped at\n * the network layer instead of triggering a read→write reconnect. Sibling (not subclass) of\n * {@link FrozenDeltaStream}, so `instanceof WritableFrozenDeltaStream` excludes the read-only\n * variant.\n */\nexport function isWritableFrozenDeltaStreamConnection(\n\tconnection: unknown,\n): connection is WritableFrozenDeltaStream {\n\treturn connection instanceof WritableFrozenDeltaStream;\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ export { createFrozenDocumentServiceFactory } from "./frozenServices.js";
8
8
  export { captureFullContainerState, createDetachedContainer, loadExistingContainer, rehydrateDetachedContainer, loadFrozenContainerFromPendingState, loadSummarizerContainerAndMakeSummary, type ICaptureFullContainerStateProps, type IContainerDriverServices, type IContainerHostProps, type IContainerLoadDriverProps, type ICreateAndLoadContainerProps, type ICreateDetachedContainerProps, type ILoadExistingContainerProps, type ILoadSummarizerContainerProps, type IRehydrateDetachedContainerProps, type ILoadFrozenContainerFromPendingStateProps, } from "./createAndLoadContainerUtils.js";
9
9
  export type { LoadSummarizerSummaryResult, OnDemandSummaryResults, SummaryStage, } from "./summarizerResultTypes.js";
10
10
  export { type ICodeDetailsLoader, type IFluidModuleWithDetails, type ILoaderProps, type ILoaderServices, Loader, } from "./loader.js";
11
- export { driverSupportRequirementsForLoader, loaderCoreCompatDetails, runtimeSupportRequirementsForLoader, loaderCompatDetailsForRuntime, } from "./loaderLayerCompatState.js";
11
+ export { driverSupportRequirementsForLoader, loaderCoreCompatDetails, runtimeSupportRequirementsForLoader, loaderCompatDetailsForRuntime, loaderCompatDetailsForDriver, } from "./loaderLayerCompatState.js";
12
12
  export { loadContainerPaused } from "./loadPaused.js";
13
13
  export { loadContainerToSequenceNumber, type ILoadContainerToSequenceNumberProps, } from "./loadContainerToSequenceNumber.js";
14
14
  export { isLocationRedirectionError, resolveWithLocationRedirectionHandling, } from "./location-redirection-utilities/index.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,KAAK,cAAc,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC5F,OAAO,EAAE,kCAAkC,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EACN,yBAAyB,EACzB,uBAAuB,EACvB,qBAAqB,EACrB,0BAA0B,EAC1B,mCAAmC,EACnC,qCAAqC,EACrC,KAAK,+BAA+B,EACpC,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,4BAA4B,EACjC,KAAK,6BAA6B,EAClC,KAAK,2BAA2B,EAChC,KAAK,6BAA6B,EAClC,KAAK,gCAAgC,EACrC,KAAK,yCAAyC,GAC9C,MAAM,kCAAkC,CAAC;AAC1C,YAAY,EACX,2BAA2B,EAC3B,sBAAsB,EACtB,YAAY,GACZ,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACN,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,MAAM,GACN,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,kCAAkC,EAClC,uBAAuB,EACvB,mCAAmC,EACnC,6BAA6B,GAC7B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EACN,6BAA6B,EAC7B,KAAK,mCAAmC,GACxC,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACN,0BAA0B,EAC1B,sCAAsC,GACtC,MAAM,2CAA2C,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EACN,6BAA6B,EAC7B,KAAK,UAAU,GACf,MAAM,YAAY,CAAC;AACpB,YAAY,EACX,oBAAoB,EACpB,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,uBAAuB,GACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EACN,2BAA2B,EAC3B,mBAAmB,EACnB,KAAK,oBAAoB,GACzB,MAAM,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,KAAK,cAAc,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC5F,OAAO,EAAE,kCAAkC,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EACN,yBAAyB,EACzB,uBAAuB,EACvB,qBAAqB,EACrB,0BAA0B,EAC1B,mCAAmC,EACnC,qCAAqC,EACrC,KAAK,+BAA+B,EACpC,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,4BAA4B,EACjC,KAAK,6BAA6B,EAClC,KAAK,2BAA2B,EAChC,KAAK,6BAA6B,EAClC,KAAK,gCAAgC,EACrC,KAAK,yCAAyC,GAC9C,MAAM,kCAAkC,CAAC;AAC1C,YAAY,EACX,2BAA2B,EAC3B,sBAAsB,EACtB,YAAY,GACZ,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACN,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,MAAM,GACN,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,kCAAkC,EAClC,uBAAuB,EACvB,mCAAmC,EACnC,6BAA6B,EAC7B,4BAA4B,GAC5B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EACN,6BAA6B,EAC7B,KAAK,mCAAmC,GACxC,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACN,0BAA0B,EAC1B,sCAAsC,GACtC,MAAM,2CAA2C,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EACN,6BAA6B,EAC7B,KAAK,UAAU,GACf,MAAM,YAAY,CAAC;AACpB,YAAY,EACX,oBAAoB,EACpB,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,uBAAuB,GACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EACN,2BAA2B,EAC3B,mBAAmB,EACnB,KAAK,oBAAoB,GACzB,MAAM,gCAAgC,CAAC"}
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.wireFormatConstants = exports.extractBlobAttachReferences = exports.PendingLocalStateStore = exports.tryParseCompatibleResolvedUrl = exports.resolveWithLocationRedirectionHandling = exports.isLocationRedirectionError = exports.loadContainerToSequenceNumber = exports.loadContainerPaused = exports.loaderCompatDetailsForRuntime = exports.runtimeSupportRequirementsForLoader = exports.loaderCoreCompatDetails = exports.driverSupportRequirementsForLoader = exports.Loader = exports.loadSummarizerContainerAndMakeSummary = exports.loadFrozenContainerFromPendingState = exports.rehydrateDetachedContainer = exports.loadExistingContainer = exports.createDetachedContainer = exports.captureFullContainerState = exports.createFrozenDocumentServiceFactory = exports.asLegacyAlpha = exports.waitContainerToCatchUp = exports.ConnectionState = void 0;
7
+ exports.wireFormatConstants = exports.extractBlobAttachReferences = exports.PendingLocalStateStore = exports.tryParseCompatibleResolvedUrl = exports.resolveWithLocationRedirectionHandling = exports.isLocationRedirectionError = exports.loadContainerToSequenceNumber = exports.loadContainerPaused = exports.loaderCompatDetailsForDriver = exports.loaderCompatDetailsForRuntime = exports.runtimeSupportRequirementsForLoader = exports.loaderCoreCompatDetails = exports.driverSupportRequirementsForLoader = exports.Loader = exports.loadSummarizerContainerAndMakeSummary = exports.loadFrozenContainerFromPendingState = exports.rehydrateDetachedContainer = exports.loadExistingContainer = exports.createDetachedContainer = exports.captureFullContainerState = exports.createFrozenDocumentServiceFactory = exports.asLegacyAlpha = exports.waitContainerToCatchUp = exports.ConnectionState = void 0;
8
8
  var connectionState_js_1 = require("./connectionState.js");
9
9
  Object.defineProperty(exports, "ConnectionState", { enumerable: true, get: function () { return connectionState_js_1.ConnectionState; } });
10
10
  var container_js_1 = require("./container.js");
@@ -26,6 +26,7 @@ Object.defineProperty(exports, "driverSupportRequirementsForLoader", { enumerabl
26
26
  Object.defineProperty(exports, "loaderCoreCompatDetails", { enumerable: true, get: function () { return loaderLayerCompatState_js_1.loaderCoreCompatDetails; } });
27
27
  Object.defineProperty(exports, "runtimeSupportRequirementsForLoader", { enumerable: true, get: function () { return loaderLayerCompatState_js_1.runtimeSupportRequirementsForLoader; } });
28
28
  Object.defineProperty(exports, "loaderCompatDetailsForRuntime", { enumerable: true, get: function () { return loaderLayerCompatState_js_1.loaderCompatDetailsForRuntime; } });
29
+ Object.defineProperty(exports, "loaderCompatDetailsForDriver", { enumerable: true, get: function () { return loaderLayerCompatState_js_1.loaderCompatDetailsForDriver; } });
29
30
  var loadPaused_js_1 = require("./loadPaused.js");
30
31
  Object.defineProperty(exports, "loadContainerPaused", { enumerable: true, get: function () { return loadPaused_js_1.loadContainerPaused; } });
31
32
  var loadContainerToSequenceNumber_js_1 = require("./loadContainerToSequenceNumber.js");
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,2DAAuD;AAA9C,qHAAA,eAAe,OAAA;AACxB,+CAA4F;AAA9D,sHAAA,sBAAsB,OAAA;AAAE,6GAAA,aAAa,OAAA;AACnE,yDAAyE;AAAhE,uIAAA,kCAAkC,OAAA;AAC3C,mFAiB0C;AAhBzC,2IAAA,yBAAyB,OAAA;AACzB,yIAAA,uBAAuB,OAAA;AACvB,uIAAA,qBAAqB,OAAA;AACrB,4IAAA,0BAA0B,OAAA;AAC1B,qJAAA,mCAAmC,OAAA;AACnC,uJAAA,qCAAqC,OAAA;AAiBtC,yCAMqB;AADpB,mGAAA,MAAM,OAAA;AAEP,yEAKqC;AAJpC,+IAAA,kCAAkC,OAAA;AAClC,oIAAA,uBAAuB,OAAA;AACvB,gJAAA,mCAAmC,OAAA;AACnC,0IAAA,6BAA6B,OAAA;AAE9B,iDAAsD;AAA7C,oHAAA,mBAAmB,OAAA;AAC5B,uFAG4C;AAF3C,iJAAA,6BAA6B,OAAA;AAG9B,sEAGmD;AAFlD,sHAAA,0BAA0B,OAAA;AAC1B,kIAAA,sCAAsC,OAAA;AAGvC,uCAGoB;AAFnB,yHAAA,6BAA6B,OAAA;AAU9B,yEAAqE;AAA5D,mIAAA,sBAAsB,OAAA;AAC/B,+EAIwC;AAHvC,2IAAA,2BAA2B,OAAA;AAC3B,mIAAA,mBAAmB,OAAA","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport { ConnectionState } from \"./connectionState.js\";\nexport { type ContainerAlpha, waitContainerToCatchUp, asLegacyAlpha } from \"./container.js\";\nexport { createFrozenDocumentServiceFactory } from \"./frozenServices.js\";\nexport {\n\tcaptureFullContainerState,\n\tcreateDetachedContainer,\n\tloadExistingContainer,\n\trehydrateDetachedContainer,\n\tloadFrozenContainerFromPendingState,\n\tloadSummarizerContainerAndMakeSummary,\n\ttype ICaptureFullContainerStateProps,\n\ttype IContainerDriverServices,\n\ttype IContainerHostProps,\n\ttype IContainerLoadDriverProps,\n\ttype ICreateAndLoadContainerProps,\n\ttype ICreateDetachedContainerProps,\n\ttype ILoadExistingContainerProps,\n\ttype ILoadSummarizerContainerProps,\n\ttype IRehydrateDetachedContainerProps,\n\ttype ILoadFrozenContainerFromPendingStateProps,\n} from \"./createAndLoadContainerUtils.js\";\nexport type {\n\tLoadSummarizerSummaryResult,\n\tOnDemandSummaryResults,\n\tSummaryStage,\n} from \"./summarizerResultTypes.js\";\nexport {\n\ttype ICodeDetailsLoader,\n\ttype IFluidModuleWithDetails,\n\ttype ILoaderProps,\n\ttype ILoaderServices,\n\tLoader,\n} from \"./loader.js\";\nexport {\n\tdriverSupportRequirementsForLoader,\n\tloaderCoreCompatDetails,\n\truntimeSupportRequirementsForLoader,\n\tloaderCompatDetailsForRuntime,\n} from \"./loaderLayerCompatState.js\";\nexport { loadContainerPaused } from \"./loadPaused.js\";\nexport {\n\tloadContainerToSequenceNumber,\n\ttype ILoadContainerToSequenceNumberProps,\n} from \"./loadContainerToSequenceNumber.js\";\nexport {\n\tisLocationRedirectionError,\n\tresolveWithLocationRedirectionHandling,\n} from \"./location-redirection-utilities/index.js\";\nexport type { IProtocolHandler, ProtocolHandlerBuilder } from \"./protocol.js\";\nexport {\n\ttryParseCompatibleResolvedUrl,\n\ttype IParsedUrl,\n} from \"./utils.js\";\nexport type {\n\tIBaseProtocolHandler,\n\tIScribeProtocolState,\n\tIQuorumSnapshot,\n\tQuorumClientsSnapshot,\n\tQuorumProposalsSnapshot,\n} from \"./protocol/index.js\";\nexport { PendingLocalStateStore } from \"./pendingLocalStateStore.js\";\nexport {\n\textractBlobAttachReferences,\n\twireFormatConstants,\n\ttype IBlobAttachReference,\n} from \"./captureReferencedContents.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,2DAAuD;AAA9C,qHAAA,eAAe,OAAA;AACxB,+CAA4F;AAA9D,sHAAA,sBAAsB,OAAA;AAAE,6GAAA,aAAa,OAAA;AACnE,yDAAyE;AAAhE,uIAAA,kCAAkC,OAAA;AAC3C,mFAiB0C;AAhBzC,2IAAA,yBAAyB,OAAA;AACzB,yIAAA,uBAAuB,OAAA;AACvB,uIAAA,qBAAqB,OAAA;AACrB,4IAAA,0BAA0B,OAAA;AAC1B,qJAAA,mCAAmC,OAAA;AACnC,uJAAA,qCAAqC,OAAA;AAiBtC,yCAMqB;AADpB,mGAAA,MAAM,OAAA;AAEP,yEAMqC;AALpC,+IAAA,kCAAkC,OAAA;AAClC,oIAAA,uBAAuB,OAAA;AACvB,gJAAA,mCAAmC,OAAA;AACnC,0IAAA,6BAA6B,OAAA;AAC7B,yIAAA,4BAA4B,OAAA;AAE7B,iDAAsD;AAA7C,oHAAA,mBAAmB,OAAA;AAC5B,uFAG4C;AAF3C,iJAAA,6BAA6B,OAAA;AAG9B,sEAGmD;AAFlD,sHAAA,0BAA0B,OAAA;AAC1B,kIAAA,sCAAsC,OAAA;AAGvC,uCAGoB;AAFnB,yHAAA,6BAA6B,OAAA;AAU9B,yEAAqE;AAA5D,mIAAA,sBAAsB,OAAA;AAC/B,+EAIwC;AAHvC,2IAAA,2BAA2B,OAAA;AAC3B,mIAAA,mBAAmB,OAAA","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport { ConnectionState } from \"./connectionState.js\";\nexport { type ContainerAlpha, waitContainerToCatchUp, asLegacyAlpha } from \"./container.js\";\nexport { createFrozenDocumentServiceFactory } from \"./frozenServices.js\";\nexport {\n\tcaptureFullContainerState,\n\tcreateDetachedContainer,\n\tloadExistingContainer,\n\trehydrateDetachedContainer,\n\tloadFrozenContainerFromPendingState,\n\tloadSummarizerContainerAndMakeSummary,\n\ttype ICaptureFullContainerStateProps,\n\ttype IContainerDriverServices,\n\ttype IContainerHostProps,\n\ttype IContainerLoadDriverProps,\n\ttype ICreateAndLoadContainerProps,\n\ttype ICreateDetachedContainerProps,\n\ttype ILoadExistingContainerProps,\n\ttype ILoadSummarizerContainerProps,\n\ttype IRehydrateDetachedContainerProps,\n\ttype ILoadFrozenContainerFromPendingStateProps,\n} from \"./createAndLoadContainerUtils.js\";\nexport type {\n\tLoadSummarizerSummaryResult,\n\tOnDemandSummaryResults,\n\tSummaryStage,\n} from \"./summarizerResultTypes.js\";\nexport {\n\ttype ICodeDetailsLoader,\n\ttype IFluidModuleWithDetails,\n\ttype ILoaderProps,\n\ttype ILoaderServices,\n\tLoader,\n} from \"./loader.js\";\nexport {\n\tdriverSupportRequirementsForLoader,\n\tloaderCoreCompatDetails,\n\truntimeSupportRequirementsForLoader,\n\tloaderCompatDetailsForRuntime,\n\tloaderCompatDetailsForDriver,\n} from \"./loaderLayerCompatState.js\";\nexport { loadContainerPaused } from \"./loadPaused.js\";\nexport {\n\tloadContainerToSequenceNumber,\n\ttype ILoadContainerToSequenceNumberProps,\n} from \"./loadContainerToSequenceNumber.js\";\nexport {\n\tisLocationRedirectionError,\n\tresolveWithLocationRedirectionHandling,\n} from \"./location-redirection-utilities/index.js\";\nexport type { IProtocolHandler, ProtocolHandlerBuilder } from \"./protocol.js\";\nexport {\n\ttryParseCompatibleResolvedUrl,\n\ttype IParsedUrl,\n} from \"./utils.js\";\nexport type {\n\tIBaseProtocolHandler,\n\tIScribeProtocolState,\n\tIQuorumSnapshot,\n\tQuorumClientsSnapshot,\n\tQuorumProposalsSnapshot,\n} from \"./protocol/index.js\";\nexport { PendingLocalStateStore } from \"./pendingLocalStateStore.js\";\nexport {\n\textractBlobAttachReferences,\n\twireFormatConstants,\n\ttype IBlobAttachReference,\n} from \"./captureReferencedContents.js\";\n"]}
@@ -4,7 +4,7 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.loadContainerToSequenceNumber = void 0;
7
+ exports.loadContainerToSequenceNumber = loadContainerToSequenceNumber;
8
8
  const internal_1 = require("@fluidframework/driver-utils/internal");
9
9
  const loadPaused_js_1 = require("./loadPaused.js");
10
10
  const pointInTimeServices_js_1 = require("./pointInTimeServices.js");
@@ -42,5 +42,4 @@ async function loadContainerToSequenceNumber(props) {
42
42
  const pointInTimeFactory = new pointInTimeServices_js_1.PointInTimeDocumentServiceFactory(capableFactory, loadToSequenceNumber);
43
43
  return (0, loadPaused_js_1.loadContainerPaused)({ ...props, documentServiceFactory: pointInTimeFactory }, props.request, loadToSequenceNumber, props.signal);
44
44
  }
45
- exports.loadContainerToSequenceNumber = loadContainerToSequenceNumber;
46
45
  //# sourceMappingURL=loadContainerToSequenceNumber.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"loadContainerToSequenceNumber.js","sourceRoot":"","sources":["../src/loadContainerToSequenceNumber.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIH,oEAAmE;AAMnE,mDAAsD;AACtD,qEAGkC;AAkClC;;;;;;;;;;;;;;;;;;;GAmBG;AACI,KAAK,UAAU,6BAA6B,CAClD,KAA0C;IAE1C,MAAM,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,GAAG,KAAK,CAAC;IAC/D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,oBAAoB,CAAC,IAAI,oBAAoB,GAAG,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,qBAAU,CACnB,4DAA4D,oBAAoB,GAAG,CACnF,CAAC;IACH,CAAC;IAED,MAAM,cAAc,GAAG,IAAA,oDAA2B,EAAC,sBAAsB,CAAC,CAAC;IAC3E,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,IAAI,qBAAU,CACnB,kKAAkK,CAClK,CAAC;IACH,CAAC;IAED,iGAAiG;IACjG,kFAAkF;IAClF,MAAM,kBAAkB,GAAG,IAAI,0DAAiC,CAC/D,cAAc,EACd,oBAAoB,CACpB,CAAC;IAEF,OAAO,IAAA,mCAAmB,EACzB,EAAE,GAAG,KAAK,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,EACxD,KAAK,CAAC,OAAO,EACb,oBAAoB,EACpB,KAAK,CAAC,MAAM,CACZ,CAAC;AACH,CAAC;AA9BD,sEA8BC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { IContainer } from \"@fluidframework/container-definitions/internal\";\nimport type { IRequest } from \"@fluidframework/core-interfaces\";\nimport { UsageError } from \"@fluidframework/driver-utils/internal\";\n\nimport type {\n\tIContainerDriverServices,\n\tIContainerHostProps,\n} from \"./createAndLoadContainerUtils.js\";\nimport { loadContainerPaused } from \"./loadPaused.js\";\nimport {\n\tasPointInTimeCapableFactory,\n\tPointInTimeDocumentServiceFactory,\n} from \"./pointInTimeServices.js\";\n\n/**\n * Properties used to materialize a container at a point in document history.\n *\n * @remarks\n * This is distinct from normal container loading. The supplied\n * {@link IContainerDriverServices.documentServiceFactory} must be able to materialize the document\n * at {@link ILoadContainerToSequenceNumberProps.loadToSequenceNumber} - i.e. it must implement the\n * point-in-time capability the loader detects. For ODSP, call\n * `createOdspDocumentServiceFactory` with the implementation imported from\n * `@fluidframework/odsp-driver/legacy/point-in-time`.\n *\n * @legacy @beta\n */\nexport interface ILoadContainerToSequenceNumberProps\n\textends IContainerHostProps,\n\t\tIContainerDriverServices {\n\t/**\n\t * The request identifying the container instance.\n\t */\n\treadonly request: IRequest;\n\n\t/**\n\t * The sequence number at which to materialize the container.\n\t */\n\treadonly loadToSequenceNumber: number;\n\n\t/**\n\t * Cancels replay while waiting for the target sequence number.\n\t */\n\treadonly signal?: AbortSignal | undefined;\n}\n\n/**\n * Loads a read-only container at a target sequence number.\n *\n * @remarks\n * The returned container is disconnected with inbound and outbound processing paused. It is a\n * historical view and must not be used as a normal collaborative container.\n *\n * The supplied {@link IContainerDriverServices.documentServiceFactory} must support point-in-time\n * loading: it must be able to serve a snapshot at or before\n * {@link ILoadContainerToSequenceNumberProps.loadToSequenceNumber} and replay the document forward\n * through that sequence number. For ODSP, inject `createPointInTimeDocumentService` from the\n * dedicated point-in-time entrypoint through `createOdspDocumentServiceFactory` options. The loader\n * materializes the point-in-time view itself, so no wrapping or decoration is required.\n *\n * @param props - The load options, point-in-time-capable driver services, target sequence number, and\n * optional cancellation signal.\n * @returns A disconnected, read-only container materialized at the requested sequence number.\n *\n * @legacy @beta\n */\nexport async function loadContainerToSequenceNumber(\n\tprops: ILoadContainerToSequenceNumberProps,\n): Promise<IContainer> {\n\tconst { loadToSequenceNumber, documentServiceFactory } = props;\n\tif (!Number.isInteger(loadToSequenceNumber) || loadToSequenceNumber < 0) {\n\t\tthrow new UsageError(\n\t\t\t`loadToSequenceNumber must be a non-negative integer, got ${loadToSequenceNumber}.`,\n\t\t);\n\t}\n\n\tconst capableFactory = asPointInTimeCapableFactory(documentServiceFactory);\n\tif (capableFactory === undefined) {\n\t\tthrow new UsageError(\n\t\t\t\"The provided documentServiceFactory does not support point-in-time loading. For ODSP, call createOdspDocumentServiceFactory with a point-in-time implementation.\",\n\t\t);\n\t}\n\n\t// The loader owns materializing the target: it routes the container's createDocumentService call\n\t// to the driver's point-in-time service, so the caller never wraps their factory.\n\tconst pointInTimeFactory = new PointInTimeDocumentServiceFactory(\n\t\tcapableFactory,\n\t\tloadToSequenceNumber,\n\t);\n\n\treturn loadContainerPaused(\n\t\t{ ...props, documentServiceFactory: pointInTimeFactory },\n\t\tprops.request,\n\t\tloadToSequenceNumber,\n\t\tprops.signal,\n\t);\n}\n"]}
1
+ {"version":3,"file":"loadContainerToSequenceNumber.js","sourceRoot":"","sources":["../src/loadContainerToSequenceNumber.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAoEH,sEA8BC;AA9FD,oEAAmE;AAMnE,mDAAsD;AACtD,qEAGkC;AAkClC;;;;;;;;;;;;;;;;;;;GAmBG;AACI,KAAK,UAAU,6BAA6B,CAClD,KAA0C;IAE1C,MAAM,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,GAAG,KAAK,CAAC;IAC/D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,oBAAoB,CAAC,IAAI,oBAAoB,GAAG,CAAC,EAAE,CAAC;QACzE,MAAM,IAAI,qBAAU,CACnB,4DAA4D,oBAAoB,GAAG,CACnF,CAAC;IACH,CAAC;IAED,MAAM,cAAc,GAAG,IAAA,oDAA2B,EAAC,sBAAsB,CAAC,CAAC;IAC3E,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,IAAI,qBAAU,CACnB,kKAAkK,CAClK,CAAC;IACH,CAAC;IAED,iGAAiG;IACjG,kFAAkF;IAClF,MAAM,kBAAkB,GAAG,IAAI,0DAAiC,CAC/D,cAAc,EACd,oBAAoB,CACpB,CAAC;IAEF,OAAO,IAAA,mCAAmB,EACzB,EAAE,GAAG,KAAK,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,EACxD,KAAK,CAAC,OAAO,EACb,oBAAoB,EACpB,KAAK,CAAC,MAAM,CACZ,CAAC;AACH,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { IContainer } from \"@fluidframework/container-definitions/internal\";\nimport type { IRequest } from \"@fluidframework/core-interfaces\";\nimport { UsageError } from \"@fluidframework/driver-utils/internal\";\n\nimport type {\n\tIContainerDriverServices,\n\tIContainerHostProps,\n} from \"./createAndLoadContainerUtils.js\";\nimport { loadContainerPaused } from \"./loadPaused.js\";\nimport {\n\tasPointInTimeCapableFactory,\n\tPointInTimeDocumentServiceFactory,\n} from \"./pointInTimeServices.js\";\n\n/**\n * Properties used to materialize a container at a point in document history.\n *\n * @remarks\n * This is distinct from normal container loading. The supplied\n * {@link IContainerDriverServices.documentServiceFactory} must be able to materialize the document\n * at {@link ILoadContainerToSequenceNumberProps.loadToSequenceNumber} - i.e. it must implement the\n * point-in-time capability the loader detects. For ODSP, call\n * `createOdspDocumentServiceFactory` with the implementation imported from\n * `@fluidframework/odsp-driver/legacy/point-in-time`.\n *\n * @legacy @beta\n */\nexport interface ILoadContainerToSequenceNumberProps\n\textends IContainerHostProps,\n\t\tIContainerDriverServices {\n\t/**\n\t * The request identifying the container instance.\n\t */\n\treadonly request: IRequest;\n\n\t/**\n\t * The sequence number at which to materialize the container.\n\t */\n\treadonly loadToSequenceNumber: number;\n\n\t/**\n\t * Cancels replay while waiting for the target sequence number.\n\t */\n\treadonly signal?: AbortSignal | undefined;\n}\n\n/**\n * Loads a read-only container at a target sequence number.\n *\n * @remarks\n * The returned container is disconnected with inbound and outbound processing paused. It is a\n * historical view and must not be used as a normal collaborative container.\n *\n * The supplied {@link IContainerDriverServices.documentServiceFactory} must support point-in-time\n * loading: it must be able to serve a snapshot at or before\n * {@link ILoadContainerToSequenceNumberProps.loadToSequenceNumber} and replay the document forward\n * through that sequence number. For ODSP, inject `createPointInTimeDocumentService` from the\n * dedicated point-in-time entrypoint through `createOdspDocumentServiceFactory` options. The loader\n * materializes the point-in-time view itself, so no wrapping or decoration is required.\n *\n * @param props - The load options, point-in-time-capable driver services, target sequence number, and\n * optional cancellation signal.\n * @returns A disconnected, read-only container materialized at the requested sequence number.\n *\n * @legacy @beta\n */\nexport async function loadContainerToSequenceNumber(\n\tprops: ILoadContainerToSequenceNumberProps,\n): Promise<IContainer> {\n\tconst { loadToSequenceNumber, documentServiceFactory } = props;\n\tif (!Number.isInteger(loadToSequenceNumber) || loadToSequenceNumber < 0) {\n\t\tthrow new UsageError(\n\t\t\t`loadToSequenceNumber must be a non-negative integer, got ${loadToSequenceNumber}.`,\n\t\t);\n\t}\n\n\tconst capableFactory = asPointInTimeCapableFactory(documentServiceFactory);\n\tif (capableFactory === undefined) {\n\t\tthrow new UsageError(\n\t\t\t\"The provided documentServiceFactory does not support point-in-time loading. For ODSP, call createOdspDocumentServiceFactory with a point-in-time implementation.\",\n\t\t);\n\t}\n\n\t// The loader owns materializing the target: it routes the container's createDocumentService call\n\t// to the driver's point-in-time service, so the caller never wraps their factory.\n\tconst pointInTimeFactory = new PointInTimeDocumentServiceFactory(\n\t\tcapableFactory,\n\t\tloadToSequenceNumber,\n\t);\n\n\treturn loadContainerPaused(\n\t\t{ ...props, documentServiceFactory: pointInTimeFactory },\n\t\tprops.request,\n\t\tloadToSequenceNumber,\n\t\tprops.signal,\n\t);\n}\n"]}
@@ -4,7 +4,7 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.loadContainerPaused = void 0;
7
+ exports.loadContainerPaused = loadContainerPaused;
8
8
  const internal_1 = require("@fluidframework/container-definitions/internal");
9
9
  const internal_2 = require("@fluidframework/core-utils/internal");
10
10
  const internal_3 = require("@fluidframework/telemetry-utils/internal");
@@ -121,6 +121,5 @@ async function loadContainerPaused(loaderProps, request, loadToSequenceNumber, s
121
121
  });
122
122
  return container;
123
123
  }
124
- exports.loadContainerPaused = loadContainerPaused;
125
124
  /* eslint-enable jsdoc/check-indentation */
126
125
  //# sourceMappingURL=loadPaused.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"loadPaused.js","sourceRoot":"","sources":["../src/loadPaused.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tisIDeltaManagerFull,\n\tLoaderHeader,\n\ttype IContainer,\n} from \"@fluidframework/container-definitions/internal\";\nimport type { IRequest, IErrorBase } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { GenericError } from \"@fluidframework/telemetry-utils/internal\";\n\nimport { loadExistingContainer } from \"./createAndLoadContainerUtils.js\";\nimport type { ILoaderProps } from \"./loader.js\";\n\n/* eslint-disable jsdoc/check-indentation */\n\n/**\n * Loads container and leaves it in a state where it does not process any ops.\n * Container instance returned by this function is in special mode where some functionality that is available in normal use will not work correctly\n * with instance of container returned by this function. Some examples:\n * 1. calling IContainer.connect() will have very little impact on this container as it will not process ops.\n * 2. functionality like waitContainerToCatchUp() or waiting for ops in any other way would hand infinitely, as this container is not processing ops\n * 3. No changes can be made to this container - they will be lost.\n *\n * If sequence number is provided, loads up to this sequence number and stops there, otherwise stops immediately after loading snapshot.\n * In all cases, container is returned disconnected & paused, or an exception is thrown\n * Notes:\n * 1. Ignores LoaderHeader.loadMode headers. Container is always returned with ops applied upt to provided sequence number,\n * or no ops applied at all (if sequence number is not provided)\n * 2. This call can hang infinitately if disconnected from internet (or hit some other conditions, like 429 storm).\n * Compare to Container.load() experience (with default settings) - it either returns failure right away, or succeeds, with\n * ops fetching / delta connection happening in parallel / after container load flow, and thus providing an object (Container instance) to observe\n * network connectivity issues / ability to cancel (IContainer.disconnect) or close container (IContainer.close)\n * This flow needs to fetch ops (potentially connecting to delta connection), and any retriable errors on this path result in infinite retry.\n * If you need to cancel that process, consider supplying AbortSignal parameter.\n * @param loaderProps - The loader props to use to load the container.\n * @param request - request identifying container instance / load parameters. LoaderHeader.loadMode headers are ignored (see above)\n * @param loadToSequenceNumber - optional sequence number. If provided, ops are processed up to this sequence number.\n * @param signal - optional abort signal that can be used to cancel waiting for the ops.\n * @returns IContainer instance\n *\n * @internal\n */\nexport async function loadContainerPaused(\n\tloaderProps: ILoaderProps,\n\trequest: IRequest,\n\tloadToSequenceNumber?: number,\n\tsignal?: AbortSignal,\n): Promise<IContainer> {\n\tconst container = await loadExistingContainer({\n\t\t...loaderProps,\n\t\trequest: {\n\t\t\turl: request.url,\n\t\t\theaders: {\n\t\t\t\t...request.headers,\n\t\t\t\t// ensure we do not process any ops, such that we can examine container before ops starts to flow.\n\t\t\t\t[LoaderHeader.loadMode]: { opsBeforeReturn: undefined, deltaConnection: \"none\" },\n\t\t\t},\n\t\t},\n\t});\n\n\t// Force readonly mode - this will ensure we don't receive an error for the lack of join op\n\tcontainer.forceReadonly?.(true);\n\n\tconst dm = container.deltaManager;\n\tconst lastProcessedSequenceNumber = dm.initialSequenceNumber;\n\n\tconst pauseContainer = (): void => {\n\t\tassert(\n\t\t\tisIDeltaManagerFull(dm),\n\t\t\t0xa7f /* Delta manager does not have inbound/outbound queues. */,\n\t\t);\n\t\t// eslint-disable-next-line no-void\n\t\tvoid dm.inbound.pause();\n\t\t// eslint-disable-next-line no-void\n\t\tvoid dm.outbound.pause();\n\t};\n\n\t// Happy path - we are already there.\n\tif (\n\t\tloadToSequenceNumber === undefined ||\n\t\tlastProcessedSequenceNumber === loadToSequenceNumber\n\t) {\n\t\t// If we have already reached the desired sequence number, call pauseContainer() to pause immediately.\n\t\tpauseContainer();\n\t\treturn container;\n\t}\n\n\t// If we are trying to pause at a specific sequence number, ensure the latest snapshot is not newer than the desired sequence number.\n\tif (lastProcessedSequenceNumber > loadToSequenceNumber) {\n\t\tconst error = new GenericError(\n\t\t\t\"Cannot satisfy request to pause the container at the specified sequence number. Most recent snapshot is newer than the specified sequence number.\",\n\t\t);\n\t\tcontainer.close(error);\n\t\tthrow error;\n\t}\n\n\tlet opHandler: () => void;\n\tlet onAbort: () => void;\n\tlet onClose: (error?: IErrorBase) => void;\n\n\tconst promise = new Promise<void>((resolve, reject) => {\n\t\tonAbort = (): void => reject(new GenericError(\"Canceled due to cancellation request.\"));\n\t\t// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n\t\tonClose = (error?: IErrorBase): void => reject(error);\n\n\t\t// We need to setup a listener to stop op processing once we reach the desired sequence number (if specified).\n\t\topHandler = (): void => {\n\t\t\t// If there is a specified sequence number, keep processing until we reach it.\n\t\t\tif (\n\t\t\t\tloadToSequenceNumber !== undefined &&\n\t\t\t\tdm.lastSequenceNumber >= loadToSequenceNumber\n\t\t\t) {\n\t\t\t\t// Pause op processing once we have processed the desired number of ops.\n\t\t\t\tpauseContainer();\n\t\t\t\tresolve();\n\t\t\t}\n\t\t};\n\n\t\t// If we have not yet reached the desired sequence number, setup a listener to pause once we reach it.\n\t\tsignal?.addEventListener(\"abort\", onAbort);\n\t\tcontainer.on(\"op\", opHandler);\n\t\tcontainer.on(\"closed\", onClose);\n\t});\n\n\t// There are no guarantees on when ops will land in storage.\n\t// No guarantees that driver implements ops caching (i.e. ops observed in previous session can be served from cache)\n\t// or that browser will provide caching capabilities / keep the data (localStorage).\n\t// Thus, we have to ensure we connect to delta storage in order to make forward progress with ops.\n\t// We also instructed not to fetch / apply any ops from storage above (to be able to install callback above before ops are processed),\n\t// connect() call will fetch ops as needed.\n\tcontainer.connect();\n\n\t// Wait for the ops to be processed.\n\tawait promise\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t.catch((error: any) => {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n\t\t\tcontainer.close(error);\n\t\t\tthrow error;\n\t\t})\n\t\t.finally(() => {\n\t\t\t// There is not much value in leaving delta connection on. We are not processing ops, we also can't advance to \"connected\" state because of it.\n\t\t\t// We are not sending ops (due to forceReadonly() call above). We are holding collab window and any consensus-based processes.\n\t\t\t// It's better not to have connection in such case, as there are only nagatives, and no positives.\n\t\t\tcontainer.disconnect();\n\n\t\t\tcontainer.off(\"op\", opHandler);\n\t\t\tcontainer.off(\"closed\", onClose);\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t});\n\n\treturn container;\n}\n\n/* eslint-enable jsdoc/check-indentation */\n"]}
1
+ {"version":3,"file":"loadPaused.js","sourceRoot":"","sources":["../src/loadPaused.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\tisIDeltaManagerFull,\n\tLoaderHeader,\n\ttype IContainer,\n} from \"@fluidframework/container-definitions/internal\";\nimport type { IRequest, IErrorBase } from \"@fluidframework/core-interfaces\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { GenericError } from \"@fluidframework/telemetry-utils/internal\";\n\nimport { loadExistingContainer } from \"./createAndLoadContainerUtils.js\";\nimport type { ILoaderProps } from \"./loader.js\";\n\n/* eslint-disable jsdoc/check-indentation */\n\n/**\n * Loads container and leaves it in a state where it does not process any ops.\n * Container instance returned by this function is in special mode where some functionality that is available in normal use will not work correctly\n * with instance of container returned by this function. Some examples:\n * 1. calling IContainer.connect() will have very little impact on this container as it will not process ops.\n * 2. functionality like waitContainerToCatchUp() or waiting for ops in any other way would hand infinitely, as this container is not processing ops\n * 3. No changes can be made to this container - they will be lost.\n *\n * If sequence number is provided, loads up to this sequence number and stops there, otherwise stops immediately after loading snapshot.\n * In all cases, container is returned disconnected & paused, or an exception is thrown\n * Notes:\n * 1. Ignores LoaderHeader.loadMode headers. Container is always returned with ops applied upt to provided sequence number,\n * or no ops applied at all (if sequence number is not provided)\n * 2. This call can hang infinitately if disconnected from internet (or hit some other conditions, like 429 storm).\n * Compare to Container.load() experience (with default settings) - it either returns failure right away, or succeeds, with\n * ops fetching / delta connection happening in parallel / after container load flow, and thus providing an object (Container instance) to observe\n * network connectivity issues / ability to cancel (IContainer.disconnect) or close container (IContainer.close)\n * This flow needs to fetch ops (potentially connecting to delta connection), and any retriable errors on this path result in infinite retry.\n * If you need to cancel that process, consider supplying AbortSignal parameter.\n * @param loaderProps - The loader props to use to load the container.\n * @param request - request identifying container instance / load parameters. LoaderHeader.loadMode headers are ignored (see above)\n * @param loadToSequenceNumber - optional sequence number. If provided, ops are processed up to this sequence number.\n * @param signal - optional abort signal that can be used to cancel waiting for the ops.\n * @returns IContainer instance\n *\n * @internal\n */\nexport async function loadContainerPaused(\n\tloaderProps: ILoaderProps,\n\trequest: IRequest,\n\tloadToSequenceNumber?: number,\n\tsignal?: AbortSignal,\n): Promise<IContainer> {\n\tconst container = await loadExistingContainer({\n\t\t...loaderProps,\n\t\trequest: {\n\t\t\turl: request.url,\n\t\t\theaders: {\n\t\t\t\t...request.headers,\n\t\t\t\t// ensure we do not process any ops, such that we can examine container before ops starts to flow.\n\t\t\t\t[LoaderHeader.loadMode]: { opsBeforeReturn: undefined, deltaConnection: \"none\" },\n\t\t\t},\n\t\t},\n\t});\n\n\t// Force readonly mode - this will ensure we don't receive an error for the lack of join op\n\tcontainer.forceReadonly?.(true);\n\n\tconst dm = container.deltaManager;\n\tconst lastProcessedSequenceNumber = dm.initialSequenceNumber;\n\n\tconst pauseContainer = (): void => {\n\t\tassert(\n\t\t\tisIDeltaManagerFull(dm),\n\t\t\t0xa7f /* Delta manager does not have inbound/outbound queues. */,\n\t\t);\n\t\t// eslint-disable-next-line no-void\n\t\tvoid dm.inbound.pause();\n\t\t// eslint-disable-next-line no-void\n\t\tvoid dm.outbound.pause();\n\t};\n\n\t// Happy path - we are already there.\n\tif (\n\t\tloadToSequenceNumber === undefined ||\n\t\tlastProcessedSequenceNumber === loadToSequenceNumber\n\t) {\n\t\t// If we have already reached the desired sequence number, call pauseContainer() to pause immediately.\n\t\tpauseContainer();\n\t\treturn container;\n\t}\n\n\t// If we are trying to pause at a specific sequence number, ensure the latest snapshot is not newer than the desired sequence number.\n\tif (lastProcessedSequenceNumber > loadToSequenceNumber) {\n\t\tconst error = new GenericError(\n\t\t\t\"Cannot satisfy request to pause the container at the specified sequence number. Most recent snapshot is newer than the specified sequence number.\",\n\t\t);\n\t\tcontainer.close(error);\n\t\tthrow error;\n\t}\n\n\tlet opHandler: () => void;\n\tlet onAbort: () => void;\n\tlet onClose: (error?: IErrorBase) => void;\n\n\tconst promise = new Promise<void>((resolve, reject) => {\n\t\tonAbort = (): void => reject(new GenericError(\"Canceled due to cancellation request.\"));\n\t\t// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n\t\tonClose = (error?: IErrorBase): void => reject(error);\n\n\t\t// We need to setup a listener to stop op processing once we reach the desired sequence number (if specified).\n\t\topHandler = (): void => {\n\t\t\t// If there is a specified sequence number, keep processing until we reach it.\n\t\t\tif (\n\t\t\t\tloadToSequenceNumber !== undefined &&\n\t\t\t\tdm.lastSequenceNumber >= loadToSequenceNumber\n\t\t\t) {\n\t\t\t\t// Pause op processing once we have processed the desired number of ops.\n\t\t\t\tpauseContainer();\n\t\t\t\tresolve();\n\t\t\t}\n\t\t};\n\n\t\t// If we have not yet reached the desired sequence number, setup a listener to pause once we reach it.\n\t\tsignal?.addEventListener(\"abort\", onAbort);\n\t\tcontainer.on(\"op\", opHandler);\n\t\tcontainer.on(\"closed\", onClose);\n\t});\n\n\t// There are no guarantees on when ops will land in storage.\n\t// No guarantees that driver implements ops caching (i.e. ops observed in previous session can be served from cache)\n\t// or that browser will provide caching capabilities / keep the data (localStorage).\n\t// Thus, we have to ensure we connect to delta storage in order to make forward progress with ops.\n\t// We also instructed not to fetch / apply any ops from storage above (to be able to install callback above before ops are processed),\n\t// connect() call will fetch ops as needed.\n\tcontainer.connect();\n\n\t// Wait for the ops to be processed.\n\tawait promise\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t.catch((error: any) => {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n\t\t\tcontainer.close(error);\n\t\t\tthrow error;\n\t\t})\n\t\t.finally(() => {\n\t\t\t// There is not much value in leaving delta connection on. We are not processing ops, we also can't advance to \"connected\" state because of it.\n\t\t\t// We are not sending ops (due to forceReadonly() call above). We are holding collab window and any consensus-based processes.\n\t\t\t// It's better not to have connection in such case, as there are only nagatives, and no positives.\n\t\t\tcontainer.disconnect();\n\n\t\t\tcontainer.off(\"op\", opHandler);\n\t\t\tcontainer.off(\"closed\", onClose);\n\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t});\n\n\treturn container;\n}\n\n/* eslint-enable jsdoc/check-indentation */\n"]}
package/dist/loader.js CHANGED
@@ -21,6 +21,8 @@ function ensureResolvedUrlDefined(resolved) {
21
21
  * @internal
22
22
  */
23
23
  class RelativeLoader {
24
+ container;
25
+ loader;
24
26
  constructor(container, loader) {
25
27
  this.container = container;
26
28
  this.loader = loader;
@@ -56,13 +58,15 @@ exports.RelativeLoader = RelativeLoader;
56
58
  * @remarks The Loader class is deprecated and will be removed in a future release. Use the free-form functions instead (See issue #24450 for more details).
57
59
  */
58
60
  class Loader {
61
+ services;
62
+ mc;
59
63
  constructor(loaderProps) {
60
64
  const { urlResolver, documentServiceFactory, codeLoader, options, scope, logger, configProvider, protocolHandlerBuilder, } = loaderProps;
61
65
  const telemetryProps = {
62
66
  loaderId: (0, uuid_1.v4)(),
63
67
  loaderVersion: packageVersion_js_1.pkgVersion,
64
68
  };
65
- const subMc = (0, internal_2.mixinMonitoringContext)(debugLogger_js_1.DebugLogger.mixinDebugLogger("fluid:telemetry", logger, {
69
+ const subMc = (0, internal_2.mixinMonitoringContext)((0, debugLogger_js_1.mixinDebugLogger)("fluid:telemetry", logger, {
66
70
  all: telemetryProps,
67
71
  }), internal_2.sessionStorageConfigProvider.value, configProvider);
68
72
  this.services = {
@@ -1 +1 @@
1
- {"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\ttype IContainer,\n\ttype IFluidCodeDetails,\n\ttype IFluidModule,\n\ttype IHostLoader,\n\ttype ILoader,\n\ttype ILoaderOptions,\n\ttype IProvideFluidCodeDetailsComparer,\n\tLoaderHeader,\n} from \"@fluidframework/container-definitions/internal\";\nimport type {\n\tFluidObject,\n\tIConfigProviderBase,\n\tIRequest,\n\tITelemetryBaseLogger,\n} from \"@fluidframework/core-interfaces\";\nimport type { IClientDetails } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentServiceFactory,\n\tIResolvedUrl,\n\tIUrlResolver,\n} from \"@fluidframework/driver-definitions/internal\";\nimport {\n\ttype MonitoringContext,\n\tPerformanceEvent,\n\tcreateChildMonitoringContext,\n\tmixinMonitoringContext,\n\tsessionStorageConfigProvider,\n\ttoITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n// eslint-disable-next-line import-x/no-internal-modules -- Needed to avoid specialized /internal ITelemetryLoggerExt\nimport type { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils/legacy\";\nimport { v4 as uuid } from \"uuid\";\n\nimport { Container } from \"./container.js\";\nimport { DebugLogger } from \"./debugLogger.js\";\nimport { pkgVersion } from \"./packageVersion.js\";\nimport type { ProtocolHandlerBuilder } from \"./protocol.js\";\nimport type { IPendingContainerState } from \"./serializedStateManager.js\";\nimport {\n\tgetAttachedContainerStateFromSerializedContainer,\n\ttryParseCompatibleResolvedUrl,\n} from \"./utils.js\";\n\nfunction ensureResolvedUrlDefined(\n\tresolved: IResolvedUrl | undefined,\n): asserts resolved is IResolvedUrl {\n\tif (resolved === undefined) {\n\t\tthrow new Error(`Object is not a IResolveUrl.`);\n\t}\n}\n/**\n * @internal\n */\nexport class RelativeLoader implements ILoader {\n\tconstructor(\n\t\tprivate readonly container: Container,\n\t\tprivate readonly loader: ILoader | undefined,\n\t) {}\n\n\tpublic async resolve(request: IRequest): Promise<IContainer> {\n\t\tif (request.url.startsWith(\"/\")) {\n\t\t\tensureResolvedUrlDefined(this.container.resolvedUrl);\n\t\t\tconst container = await this.container.clone(\n\t\t\t\t{\n\t\t\t\t\tresolvedUrl: { ...this.container.resolvedUrl },\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\t\tversion: request.headers?.[LoaderHeader.version] ?? undefined,\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\t\tloadMode: request.headers?.[LoaderHeader.loadMode],\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\t\tcanReconnect: request.headers?.[LoaderHeader.reconnect],\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\t\tclientDetailsOverride: request.headers?.[LoaderHeader.clientDetails],\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn container;\n\t\t}\n\n\t\tif (this.loader === undefined) {\n\t\t\tthrow new Error(\"Cannot resolve external containers\");\n\t\t}\n\t\treturn this.loader.resolve(request);\n\t}\n}\n\n/**\n * @deprecated IFluidModuleWithDetails interface is moved to\n * {@link @fluidframework/container-definitions#IFluidModuleWithDetails}\n * to have all the code loading modules in one package. #8193\n * Encapsulates a module entry point with corresponding code details.\n * @legacy @beta\n */\nexport interface IFluidModuleWithDetails {\n\t/**\n\t * Fluid code module that implements the runtime factory needed to instantiate the container runtime.\n\t */\n\tmodule: IFluidModule;\n\t/**\n\t * Code details associated with the module. Represents a document schema this module supports.\n\t * If the code loader implements the {@link @fluidframework/core-interfaces#IFluidCodeDetailsComparer} interface,\n\t * it'll be called to determine whether the module code details satisfy the new code proposal in the quorum.\n\t */\n\tdetails: IFluidCodeDetails;\n}\n\n/**\n * @deprecated ICodeDetailsLoader interface is moved to {@link @fluidframework/container-definitions#ICodeDetailsLoader}\n * to have code loading modules in one package. #8193\n * Fluid code loader resolves a code module matching the document schema, i.e. code details, such as\n * a package name and package version range.\n * @legacy @beta\n */\nexport interface ICodeDetailsLoader extends Partial<IProvideFluidCodeDetailsComparer> {\n\t/**\n\t * Load the code module (package) that is capable to interact with the document.\n\t *\n\t * @param source - Code proposal that articulates the current schema the document is written in.\n\t * @returns Code module entry point along with the code details associated with it.\n\t */\n\tload(source: IFluidCodeDetails): Promise<IFluidModuleWithDetails>;\n}\n\n/**\n * Services and properties necessary for creating a loader\n * @legacy @beta\n */\nexport interface ILoaderProps {\n\t/**\n\t * The url resolver used by the loader for resolving external urls\n\t * into Fluid urls such that the container specified by the\n\t * external url can be loaded.\n\t */\n\treadonly urlResolver: IUrlResolver;\n\t/**\n\t * The document service factory take the Fluid url provided\n\t * by the resolved url and constructs all the necessary services\n\t * for communication with the container's server.\n\t */\n\treadonly documentServiceFactory: IDocumentServiceFactory;\n\t/**\n\t * The code loader handles loading the necessary code\n\t * for running a container once it is loaded.\n\t */\n\treadonly codeLoader: ICodeDetailsLoader;\n\n\t/**\n\t * A property bag of options used by various layers\n\t * to control features\n\t */\n\treadonly options?: ILoaderOptions;\n\n\t/**\n\t * Scope is provided to all container and is a set of shared\n\t * services for container's to integrate with their host environment.\n\t */\n\treadonly scope?: FluidObject;\n\n\t/**\n\t * The logger that all telemetry should be pushed to.\n\t */\n\treadonly logger?: ITelemetryBaseLogger;\n\n\t/**\n\t * The configuration provider which may be used to control features.\n\t */\n\treadonly configProvider?: IConfigProviderBase;\n\n\t/**\n\t * Optional property for allowing the container to use a custom\n\t * protocol implementation for handling the quorum and/or the audience.\n\t */\n\treadonly protocolHandlerBuilder?: ProtocolHandlerBuilder;\n}\n\n/**\n * Services and properties used by and exposed by the loader\n * @legacy @beta\n */\nexport interface ILoaderServices {\n\t/**\n\t * The url resolver used by the loader for resolving external urls\n\t * into Fluid urls such that the container specified by the\n\t * external url can be loaded.\n\t */\n\treadonly urlResolver: IUrlResolver;\n\t/**\n\t * The document service factory take the Fluid url provided\n\t * by the resolved url and constructs all the necessary services\n\t * for communication with the container's server.\n\t */\n\treadonly documentServiceFactory: IDocumentServiceFactory;\n\t/**\n\t * The code loader handles loading the necessary code\n\t * for running a container once it is loaded.\n\t */\n\treadonly codeLoader: ICodeDetailsLoader;\n\n\t/**\n\t * A property bag of options used by various layers\n\t * to control features\n\t */\n\treadonly options: ILoaderOptions;\n\n\t/**\n\t * Scope is provided to all container and is a set of shared\n\t * services for container's to integrate with their host environment.\n\t */\n\treadonly scope: FluidObject;\n\n\t/**\n\t * The logger downstream consumers should construct their loggers from\n\t */\n\treadonly subLogger: ITelemetryLoggerExt;\n\n\t/**\n\t * Optional property for allowing the container to use a custom\n\t * protocol implementation for handling the quorum and/or the audience.\n\t */\n\treadonly protocolHandlerBuilder?: ProtocolHandlerBuilder;\n}\n\n/**\n * Manages Fluid resource loading\n * @legacy @beta\n *\n * @remarks The Loader class is deprecated and will be removed in a future release. Use the free-form functions instead (See issue #24450 for more details).\n */\nexport class Loader implements IHostLoader {\n\tpublic readonly services: ILoaderServices;\n\tprivate readonly mc: MonitoringContext;\n\n\tconstructor(loaderProps: ILoaderProps) {\n\t\tconst {\n\t\t\turlResolver,\n\t\t\tdocumentServiceFactory,\n\t\t\tcodeLoader,\n\t\t\toptions,\n\t\t\tscope,\n\t\t\tlogger,\n\t\t\tconfigProvider,\n\t\t\tprotocolHandlerBuilder,\n\t\t} = loaderProps;\n\n\t\tconst telemetryProps = {\n\t\t\tloaderId: uuid(),\n\t\t\tloaderVersion: pkgVersion,\n\t\t};\n\n\t\tconst subMc = mixinMonitoringContext(\n\t\t\tDebugLogger.mixinDebugLogger(\"fluid:telemetry\", logger, {\n\t\t\t\tall: telemetryProps,\n\t\t\t}),\n\t\t\tsessionStorageConfigProvider.value,\n\t\t\tconfigProvider,\n\t\t);\n\n\t\tthis.services = {\n\t\t\turlResolver,\n\t\t\tdocumentServiceFactory,\n\t\t\tcodeLoader,\n\t\t\toptions: options ?? {},\n\t\t\tscope:\n\t\t\t\toptions?.provideScopeLoader === false ? { ...scope } : { ...scope, ILoader: this },\n\t\t\tprotocolHandlerBuilder,\n\t\t\tsubLogger: toITelemetryLoggerExt(subMc.logger),\n\t\t};\n\t\tthis.mc = createChildMonitoringContext({\n\t\t\tlogger: this.services.subLogger,\n\t\t\tnamespace: \"Loader\",\n\t\t});\n\t}\n\n\tpublic async createDetachedContainer(\n\t\tcodeDetails: IFluidCodeDetails,\n\t\tcreateDetachedProps?: {\n\t\t\tcanReconnect?: boolean;\n\t\t\tclientDetailsOverride?: IClientDetails;\n\t\t},\n\t): Promise<IContainer> {\n\t\treturn Container.createDetached(\n\t\t\t{\n\t\t\t\t...createDetachedProps,\n\t\t\t\t...this.services,\n\t\t\t},\n\t\t\tcodeDetails,\n\t\t);\n\t}\n\n\tpublic async rehydrateDetachedContainerFromSnapshot(\n\t\tsnapshot: string,\n\t\tcreateDetachedProps?: {\n\t\t\tcanReconnect?: boolean;\n\t\t\tclientDetailsOverride?: IClientDetails;\n\t\t},\n\t): Promise<IContainer> {\n\t\treturn Container.rehydrateDetachedFromSnapshot(\n\t\t\t{\n\t\t\t\t...createDetachedProps,\n\t\t\t\t...this.services,\n\t\t\t},\n\t\t\tsnapshot,\n\t\t);\n\t}\n\n\tpublic async resolve(request: IRequest, pendingLocalState?: string): Promise<IContainer> {\n\t\tconst eventName = pendingLocalState === undefined ? \"Resolve\" : \"ResolveWithPendingState\";\n\t\treturn PerformanceEvent.timedExecAsync(this.mc.logger, { eventName }, async () => {\n\t\t\treturn this.resolveCore(\n\t\t\t\trequest,\n\t\t\t\tgetAttachedContainerStateFromSerializedContainer(pendingLocalState),\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate async resolveCore(\n\t\trequest: IRequest,\n\t\tpendingLocalState?: IPendingContainerState,\n\t): Promise<Container> {\n\t\tconst resolvedAsFluid = await this.services.urlResolver.resolve(request);\n\t\tensureResolvedUrlDefined(resolvedAsFluid);\n\n\t\t// Parse URL into data stores\n\t\tconst parsed = tryParseCompatibleResolvedUrl(resolvedAsFluid.url);\n\t\tif (parsed === undefined) {\n\t\t\tthrow new Error(`Invalid URL ${resolvedAsFluid.url}`);\n\t\t}\n\n\t\tif (pendingLocalState !== undefined) {\n\t\t\tconst parsedPendingUrl = tryParseCompatibleResolvedUrl(pendingLocalState.url);\n\t\t\tif (\n\t\t\t\tparsedPendingUrl?.id !== parsed.id ||\n\t\t\t\tparsedPendingUrl?.path.replace(/\\/$/, \"\") !== parsed.path.replace(/\\/$/, \"\")\n\t\t\t) {\n\t\t\t\tconst message = `URL ${resolvedAsFluid.url} does not match pending state URL ${pendingLocalState.url}`;\n\t\t\t\tthrow new Error(message);\n\t\t\t}\n\t\t}\n\n\t\trequest.headers ??= {};\n\t\t// If set in both query string and headers, use query string. Also write the value from the query string into the header either way.\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\trequest.headers[LoaderHeader.version] =\n\t\t\tparsed.version ?? request.headers[LoaderHeader.version];\n\n\t\treturn this.loadContainer(request, resolvedAsFluid, pendingLocalState);\n\t}\n\n\tprivate async loadContainer(\n\t\trequest: IRequest,\n\t\tresolvedUrl: IResolvedUrl,\n\t\tpendingLocalState?: IPendingContainerState,\n\t): Promise<Container> {\n\t\treturn Container.load(\n\t\t\t{\n\t\t\t\tresolvedUrl,\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\tversion: request.headers?.[LoaderHeader.version] ?? undefined,\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\tloadMode: request.headers?.[LoaderHeader.loadMode],\n\t\t\t\tpendingLocalState,\n\t\t\t},\n\t\t\t{\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\tcanReconnect: request.headers?.[LoaderHeader.reconnect],\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\tclientDetailsOverride: request.headers?.[LoaderHeader.clientDetails],\n\t\t\t\t...this.services,\n\t\t\t},\n\t\t);\n\t}\n}\n"]}
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../src/loader.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport {\n\ttype IContainer,\n\ttype IFluidCodeDetails,\n\ttype IFluidModule,\n\ttype IHostLoader,\n\ttype ILoader,\n\ttype ILoaderOptions,\n\ttype IProvideFluidCodeDetailsComparer,\n\tLoaderHeader,\n} from \"@fluidframework/container-definitions/internal\";\nimport type {\n\tFluidObject,\n\tIConfigProviderBase,\n\tIRequest,\n\tITelemetryBaseLogger,\n} from \"@fluidframework/core-interfaces\";\nimport type { IClientDetails } from \"@fluidframework/driver-definitions\";\nimport type {\n\tIDocumentServiceFactory,\n\tIResolvedUrl,\n\tIUrlResolver,\n} from \"@fluidframework/driver-definitions/internal\";\nimport {\n\ttype MonitoringContext,\n\tPerformanceEvent,\n\tcreateChildMonitoringContext,\n\tmixinMonitoringContext,\n\tsessionStorageConfigProvider,\n\ttoITelemetryLoggerExt,\n} from \"@fluidframework/telemetry-utils/internal\";\n// eslint-disable-next-line import-x/no-internal-modules -- Needed to avoid specialized /internal ITelemetryLoggerExt\nimport type { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils/legacy\";\nimport { v4 as uuid } from \"uuid\";\n\nimport { Container } from \"./container.js\";\nimport { mixinDebugLogger } from \"./debugLogger.js\";\nimport { pkgVersion } from \"./packageVersion.js\";\nimport type { ProtocolHandlerBuilder } from \"./protocol.js\";\nimport type { IPendingContainerState } from \"./serializedStateManager.js\";\nimport {\n\tgetAttachedContainerStateFromSerializedContainer,\n\ttryParseCompatibleResolvedUrl,\n} from \"./utils.js\";\n\nfunction ensureResolvedUrlDefined(\n\tresolved: IResolvedUrl | undefined,\n): asserts resolved is IResolvedUrl {\n\tif (resolved === undefined) {\n\t\tthrow new Error(`Object is not a IResolveUrl.`);\n\t}\n}\n/**\n * @internal\n */\nexport class RelativeLoader implements ILoader {\n\tconstructor(\n\t\tprivate readonly container: Container,\n\t\tprivate readonly loader: ILoader | undefined,\n\t) {}\n\n\tpublic async resolve(request: IRequest): Promise<IContainer> {\n\t\tif (request.url.startsWith(\"/\")) {\n\t\t\tensureResolvedUrlDefined(this.container.resolvedUrl);\n\t\t\tconst container = await this.container.clone(\n\t\t\t\t{\n\t\t\t\t\tresolvedUrl: { ...this.container.resolvedUrl },\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\t\tversion: request.headers?.[LoaderHeader.version] ?? undefined,\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\t\tloadMode: request.headers?.[LoaderHeader.loadMode],\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\t\tcanReconnect: request.headers?.[LoaderHeader.reconnect],\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\t\tclientDetailsOverride: request.headers?.[LoaderHeader.clientDetails],\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn container;\n\t\t}\n\n\t\tif (this.loader === undefined) {\n\t\t\tthrow new Error(\"Cannot resolve external containers\");\n\t\t}\n\t\treturn this.loader.resolve(request);\n\t}\n}\n\n/**\n * @deprecated IFluidModuleWithDetails interface is moved to\n * {@link @fluidframework/container-definitions#IFluidModuleWithDetails}\n * to have all the code loading modules in one package. #8193\n * Encapsulates a module entry point with corresponding code details.\n * @legacy @beta\n */\nexport interface IFluidModuleWithDetails {\n\t/**\n\t * Fluid code module that implements the runtime factory needed to instantiate the container runtime.\n\t */\n\tmodule: IFluidModule;\n\t/**\n\t * Code details associated with the module. Represents a document schema this module supports.\n\t * If the code loader implements the {@link @fluidframework/core-interfaces#IFluidCodeDetailsComparer} interface,\n\t * it'll be called to determine whether the module code details satisfy the new code proposal in the quorum.\n\t */\n\tdetails: IFluidCodeDetails;\n}\n\n/**\n * @deprecated ICodeDetailsLoader interface is moved to {@link @fluidframework/container-definitions#ICodeDetailsLoader}\n * to have code loading modules in one package. #8193\n * Fluid code loader resolves a code module matching the document schema, i.e. code details, such as\n * a package name and package version range.\n * @legacy @beta\n */\nexport interface ICodeDetailsLoader extends Partial<IProvideFluidCodeDetailsComparer> {\n\t/**\n\t * Load the code module (package) that is capable to interact with the document.\n\t *\n\t * @param source - Code proposal that articulates the current schema the document is written in.\n\t * @returns Code module entry point along with the code details associated with it.\n\t */\n\tload(source: IFluidCodeDetails): Promise<IFluidModuleWithDetails>;\n}\n\n/**\n * Services and properties necessary for creating a loader\n * @legacy @beta\n */\nexport interface ILoaderProps {\n\t/**\n\t * The url resolver used by the loader for resolving external urls\n\t * into Fluid urls such that the container specified by the\n\t * external url can be loaded.\n\t */\n\treadonly urlResolver: IUrlResolver;\n\t/**\n\t * The document service factory take the Fluid url provided\n\t * by the resolved url and constructs all the necessary services\n\t * for communication with the container's server.\n\t */\n\treadonly documentServiceFactory: IDocumentServiceFactory;\n\t/**\n\t * The code loader handles loading the necessary code\n\t * for running a container once it is loaded.\n\t */\n\treadonly codeLoader: ICodeDetailsLoader;\n\n\t/**\n\t * A property bag of options used by various layers\n\t * to control features\n\t */\n\treadonly options?: ILoaderOptions;\n\n\t/**\n\t * Scope is provided to all container and is a set of shared\n\t * services for container's to integrate with their host environment.\n\t */\n\treadonly scope?: FluidObject;\n\n\t/**\n\t * The logger that all telemetry should be pushed to.\n\t */\n\treadonly logger?: ITelemetryBaseLogger;\n\n\t/**\n\t * The configuration provider which may be used to control features.\n\t */\n\treadonly configProvider?: IConfigProviderBase;\n\n\t/**\n\t * Optional property for allowing the container to use a custom\n\t * protocol implementation for handling the quorum and/or the audience.\n\t */\n\treadonly protocolHandlerBuilder?: ProtocolHandlerBuilder;\n}\n\n/**\n * Services and properties used by and exposed by the loader\n * @legacy @beta\n */\nexport interface ILoaderServices {\n\t/**\n\t * The url resolver used by the loader for resolving external urls\n\t * into Fluid urls such that the container specified by the\n\t * external url can be loaded.\n\t */\n\treadonly urlResolver: IUrlResolver;\n\t/**\n\t * The document service factory take the Fluid url provided\n\t * by the resolved url and constructs all the necessary services\n\t * for communication with the container's server.\n\t */\n\treadonly documentServiceFactory: IDocumentServiceFactory;\n\t/**\n\t * The code loader handles loading the necessary code\n\t * for running a container once it is loaded.\n\t */\n\treadonly codeLoader: ICodeDetailsLoader;\n\n\t/**\n\t * A property bag of options used by various layers\n\t * to control features\n\t */\n\treadonly options: ILoaderOptions;\n\n\t/**\n\t * Scope is provided to all container and is a set of shared\n\t * services for container's to integrate with their host environment.\n\t */\n\treadonly scope: FluidObject;\n\n\t/**\n\t * The logger downstream consumers should construct their loggers from\n\t */\n\treadonly subLogger: ITelemetryLoggerExt;\n\n\t/**\n\t * Optional property for allowing the container to use a custom\n\t * protocol implementation for handling the quorum and/or the audience.\n\t */\n\treadonly protocolHandlerBuilder?: ProtocolHandlerBuilder;\n}\n\n/**\n * Manages Fluid resource loading\n * @legacy @beta\n *\n * @remarks The Loader class is deprecated and will be removed in a future release. Use the free-form functions instead (See issue #24450 for more details).\n */\nexport class Loader implements IHostLoader {\n\tpublic readonly services: ILoaderServices;\n\tprivate readonly mc: MonitoringContext;\n\n\tconstructor(loaderProps: ILoaderProps) {\n\t\tconst {\n\t\t\turlResolver,\n\t\t\tdocumentServiceFactory,\n\t\t\tcodeLoader,\n\t\t\toptions,\n\t\t\tscope,\n\t\t\tlogger,\n\t\t\tconfigProvider,\n\t\t\tprotocolHandlerBuilder,\n\t\t} = loaderProps;\n\n\t\tconst telemetryProps = {\n\t\t\tloaderId: uuid(),\n\t\t\tloaderVersion: pkgVersion,\n\t\t};\n\n\t\tconst subMc = mixinMonitoringContext(\n\t\t\tmixinDebugLogger(\"fluid:telemetry\", logger, {\n\t\t\t\tall: telemetryProps,\n\t\t\t}),\n\t\t\tsessionStorageConfigProvider.value,\n\t\t\tconfigProvider,\n\t\t);\n\n\t\tthis.services = {\n\t\t\turlResolver,\n\t\t\tdocumentServiceFactory,\n\t\t\tcodeLoader,\n\t\t\toptions: options ?? {},\n\t\t\tscope:\n\t\t\t\toptions?.provideScopeLoader === false ? { ...scope } : { ...scope, ILoader: this },\n\t\t\tprotocolHandlerBuilder,\n\t\t\tsubLogger: toITelemetryLoggerExt(subMc.logger),\n\t\t};\n\t\tthis.mc = createChildMonitoringContext({\n\t\t\tlogger: this.services.subLogger,\n\t\t\tnamespace: \"Loader\",\n\t\t});\n\t}\n\n\tpublic async createDetachedContainer(\n\t\tcodeDetails: IFluidCodeDetails,\n\t\tcreateDetachedProps?: {\n\t\t\tcanReconnect?: boolean;\n\t\t\tclientDetailsOverride?: IClientDetails;\n\t\t},\n\t): Promise<IContainer> {\n\t\treturn Container.createDetached(\n\t\t\t{\n\t\t\t\t...createDetachedProps,\n\t\t\t\t...this.services,\n\t\t\t},\n\t\t\tcodeDetails,\n\t\t);\n\t}\n\n\tpublic async rehydrateDetachedContainerFromSnapshot(\n\t\tsnapshot: string,\n\t\tcreateDetachedProps?: {\n\t\t\tcanReconnect?: boolean;\n\t\t\tclientDetailsOverride?: IClientDetails;\n\t\t},\n\t): Promise<IContainer> {\n\t\treturn Container.rehydrateDetachedFromSnapshot(\n\t\t\t{\n\t\t\t\t...createDetachedProps,\n\t\t\t\t...this.services,\n\t\t\t},\n\t\t\tsnapshot,\n\t\t);\n\t}\n\n\tpublic async resolve(request: IRequest, pendingLocalState?: string): Promise<IContainer> {\n\t\tconst eventName = pendingLocalState === undefined ? \"Resolve\" : \"ResolveWithPendingState\";\n\t\treturn PerformanceEvent.timedExecAsync(this.mc.logger, { eventName }, async () => {\n\t\t\treturn this.resolveCore(\n\t\t\t\trequest,\n\t\t\t\tgetAttachedContainerStateFromSerializedContainer(pendingLocalState),\n\t\t\t);\n\t\t});\n\t}\n\n\tprivate async resolveCore(\n\t\trequest: IRequest,\n\t\tpendingLocalState?: IPendingContainerState,\n\t): Promise<Container> {\n\t\tconst resolvedAsFluid = await this.services.urlResolver.resolve(request);\n\t\tensureResolvedUrlDefined(resolvedAsFluid);\n\n\t\t// Parse URL into data stores\n\t\tconst parsed = tryParseCompatibleResolvedUrl(resolvedAsFluid.url);\n\t\tif (parsed === undefined) {\n\t\t\tthrow new Error(`Invalid URL ${resolvedAsFluid.url}`);\n\t\t}\n\n\t\tif (pendingLocalState !== undefined) {\n\t\t\tconst parsedPendingUrl = tryParseCompatibleResolvedUrl(pendingLocalState.url);\n\t\t\tif (\n\t\t\t\tparsedPendingUrl?.id !== parsed.id ||\n\t\t\t\tparsedPendingUrl?.path.replace(/\\/$/, \"\") !== parsed.path.replace(/\\/$/, \"\")\n\t\t\t) {\n\t\t\t\tconst message = `URL ${resolvedAsFluid.url} does not match pending state URL ${pendingLocalState.url}`;\n\t\t\t\tthrow new Error(message);\n\t\t\t}\n\t\t}\n\n\t\trequest.headers ??= {};\n\t\t// If set in both query string and headers, use query string. Also write the value from the query string into the header either way.\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\trequest.headers[LoaderHeader.version] =\n\t\t\tparsed.version ?? request.headers[LoaderHeader.version];\n\n\t\treturn this.loadContainer(request, resolvedAsFluid, pendingLocalState);\n\t}\n\n\tprivate async loadContainer(\n\t\trequest: IRequest,\n\t\tresolvedUrl: IResolvedUrl,\n\t\tpendingLocalState?: IPendingContainerState,\n\t): Promise<Container> {\n\t\treturn Container.load(\n\t\t\t{\n\t\t\t\tresolvedUrl,\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\tversion: request.headers?.[LoaderHeader.version] ?? undefined,\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\tloadMode: request.headers?.[LoaderHeader.loadMode],\n\t\t\t\tpendingLocalState,\n\t\t\t},\n\t\t\t{\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\tcanReconnect: request.headers?.[LoaderHeader.reconnect],\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\tclientDetailsOverride: request.headers?.[LoaderHeader.clientDetails],\n\t\t\t\t...this.services,\n\t\t\t},\n\t\t);\n\t}\n}\n"]}