@fluidframework/odsp-driver 1.4.0-121020 → 2.0.0-dev-rc.1.0.0.225277

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 (666) hide show
  1. package/.eslintrc.js +12 -12
  2. package/.mocharc.js +12 -0
  3. package/CHANGELOG.md +162 -0
  4. package/README.md +56 -0
  5. package/api-extractor-esm.json +4 -0
  6. package/api-extractor-lint.json +4 -0
  7. package/api-extractor.json +2 -2
  8. package/api-report/odsp-driver.api.md +309 -0
  9. package/dist/{ReadBufferUtils.js → ReadBufferUtils.cjs} +16 -9
  10. package/dist/ReadBufferUtils.cjs.map +1 -0
  11. package/dist/ReadBufferUtils.d.ts.map +1 -1
  12. package/dist/{WriteBufferUtils.js → WriteBufferUtils.cjs} +73 -69
  13. package/dist/WriteBufferUtils.cjs.map +1 -0
  14. package/dist/WriteBufferUtils.d.ts +3 -5
  15. package/dist/WriteBufferUtils.d.ts.map +1 -1
  16. package/dist/{checkUrl.js → checkUrl.cjs} +7 -6
  17. package/dist/checkUrl.cjs.map +1 -0
  18. package/dist/checkUrl.d.ts +1 -0
  19. package/dist/checkUrl.d.ts.map +1 -1
  20. package/dist/compactSnapshotParser.cjs +207 -0
  21. package/dist/compactSnapshotParser.cjs.map +1 -0
  22. package/dist/compactSnapshotParser.d.ts +12 -3
  23. package/dist/compactSnapshotParser.d.ts.map +1 -1
  24. package/dist/{compactSnapshotWriter.js → compactSnapshotWriter.cjs} +43 -33
  25. package/dist/compactSnapshotWriter.cjs.map +1 -0
  26. package/dist/compactSnapshotWriter.d.ts +2 -3
  27. package/dist/compactSnapshotWriter.d.ts.map +1 -1
  28. package/dist/{constants.js → constants.cjs} +7 -1
  29. package/dist/constants.cjs.map +1 -0
  30. package/dist/constants.d.ts +6 -0
  31. package/dist/constants.d.ts.map +1 -1
  32. package/dist/{contracts.js → contracts.cjs} +1 -1
  33. package/dist/contracts.cjs.map +1 -0
  34. package/dist/contracts.d.ts +16 -53
  35. package/dist/contracts.d.ts.map +1 -1
  36. package/dist/{contractsPublic.js → contractsPublic.cjs} +9 -3
  37. package/dist/contractsPublic.cjs.map +1 -0
  38. package/dist/contractsPublic.d.ts +15 -0
  39. package/dist/contractsPublic.d.ts.map +1 -1
  40. package/dist/createFile.cjs +177 -0
  41. package/dist/createFile.cjs.map +1 -0
  42. package/dist/createFile.d.ts +6 -10
  43. package/dist/createFile.d.ts.map +1 -1
  44. package/dist/createNewContainerOnExistingFile.cjs +60 -0
  45. package/dist/createNewContainerOnExistingFile.cjs.map +1 -0
  46. package/dist/createNewContainerOnExistingFile.d.ts +22 -0
  47. package/dist/createNewContainerOnExistingFile.d.ts.map +1 -0
  48. package/dist/createNewModule.cjs +12 -0
  49. package/dist/createNewModule.cjs.map +1 -0
  50. package/dist/createNewModule.d.ts +7 -0
  51. package/dist/createNewModule.d.ts.map +1 -0
  52. package/dist/createNewUtils.cjs +203 -0
  53. package/dist/createNewUtils.cjs.map +1 -0
  54. package/dist/createNewUtils.d.ts +16 -0
  55. package/dist/createNewUtils.d.ts.map +1 -1
  56. package/dist/{createOdspCreateContainerRequest.js → createOdspCreateContainerRequest.cjs} +8 -4
  57. package/dist/createOdspCreateContainerRequest.cjs.map +1 -0
  58. package/dist/createOdspCreateContainerRequest.d.ts +5 -3
  59. package/dist/createOdspCreateContainerRequest.d.ts.map +1 -1
  60. package/dist/{createOdspUrl.js → createOdspUrl.cjs} +2 -1
  61. package/dist/createOdspUrl.cjs.map +1 -0
  62. package/dist/createOdspUrl.d.ts +1 -0
  63. package/dist/createOdspUrl.d.ts.map +1 -1
  64. package/dist/{epochTracker.js → epochTracker.cjs} +102 -48
  65. package/dist/epochTracker.cjs.map +1 -0
  66. package/dist/epochTracker.d.ts +32 -8
  67. package/dist/epochTracker.d.ts.map +1 -1
  68. package/dist/{fetch.js → fetch.cjs} +1 -1
  69. package/dist/fetch.cjs.map +1 -0
  70. package/dist/fetch.d.ts +1 -1
  71. package/dist/fetch.d.ts.map +1 -1
  72. package/dist/{fetchSnapshot.js → fetchSnapshot.cjs} +192 -176
  73. package/dist/fetchSnapshot.cjs.map +1 -0
  74. package/dist/fetchSnapshot.d.ts +10 -5
  75. package/dist/fetchSnapshot.d.ts.map +1 -1
  76. package/dist/{getFileLink.js → getFileLink.cjs} +52 -41
  77. package/dist/getFileLink.cjs.map +1 -0
  78. package/dist/getFileLink.d.ts +4 -7
  79. package/dist/getFileLink.d.ts.map +1 -1
  80. package/dist/{getQueryString.js → getQueryString.cjs} +1 -1
  81. package/dist/getQueryString.cjs.map +1 -0
  82. package/dist/getQueryString.d.ts.map +1 -1
  83. package/dist/{getUrlAndHeadersWithAuth.js → getUrlAndHeadersWithAuth.cjs} +4 -2
  84. package/dist/getUrlAndHeadersWithAuth.cjs.map +1 -0
  85. package/dist/getUrlAndHeadersWithAuth.d.ts.map +1 -1
  86. package/dist/index.cjs +59 -0
  87. package/dist/index.cjs.map +1 -0
  88. package/dist/index.d.ts +19 -16
  89. package/dist/index.d.ts.map +1 -1
  90. package/dist/localOdspDriver/localOdspDeltaStorageService.cjs +35 -0
  91. package/dist/localOdspDriver/localOdspDeltaStorageService.cjs.map +1 -0
  92. package/dist/localOdspDriver/localOdspDeltaStorageService.d.ts +17 -0
  93. package/dist/localOdspDriver/localOdspDeltaStorageService.d.ts.map +1 -0
  94. package/dist/localOdspDriver/{localOdspDocumentService.js → localOdspDocumentService.cjs} +7 -5
  95. package/dist/localOdspDriver/localOdspDocumentService.cjs.map +1 -0
  96. package/dist/localOdspDriver/localOdspDocumentService.d.ts +3 -2
  97. package/dist/localOdspDriver/localOdspDocumentService.d.ts.map +1 -1
  98. package/dist/localOdspDriver/{localOdspDocumentServiceFactory.js → localOdspDocumentServiceFactory.cjs} +9 -10
  99. package/dist/localOdspDriver/localOdspDocumentServiceFactory.cjs.map +1 -0
  100. package/dist/localOdspDriver/localOdspDocumentServiceFactory.d.ts +2 -3
  101. package/dist/localOdspDriver/localOdspDocumentServiceFactory.d.ts.map +1 -1
  102. package/dist/localOdspDriver/{localOdspDocumentStorageManager.js → localOdspDocumentStorageManager.cjs} +13 -11
  103. package/dist/localOdspDriver/localOdspDocumentStorageManager.cjs.map +1 -0
  104. package/dist/localOdspDriver/localOdspDocumentStorageManager.d.ts +2 -2
  105. package/dist/localOdspDriver/localOdspDocumentStorageManager.d.ts.map +1 -1
  106. package/dist/odsp-driver-alpha.d.ts +496 -0
  107. package/dist/odsp-driver-beta.d.ts +160 -0
  108. package/dist/odsp-driver-public.d.ts +160 -0
  109. package/dist/odsp-driver-untrimmed.d.ts +565 -0
  110. package/dist/{odspCache.js → odspCache.cjs} +9 -10
  111. package/dist/odspCache.cjs.map +1 -0
  112. package/dist/odspCache.d.ts +19 -4
  113. package/dist/odspCache.d.ts.map +1 -1
  114. package/dist/odspDelayLoadedDeltaStream.cjs +291 -0
  115. package/dist/odspDelayLoadedDeltaStream.cjs.map +1 -0
  116. package/dist/odspDelayLoadedDeltaStream.d.ts +75 -0
  117. package/dist/odspDelayLoadedDeltaStream.d.ts.map +1 -0
  118. package/dist/{odspDeltaStorageService.js → odspDeltaStorageService.cjs} +70 -71
  119. package/dist/odspDeltaStorageService.cjs.map +1 -0
  120. package/dist/odspDeltaStorageService.d.ts +8 -6
  121. package/dist/odspDeltaStorageService.d.ts.map +1 -1
  122. package/dist/{odspDocumentDeltaConnection.js → odspDocumentDeltaConnection.cjs} +224 -113
  123. package/dist/odspDocumentDeltaConnection.cjs.map +1 -0
  124. package/dist/odspDocumentDeltaConnection.d.ts +32 -12
  125. package/dist/odspDocumentDeltaConnection.d.ts.map +1 -1
  126. package/dist/odspDocumentService.cjs +225 -0
  127. package/dist/odspDocumentService.cjs.map +1 -0
  128. package/dist/odspDocumentService.d.ts +11 -25
  129. package/dist/odspDocumentService.d.ts.map +1 -1
  130. package/dist/{odspDocumentServiceFactory.js → odspDocumentServiceFactory.cjs} +8 -5
  131. package/dist/odspDocumentServiceFactory.cjs.map +1 -0
  132. package/dist/odspDocumentServiceFactory.d.ts +4 -0
  133. package/dist/odspDocumentServiceFactory.d.ts.map +1 -1
  134. package/dist/odspDocumentServiceFactoryCore.cjs +196 -0
  135. package/dist/odspDocumentServiceFactoryCore.cjs.map +1 -0
  136. package/dist/odspDocumentServiceFactoryCore.d.ts +18 -11
  137. package/dist/odspDocumentServiceFactoryCore.d.ts.map +1 -1
  138. package/dist/odspDocumentServiceFactoryWithCodeSplit.cjs +20 -0
  139. package/dist/odspDocumentServiceFactoryWithCodeSplit.cjs.map +1 -0
  140. package/dist/odspDocumentServiceFactoryWithCodeSplit.d.ts +5 -0
  141. package/dist/odspDocumentServiceFactoryWithCodeSplit.d.ts.map +1 -1
  142. package/dist/odspDocumentStorageManager.cjs +490 -0
  143. package/dist/odspDocumentStorageManager.cjs.map +1 -0
  144. package/dist/odspDocumentStorageManager.d.ts +11 -5
  145. package/dist/odspDocumentStorageManager.d.ts.map +1 -1
  146. package/dist/{odspDocumentStorageServiceBase.js → odspDocumentStorageServiceBase.cjs} +32 -34
  147. package/dist/odspDocumentStorageServiceBase.cjs.map +1 -0
  148. package/dist/odspDocumentStorageServiceBase.d.ts +7 -9
  149. package/dist/odspDocumentStorageServiceBase.d.ts.map +1 -1
  150. package/dist/{odspDriverUrlResolver.js → odspDriverUrlResolver.cjs} +50 -36
  151. package/dist/odspDriverUrlResolver.cjs.map +1 -0
  152. package/dist/odspDriverUrlResolver.d.ts +12 -0
  153. package/dist/odspDriverUrlResolver.d.ts.map +1 -1
  154. package/dist/{odspDriverUrlResolverForShareLink.js → odspDriverUrlResolverForShareLink.cjs} +37 -26
  155. package/dist/odspDriverUrlResolverForShareLink.cjs.map +1 -0
  156. package/dist/odspDriverUrlResolverForShareLink.d.ts +5 -3
  157. package/dist/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
  158. package/dist/{odspError.js → odspError.cjs} +7 -3
  159. package/dist/odspError.cjs.map +1 -0
  160. package/dist/odspError.d.ts.map +1 -1
  161. package/dist/{odspFluidFileLink.js → odspFluidFileLink.cjs} +25 -18
  162. package/dist/odspFluidFileLink.cjs.map +1 -0
  163. package/dist/odspFluidFileLink.d.ts +10 -1
  164. package/dist/odspFluidFileLink.d.ts.map +1 -1
  165. package/dist/odspLocationRedirection.cjs +24 -0
  166. package/dist/odspLocationRedirection.cjs.map +1 -0
  167. package/dist/odspLocationRedirection.d.ts +14 -0
  168. package/dist/odspLocationRedirection.d.ts.map +1 -0
  169. package/dist/{odspPublicUtils.js → odspPublicUtils.cjs} +7 -4
  170. package/dist/odspPublicUtils.cjs.map +1 -0
  171. package/dist/odspPublicUtils.d.ts +6 -0
  172. package/dist/odspPublicUtils.d.ts.map +1 -1
  173. package/dist/{odspSnapshotParser.js → odspSnapshotParser.cjs} +11 -12
  174. package/dist/odspSnapshotParser.cjs.map +1 -0
  175. package/dist/odspSnapshotParser.d.ts.map +1 -1
  176. package/dist/{odspSummaryUploadManager.js → odspSummaryUploadManager.cjs} +47 -34
  177. package/dist/odspSummaryUploadManager.cjs.map +1 -0
  178. package/dist/odspSummaryUploadManager.d.ts +7 -4
  179. package/dist/odspSummaryUploadManager.d.ts.map +1 -1
  180. package/dist/{odspUrlHelper.js → odspUrlHelper.cjs} +9 -3
  181. package/dist/odspUrlHelper.cjs.map +1 -0
  182. package/dist/odspUrlHelper.d.ts +5 -0
  183. package/dist/odspUrlHelper.d.ts.map +1 -1
  184. package/dist/{odspUtils.js → odspUtils.cjs} +118 -30
  185. package/dist/odspUtils.cjs.map +1 -0
  186. package/dist/odspUtils.d.ts +35 -6
  187. package/dist/odspUtils.d.ts.map +1 -1
  188. package/dist/{opsCaching.js → opsCaching.cjs} +25 -9
  189. package/dist/opsCaching.cjs.map +1 -0
  190. package/dist/opsCaching.d.ts +3 -3
  191. package/dist/opsCaching.d.ts.map +1 -1
  192. package/dist/{packageVersion.js → packageVersion.cjs} +2 -2
  193. package/dist/packageVersion.cjs.map +1 -0
  194. package/dist/packageVersion.d.ts +1 -1
  195. package/dist/packageVersion.d.ts.map +1 -1
  196. package/dist/prefetchLatestSnapshot.cjs +100 -0
  197. package/dist/prefetchLatestSnapshot.cjs.map +1 -0
  198. package/dist/prefetchLatestSnapshot.d.ts +12 -7
  199. package/dist/prefetchLatestSnapshot.d.ts.map +1 -1
  200. package/dist/{retryErrorsStorageAdapter.js → retryErrorsStorageAdapter.cjs} +13 -6
  201. package/dist/retryErrorsStorageAdapter.cjs.map +1 -0
  202. package/dist/retryErrorsStorageAdapter.d.ts +5 -4
  203. package/dist/retryErrorsStorageAdapter.d.ts.map +1 -1
  204. package/dist/{retryUtils.js → retryUtils.cjs} +30 -14
  205. package/dist/retryUtils.cjs.map +1 -0
  206. package/dist/retryUtils.d.ts +2 -2
  207. package/dist/retryUtils.d.ts.map +1 -1
  208. package/dist/socketModule.cjs +10 -0
  209. package/dist/socketModule.cjs.map +1 -0
  210. package/dist/socketModule.d.ts +7 -0
  211. package/dist/socketModule.d.ts.map +1 -0
  212. package/dist/tsdoc-metadata.json +11 -0
  213. package/dist/{vroom.js → vroom.cjs} +24 -9
  214. package/dist/vroom.cjs.map +1 -0
  215. package/dist/vroom.d.ts +4 -4
  216. package/dist/vroom.d.ts.map +1 -1
  217. package/dist/{zipItDataRepresentationUtils.js → zipItDataRepresentationUtils.cjs} +227 -118
  218. package/dist/zipItDataRepresentationUtils.cjs.map +1 -0
  219. package/dist/zipItDataRepresentationUtils.d.ts +47 -20
  220. package/dist/zipItDataRepresentationUtils.d.ts.map +1 -1
  221. package/lib/{ReadBufferUtils.d.ts → ReadBufferUtils.d.mts} +1 -1
  222. package/lib/ReadBufferUtils.d.mts.map +1 -0
  223. package/lib/{ReadBufferUtils.js → ReadBufferUtils.mjs} +14 -7
  224. package/lib/ReadBufferUtils.mjs.map +1 -0
  225. package/lib/{WriteBufferUtils.d.ts → WriteBufferUtils.d.mts} +4 -6
  226. package/lib/WriteBufferUtils.d.mts.map +1 -0
  227. package/lib/{WriteBufferUtils.js → WriteBufferUtils.mjs} +68 -64
  228. package/lib/WriteBufferUtils.mjs.map +1 -0
  229. package/lib/{checkUrl.d.ts → checkUrl.d.mts} +2 -1
  230. package/lib/checkUrl.d.mts.map +1 -0
  231. package/lib/{checkUrl.js → checkUrl.mjs} +7 -6
  232. package/lib/checkUrl.mjs.map +1 -0
  233. package/lib/compactSnapshotParser.d.mts +24 -0
  234. package/lib/compactSnapshotParser.d.mts.map +1 -0
  235. package/lib/compactSnapshotParser.mjs +203 -0
  236. package/lib/compactSnapshotParser.mjs.map +1 -0
  237. package/lib/{compactSnapshotWriter.d.ts → compactSnapshotWriter.d.mts} +4 -5
  238. package/lib/compactSnapshotWriter.d.mts.map +1 -0
  239. package/lib/{compactSnapshotWriter.js → compactSnapshotWriter.mjs} +41 -31
  240. package/lib/compactSnapshotWriter.mjs.map +1 -0
  241. package/lib/{constants.d.ts → constants.d.mts} +7 -1
  242. package/lib/constants.d.mts.map +1 -0
  243. package/lib/{constants.js → constants.mjs} +7 -1
  244. package/lib/constants.mjs.map +1 -0
  245. package/lib/{contracts.d.ts → contracts.d.mts} +18 -55
  246. package/lib/contracts.d.mts.map +1 -0
  247. package/lib/{contracts.js → contracts.mjs} +1 -1
  248. package/lib/contracts.mjs.map +1 -0
  249. package/lib/{contractsPublic.d.ts → contractsPublic.d.mts} +16 -1
  250. package/lib/contractsPublic.d.mts.map +1 -0
  251. package/lib/{contractsPublic.js → contractsPublic.mjs} +7 -1
  252. package/lib/contractsPublic.mjs.map +1 -0
  253. package/lib/createFile.d.mts +18 -0
  254. package/lib/createFile.d.mts.map +1 -0
  255. package/lib/createFile.mjs +171 -0
  256. package/lib/createFile.mjs.map +1 -0
  257. package/lib/createNewContainerOnExistingFile.d.mts +22 -0
  258. package/lib/createNewContainerOnExistingFile.d.mts.map +1 -0
  259. package/lib/createNewContainerOnExistingFile.mjs +56 -0
  260. package/lib/createNewContainerOnExistingFile.mjs.map +1 -0
  261. package/lib/createNewModule.d.mts +7 -0
  262. package/lib/createNewModule.d.mts.map +1 -0
  263. package/lib/createNewModule.mjs +7 -0
  264. package/lib/createNewModule.mjs.map +1 -0
  265. package/lib/createNewUtils.d.mts +27 -0
  266. package/lib/createNewUtils.d.mts.map +1 -0
  267. package/lib/createNewUtils.mjs +197 -0
  268. package/lib/createNewUtils.mjs.map +1 -0
  269. package/lib/{createOdspCreateContainerRequest.d.ts → createOdspCreateContainerRequest.d.mts} +6 -8
  270. package/lib/createOdspCreateContainerRequest.d.mts.map +1 -0
  271. package/lib/{createOdspCreateContainerRequest.js → createOdspCreateContainerRequest.mjs} +8 -4
  272. package/lib/createOdspCreateContainerRequest.mjs.map +1 -0
  273. package/lib/{createOdspUrl.d.ts → createOdspUrl.d.mts} +3 -2
  274. package/lib/createOdspUrl.d.mts.map +1 -0
  275. package/lib/{createOdspUrl.js → createOdspUrl.mjs} +2 -1
  276. package/lib/createOdspUrl.mjs.map +1 -0
  277. package/lib/{epochTracker.d.ts → epochTracker.d.mts} +35 -11
  278. package/lib/epochTracker.d.mts.map +1 -0
  279. package/lib/{epochTracker.js → epochTracker.mjs} +97 -43
  280. package/lib/epochTracker.mjs.map +1 -0
  281. package/lib/{fetch.d.ts → fetch.d.mts} +2 -2
  282. package/lib/fetch.d.mts.map +1 -0
  283. package/lib/{fetch.js → fetch.mjs} +1 -1
  284. package/lib/fetch.mjs.map +1 -0
  285. package/lib/{fetchSnapshot.d.ts → fetchSnapshot.d.mts} +15 -10
  286. package/lib/fetchSnapshot.d.mts.map +1 -0
  287. package/lib/{fetchSnapshot.js → fetchSnapshot.mjs} +185 -167
  288. package/lib/fetchSnapshot.mjs.map +1 -0
  289. package/lib/{getFileLink.d.ts → getFileLink.d.mts} +5 -8
  290. package/lib/getFileLink.d.mts.map +1 -0
  291. package/lib/{getFileLink.js → getFileLink.mjs} +49 -38
  292. package/lib/getFileLink.mjs.map +1 -0
  293. package/lib/{getQueryString.d.ts → getQueryString.d.mts} +1 -5
  294. package/lib/getQueryString.d.mts.map +1 -0
  295. package/lib/{getQueryString.js → getQueryString.mjs} +1 -1
  296. package/lib/getQueryString.mjs.map +1 -0
  297. package/lib/{getUrlAndHeadersWithAuth.d.ts → getUrlAndHeadersWithAuth.d.mts} +1 -1
  298. package/lib/getUrlAndHeadersWithAuth.d.mts.map +1 -0
  299. package/lib/{getUrlAndHeadersWithAuth.js → getUrlAndHeadersWithAuth.mjs} +4 -2
  300. package/lib/getUrlAndHeadersWithAuth.mjs.map +1 -0
  301. package/lib/index.d.mts +24 -0
  302. package/lib/index.d.mts.map +1 -0
  303. package/lib/index.mjs +22 -0
  304. package/lib/index.mjs.map +1 -0
  305. package/lib/localOdspDriver/localOdspDeltaStorageService.d.mts +17 -0
  306. package/lib/localOdspDriver/localOdspDeltaStorageService.d.mts.map +1 -0
  307. package/lib/localOdspDriver/localOdspDeltaStorageService.mjs +31 -0
  308. package/lib/localOdspDriver/localOdspDeltaStorageService.mjs.map +1 -0
  309. package/lib/localOdspDriver/{localOdspDocumentService.d.ts → localOdspDocumentService.d.mts} +4 -3
  310. package/lib/localOdspDriver/localOdspDocumentService.d.mts.map +1 -0
  311. package/lib/localOdspDriver/{localOdspDocumentService.js → localOdspDocumentService.mjs} +8 -6
  312. package/lib/localOdspDriver/localOdspDocumentService.mjs.map +1 -0
  313. package/lib/localOdspDriver/{localOdspDocumentServiceFactory.d.ts → localOdspDocumentServiceFactory.d.mts} +5 -6
  314. package/lib/localOdspDriver/localOdspDocumentServiceFactory.d.mts.map +1 -0
  315. package/lib/localOdspDriver/{localOdspDocumentServiceFactory.js → localOdspDocumentServiceFactory.mjs} +9 -10
  316. package/lib/localOdspDriver/localOdspDocumentServiceFactory.mjs.map +1 -0
  317. package/lib/localOdspDriver/{localOdspDocumentStorageManager.d.ts → localOdspDocumentStorageManager.d.mts} +4 -4
  318. package/lib/localOdspDriver/localOdspDocumentStorageManager.d.mts.map +1 -0
  319. package/lib/localOdspDriver/{localOdspDocumentStorageManager.js → localOdspDocumentStorageManager.mjs} +11 -9
  320. package/lib/localOdspDriver/localOdspDocumentStorageManager.mjs.map +1 -0
  321. package/lib/odsp-driver-alpha.d.mts +496 -0
  322. package/lib/odsp-driver-beta.d.mts +160 -0
  323. package/lib/odsp-driver-public.d.mts +160 -0
  324. package/lib/odsp-driver-untrimmed.d.mts +565 -0
  325. package/lib/{odspCache.d.ts → odspCache.d.mts} +20 -9
  326. package/lib/odspCache.d.mts.map +1 -0
  327. package/lib/{odspCache.js → odspCache.mjs} +6 -11
  328. package/lib/odspCache.mjs.map +1 -0
  329. package/lib/odspDelayLoadedDeltaStream.d.mts +75 -0
  330. package/lib/odspDelayLoadedDeltaStream.d.mts.map +1 -0
  331. package/lib/odspDelayLoadedDeltaStream.mjs +287 -0
  332. package/lib/odspDelayLoadedDeltaStream.mjs.map +1 -0
  333. package/lib/{odspDeltaStorageService.d.ts → odspDeltaStorageService.d.mts} +10 -8
  334. package/lib/odspDeltaStorageService.d.mts.map +1 -0
  335. package/lib/{odspDeltaStorageService.js → odspDeltaStorageService.mjs} +70 -68
  336. package/lib/odspDeltaStorageService.mjs.map +1 -0
  337. package/lib/{odspDocumentDeltaConnection.d.ts → odspDocumentDeltaConnection.d.mts} +34 -14
  338. package/lib/odspDocumentDeltaConnection.d.mts.map +1 -0
  339. package/lib/{odspDocumentDeltaConnection.js → odspDocumentDeltaConnection.mjs} +214 -103
  340. package/lib/odspDocumentDeltaConnection.mjs.map +1 -0
  341. package/lib/{odspDocumentService.d.ts → odspDocumentService.d.mts} +15 -29
  342. package/lib/odspDocumentService.d.mts.map +1 -0
  343. package/lib/odspDocumentService.mjs +221 -0
  344. package/lib/odspDocumentService.mjs.map +1 -0
  345. package/lib/{odspDocumentServiceFactory.d.ts → odspDocumentServiceFactory.d.mts} +6 -2
  346. package/lib/odspDocumentServiceFactory.d.mts.map +1 -0
  347. package/lib/{odspDocumentServiceFactory.js → odspDocumentServiceFactory.mjs} +8 -6
  348. package/lib/odspDocumentServiceFactory.mjs.map +1 -0
  349. package/lib/{odspDocumentServiceFactoryCore.d.ts → odspDocumentServiceFactoryCore.d.mts} +20 -13
  350. package/lib/odspDocumentServiceFactoryCore.d.mts.map +1 -0
  351. package/lib/odspDocumentServiceFactoryCore.mjs +192 -0
  352. package/lib/odspDocumentServiceFactoryCore.mjs.map +1 -0
  353. package/lib/{odspDocumentServiceFactoryWithCodeSplit.d.ts → odspDocumentServiceFactoryWithCodeSplit.d.mts} +7 -2
  354. package/lib/odspDocumentServiceFactoryWithCodeSplit.d.mts.map +1 -0
  355. package/lib/{odspDocumentServiceFactoryWithCodeSplit.js → odspDocumentServiceFactoryWithCodeSplit.mjs} +8 -3
  356. package/lib/odspDocumentServiceFactoryWithCodeSplit.mjs.map +1 -0
  357. package/lib/{odspDocumentStorageManager.d.ts → odspDocumentStorageManager.d.mts} +18 -12
  358. package/lib/odspDocumentStorageManager.d.mts.map +1 -0
  359. package/lib/odspDocumentStorageManager.mjs +486 -0
  360. package/lib/odspDocumentStorageManager.mjs.map +1 -0
  361. package/lib/{odspDocumentStorageServiceBase.d.ts → odspDocumentStorageServiceBase.d.mts} +9 -11
  362. package/lib/odspDocumentStorageServiceBase.d.mts.map +1 -0
  363. package/lib/{odspDocumentStorageServiceBase.js → odspDocumentStorageServiceBase.mjs} +31 -33
  364. package/lib/odspDocumentStorageServiceBase.mjs.map +1 -0
  365. package/lib/{odspDriverUrlResolver.d.ts → odspDriverUrlResolver.d.mts} +13 -1
  366. package/lib/odspDriverUrlResolver.d.mts.map +1 -0
  367. package/lib/{odspDriverUrlResolver.js → odspDriverUrlResolver.mjs} +50 -40
  368. package/lib/odspDriverUrlResolver.mjs.map +1 -0
  369. package/lib/{odspDriverUrlResolverForShareLink.d.ts → odspDriverUrlResolverForShareLink.d.mts} +7 -5
  370. package/lib/odspDriverUrlResolverForShareLink.d.mts.map +1 -0
  371. package/lib/{odspDriverUrlResolverForShareLink.js → odspDriverUrlResolverForShareLink.mjs} +36 -29
  372. package/lib/odspDriverUrlResolverForShareLink.mjs.map +1 -0
  373. package/lib/{odspError.d.ts → odspError.d.mts} +2 -2
  374. package/lib/odspError.d.mts.map +1 -0
  375. package/lib/{odspError.js → odspError.mjs} +7 -3
  376. package/lib/odspError.mjs.map +1 -0
  377. package/lib/{odspFluidFileLink.d.ts → odspFluidFileLink.d.mts} +12 -3
  378. package/lib/odspFluidFileLink.d.mts.map +1 -0
  379. package/lib/{odspFluidFileLink.js → odspFluidFileLink.mjs} +23 -16
  380. package/lib/odspFluidFileLink.mjs.map +1 -0
  381. package/lib/odspLocationRedirection.d.mts +14 -0
  382. package/lib/odspLocationRedirection.d.mts.map +1 -0
  383. package/lib/odspLocationRedirection.mjs +20 -0
  384. package/lib/odspLocationRedirection.mjs.map +1 -0
  385. package/lib/{odspPublicUtils.d.ts → odspPublicUtils.d.mts} +7 -1
  386. package/lib/odspPublicUtils.d.mts.map +1 -0
  387. package/lib/{odspPublicUtils.js → odspPublicUtils.mjs} +5 -2
  388. package/lib/odspPublicUtils.mjs.map +1 -0
  389. package/lib/{odspSnapshotParser.d.ts → odspSnapshotParser.d.mts} +3 -3
  390. package/lib/odspSnapshotParser.d.mts.map +1 -0
  391. package/lib/{odspSnapshotParser.js → odspSnapshotParser.mjs} +10 -11
  392. package/lib/odspSnapshotParser.mjs.map +1 -0
  393. package/lib/{odspSummaryUploadManager.d.ts → odspSummaryUploadManager.d.mts} +9 -6
  394. package/lib/odspSummaryUploadManager.d.mts.map +1 -0
  395. package/lib/{odspSummaryUploadManager.js → odspSummaryUploadManager.mjs} +41 -32
  396. package/lib/odspSummaryUploadManager.mjs.map +1 -0
  397. package/lib/{odspUrlHelper.d.ts → odspUrlHelper.d.mts} +6 -1
  398. package/lib/odspUrlHelper.d.mts.map +1 -0
  399. package/lib/{odspUrlHelper.js → odspUrlHelper.mjs} +9 -3
  400. package/lib/odspUrlHelper.mjs.map +1 -0
  401. package/lib/{odspUtils.d.ts → odspUtils.d.mts} +37 -8
  402. package/lib/odspUtils.d.mts.map +1 -0
  403. package/lib/{odspUtils.js → odspUtils.mjs} +109 -27
  404. package/lib/odspUtils.mjs.map +1 -0
  405. package/lib/{opsCaching.d.ts → opsCaching.d.mts} +4 -4
  406. package/lib/opsCaching.d.mts.map +1 -0
  407. package/lib/{opsCaching.js → opsCaching.mjs} +23 -7
  408. package/lib/opsCaching.mjs.map +1 -0
  409. package/lib/{packageVersion.d.ts → packageVersion.d.mts} +2 -2
  410. package/lib/packageVersion.d.mts.map +1 -0
  411. package/lib/{packageVersion.js → packageVersion.mjs} +2 -2
  412. package/lib/packageVersion.mjs.map +1 -0
  413. package/lib/{prefetchLatestSnapshot.d.ts → prefetchLatestSnapshot.d.mts} +14 -9
  414. package/lib/prefetchLatestSnapshot.d.mts.map +1 -0
  415. package/lib/prefetchLatestSnapshot.mjs +96 -0
  416. package/lib/prefetchLatestSnapshot.mjs.map +1 -0
  417. package/lib/{retryErrorsStorageAdapter.d.ts → retryErrorsStorageAdapter.d.mts} +6 -5
  418. package/lib/retryErrorsStorageAdapter.d.mts.map +1 -0
  419. package/lib/{retryErrorsStorageAdapter.js → retryErrorsStorageAdapter.mjs} +13 -6
  420. package/lib/retryErrorsStorageAdapter.mjs.map +1 -0
  421. package/lib/{retryUtils.d.ts → retryUtils.d.mts} +3 -3
  422. package/lib/retryUtils.d.mts.map +1 -0
  423. package/lib/{retryUtils.js → retryUtils.mjs} +27 -11
  424. package/lib/retryUtils.mjs.map +1 -0
  425. package/lib/socketModule.d.mts +7 -0
  426. package/lib/socketModule.d.mts.map +1 -0
  427. package/lib/socketModule.mjs +7 -0
  428. package/lib/socketModule.mjs.map +1 -0
  429. package/lib/{vroom.d.ts → vroom.d.mts} +7 -7
  430. package/lib/vroom.d.mts.map +1 -0
  431. package/lib/{vroom.js → vroom.mjs} +24 -9
  432. package/lib/vroom.mjs.map +1 -0
  433. package/lib/{zipItDataRepresentationUtils.d.ts → zipItDataRepresentationUtils.d.mts} +49 -22
  434. package/lib/zipItDataRepresentationUtils.d.mts.map +1 -0
  435. package/lib/{zipItDataRepresentationUtils.js → zipItDataRepresentationUtils.mjs} +213 -111
  436. package/lib/zipItDataRepresentationUtils.mjs.map +1 -0
  437. package/package.json +87 -69
  438. package/prettier.config.cjs +8 -0
  439. package/src/ReadBufferUtils.ts +51 -44
  440. package/src/WriteBufferUtils.ts +203 -181
  441. package/src/checkUrl.ts +16 -15
  442. package/src/compactSnapshotParser.ts +219 -103
  443. package/src/compactSnapshotWriter.ts +118 -97
  444. package/src/constants.ts +7 -0
  445. package/src/contracts.ts +96 -136
  446. package/src/contractsPublic.ts +31 -16
  447. package/src/createFile.ts +243 -305
  448. package/src/createNewContainerOnExistingFile.ts +93 -0
  449. package/src/createNewModule.ts +7 -0
  450. package/src/createNewUtils.ts +266 -56
  451. package/src/createOdspCreateContainerRequest.ts +22 -18
  452. package/src/createOdspUrl.ts +12 -13
  453. package/src/epochTracker.ts +596 -457
  454. package/src/fetch.ts +4 -4
  455. package/src/fetchSnapshot.ts +583 -508
  456. package/src/getFileLink.ts +194 -155
  457. package/src/getQueryString.ts +11 -9
  458. package/src/getUrlAndHeadersWithAuth.ts +34 -33
  459. package/src/index.ts +42 -18
  460. package/src/localOdspDriver/localOdspDeltaStorageService.ts +49 -0
  461. package/src/localOdspDriver/localOdspDocumentService.ts +40 -38
  462. package/src/localOdspDriver/localOdspDocumentServiceFactory.ts +46 -43
  463. package/src/localOdspDriver/localOdspDocumentStorageManager.ts +55 -50
  464. package/src/odspCache.ts +112 -90
  465. package/src/odspDelayLoadedDeltaStream.ts +459 -0
  466. package/src/odspDeltaStorageService.ts +232 -221
  467. package/src/odspDocumentDeltaConnection.ts +751 -563
  468. package/src/odspDocumentService.ts +324 -523
  469. package/src/odspDocumentServiceFactory.ts +20 -21
  470. package/src/odspDocumentServiceFactoryCore.ts +329 -200
  471. package/src/odspDocumentServiceFactoryWithCodeSplit.ts +20 -20
  472. package/src/odspDocumentStorageManager.ts +730 -534
  473. package/src/odspDocumentStorageServiceBase.ts +279 -254
  474. package/src/odspDriverUrlResolver.ts +230 -188
  475. package/src/odspDriverUrlResolverForShareLink.ts +223 -203
  476. package/src/odspError.ts +27 -19
  477. package/src/odspFluidFileLink.ts +106 -87
  478. package/src/odspLocationRedirection.ts +26 -0
  479. package/src/odspPublicUtils.ts +20 -14
  480. package/src/odspSnapshotParser.ts +53 -46
  481. package/src/odspSummaryUploadManager.ts +243 -218
  482. package/src/odspUrlHelper.ts +81 -71
  483. package/src/odspUtils.ts +401 -259
  484. package/src/opsCaching.ts +214 -193
  485. package/src/packageVersion.ts +1 -1
  486. package/src/prefetchLatestSnapshot.ts +142 -80
  487. package/src/retryErrorsStorageAdapter.ts +92 -77
  488. package/src/retryUtils.ts +80 -57
  489. package/src/socketModule.ts +8 -0
  490. package/src/vroom.ts +92 -83
  491. package/src/zipItDataRepresentationUtils.ts +534 -394
  492. package/tsc-multi.test.json +4 -0
  493. package/tsconfig.json +11 -13
  494. package/.editorconfig +0 -7
  495. package/dist/ReadBufferUtils.js.map +0 -1
  496. package/dist/WriteBufferUtils.js.map +0 -1
  497. package/dist/checkUrl.js.map +0 -1
  498. package/dist/compactSnapshotParser.js +0 -115
  499. package/dist/compactSnapshotParser.js.map +0 -1
  500. package/dist/compactSnapshotWriter.js.map +0 -1
  501. package/dist/constants.js.map +0 -1
  502. package/dist/contracts.js.map +0 -1
  503. package/dist/contractsPublic.js.map +0 -1
  504. package/dist/createFile.js +0 -242
  505. package/dist/createFile.js.map +0 -1
  506. package/dist/createNewUtils.js +0 -67
  507. package/dist/createNewUtils.js.map +0 -1
  508. package/dist/createOdspCreateContainerRequest.js.map +0 -1
  509. package/dist/createOdspUrl.js.map +0 -1
  510. package/dist/epochTracker.js.map +0 -1
  511. package/dist/fetch.js.map +0 -1
  512. package/dist/fetchSnapshot.js.map +0 -1
  513. package/dist/getFileLink.js.map +0 -1
  514. package/dist/getQueryString.js.map +0 -1
  515. package/dist/getSocketIo.d.ts +0 -11
  516. package/dist/getSocketIo.d.ts.map +0 -1
  517. package/dist/getSocketIo.js +0 -20
  518. package/dist/getSocketIo.js.map +0 -1
  519. package/dist/getUrlAndHeadersWithAuth.js.map +0 -1
  520. package/dist/index.js +0 -41
  521. package/dist/index.js.map +0 -1
  522. package/dist/localOdspDriver/localOdspDocumentService.js.map +0 -1
  523. package/dist/localOdspDriver/localOdspDocumentServiceFactory.js.map +0 -1
  524. package/dist/localOdspDriver/localOdspDocumentStorageManager.js.map +0 -1
  525. package/dist/odspCache.js.map +0 -1
  526. package/dist/odspDeltaStorageService.js.map +0 -1
  527. package/dist/odspDocumentDeltaConnection.js.map +0 -1
  528. package/dist/odspDocumentService.js +0 -364
  529. package/dist/odspDocumentService.js.map +0 -1
  530. package/dist/odspDocumentServiceFactory.js.map +0 -1
  531. package/dist/odspDocumentServiceFactoryCore.js +0 -118
  532. package/dist/odspDocumentServiceFactoryCore.js.map +0 -1
  533. package/dist/odspDocumentServiceFactoryWithCodeSplit.js +0 -34
  534. package/dist/odspDocumentServiceFactoryWithCodeSplit.js.map +0 -1
  535. package/dist/odspDocumentStorageManager.js +0 -356
  536. package/dist/odspDocumentStorageManager.js.map +0 -1
  537. package/dist/odspDocumentStorageServiceBase.js.map +0 -1
  538. package/dist/odspDriverUrlResolver.js.map +0 -1
  539. package/dist/odspDriverUrlResolverForShareLink.js.map +0 -1
  540. package/dist/odspError.js.map +0 -1
  541. package/dist/odspFluidFileLink.js.map +0 -1
  542. package/dist/odspPublicUtils.js.map +0 -1
  543. package/dist/odspSnapshotParser.js.map +0 -1
  544. package/dist/odspSummaryUploadManager.js.map +0 -1
  545. package/dist/odspUrlHelper.js.map +0 -1
  546. package/dist/odspUtils.js.map +0 -1
  547. package/dist/opsCaching.js.map +0 -1
  548. package/dist/packageVersion.js.map +0 -1
  549. package/dist/prefetchLatestSnapshot.js +0 -57
  550. package/dist/prefetchLatestSnapshot.js.map +0 -1
  551. package/dist/retryErrorsStorageAdapter.js.map +0 -1
  552. package/dist/retryUtils.js.map +0 -1
  553. package/dist/vroom.js.map +0 -1
  554. package/dist/zipItDataRepresentationUtils.js.map +0 -1
  555. package/lib/ReadBufferUtils.d.ts.map +0 -1
  556. package/lib/ReadBufferUtils.js.map +0 -1
  557. package/lib/WriteBufferUtils.d.ts.map +0 -1
  558. package/lib/WriteBufferUtils.js.map +0 -1
  559. package/lib/checkUrl.d.ts.map +0 -1
  560. package/lib/checkUrl.js.map +0 -1
  561. package/lib/compactSnapshotParser.d.ts +0 -15
  562. package/lib/compactSnapshotParser.d.ts.map +0 -1
  563. package/lib/compactSnapshotParser.js +0 -111
  564. package/lib/compactSnapshotParser.js.map +0 -1
  565. package/lib/compactSnapshotWriter.d.ts.map +0 -1
  566. package/lib/compactSnapshotWriter.js.map +0 -1
  567. package/lib/constants.d.ts.map +0 -1
  568. package/lib/constants.js.map +0 -1
  569. package/lib/contracts.d.ts.map +0 -1
  570. package/lib/contracts.js.map +0 -1
  571. package/lib/contractsPublic.d.ts.map +0 -1
  572. package/lib/contractsPublic.js.map +0 -1
  573. package/lib/createFile.d.ts +0 -22
  574. package/lib/createFile.d.ts.map +0 -1
  575. package/lib/createFile.js +0 -235
  576. package/lib/createFile.js.map +0 -1
  577. package/lib/createNewUtils.d.ts +0 -11
  578. package/lib/createNewUtils.d.ts.map +0 -1
  579. package/lib/createNewUtils.js +0 -63
  580. package/lib/createNewUtils.js.map +0 -1
  581. package/lib/createOdspCreateContainerRequest.d.ts.map +0 -1
  582. package/lib/createOdspCreateContainerRequest.js.map +0 -1
  583. package/lib/createOdspUrl.d.ts.map +0 -1
  584. package/lib/createOdspUrl.js.map +0 -1
  585. package/lib/epochTracker.d.ts.map +0 -1
  586. package/lib/epochTracker.js.map +0 -1
  587. package/lib/fetch.d.ts.map +0 -1
  588. package/lib/fetch.js.map +0 -1
  589. package/lib/fetchSnapshot.d.ts.map +0 -1
  590. package/lib/fetchSnapshot.js.map +0 -1
  591. package/lib/getFileLink.d.ts.map +0 -1
  592. package/lib/getFileLink.js.map +0 -1
  593. package/lib/getQueryString.d.ts.map +0 -1
  594. package/lib/getQueryString.js.map +0 -1
  595. package/lib/getSocketIo.d.ts +0 -11
  596. package/lib/getSocketIo.d.ts.map +0 -1
  597. package/lib/getSocketIo.js +0 -13
  598. package/lib/getSocketIo.js.map +0 -1
  599. package/lib/getUrlAndHeadersWithAuth.d.ts.map +0 -1
  600. package/lib/getUrlAndHeadersWithAuth.js.map +0 -1
  601. package/lib/index.d.ts +0 -21
  602. package/lib/index.d.ts.map +0 -1
  603. package/lib/index.js +0 -29
  604. package/lib/index.js.map +0 -1
  605. package/lib/localOdspDriver/localOdspDocumentService.d.ts.map +0 -1
  606. package/lib/localOdspDriver/localOdspDocumentService.js.map +0 -1
  607. package/lib/localOdspDriver/localOdspDocumentServiceFactory.d.ts.map +0 -1
  608. package/lib/localOdspDriver/localOdspDocumentServiceFactory.js.map +0 -1
  609. package/lib/localOdspDriver/localOdspDocumentStorageManager.d.ts.map +0 -1
  610. package/lib/localOdspDriver/localOdspDocumentStorageManager.js.map +0 -1
  611. package/lib/odspCache.d.ts.map +0 -1
  612. package/lib/odspCache.js.map +0 -1
  613. package/lib/odspDeltaStorageService.d.ts.map +0 -1
  614. package/lib/odspDeltaStorageService.js.map +0 -1
  615. package/lib/odspDocumentDeltaConnection.d.ts.map +0 -1
  616. package/lib/odspDocumentDeltaConnection.js.map +0 -1
  617. package/lib/odspDocumentService.d.ts.map +0 -1
  618. package/lib/odspDocumentService.js +0 -360
  619. package/lib/odspDocumentService.js.map +0 -1
  620. package/lib/odspDocumentServiceFactory.d.ts.map +0 -1
  621. package/lib/odspDocumentServiceFactory.js.map +0 -1
  622. package/lib/odspDocumentServiceFactoryCore.d.ts.map +0 -1
  623. package/lib/odspDocumentServiceFactoryCore.js +0 -114
  624. package/lib/odspDocumentServiceFactoryCore.js.map +0 -1
  625. package/lib/odspDocumentServiceFactoryWithCodeSplit.d.ts.map +0 -1
  626. package/lib/odspDocumentServiceFactoryWithCodeSplit.js.map +0 -1
  627. package/lib/odspDocumentStorageManager.d.ts.map +0 -1
  628. package/lib/odspDocumentStorageManager.js +0 -352
  629. package/lib/odspDocumentStorageManager.js.map +0 -1
  630. package/lib/odspDocumentStorageServiceBase.d.ts.map +0 -1
  631. package/lib/odspDocumentStorageServiceBase.js.map +0 -1
  632. package/lib/odspDriverUrlResolver.d.ts.map +0 -1
  633. package/lib/odspDriverUrlResolver.js.map +0 -1
  634. package/lib/odspDriverUrlResolverForShareLink.d.ts.map +0 -1
  635. package/lib/odspDriverUrlResolverForShareLink.js.map +0 -1
  636. package/lib/odspError.d.ts.map +0 -1
  637. package/lib/odspError.js.map +0 -1
  638. package/lib/odspFluidFileLink.d.ts.map +0 -1
  639. package/lib/odspFluidFileLink.js.map +0 -1
  640. package/lib/odspPublicUtils.d.ts.map +0 -1
  641. package/lib/odspPublicUtils.js.map +0 -1
  642. package/lib/odspSnapshotParser.d.ts.map +0 -1
  643. package/lib/odspSnapshotParser.js.map +0 -1
  644. package/lib/odspSummaryUploadManager.d.ts.map +0 -1
  645. package/lib/odspSummaryUploadManager.js.map +0 -1
  646. package/lib/odspUrlHelper.d.ts.map +0 -1
  647. package/lib/odspUrlHelper.js.map +0 -1
  648. package/lib/odspUtils.d.ts.map +0 -1
  649. package/lib/odspUtils.js.map +0 -1
  650. package/lib/opsCaching.d.ts.map +0 -1
  651. package/lib/opsCaching.js.map +0 -1
  652. package/lib/packageVersion.d.ts.map +0 -1
  653. package/lib/packageVersion.js.map +0 -1
  654. package/lib/prefetchLatestSnapshot.d.ts.map +0 -1
  655. package/lib/prefetchLatestSnapshot.js +0 -53
  656. package/lib/prefetchLatestSnapshot.js.map +0 -1
  657. package/lib/retryErrorsStorageAdapter.d.ts.map +0 -1
  658. package/lib/retryErrorsStorageAdapter.js.map +0 -1
  659. package/lib/retryUtils.d.ts.map +0 -1
  660. package/lib/retryUtils.js.map +0 -1
  661. package/lib/vroom.d.ts.map +0 -1
  662. package/lib/vroom.js.map +0 -1
  663. package/lib/zipItDataRepresentationUtils.d.ts.map +0 -1
  664. package/lib/zipItDataRepresentationUtils.js.map +0 -1
  665. package/src/getSocketIo.ts +0 -14
  666. package/tsconfig.esnext.json +0 -7
@@ -3,597 +3,785 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { ITelemetryLogger, IEvent } from "@fluidframework/common-definitions";
7
- import { assert, performance, Deferred, TypedEventEmitter } from "@fluidframework/common-utils";
6
+ import { IEvent } from "@fluidframework/core-interfaces";
7
+ import {
8
+ ITelemetryLoggerExt,
9
+ IFluidErrorBase,
10
+ loggerToMonitoringContext,
11
+ } from "@fluidframework/telemetry-utils";
12
+ import { performance, TypedEventEmitter } from "@fluid-internal/client-utils";
13
+ import { assert, Deferred } from "@fluidframework/core-utils";
8
14
  import { DocumentDeltaConnection } from "@fluidframework/driver-base";
15
+ import { IAnyDriverError } from "@fluidframework/driver-definitions";
9
16
  import { OdspError } from "@fluidframework/odsp-driver-definitions";
10
- import { IAnyDriverError } from "@fluidframework/driver-utils";
11
- import { IFluidErrorBase, loggerToMonitoringContext } from "@fluidframework/telemetry-utils";
12
17
  import {
13
- IClient,
14
- IConnect,
15
- INack,
16
- ISequencedDocumentMessage,
17
- ISignalMessage,
18
+ IClient,
19
+ IConnect,
20
+ IDocumentMessage,
21
+ INack,
22
+ ISentSignalMessage,
23
+ ISequencedDocumentMessage,
24
+ ISignalMessage,
18
25
  } from "@fluidframework/protocol-definitions";
19
- import type { Socket, io as SocketIOClientStatic } from "socket.io-client";
26
+ import { Socket } from "socket.io-client";
20
27
  import { v4 as uuid } from "uuid";
28
+ import { createGenericNetworkError } from "@fluidframework/driver-utils";
21
29
  import { IOdspSocketError, IGetOpsResponse, IFlushOpsResponse } from "./contracts";
22
30
  import { EpochTracker } from "./epochTracker";
23
31
  import { errorObjectFromSocketError } from "./odspError";
32
+ import { SocketIOClientStatic } from "./socketModule";
24
33
  import { pkgVersion } from "./packageVersion";
25
34
 
26
35
  const protocolVersions = ["^0.4.0", "^0.3.0", "^0.2.0", "^0.1.0"];
27
36
  const feature_get_ops = "api_get_ops";
28
37
  const feature_flush_ops = "api_flush_ops";
38
+ const feature_submit_signals_v2 = "submit_signals_v2";
29
39
 
30
40
  export interface FlushResult {
31
- lastPersistedSequenceNumber?: number;
32
- retryAfter?: number;
41
+ lastPersistedSequenceNumber?: number;
42
+ retryAfter?: number;
33
43
  }
34
44
 
35
45
  // How long to wait before disconnecting the socket after the last reference is removed
36
46
  // This allows reconnection after receiving a nack to be smooth
37
47
  const socketReferenceBufferTime = 2000;
38
48
 
39
- export interface ISocketEvents extends IEvent {
40
- (event: "server_disconnect", listener: (error: IFluidErrorBase & OdspError) => void);
49
+ interface ISocketEvents extends IEvent {
50
+ (
51
+ event: "disconnect",
52
+ listener: (error: IFluidErrorBase & OdspError, clientId?: string) => void,
53
+ );
41
54
  }
42
55
 
43
56
  class SocketReference extends TypedEventEmitter<ISocketEvents> {
44
- private references: number = 1;
45
- private delayDeleteTimeout: ReturnType<typeof setTimeout> | undefined;
46
- private _socket: Socket | undefined;
47
-
48
- // When making decisions about socket reuse, we do not reuse disconnected socket.
49
- // But we want to differentiate the following case from disconnected case:
50
- // Socket that never connected and never failed, it's in "attempting to connect" mode
51
- // such sockets should be reused, despite socket.disconnected === true
52
- private isPendingInitialConnection = true;
53
-
54
- // Map of all existing socket io sockets. [url, tenantId, documentId] -> socket
55
- private static readonly socketIoSockets: Map<string, SocketReference> = new Map();
56
-
57
- public static find(key: string, logger: ITelemetryLogger) {
58
- const socketReference = SocketReference.socketIoSockets.get(key);
59
-
60
- // Verify the socket is healthy before reusing it
61
- if (socketReference?.disconnected) {
62
- // The socket is in a bad state. fully remove the reference
63
- socketReference.closeSocket();
64
- return undefined;
65
- }
66
-
67
- if (socketReference) {
68
- // Clear the pending deletion if there is one
69
- socketReference.clearTimer();
70
- socketReference.references++;
71
- }
72
-
73
- return socketReference;
74
- }
75
-
76
- /**
77
- * Removes a reference for the given key
78
- * Once the ref count hits 0, the socket is disconnected and removed
79
- * @param key - socket reference key
80
- * @param isFatalError - true if the socket reference should be removed immediately due to a fatal error
81
- */
82
- public removeSocketIoReference(isFatalError: boolean) {
83
- assert(this.references > 0, 0x09f /* "No more socketIO refs to remove!" */);
84
- this.references--;
85
-
86
- // see comment in disconnected() getter
87
- this.isPendingInitialConnection = false;
88
-
89
- if (isFatalError || this.disconnected) {
90
- this.closeSocket();
91
- return;
92
- }
93
-
94
- if (this.references === 0 && this.delayDeleteTimeout === undefined) {
95
- this.delayDeleteTimeout = setTimeout(() => {
96
- // We should not get here with active users.
97
- assert(this.references === 0, 0x0a0 /* "Unexpected socketIO references on timeout" */);
98
- this.closeSocket();
99
- }, socketReferenceBufferTime);
100
- }
101
- }
102
-
103
- public get socket() {
104
- if (!this._socket) {
105
- throw new Error(`Invalid socket for key "${this.key}`);
106
- }
107
- return this._socket;
108
- }
109
-
110
- public constructor(public readonly key: string, socket: Socket) {
111
- super();
112
-
113
- this._socket = socket;
114
- assert(!SocketReference.socketIoSockets.has(key), 0x220 /* "socket key collision" */);
115
- SocketReference.socketIoSockets.set(key, this);
116
-
117
- // The server always closes the socket after sending this message
118
- // fully remove the socket reference now
119
- socket.on("server_disconnect", (socketError: IOdspSocketError) => {
120
- // Treat all errors as recoverable, and rely on joinSession / reconnection flow to
121
- // filter out retryable vs. non-retryable cases.
122
- const error = errorObjectFromSocketError(socketError, "server_disconnect");
123
- error.canRetry = true;
124
-
125
- // see comment in disconnected() getter
126
- // Setting it here to ensure socket reuse does not happen if new request to connect
127
- // comes in from "disconnect" listener below, before we close socket.
128
- this.isPendingInitialConnection = false;
129
-
130
- // Explicitly cast error to the specified event args type to ensure type compatibility
131
- this.emit("server_disconnect", error);
132
- this.closeSocket();
133
- });
134
- }
135
-
136
- private clearTimer() {
137
- if (this.delayDeleteTimeout !== undefined) {
138
- clearTimeout(this.delayDeleteTimeout);
139
- this.delayDeleteTimeout = undefined;
140
- }
141
- }
142
-
143
- private closeSocket() {
144
- if (!this._socket) { return; }
145
-
146
- this.clearTimer();
147
-
148
- assert(SocketReference.socketIoSockets.get(this.key) === this,
149
- 0x0a1 /* "Socket reference set unexpectedly does not point to this socket!" */);
150
- SocketReference.socketIoSockets.delete(this.key);
151
-
152
- const socket = this._socket;
153
- this._socket = undefined;
154
-
155
- // Delay closing socket, to make sure all users of socket observe the same event that causes
156
- // this instance to close, and thus properly record reason for closure.
157
- // All event raising is synchronous, so clients will have a chance to react before socket is
158
- // closed without any extra data on why it was closed.
159
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
160
- Promise.resolve().then(() => { socket.disconnect(); });
161
- }
162
-
163
- private get disconnected() {
164
- if (this._socket === undefined) { return true; }
165
- if (this.socket.connected) { return false; }
166
-
167
- // We have a socket that is not connected. Possible cases:
168
- // 1) It was connected some time ago and lost connection. We do not want to reuse it.
169
- // 2) It failed to connect (was never connected).
170
- // 3) It was just created and never had a chance to connect - connection is in process.
171
- // We have to differentiate 1 from 2-3 (specifically 1 & 3) in order to be able to reuse socket in #3.
172
- // We will use the fact that socket had some activity. I.e. if socket disconnected, or client stopped using
173
- // socket, then removeSocketIoReference() will be called for it, and it will be the indiction that it's not #3.
174
- return !this.isPendingInitialConnection;
175
- }
57
+ private references: number = 1;
58
+ private delayDeleteTimeout: ReturnType<typeof setTimeout> | undefined;
59
+ private _socket: Socket | undefined;
60
+
61
+ // When making decisions about socket reuse, we do not reuse disconnected socket.
62
+ // But we want to differentiate the following case from disconnected case:
63
+ // Socket that never connected and never failed, it's in "attempting to connect" mode
64
+ // such sockets should be reused, despite socket.disconnected === true
65
+ private isPendingInitialConnection = true;
66
+
67
+ // Map of all existing socket io sockets. [url, tenantId, documentId] -> socket
68
+ private static readonly socketIoSockets: Map<string, SocketReference> = new Map();
69
+
70
+ public static find(key: string, logger: ITelemetryLoggerExt) {
71
+ const socketReference = SocketReference.socketIoSockets.get(key);
72
+
73
+ // Verify the socket is healthy before reusing it
74
+ if (socketReference?.disconnected) {
75
+ // The socket is in a bad state. fully remove the reference
76
+ socketReference.closeSocket();
77
+ return undefined;
78
+ }
79
+
80
+ if (socketReference) {
81
+ // Clear the pending deletion if there is one
82
+ socketReference.clearTimer();
83
+ socketReference.references++;
84
+ }
85
+
86
+ return socketReference;
87
+ }
88
+
89
+ /**
90
+ * Removes a reference for the given key
91
+ * Once the ref count hits 0, the socket is disconnected and removed
92
+ */
93
+ public removeSocketIoReference() {
94
+ assert(this.references > 0, 0x09f /* "No more socketIO refs to remove!" */);
95
+ this.references--;
96
+
97
+ // see comment in disconnected() getter
98
+ this.isPendingInitialConnection = false;
99
+
100
+ if (this.disconnected) {
101
+ this.closeSocket();
102
+ return;
103
+ }
104
+
105
+ if (this.references === 0 && this.delayDeleteTimeout === undefined) {
106
+ this.delayDeleteTimeout = setTimeout(() => {
107
+ // We should not get here with active users.
108
+ assert(
109
+ this.references === 0,
110
+ 0x0a0 /* "Unexpected socketIO references on timeout" */,
111
+ );
112
+ this.closeSocket();
113
+ }, socketReferenceBufferTime);
114
+ }
115
+ }
116
+
117
+ public get socket() {
118
+ if (!this._socket) {
119
+ throw new Error(`Invalid socket for key "${this.key}`);
120
+ }
121
+ return this._socket;
122
+ }
123
+
124
+ public constructor(
125
+ public readonly key: string,
126
+ socket: Socket,
127
+ ) {
128
+ super();
129
+
130
+ this._socket = socket;
131
+ assert(!SocketReference.socketIoSockets.has(key), 0x220 /* "socket key collision" */);
132
+ SocketReference.socketIoSockets.set(key, this);
133
+
134
+ // Server sends this event when it wants to disconnect a particular client in which case the client id would
135
+ // be present or if it wants to disconnect all the clients. The server always closes the socket in case all
136
+ // clients needs to be disconnected. So fully remove the socket reference in this case.
137
+ socket.on("server_disconnect", this.serverDisconnectEventHandler);
138
+ }
139
+
140
+ private readonly serverDisconnectEventHandler = (
141
+ socketError: IOdspSocketError,
142
+ clientId?: string,
143
+ ) => {
144
+ // Treat all errors as recoverable, and rely on joinSession / reconnection flow to
145
+ // filter out retryable vs. non-retryable cases.
146
+ const error = errorObjectFromSocketError(socketError, "server_disconnect");
147
+ error.addTelemetryProperties({ disconnectClientId: clientId });
148
+ error.canRetry = true;
149
+
150
+ // see comment in disconnected() getter
151
+ // Setting it here to ensure socket reuse does not happen if new request to connect
152
+ // comes in from "disconnect" listener below, before we close socket.
153
+ this.isPendingInitialConnection = false;
154
+
155
+ if (clientId === undefined) {
156
+ // We could first raise "disconnect" event, but that may result in socket reuse due to
157
+ // new connection comming in. So, it's better to have more explicit flow to make it impossible.
158
+ this.closeSocket(error);
159
+ } else {
160
+ this.emit("disconnect", error, clientId);
161
+ }
162
+ };
163
+
164
+ private clearTimer() {
165
+ if (this.delayDeleteTimeout !== undefined) {
166
+ clearTimeout(this.delayDeleteTimeout);
167
+ this.delayDeleteTimeout = undefined;
168
+ }
169
+ }
170
+
171
+ public closeSocket(error?: IAnyDriverError) {
172
+ if (!this._socket) {
173
+ return;
174
+ }
175
+
176
+ this._socket.off("server_disconnect", this.serverDisconnectEventHandler);
177
+ this.clearTimer();
178
+
179
+ assert(
180
+ SocketReference.socketIoSockets.get(this.key) === this,
181
+ 0x0a1 /* "Socket reference set unexpectedly does not point to this socket!" */,
182
+ );
183
+
184
+ // First, remove socket to ensure no socket reuse is possible.
185
+ SocketReference.socketIoSockets.delete(this.key);
186
+
187
+ // Block access to socket. From now on, calls like flush() or requestOps()
188
+ // Disconnect flow should be synchronous and result in system fully forgetting about this connection / socket.
189
+ const socket = this._socket;
190
+ this._socket = undefined;
191
+
192
+ // Let all connections know they need to go through disconnect flow.
193
+ this.emit(
194
+ "disconnect",
195
+ error ??
196
+ createGenericNetworkError(
197
+ "Socket closed without error",
198
+ { canRetry: true },
199
+ { driverVersion: pkgVersion },
200
+ ),
201
+ undefined /* clientId */,
202
+ );
203
+
204
+ // We should not have any users now, assuming synchronous disconnect flow in response to
205
+ // "disconnect" event
206
+ assert(
207
+ this.references === 0,
208
+ 0x412 /* Nobody should be connected to this socket at this point! */,
209
+ );
210
+
211
+ socket.disconnect();
212
+ }
213
+
214
+ public get disconnected() {
215
+ if (this._socket === undefined) {
216
+ return true;
217
+ }
218
+ if (this.socket.connected) {
219
+ return false;
220
+ }
221
+
222
+ // We have a socket that is not connected. Possible cases:
223
+ // 1) It was connected some time ago and lost connection. We do not want to reuse it.
224
+ // 2) It failed to connect (was never connected).
225
+ // 3) It was just created and never had a chance to connect - connection is in process.
226
+ // We have to differentiate 1 from 2-3 (specifically 1 & 3) in order to be able to reuse socket in #3.
227
+ // We will use the fact that socket had some activity. I.e. if socket disconnected, or client stopped using
228
+ // socket, then removeSocketIoReference() will be called for it, and it will be the indiction that it's not #3.
229
+ return !this.isPendingInitialConnection;
230
+ }
176
231
  }
177
232
 
178
233
  /**
179
234
  * Represents a connection to a stream of delta updates
180
235
  */
181
236
  export class OdspDocumentDeltaConnection extends DocumentDeltaConnection {
182
- /**
183
- * Create a OdspDocumentDeltaConnection
184
- * If url #1 fails to connect, will try url #2 if applicable.
185
- *
186
- * @param tenantId - the ID of the tenant
187
- * @param documentId - document ID
188
- * @param token - authorization token for storage service
189
- * @param io - websocket library
190
- * @param client - information about the client
191
- * @param mode - mode of the client
192
- * @param url - websocket URL
193
- * @param telemetryLogger - optional telemetry logger
194
- * @param timeoutMs - time limit on making the connection
195
- * @param epochTracker - track epoch changes
196
- * @param socketReferenceKeyPrefix - (optional) prefix to isolate socket reuse cache
197
- */
198
- public static async create(
199
- tenantId: string,
200
- documentId: string,
201
- token: string | null,
202
- io: typeof SocketIOClientStatic,
203
- client: IClient,
204
- url: string,
205
- telemetryLogger: ITelemetryLogger,
206
- timeoutMs: number,
207
- epochTracker: EpochTracker,
208
- socketReferenceKeyPrefix: string | undefined): Promise<OdspDocumentDeltaConnection> {
209
- const mc = loggerToMonitoringContext(telemetryLogger);
210
-
211
- // enable multiplexing when the websocket url does not include the tenant/document id
212
- const parsedUrl = new URL(url);
213
- const enableMultiplexing = !parsedUrl.searchParams.has("documentId") && !parsedUrl.searchParams.has("tenantId");
214
-
215
- // do not include the specific tenant/doc id in the ref key when multiplexing
216
- // this will allow multiple documents to share the same websocket connection
217
- const key = socketReferenceKeyPrefix ? `${socketReferenceKeyPrefix},${url}` : url;
218
- const socketReferenceKey = enableMultiplexing ? key : `${key},${tenantId},${documentId}`;
219
-
220
- const socketReference = OdspDocumentDeltaConnection.getOrCreateSocketIoReference(
221
- io, timeoutMs, socketReferenceKey, url, enableMultiplexing, tenantId, documentId, telemetryLogger);
222
-
223
- const socket = socketReference.socket;
224
-
225
- const connectMessage: IConnect = {
226
- client,
227
- id: documentId,
228
- mode: client.mode,
229
- tenantId,
230
- token, // Token is going to indicate tenant level information, etc...
231
- versions: protocolVersions,
232
- nonce: uuid(),
233
- epoch: epochTracker.fluidEpoch,
234
- relayUserAgent: [client.details.environment, ` driverVersion:${pkgVersion}`].join(";"),
235
- };
236
-
237
- // Reference to this client supporting get_ops flow.
238
- connectMessage.supportedFeatures = { };
239
- if (mc.config.getBoolean("Fluid.Driver.Odsp.GetOpsEnabled") !== false) {
240
- connectMessage.supportedFeatures[feature_get_ops] = true;
241
- }
242
-
243
- const deltaConnection = new OdspDocumentDeltaConnection(
244
- socket,
245
- documentId,
246
- socketReference,
247
- telemetryLogger,
248
- enableMultiplexing);
249
-
250
- try {
251
- await deltaConnection.initialize(connectMessage, timeoutMs);
252
- await epochTracker.validateEpochFromPush(deltaConnection.details);
253
- } catch (errorObject: any) {
254
- if (errorObject !== null && typeof errorObject === "object") {
255
- // We have to special-case error types here in terms of what is re-triable.
256
- // These errors have to re-retried, we just need new joinSession result to connect to right server:
257
- // 400: Invalid tenant or document id. The WebSocket is connected to a different document
258
- // Document is full (with retryAfter)
259
- // 404: Invalid document. The document \"local/w1-...\" does not exist
260
- // But this has to stay not-retriable:
261
- // 406: Unsupported client protocol. This path is the only gatekeeper, have to fail!
262
- // 409: Epoch Version Mismatch. Client epoch and server epoch does not match, so app needs
263
- // to be refreshed.
264
- // This one is fine either way
265
- // 401/403: Code will retry once with new token either way, then it becomes fatal - on this path
266
- // and on join Session path.
267
- // 501: (Fluid not enabled): this is fine either way, as joinSession is gatekeeper
268
- if (errorObject.statusCode === 400 || errorObject.statusCode === 404) {
269
- errorObject.canRetry = true;
270
- }
271
- }
272
- throw errorObject;
273
- }
274
-
275
- return deltaConnection;
276
- }
277
-
278
- private socketReference: SocketReference | undefined;
279
-
280
- private readonly requestOpsNoncePrefix: string;
281
- private pushCallCounter = 0;
282
- private readonly getOpsMap: Map<string, { start: number; from: number; to: number; }> = new Map();
283
- private flushOpNonce: string | undefined;
284
- private flushDeferred: Deferred<FlushResult> | undefined;
285
-
286
- /**
287
- * Error raising for socket.io issues
288
- */
289
- protected createErrorObject(handler: string, error?: any, canRetry = true): IAnyDriverError {
290
- // Note: we suspect the incoming error object is either:
291
- // - a socketError: add it to the OdspError object for driver to be able to parse it and reason over it.
292
- // - anything else: let base class handle it
293
- if (canRetry && Number.isInteger(error?.code) && typeof error?.message === "string") {
294
- return errorObjectFromSocketError(error as IOdspSocketError, handler);
295
- } else {
296
- return super.createErrorObject(handler, error, canRetry);
297
- }
298
- }
299
-
300
- /**
301
- * Gets or create a socket io connection for the given key
302
- */
303
- private static getOrCreateSocketIoReference(
304
- io: typeof SocketIOClientStatic,
305
- timeoutMs: number,
306
- key: string,
307
- url: string,
308
- enableMultiplexing: boolean,
309
- tenantId: string,
310
- documentId: string,
311
- logger: ITelemetryLogger,
312
- ): SocketReference {
313
- const existingSocketReference = SocketReference.find(key, logger);
314
- if (existingSocketReference) {
315
- return existingSocketReference;
316
- }
317
-
318
- const query = enableMultiplexing ? undefined : { documentId, tenantId };
319
-
320
- const socket = io(
321
- url,
322
- {
323
- multiplex: false, // Don't rely on socket.io built-in multiplexing
324
- query,
325
- reconnection: false,
326
- transports: ["websocket"],
327
- timeout: timeoutMs,
328
- });
329
-
330
- return new SocketReference(key, socket);
331
- }
332
-
333
- /**
334
- * @param socket - websocket to be used
335
- * @param documentId - ID of the document
336
- * @param details - details of the websocket connection
337
- * @param socketReferenceKey - socket reference key
338
- * @param enableMultiplexing - If the websocket is multiplexing multiple documents
339
- */
340
- private constructor(
341
- socket: Socket,
342
- documentId: string,
343
- socketReference: SocketReference,
344
- logger: ITelemetryLogger,
345
- private readonly enableMultiplexing?: boolean,
346
- ) {
347
- super(socket, documentId, logger);
348
- this.socketReference = socketReference;
349
- this.requestOpsNoncePrefix = `${uuid()}-`;
350
- }
351
-
352
- /**
353
- * Retrieves ops from PUSH
354
- * @param from - inclusive
355
- * @param to - exclusive
356
- * @returns ops retrieved
357
- */
358
- public requestOps(from: number, to: number) {
359
- // Given that to is exclusive, we should be asking for at least something!
360
- assert(to > from, 0x272 /* "empty request" */);
361
-
362
- // PUSH may disable this functionality
363
- // back-compat: remove cast to any once latest version of IConnected is consumed
364
- if ((this.details as any).supportedFeatures?.[feature_get_ops] !== true) {
365
- return;
366
- }
367
-
368
- this.pushCallCounter++;
369
- const nonce = `${this.requestOpsNoncePrefix}${this.pushCallCounter}`;
370
- const start = performance.now();
371
-
372
- // We may keep keep accumulating memory for nothing, if we are not getting responses.
373
- // Note that we should not have overlapping requests, as DeltaManager allows only one
374
- // outstanding request to storage, and that's the only way to get here.
375
- // But requests could be cancelled, and thus overlapping requests might be in the picture
376
- // If it happens, we do not care about stale requests.
377
- // So track some number of requests, but log if we get too many in flight - that likely
378
- // indicates an error somewhere.
379
- if (this.getOpsMap.size >= 5) {
380
- let time = start;
381
- let key: string | undefined;
382
- for (const [keyCandidate, value] of this.getOpsMap.entries()) {
383
- if (value.start <= time || key === undefined) {
384
- time = value.start;
385
- key = keyCandidate;
386
- }
387
- }
388
- const payloadToDelete = this.getOpsMap.get(key!)!;
389
- this.logger.sendErrorEvent({
390
- eventName: "GetOpsTooMany",
391
- nonce,
392
- from: payloadToDelete.from,
393
- to: payloadToDelete.to,
394
- length: payloadToDelete.to - payloadToDelete.from,
395
- duration: performance.now() - payloadToDelete.start,
396
- });
397
- this.getOpsMap.delete(key!);
398
- }
399
- this.getOpsMap.set(
400
- nonce,
401
- {
402
- start,
403
- from,
404
- to,
405
- },
406
- );
407
- this.socket.emit("get_ops", this.clientId, {
408
- nonce,
409
- from,
410
- to: to - 1,
411
- });
412
- }
413
-
414
- public async flush(): Promise<FlushResult> {
415
- // back-compat: remove cast to any once latest version of IConnected is consumed
416
- if ((this.details as any).supportedFeatures?.[feature_flush_ops] !== true) {
417
- // Once single-commit summary is enabled end-to-end, flush support is a must!
418
- // The only alternative is change in design where SPO fetches ops from PUSH OR
419
- // summary includes required ops and SPO has some validation mechanism to ensure
420
- // they are not forged by client.
421
- // If design changes, we can reconsider it, but right now it's non-recoverable failure.
422
- this.logger.sendErrorEvent({ eventName: "FlushOpsNotSupported" });
423
- throw new Error("flush() API is not supported by PUSH, required for single-commit summaries");
424
- }
425
-
426
- this.pushCallCounter++;
427
- const nonce = `${this.requestOpsNoncePrefix}${this.pushCallCounter}`;
428
- // There should be only one flush ops in flight, kicked out by upload summary workflow
429
- // That said, it could timeout and request could be repeated, so theoretically we can
430
- // get overlapping requests, but it should be very rare
431
- if (this.flushDeferred !== undefined) {
432
- this.logger.sendErrorEvent({ eventName: "FlushOpsTooMany" });
433
- this.flushDeferred.reject("process involving flush() was cancelled OR unsupported concurrency");
434
- }
435
- this.socket.emit("flush_ops", this.clientId, { nonce });
436
-
437
- this.flushOpNonce = nonce;
438
- this.flushDeferred = new Deferred<FlushResult>();
439
- return this.flushDeferred.promise;
440
- }
441
-
442
- protected serverDisconnectHandler = (error: IFluidErrorBase & OdspError) => {
443
- this.logger.sendTelemetryEvent({ eventName: "ServerDisconnect", clientId: this.clientId }, error);
444
- this.disposeCore(true, error);
445
- };
446
-
447
- protected async initialize(connectMessage: IConnect, timeout: number) {
448
- if (this.enableMultiplexing) {
449
- // multiplex compatible early handlers
450
- this.earlyOpHandler = (messageDocumentId: string, msgs: ISequencedDocumentMessage[]) => {
451
- if (this.documentId === messageDocumentId) {
452
- this.queuedMessages.push(...msgs);
453
- }
454
- };
455
-
456
- this.earlySignalHandler = (msg: ISignalMessage, messageDocumentId?: string) => {
457
- if (messageDocumentId === undefined || messageDocumentId === this.documentId) {
458
- this.queuedSignals.push(msg);
459
- }
460
- };
461
- }
462
-
463
- this.socketReference!.on("server_disconnect", this.serverDisconnectHandler);
464
-
465
- this.socket.on("get_ops_response", (result: IGetOpsResponse) => {
466
- const messages = result.messages;
467
- const data = this.getOpsMap.get(result.nonce);
468
- // Due to socket multiplexing, this client may not have asked for any data
469
- // If so, there it most likely does not need these ops (otherwise it already asked for them)
470
- // Also we may have deleted entry in this.getOpsMap due to too many requests and too slow response.
471
- // But not processing such result may push us into infinite loop of fast requests and dropping all responses
472
- if (data !== undefined || result.nonce.indexOf(this.requestOpsNoncePrefix) === 0) {
473
- this.getOpsMap.delete(result.nonce);
474
- const common = {
475
- eventName: "GetOps",
476
- // We need nonce only to pair with GetOpsTooMany events, i.e. when record was deleted
477
- nonce: data === undefined ? result.nonce : undefined,
478
- code: result.code,
479
- from: data?.from,
480
- to: data?.to,
481
- duration: data === undefined ? undefined : performance.now() - data.start,
482
- };
483
- if (messages !== undefined && messages.length > 0) {
484
- this.logger.sendPerformanceEvent({
485
- ...common,
486
- first: messages[0].sequenceNumber,
487
- last: messages[messages.length - 1].sequenceNumber,
488
- length: messages.length,
489
- });
490
- this.emit("op", this.documentId, messages);
491
- } else {
492
- this.logger.sendPerformanceEvent({
493
- ...common,
494
- length: 0,
495
- });
496
- }
497
- }
498
- });
499
-
500
- this.socket.on("flush_ops_response", (result: IFlushOpsResponse) => {
501
- if (this.flushOpNonce === result.nonce) {
502
- const seq = result.lastPersistedSequenceNumber;
503
- let category: "generic" | "error" = "generic";
504
- if (result.lastPersistedSequenceNumber === undefined || result.code !== 200) {
505
- switch (result.code) {
506
- case 409:
507
- case 429:
508
- category = "error";
509
- break;
510
- case 204:
511
- break;
512
- default:
513
- category = "error";
514
- break;
515
- }
516
- }
517
- this.logger.sendTelemetryEvent({
518
- eventName: "FlushResult",
519
- code: result.code,
520
- sequenceNumber: seq,
521
- category,
522
- });
523
- this.flushDeferred!.resolve(result);
524
- this.flushDeferred = undefined;
525
- this.flushOpNonce = undefined;
526
- }
527
- });
528
-
529
- await super.initialize(connectMessage, timeout);
530
- }
531
-
532
- protected addTrackedListener(event: string, listener: (...args: any[]) => void) {
533
- // override some event listeners in order to support multiple documents/clients over the same websocket
534
- switch (event) {
535
- case "op":
536
- // per document op handling
537
- super.addTrackedListener(event, (documentId: string, msgs: ISequencedDocumentMessage[]) => {
538
- if (!this.enableMultiplexing || this.documentId === documentId) {
539
- listener(documentId, msgs);
540
- }
541
- });
542
- break;
543
-
544
- case "signal":
545
- // per document signal handling
546
- super.addTrackedListener(event, (msg: ISignalMessage, documentId?: string) => {
547
- if (!this.enableMultiplexing || !documentId || documentId === this.documentId) {
548
- listener(msg, documentId);
549
- }
550
- });
551
- break;
552
-
553
- case "nack":
554
- // per client / document nack handling
555
- super.addTrackedListener(event, (clientIdOrDocumentId: string, nacks: INack[]) => {
556
- const handle = clientIdOrDocumentId.length === 0 ||
557
- clientIdOrDocumentId === this.documentId ||
558
- (clientIdOrDocumentId === this.clientId);
559
- const { code, type, message, retryAfter } = nacks[0]?.content ?? {};
560
- this.logger.sendTelemetryEvent({
561
- eventName: "ServerNack",
562
- code,
563
- type,
564
- message,
565
- retryAfterSeconds: retryAfter,
566
- clientId: this.clientId,
567
- handle,
568
- });
569
- if (handle) {
570
- this.emit("nack", clientIdOrDocumentId, nacks);
571
- }
572
- });
573
- break;
574
-
575
- default:
576
- super.addTrackedListener(event, listener);
577
- break;
578
- }
579
- }
580
-
581
- /**
582
- * Disconnect from the websocket
583
- */
584
- protected disconnect(socketProtocolError: boolean, reason: IAnyDriverError) {
585
- const socket = this.socketReference;
586
- assert(socket !== undefined, 0x0a2 /* "reentrancy not supported!" */);
587
-
588
- this.socketReference?.off("server_disconnect", this.serverDisconnectHandler);
589
- this.socketReference = undefined;
590
-
591
- if (!socketProtocolError && this.hasDetails) {
592
- // tell the server we are disconnecting this client from the document
593
- this.socket.emit("disconnect_document", this.clientId, this.documentId);
594
- }
595
-
596
- socket.removeSocketIoReference(socketProtocolError);
597
- this.emit("disconnect", reason);
598
- }
237
+ /**
238
+ * Create a OdspDocumentDeltaConnection
239
+ * If url #1 fails to connect, will try url #2 if applicable.
240
+ *
241
+ * @param tenantId - the ID of the tenant
242
+ * @param documentId - document ID
243
+ * @param token - authorization token for storage service
244
+ * @param client - information about the client
245
+ * @param mode - mode of the client
246
+ * @param url - websocket URL
247
+ * @param telemetryLogger - optional telemetry logger
248
+ * @param timeoutMs - time limit on making the connection
249
+ * @param epochTracker - track epoch changes
250
+ * @param socketReferenceKeyPrefix - (optional) prefix to isolate socket reuse cache
251
+ */
252
+ public static async create(
253
+ tenantId: string,
254
+ documentId: string,
255
+ // eslint-disable-next-line @rushstack/no-new-null
256
+ token: string | null,
257
+ client: IClient,
258
+ url: string,
259
+ telemetryLogger: ITelemetryLoggerExt,
260
+ timeoutMs: number,
261
+ epochTracker: EpochTracker,
262
+ socketReferenceKeyPrefix: string | undefined,
263
+ ): Promise<OdspDocumentDeltaConnection> {
264
+ const mc = loggerToMonitoringContext(telemetryLogger);
265
+
266
+ // enable multiplexing when the websocket url does not include the tenant/document id
267
+ const parsedUrl = new URL(url);
268
+ const enableMultiplexing =
269
+ !parsedUrl.searchParams.has("documentId") && !parsedUrl.searchParams.has("tenantId");
270
+
271
+ // do not include the specific tenant/doc id in the ref key when multiplexing
272
+ // this will allow multiple documents to share the same websocket connection
273
+ const key = socketReferenceKeyPrefix ? `${socketReferenceKeyPrefix},${url}` : url;
274
+ const socketReferenceKey = enableMultiplexing ? key : `${key},${tenantId},${documentId}`;
275
+
276
+ const socketReference = OdspDocumentDeltaConnection.getOrCreateSocketIoReference(
277
+ timeoutMs,
278
+ socketReferenceKey,
279
+ url,
280
+ enableMultiplexing,
281
+ tenantId,
282
+ documentId,
283
+ telemetryLogger,
284
+ );
285
+
286
+ const socket = socketReference.socket;
287
+ const connectionId = uuid();
288
+ const connectMessage: IConnect = {
289
+ client,
290
+ id: documentId,
291
+ mode: client.mode,
292
+ tenantId,
293
+ token, // Token is going to indicate tenant level information, etc...
294
+ versions: protocolVersions,
295
+ driverVersion: pkgVersion,
296
+ nonce: connectionId,
297
+ epoch: epochTracker.fluidEpoch,
298
+ relayUserAgent: [client.details.environment, ` driverVersion:${pkgVersion}`].join(";"),
299
+ };
300
+
301
+ connectMessage.supportedFeatures = {
302
+ [feature_submit_signals_v2]: true,
303
+ };
304
+
305
+ // Reference to this client supporting get_ops flow.
306
+ if (mc.config.getBoolean("Fluid.Driver.Odsp.GetOpsEnabled") !== false) {
307
+ connectMessage.supportedFeatures[feature_get_ops] = true;
308
+ }
309
+
310
+ const deltaConnection = new OdspDocumentDeltaConnection(
311
+ socket,
312
+ documentId,
313
+ socketReference,
314
+ telemetryLogger,
315
+ enableMultiplexing,
316
+ connectionId,
317
+ );
318
+
319
+ try {
320
+ await deltaConnection.initialize(connectMessage, timeoutMs);
321
+ await epochTracker.validateEpoch(deltaConnection.details.epoch, "push");
322
+ } catch (errorObject: any) {
323
+ if (errorObject !== null && typeof errorObject === "object") {
324
+ // We have to special-case error types here in terms of what is re-triable.
325
+ // These errors have to re-retried, we just need new joinSession result to connect to right server:
326
+ // 400: Invalid tenant or document id. The WebSocket is connected to a different document
327
+ // Document is full (with retryAfter)
328
+ // 404: Invalid document. The document \"local/w1-...\" does not exist
329
+ // But this has to stay not-retriable:
330
+ // 406: Unsupported client protocol. This path is the only gatekeeper, have to fail!
331
+ // 409: Epoch Version Mismatch. Client epoch and server epoch does not match, so app needs
332
+ // to be refreshed.
333
+ // This one is fine either way
334
+ // 401/403: Code will retry once with new token either way, then it becomes fatal - on this path
335
+ // and on join Session path.
336
+ // 501: (Fluid not enabled): this is fine either way, as joinSession is gatekeeper
337
+ if (errorObject.statusCode === 400 || errorObject.statusCode === 404) {
338
+ errorObject.canRetry = true;
339
+ }
340
+ }
341
+ throw errorObject;
342
+ }
343
+
344
+ return deltaConnection;
345
+ }
346
+
347
+ private socketReference: SocketReference | undefined;
348
+
349
+ private readonly requestOpsNoncePrefix: string;
350
+ private pushCallCounter = 0;
351
+ private readonly getOpsMap: Map<string, { start: number; from: number; to: number }> =
352
+ new Map();
353
+ private flushOpNonce: string | undefined;
354
+ private flushDeferred: Deferred<FlushResult> | undefined;
355
+ private connectionNotYetDisposedTimeout: ReturnType<typeof setTimeout> | undefined;
356
+
357
+ /**
358
+ * Error raising for socket.io issues
359
+ */
360
+ protected createErrorObject(handler: string, error?: any, canRetry = true): IAnyDriverError {
361
+ // Note: we suspect the incoming error object is either:
362
+ // - a socketError: add it to the OdspError object for driver to be able to parse it and reason over it.
363
+ // - anything else: let base class handle it
364
+ return canRetry && Number.isInteger(error?.code) && typeof error?.message === "string"
365
+ ? errorObjectFromSocketError(error as IOdspSocketError, handler)
366
+ : super.createErrorObject(handler, error, canRetry);
367
+ }
368
+
369
+ /**
370
+ * Gets or create a socket io connection for the given key
371
+ */
372
+ private static getOrCreateSocketIoReference(
373
+ timeoutMs: number,
374
+ key: string,
375
+ url: string,
376
+ enableMultiplexing: boolean,
377
+ tenantId: string,
378
+ documentId: string,
379
+ logger: ITelemetryLoggerExt,
380
+ ): SocketReference {
381
+ const existingSocketReference = SocketReference.find(key, logger);
382
+ if (existingSocketReference) {
383
+ return existingSocketReference;
384
+ }
385
+
386
+ const query = enableMultiplexing ? undefined : { documentId, tenantId };
387
+
388
+ const socket = SocketIOClientStatic(url, {
389
+ multiplex: false, // Don't rely on socket.io built-in multiplexing
390
+ query,
391
+ reconnection: false,
392
+ transports: ["websocket"],
393
+ timeout: timeoutMs,
394
+ });
395
+
396
+ return new SocketReference(key, socket);
397
+ }
398
+
399
+ /**
400
+ * @param socket - websocket to be used
401
+ * @param documentId - ID of the document
402
+ * @param details - details of the websocket connection
403
+ * @param socketReferenceKey - socket reference key
404
+ * @param enableMultiplexing - If the websocket is multiplexing multiple documents
405
+ */
406
+ private constructor(
407
+ socket: Socket,
408
+ documentId: string,
409
+ socketReference: SocketReference,
410
+ logger: ITelemetryLoggerExt,
411
+ private readonly enableMultiplexing?: boolean,
412
+ connectionId?: string,
413
+ ) {
414
+ super(socket, documentId, logger, false, connectionId);
415
+ this.socketReference = socketReference;
416
+ this.requestOpsNoncePrefix = `${uuid()}-`;
417
+ }
418
+
419
+ /**
420
+ * Retrieves ops from PUSH
421
+ * @param from - inclusive
422
+ * @param to - exclusive
423
+ * @returns ops retrieved
424
+ */
425
+ public requestOps(from: number, to: number) {
426
+ assert(!this.socketReference?.disconnected, 0x413 /* non-active socket */);
427
+
428
+ // Given that to is exclusive, we should be asking for at least something!
429
+ assert(to > from, 0x272 /* "empty request" */);
430
+
431
+ // PUSH may disable this functionality
432
+ // back-compat: remove cast to any once latest version of IConnected is consumed
433
+ if ((this.details as any).supportedFeatures?.[feature_get_ops] !== true) {
434
+ return;
435
+ }
436
+
437
+ this.pushCallCounter++;
438
+ const nonce = `${this.requestOpsNoncePrefix}${this.pushCallCounter}`;
439
+ const start = performance.now();
440
+
441
+ // We may keep keep accumulating memory for nothing, if we are not getting responses.
442
+ // Note that we should not have overlapping requests, as DeltaManager allows only one
443
+ // outstanding request to storage, and that's the only way to get here.
444
+ // But requests could be cancelled, and thus overlapping requests might be in the picture
445
+ // If it happens, we do not care about stale requests.
446
+ // So track some number of requests, but log if we get too many in flight - that likely
447
+ // indicates an error somewhere.
448
+ if (this.getOpsMap.size >= 5) {
449
+ let time = start;
450
+ let key: string | undefined;
451
+ for (const [keyCandidate, value] of this.getOpsMap.entries()) {
452
+ if (value.start <= time || key === undefined) {
453
+ time = value.start;
454
+ key = keyCandidate;
455
+ }
456
+ }
457
+ const payloadToDelete = this.getOpsMap.get(key!)!;
458
+ this.logger.sendErrorEvent({
459
+ eventName: "GetOpsTooMany",
460
+ nonce,
461
+ from: payloadToDelete.from,
462
+ to: payloadToDelete.to,
463
+ length: payloadToDelete.to - payloadToDelete.from,
464
+ duration: performance.now() - payloadToDelete.start,
465
+ });
466
+ this.getOpsMap.delete(key!);
467
+ }
468
+ this.getOpsMap.set(nonce, {
469
+ start,
470
+ from,
471
+ to,
472
+ });
473
+ this.socket.emit("get_ops", this.clientId, {
474
+ nonce,
475
+ from,
476
+ to: to - 1,
477
+ });
478
+ }
479
+
480
+ public async flush(): Promise<FlushResult> {
481
+ assert(!this.socketReference?.disconnected, 0x414 /* non-active socket */);
482
+
483
+ // back-compat: remove cast to any once latest version of IConnected is consumed
484
+ if ((this.details as any).supportedFeatures?.[feature_flush_ops] !== true) {
485
+ // Once single-commit summary is enabled end-to-end, flush support is a must!
486
+ // The only alternative is change in design where SPO fetches ops from PUSH OR
487
+ // summary includes required ops and SPO has some validation mechanism to ensure
488
+ // they are not forged by client.
489
+ // If design changes, we can reconsider it, but right now it's non-recoverable failure.
490
+ this.logger.sendErrorEvent({ eventName: "FlushOpsNotSupported" });
491
+ throw new Error(
492
+ "flush() API is not supported by PUSH, required for single-commit summaries",
493
+ );
494
+ }
495
+
496
+ this.pushCallCounter++;
497
+ const nonce = `${this.requestOpsNoncePrefix}${this.pushCallCounter}`;
498
+ // There should be only one flush ops in flight, kicked out by upload summary workflow
499
+ // That said, it could timeout and request could be repeated, so theoretically we can
500
+ // get overlapping requests, but it should be very rare
501
+ if (this.flushDeferred !== undefined) {
502
+ this.logger.sendErrorEvent({ eventName: "FlushOpsTooMany" });
503
+ this.flushDeferred.reject(
504
+ "process involving flush() was cancelled OR unsupported concurrency",
505
+ );
506
+ }
507
+ this.socket.emit("flush_ops", this.clientId, { nonce });
508
+
509
+ this.flushOpNonce = nonce;
510
+ this.flushDeferred = new Deferred<FlushResult>();
511
+ return this.flushDeferred.promise;
512
+ }
513
+
514
+ protected disconnectHandler = (error: IFluidErrorBase & OdspError, clientId?: string) => {
515
+ if (clientId === undefined || clientId === this.clientId) {
516
+ this.logger.sendTelemetryEvent(
517
+ {
518
+ eventName: "ServerDisconnect",
519
+ driverVersion: pkgVersion,
520
+ details: JSON.stringify({
521
+ ...this.getConnectionDetailsProps(),
522
+ }),
523
+ },
524
+ error,
525
+ );
526
+ this.disconnect(error);
527
+ }
528
+ };
529
+
530
+ protected async initialize(connectMessage: IConnect, timeout: number) {
531
+ assert(!this.socketReference?.disconnected, 0x415 /* non-active socket */);
532
+
533
+ if (this.enableMultiplexing) {
534
+ // multiplex compatible early handlers
535
+ this.earlyOpHandler = (
536
+ messageDocumentId: string,
537
+ msgs: ISequencedDocumentMessage[],
538
+ ) => {
539
+ if (this.documentId === messageDocumentId) {
540
+ this.queuedMessages.push(...msgs);
541
+ }
542
+ };
543
+
544
+ this.earlySignalHandler = (
545
+ msg: ISignalMessage | ISignalMessage[],
546
+ messageDocumentId?: string,
547
+ ) => {
548
+ if (messageDocumentId === undefined || messageDocumentId === this.documentId) {
549
+ if (Array.isArray(msg)) {
550
+ this.queuedSignals.push(...msg);
551
+ } else {
552
+ this.queuedSignals.push(msg);
553
+ }
554
+ }
555
+ };
556
+ }
557
+
558
+ this.socketReference!.on("disconnect", this.disconnectHandler);
559
+
560
+ this.addTrackedListener("get_ops_response", (result: IGetOpsResponse) => {
561
+ const messages = result.messages;
562
+ const data = this.getOpsMap.get(result.nonce);
563
+ // Due to socket multiplexing, this client may not have asked for any data
564
+ // If so, there it most likely does not need these ops (otherwise it already asked for them)
565
+ // Also we may have deleted entry in this.getOpsMap due to too many requests and too slow response.
566
+ // But not processing such result may push us into infinite loop of fast requests and dropping all responses
567
+ if (data !== undefined || result.nonce.startsWith(this.requestOpsNoncePrefix)) {
568
+ this.getOpsMap.delete(result.nonce);
569
+ const common = {
570
+ eventName: "GetOps",
571
+ // We need nonce only to pair with GetOpsTooMany events, i.e. when record was deleted
572
+ nonce: data === undefined ? result.nonce : undefined,
573
+ code: result.code,
574
+ from: data?.from,
575
+ to: data?.to,
576
+ duration: data === undefined ? undefined : performance.now() - data.start,
577
+ };
578
+ if (messages !== undefined && messages.length > 0) {
579
+ this.logger.sendPerformanceEvent({
580
+ ...common,
581
+ first: messages[0].sequenceNumber,
582
+ last: messages[messages.length - 1].sequenceNumber,
583
+ length: messages.length,
584
+ });
585
+ this.emit("op", this.documentId, messages);
586
+ } else {
587
+ this.logger.sendPerformanceEvent({
588
+ ...common,
589
+ length: 0,
590
+ });
591
+ }
592
+ }
593
+ });
594
+
595
+ this.addTrackedListener("flush_ops_response", (result: IFlushOpsResponse) => {
596
+ if (this.flushOpNonce === result.nonce) {
597
+ const seq = result.lastPersistedSequenceNumber;
598
+ let category: "generic" | "error" = "generic";
599
+ if (result.lastPersistedSequenceNumber === undefined || result.code !== 200) {
600
+ switch (result.code) {
601
+ case 409:
602
+ case 429:
603
+ category = "error";
604
+ break;
605
+ case 204:
606
+ break;
607
+ default:
608
+ category = "error";
609
+ break;
610
+ }
611
+ }
612
+ this.logger.sendTelemetryEvent({
613
+ eventName: "FlushResult",
614
+ code: result.code,
615
+ sequenceNumber: seq,
616
+ category,
617
+ });
618
+ this.flushDeferred!.resolve(result);
619
+ this.flushDeferred = undefined;
620
+ this.flushOpNonce = undefined;
621
+ }
622
+ });
623
+
624
+ await super.initialize(connectMessage, timeout).finally(() => {
625
+ this.logger.sendTelemetryEvent({
626
+ eventName: "ConnectionAttemptInfo",
627
+ ...this.getConnectionDetailsProps(),
628
+ });
629
+ });
630
+ }
631
+
632
+ protected addTrackedListener(event: string, listener: (...args: any[]) => void) {
633
+ // override some event listeners in order to support multiple documents/clients over the same websocket
634
+ switch (event) {
635
+ case "op":
636
+ // per document op handling
637
+ super.addTrackedListener(
638
+ event,
639
+ (documentId: string, msgs: ISequencedDocumentMessage[]) => {
640
+ if (!this.enableMultiplexing || this.documentId === documentId) {
641
+ listener(documentId, msgs);
642
+ }
643
+ },
644
+ );
645
+ break;
646
+
647
+ case "signal":
648
+ // per document signal handling
649
+ super.addTrackedListener(
650
+ event,
651
+ (msg: ISignalMessage | ISignalMessage[], documentId?: string) => {
652
+ if (
653
+ !this.enableMultiplexing ||
654
+ !documentId ||
655
+ documentId === this.documentId
656
+ ) {
657
+ listener(msg, documentId);
658
+ }
659
+ },
660
+ );
661
+ break;
662
+
663
+ case "nack":
664
+ // per client / document nack handling
665
+ super.addTrackedListener(event, (clientIdOrDocumentId: string, nacks: INack[]) => {
666
+ const handle =
667
+ clientIdOrDocumentId.length === 0 ||
668
+ clientIdOrDocumentId === this.documentId ||
669
+ clientIdOrDocumentId === this.clientId;
670
+ const { code, type, message, retryAfter } = nacks[0]?.content ?? {};
671
+ const { clientSequenceNumber, referenceSequenceNumber } =
672
+ nacks[0]?.operation ?? {};
673
+ this.logger.sendTelemetryEvent({
674
+ eventName: "ServerNack",
675
+ code,
676
+ type,
677
+ message,
678
+ retryAfterSeconds: retryAfter,
679
+ clientId: this.clientId,
680
+ handle,
681
+ clientSequenceNumber,
682
+ referenceSequenceNumber,
683
+ opType: nacks[0]?.operation?.type,
684
+ });
685
+ if (handle) {
686
+ this.emit("nack", clientIdOrDocumentId, nacks);
687
+ }
688
+ });
689
+ break;
690
+
691
+ default:
692
+ super.addTrackedListener(event, listener);
693
+ break;
694
+ }
695
+ }
696
+
697
+ public get disposed() {
698
+ if (!(this._disposed || this.socket.connected)) {
699
+ // Send error event if this connection is not yet disposed after socket is disconnected for 15s.
700
+ if (this.connectionNotYetDisposedTimeout === undefined) {
701
+ this.connectionNotYetDisposedTimeout = setTimeout(() => {
702
+ if (!this._disposed) {
703
+ this.logger.sendErrorEvent({
704
+ eventName: "ConnectionNotYetDisposed",
705
+ driverVersion: pkgVersion,
706
+ details: JSON.stringify({
707
+ ...this.getConnectionDetailsProps(),
708
+ }),
709
+ });
710
+ }
711
+ }, 15000);
712
+ }
713
+ }
714
+ return this._disposed;
715
+ }
716
+
717
+ /**
718
+ * Returns true in case the connection is not yet disposed and the socket is also connected. The expectation is
719
+ * that it will be called only after connection is fully established. i.e. there should no way to submit an op
720
+ * while we are connecting, as connection object is not exposed to Loader layer until connection is established.
721
+ */
722
+ private get connected(): boolean {
723
+ return !this.disposed && this.socket.connected;
724
+ }
725
+
726
+ protected emitMessages(type: string, messages: IDocumentMessage[][]) {
727
+ // Only submit the op/signals if we are connected.
728
+ if (this.connected) {
729
+ this.socket.emit(type, this.clientId, messages);
730
+ }
731
+ }
732
+
733
+ /**
734
+ * Submits a new delta operation to the server
735
+ * @param message - delta operation to submit
736
+ */
737
+ public submit(messages: IDocumentMessage[]): void {
738
+ this.emitMessages("submitOp", [messages]);
739
+ }
740
+
741
+ /**
742
+ * Submits a new signal to the server
743
+ *
744
+ * @param content - Content of the signal.
745
+ * @param targetClientId - When specified, the signal is only sent to the provided client id.
746
+ */
747
+ public submitSignal(content: IDocumentMessage, targetClientId?: string): void {
748
+ const signal: ISentSignalMessage = {
749
+ content,
750
+ targetClientId,
751
+ };
752
+
753
+ // back-compat: the typing for this method and emitMessages is incorrect, will be fixed in a future PR
754
+ this.emitMessages("submitSignal", [signal] as any);
755
+ }
756
+
757
+ /**
758
+ * Critical path where we need to also close the socket for an error.
759
+ * @param error - Error causing the socket to close.
760
+ */
761
+ protected closeSocketCore(error: IAnyDriverError) {
762
+ const socket = this.socketReference;
763
+ assert(socket !== undefined, 0x416 /* reentrancy not supported in close socket */);
764
+ socket.closeSocket(error);
765
+ assert(
766
+ this.socketReference === undefined,
767
+ 0x417 /* disconnect flow did not work correctly */,
768
+ );
769
+ }
770
+
771
+ /**
772
+ * Disconnect from the websocket
773
+ */
774
+ protected disconnectCore() {
775
+ const socket = this.socketReference;
776
+ assert(socket !== undefined, 0x0a2 /* "reentrancy not supported!" */);
777
+ this.socketReference = undefined;
778
+
779
+ socket.off("disconnect", this.disconnectHandler);
780
+ if (this.hasDetails) {
781
+ // tell the server we are disconnecting this client from the document
782
+ this.socket.emit("disconnect_document", this.clientId, this.documentId);
783
+ }
784
+
785
+ socket.removeSocketIoReference();
786
+ }
599
787
  }