@fluidframework/container-loader 2.0.0-rc.3.0.2 → 2.0.0-rc.4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/api-report/container-loader.api.md +5 -1
- package/dist/attachment.d.ts +3 -2
- package/dist/attachment.d.ts.map +1 -1
- package/dist/attachment.js +5 -5
- package/dist/attachment.js.map +1 -1
- package/dist/audience.d.ts +6 -4
- package/dist/audience.d.ts.map +1 -1
- package/dist/audience.js +18 -3
- package/dist/audience.js.map +1 -1
- package/dist/catchUpMonitor.d.ts +1 -1
- package/dist/catchUpMonitor.d.ts.map +1 -1
- package/dist/catchUpMonitor.js.map +1 -1
- package/dist/connectionManager.d.ts +7 -3
- package/dist/connectionManager.d.ts.map +1 -1
- package/dist/connectionManager.js +57 -38
- package/dist/connectionManager.js.map +1 -1
- package/dist/connectionStateHandler.d.ts +31 -10
- package/dist/connectionStateHandler.d.ts.map +1 -1
- package/dist/connectionStateHandler.js +49 -36
- package/dist/connectionStateHandler.js.map +1 -1
- package/dist/container.d.ts +22 -13
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +145 -117
- package/dist/container.js.map +1 -1
- package/dist/containerContext.d.ts +3 -3
- package/dist/containerContext.d.ts.map +1 -1
- package/dist/containerContext.js.map +1 -1
- package/dist/containerStorageAdapter.d.ts +12 -3
- package/dist/containerStorageAdapter.d.ts.map +1 -1
- package/dist/containerStorageAdapter.js +42 -4
- package/dist/containerStorageAdapter.js.map +1 -1
- package/dist/contracts.d.ts +2 -2
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js.map +1 -1
- package/dist/debugLogger.d.ts +1 -2
- package/dist/debugLogger.d.ts.map +1 -1
- package/dist/debugLogger.js.map +1 -1
- package/dist/deltaManager.d.ts +5 -6
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +29 -24
- package/dist/deltaManager.js.map +1 -1
- package/dist/deltaQueue.d.ts +1 -1
- package/dist/deltaQueue.d.ts.map +1 -1
- package/dist/deltaQueue.js.map +1 -1
- package/dist/error.d.ts +1 -2
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/legacy.d.ts +2 -2
- package/dist/loadPaused.d.ts +35 -0
- package/dist/loadPaused.d.ts.map +1 -0
- package/dist/loadPaused.js +115 -0
- package/dist/loadPaused.js.map +1 -0
- package/dist/loader.d.ts +1 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +1 -14
- package/dist/loader.js.map +1 -1
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -1
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js +4 -4
- package/dist/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +3 -0
- package/dist/protocol.js.map +1 -1
- package/dist/public.d.ts +1 -1
- package/dist/retriableDocumentStorageService.d.ts +1 -1
- package/dist/retriableDocumentStorageService.d.ts.map +1 -1
- package/dist/retriableDocumentStorageService.js.map +1 -1
- package/dist/serializedStateManager.d.ts +89 -9
- package/dist/serializedStateManager.d.ts.map +1 -1
- package/dist/serializedStateManager.js +150 -34
- package/dist/serializedStateManager.js.map +1 -1
- package/dist/utils.d.ts +11 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +29 -14
- package/dist/utils.js.map +1 -1
- package/lib/attachment.d.ts +3 -2
- package/lib/attachment.d.ts.map +1 -1
- package/lib/attachment.js +5 -5
- package/lib/attachment.js.map +1 -1
- package/lib/audience.d.ts +6 -4
- package/lib/audience.d.ts.map +1 -1
- package/lib/audience.js +19 -4
- package/lib/audience.js.map +1 -1
- package/lib/catchUpMonitor.d.ts +1 -1
- package/lib/catchUpMonitor.d.ts.map +1 -1
- package/lib/catchUpMonitor.js.map +1 -1
- package/lib/connectionManager.d.ts +7 -3
- package/lib/connectionManager.d.ts.map +1 -1
- package/lib/connectionManager.js +36 -17
- package/lib/connectionManager.js.map +1 -1
- package/lib/connectionStateHandler.d.ts +31 -10
- package/lib/connectionStateHandler.d.ts.map +1 -1
- package/lib/connectionStateHandler.js +49 -36
- package/lib/connectionStateHandler.js.map +1 -1
- package/lib/container.d.ts +22 -13
- package/lib/container.d.ts.map +1 -1
- package/lib/container.js +146 -118
- package/lib/container.js.map +1 -1
- package/lib/containerContext.d.ts +3 -3
- package/lib/containerContext.d.ts.map +1 -1
- package/lib/containerContext.js.map +1 -1
- package/lib/containerStorageAdapter.d.ts +12 -3
- package/lib/containerStorageAdapter.d.ts.map +1 -1
- package/lib/containerStorageAdapter.js +42 -4
- package/lib/containerStorageAdapter.js.map +1 -1
- package/lib/contracts.d.ts +2 -2
- package/lib/contracts.d.ts.map +1 -1
- package/lib/contracts.js +1 -1
- package/lib/contracts.js.map +1 -1
- package/lib/debugLogger.d.ts +1 -2
- package/lib/debugLogger.d.ts.map +1 -1
- package/lib/debugLogger.js.map +1 -1
- package/lib/deltaManager.d.ts +5 -6
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +10 -5
- package/lib/deltaManager.js.map +1 -1
- package/lib/deltaQueue.d.ts +1 -1
- package/lib/deltaQueue.d.ts.map +1 -1
- package/lib/deltaQueue.js.map +1 -1
- package/lib/error.d.ts +1 -2
- package/lib/error.d.ts.map +1 -1
- package/lib/error.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/legacy.d.ts +2 -2
- package/lib/loadPaused.d.ts +35 -0
- package/lib/loadPaused.d.ts.map +1 -0
- package/lib/loadPaused.js +111 -0
- package/lib/loadPaused.js.map +1 -0
- package/lib/loader.d.ts +1 -1
- package/lib/loader.d.ts.map +1 -1
- package/lib/loader.js +3 -16
- package/lib/loader.js.map +1 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.d.ts.map +1 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.js +1 -1
- package/lib/location-redirection-utilities/resolveWithLocationRedirection.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/protocol.d.ts.map +1 -1
- package/lib/protocol.js +3 -0
- package/lib/protocol.js.map +1 -1
- package/lib/public.d.ts +1 -1
- package/lib/retriableDocumentStorageService.d.ts +1 -1
- package/lib/retriableDocumentStorageService.d.ts.map +1 -1
- package/lib/retriableDocumentStorageService.js +1 -1
- package/lib/retriableDocumentStorageService.js.map +1 -1
- package/lib/serializedStateManager.d.ts +89 -9
- package/lib/serializedStateManager.d.ts.map +1 -1
- package/lib/serializedStateManager.js +146 -30
- package/lib/serializedStateManager.js.map +1 -1
- package/lib/tsdoc-metadata.json +1 -1
- package/lib/utils.d.ts +11 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +15 -1
- package/lib/utils.js.map +1 -1
- package/package.json +24 -21
- package/src/attachment.ts +12 -13
- package/src/audience.ts +30 -9
- package/src/catchUpMonitor.ts +1 -1
- package/src/connectionManager.ts +45 -22
- package/src/connectionStateHandler.ts +78 -45
- package/src/container.ts +181 -160
- package/src/containerContext.ts +2 -2
- package/src/containerStorageAdapter.ts +61 -6
- package/src/contracts.ts +5 -4
- package/src/debugLogger.ts +1 -1
- package/src/deltaManager.ts +15 -8
- package/src/deltaQueue.ts +1 -1
- package/src/error.ts +1 -1
- package/src/index.ts +1 -0
- package/src/loadPaused.ts +140 -0
- package/src/loader.ts +6 -23
- package/src/location-redirection-utilities/resolveWithLocationRedirection.ts +1 -1
- package/src/packageVersion.ts +1 -1
- package/src/protocol.ts +4 -0
- package/src/retriableDocumentStorageService.ts +5 -2
- package/src/serializedStateManager.ts +215 -48
- package/src/utils.ts +19 -1
package/lib/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EACN,uBAAuB,EACvB,KAAK,SAAS,EACd,MAAM,6CAA6C,CAAC;AACrD,OAAO,EACN,6BAA6B,EAC7B,mCAAmC,EAGnC,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACN,mBAAmB,EACnB,aAAa,EACb,YAAY,EAEZ,MAAM,sCAAsC,CAAC;AAI9C,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,KAAK,EACX,8BAA8B,EAC9B,aAAa,EACb,iBAAiB,EACjB,MAAM,6BAA6B,CAAC;AAIrC,MAAM,WAAW,6BAA8B,SAAQ,aAAa;IACnE,aAAa,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAA;KAAE,CAAC;IACnD,KAAK,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,6BAA6B,CAAA;KAAE,CAAC;CACzD;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IAC1B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAiBjF;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC3C,UAAU,EAAE,YAAY,EACxB,eAAe,EAAE,YAAY,GAC3B,6BAA6B,CAiB/B;AAqDD;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,SAAS,GAAG,aAAa,CAWhF;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC5C,YAAY,EAAE,aAAa,EAC3B,sBAAsB,EAAE,MAAM,GAC5B,SAAS,CAaX;AAqBD,eAAO,MAAM,8CAA8C,8BAC/B,YAAY,KACrC,iBAYF,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,aAAa,GAAG,aAAa,CAE9E;AAED,eAAO,MAAM,mCAAmC,iBACjC,aAAa,iBACZ,yBAAyB,KACtC,6BAwBF,CAAC;AAEF,wBAAgB,qCAAqC,CACpD,KAAK,EAAE,GAAG,GACR,KAAK,IAAI,mCAAmC,CAM9C;AAoBD,wBAAgB,gDAAgD,CAC/D,mBAAmB,EAAE,MAAM,GACzB,8BAA8B,CAkBhC;AAED;;;GAGG;AACH,eAAO,MAAM,SAAS,sFAsBrB,CAAC;AAEF,wBAAsB,qBAAqB,CAC1C,OAAO,EAAE,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC,EAClD,IAAI,EAAE,aAAa,GAAG,SAAS,GAC7B,OAAO,CAAC,mBAAmB,CAAC,CAiB9B"}
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EACN,uBAAuB,EACvB,KAAK,SAAS,EACd,MAAM,6CAA6C,CAAC;AACrD,OAAO,EACN,6BAA6B,EAC7B,mCAAmC,EAGnC,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EACN,mBAAmB,EACnB,aAAa,EACb,YAAY,EAEZ,MAAM,sCAAsC,CAAC;AAI9C,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AACzE,OAAO,KAAK,EACX,sBAAsB,EACtB,8BAA8B,EAC9B,aAAa,EACb,iBAAiB,EACjB,MAAM,6BAA6B,CAAC;AAIrC,MAAM,WAAW,6BAA8B,SAAQ,aAAa;IACnE,aAAa,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAAA;KAAE,CAAC;IACnD,KAAK,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,6BAA6B,CAAA;KAAE,CAAC;CACzD;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IAC1B;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAiBjF;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC3C,UAAU,EAAE,YAAY,EACxB,eAAe,EAAE,YAAY,GAC3B,6BAA6B,CAiB/B;AAqDD;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,SAAS,GAAG,aAAa,CAWhF;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC5C,YAAY,EAAE,aAAa,EAC3B,sBAAsB,EAAE,MAAM,GAC5B,SAAS,CAaX;AAqBD,eAAO,MAAM,8CAA8C,8BAC/B,YAAY,KACrC,iBAYF,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,aAAa,GAAG,aAAa,CAE9E;AAED,eAAO,MAAM,mCAAmC,iBACjC,aAAa,iBACZ,yBAAyB,KACtC,6BAwBF,CAAC;AAEF,wBAAgB,qCAAqC,CACpD,KAAK,EAAE,GAAG,GACR,KAAK,IAAI,mCAAmC,CAM9C;AAoBD;;;;GAIG;AACH,wBAAgB,gDAAgD,CAC/D,mBAAmB,EAAE,MAAM,GACzB,8BAA8B,CAkBhC;AAED;;;GAGG;AACH,wBAAgB,gDAAgD,CAC/D,mBAAmB,EAAE,MAAM,GAAG,SAAS,GACrC,sBAAsB,GAAG,SAAS,CAIpC;AAED;;;GAGG;AACH,eAAO,MAAM,SAAS,sFAsBrB,CAAC;AAEF,wBAAsB,qBAAqB,CAC1C,OAAO,EAAE,IAAI,CAAC,uBAAuB,EAAE,UAAU,CAAC,EAClD,IAAI,EAAE,aAAa,GAAG,SAAS,GAC7B,OAAO,CAAC,mBAAmB,CAAC,CAiB9B"}
|
package/lib/utils.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { Uint8ArrayToString, bufferToString, stringToBuffer } from "@fluid-internal/client-utils";
|
|
6
6
|
import { assert, compareArrays, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
7
|
-
import { DriverErrorTypes } from "@fluidframework/driver-definitions";
|
|
7
|
+
import { DriverErrorTypes } from "@fluidframework/driver-definitions/internal";
|
|
8
8
|
import { isCombinedAppAndProtocolSummary, readAndParse, } from "@fluidframework/driver-utils/internal";
|
|
9
9
|
import { SummaryType, } from "@fluidframework/protocol-definitions";
|
|
10
10
|
import { LoggingError, UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
@@ -203,6 +203,11 @@ function isPendingDetachedContainerState(detachedContainerState) {
|
|
|
203
203
|
}
|
|
204
204
|
return true;
|
|
205
205
|
}
|
|
206
|
+
/**
|
|
207
|
+
* Parses the given string into {@link IPendingDetachedContainerState} format,
|
|
208
|
+
* with validation (if invalid, throws a UsageError).
|
|
209
|
+
* This is the inverse of the JSON.stringify call in {@link Container.serialize}
|
|
210
|
+
*/
|
|
206
211
|
export function getDetachedContainerStateFromSerializedContainer(serializedContainer) {
|
|
207
212
|
const hasBlobsSummaryTree = ".hasAttachmentBlobs";
|
|
208
213
|
const parsedContainerState = JSON.parse(serializedContainer);
|
|
@@ -223,6 +228,15 @@ export function getDetachedContainerStateFromSerializedContainer(serializedConta
|
|
|
223
228
|
throw new UsageError("Cannot rehydrate detached container. Incorrect format");
|
|
224
229
|
}
|
|
225
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* Blindly parses the given string into {@link IPendingContainerState} format.
|
|
233
|
+
* This is the inverse of the JSON.stringify call in {@link SerializedStateManager.getPendingLocalState}
|
|
234
|
+
*/
|
|
235
|
+
export function getAttachedContainerStateFromSerializedContainer(serializedContainer) {
|
|
236
|
+
return serializedContainer !== undefined
|
|
237
|
+
? JSON.parse(serializedContainer)
|
|
238
|
+
: undefined;
|
|
239
|
+
}
|
|
226
240
|
/**
|
|
227
241
|
* Ensures only a single instance of the provided async function is running.
|
|
228
242
|
* If there are multiple calls they will all get the same promise to wait on.
|
package/lib/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.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 { Uint8ArrayToString, bufferToString, stringToBuffer } from \"@fluid-internal/client-utils\";\nimport { assert, compareArrays, unreachableCase } from \"@fluidframework/core-utils/internal\";\nimport { DriverErrorTypes } from \"@fluidframework/driver-definitions\";\nimport {\n\tIDocumentStorageService,\n\ttype ISnapshot,\n} from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tCombinedAppAndProtocolSummary,\n\tDeltaStreamConnectionForbiddenError,\n\tisCombinedAppAndProtocolSummary,\n\treadAndParse,\n} from \"@fluidframework/driver-utils/internal\";\nimport {\n\tIDocumentAttributes,\n\tISnapshotTree,\n\tISummaryTree,\n\tSummaryType,\n} from \"@fluidframework/protocol-definitions\";\nimport { LoggingError, UsageError } from \"@fluidframework/telemetry-utils/internal\";\nimport { v4 as uuid } from \"uuid\";\n\nimport { ISerializableBlobContents } from \"./containerStorageAdapter.js\";\nimport type {\n\tIPendingDetachedContainerState,\n\tISnapshotInfo,\n\tSnapshotWithBlobs,\n} from \"./serializedStateManager.js\";\n\n// This is used when we rehydrate a container from the snapshot. Here we put the blob contents\n// in separate property: blobContents.\nexport interface ISnapshotTreeWithBlobContents extends ISnapshotTree {\n\tblobsContents: { [path: string]: ArrayBufferLike };\n\ttrees: { [path: string]: ISnapshotTreeWithBlobContents };\n}\n\n/**\n * Interface to represent the parsed parts of IResolvedUrl.url to help\n * in getting info about different parts of the url.\n * May not be compatible or relevant for any Url Resolver\n * @alpha\n */\nexport interface IParsedUrl {\n\t/**\n\t * It is combination of tenantid/docId part of the url.\n\t */\n\tid: string;\n\t/**\n\t * It is the deep link path in the url.\n\t */\n\tpath: string;\n\t/**\n\t * Query string part of the url.\n\t */\n\tquery: string;\n\t/**\n\t * Undefined means load latest snapshot, otherwise it's version ID passed to IDocumentStorageService.getVersions()\n\t * to figure out what snapshot to use.\n\t */\n\tversion: string | undefined;\n}\n\n/**\n * Utility api to parse the IResolvedUrl.url into specific parts like querystring, path to get\n * deep link info etc.\n * Warning - This function may not be compatible with any Url Resolver's resolved url. It works\n * with urls of type: protocol://<string>/.../..?<querystring>\n * @param url - This is the IResolvedUrl.url part of the resolved url.\n * @returns The IParsedUrl representing the input URL, or undefined if the format was not supported\n * @alpha\n */\nexport function tryParseCompatibleResolvedUrl(url: string): IParsedUrl | undefined {\n\tconst parsed = new URL(url);\n\tif (typeof parsed.pathname !== \"string\") {\n\t\tthrow new LoggingError(\"Failed to parse pathname\");\n\t}\n\tconst query = parsed.search ?? \"\";\n\tconst regex = /^\\/([^/]*\\/[^/]*)(\\/?.*)$/;\n\tconst match = regex.exec(parsed.pathname);\n\treturn match?.length === 3\n\t\t? {\n\t\t\t\tid: match[1],\n\t\t\t\tpath: match[2],\n\t\t\t\tquery,\n\t\t\t\t// URLSearchParams returns null if the param is not provided.\n\t\t\t\tversion: parsed.searchParams.get(\"version\") ?? undefined,\n\t\t }\n\t\t: undefined;\n}\n\n/**\n * Combine the app summary and protocol summary in 1 tree.\n * @param appSummary - Summary of the app.\n * @param protocolSummary - Summary of the protocol.\n * @internal\n */\nexport function combineAppAndProtocolSummary(\n\tappSummary: ISummaryTree,\n\tprotocolSummary: ISummaryTree,\n): CombinedAppAndProtocolSummary {\n\tassert(\n\t\t!isCombinedAppAndProtocolSummary(appSummary),\n\t\t0x5a8 /* app summary is already a combined tree! */,\n\t);\n\tassert(\n\t\t!isCombinedAppAndProtocolSummary(protocolSummary),\n\t\t0x5a9 /* protocol summary is already a combined tree! */,\n\t);\n\tconst createNewSummary: CombinedAppAndProtocolSummary = {\n\t\ttype: SummaryType.Tree,\n\t\ttree: {\n\t\t\t\".protocol\": protocolSummary,\n\t\t\t\".app\": appSummary,\n\t\t},\n\t};\n\treturn createNewSummary;\n}\n\n/**\n * Converts a summary to snapshot tree and separate its blob contents\n * to align detached container format with IPendingContainerState\n * @param summary - ISummaryTree\n */\nfunction convertSummaryToSnapshotAndBlobs(summary: ISummaryTree): SnapshotWithBlobs {\n\tlet blobContents: ISerializableBlobContents = {};\n\tconst treeNode: ISnapshotTree = {\n\t\tblobs: {},\n\t\ttrees: {},\n\t\tid: uuid(),\n\t\tunreferenced: summary.unreferenced,\n\t\tgroupId: summary.groupId,\n\t};\n\tconst keys = Object.keys(summary.tree);\n\tfor (const key of keys) {\n\t\tconst summaryObject = summary.tree[key];\n\n\t\tswitch (summaryObject.type) {\n\t\t\tcase SummaryType.Tree: {\n\t\t\t\tconst innerSnapshot = convertSummaryToSnapshotAndBlobs(summaryObject);\n\t\t\t\ttreeNode.trees[key] = innerSnapshot.baseSnapshot;\n\t\t\t\tblobContents = { ...blobContents, ...innerSnapshot.snapshotBlobs };\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SummaryType.Attachment:\n\t\t\t\ttreeNode.blobs[key] = summaryObject.id;\n\t\t\t\tbreak;\n\t\t\tcase SummaryType.Blob: {\n\t\t\t\tconst blobId = uuid();\n\t\t\t\ttreeNode.blobs[key] = blobId;\n\t\t\t\tconst contentString: string =\n\t\t\t\t\tsummaryObject.content instanceof Uint8Array\n\t\t\t\t\t\t? Uint8ArrayToString(summaryObject.content)\n\t\t\t\t\t\t: summaryObject.content;\n\t\t\t\tblobContents[blobId] = contentString;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SummaryType.Handle:\n\t\t\t\tthrow new LoggingError(\n\t\t\t\t\t\"No handles should be there in summary in detached container!!\",\n\t\t\t\t);\n\t\t\tdefault: {\n\t\t\t\tunreachableCase(summaryObject, `Unknown tree type ${(summaryObject as any).type}`);\n\t\t\t}\n\t\t}\n\t}\n\tconst pendingSnapshot = { baseSnapshot: treeNode, snapshotBlobs: blobContents };\n\treturn pendingSnapshot;\n}\n\n/**\n * Converts a snapshot to snapshotInfo with its blob contents\n * to align detached container format with IPendingContainerState\n *\n * Note, this assumes the ISnapshot sequence number is defined. Otherwise an assert will be thrown\n * @param snapshot - ISnapshot\n */\nexport function convertSnapshotToSnapshotInfo(snapshot: ISnapshot): ISnapshotInfo {\n\tassert(snapshot.sequenceNumber !== undefined, 0x93a /* Snapshot sequence number is missing */);\n\tconst snapshotBlobs: ISerializableBlobContents = {};\n\tfor (const [blobId, arrayBufferLike] of snapshot.blobContents.entries()) {\n\t\tsnapshotBlobs[blobId] = bufferToString(arrayBufferLike, \"utf8\");\n\t}\n\treturn {\n\t\tbaseSnapshot: snapshot.snapshotTree,\n\t\tsnapshotBlobs,\n\t\tsnapshotSequenceNumber: snapshot.sequenceNumber,\n\t};\n}\n\n/**\n * Converts a snapshot to snapshotInfo with its blob contents\n * to align detached container format with IPendingContainerState\n *\n * Note, this assumes the ISnapshot sequence number is defined. Otherwise an assert will be thrown\n * @param snapshot - ISnapshot\n */\nexport function convertSnapshotInfoToSnapshot(\n\tsnapshotInfo: ISnapshotInfo,\n\tsnapshotSequenceNumber: number,\n): ISnapshot {\n\tconst blobContents = new Map<string, ArrayBufferLike>();\n\tfor (const [blobId, serializedContent] of Object.entries(snapshotInfo.snapshotBlobs)) {\n\t\tblobContents.set(blobId, stringToBuffer(serializedContent, \"utf8\"));\n\t}\n\treturn {\n\t\tsnapshotTree: snapshotInfo.baseSnapshot,\n\t\tblobContents,\n\t\tops: [],\n\t\tsequenceNumber: snapshotSequenceNumber,\n\t\tlatestSequenceNumber: undefined,\n\t\tsnapshotFormatV: 1,\n\t};\n}\n\n/**\n * Converts summary parts into a SnapshotTree and its blob contents.\n * @param protocolSummaryTree - Protocol Summary Tree\n * @param appSummaryTree - App Summary Tree\n */\nfunction convertProtocolAndAppSummaryToSnapshotAndBlobs(\n\tprotocolSummaryTree: ISummaryTree,\n\tappSummaryTree: ISummaryTree,\n): SnapshotWithBlobs {\n\tconst combinedSummary: ISummaryTree = {\n\t\ttype: SummaryType.Tree,\n\t\ttree: { ...appSummaryTree.tree },\n\t};\n\n\tcombinedSummary.tree[\".protocol\"] = protocolSummaryTree;\n\tconst snapshotTreeWithBlobContents = convertSummaryToSnapshotAndBlobs(combinedSummary);\n\treturn snapshotTreeWithBlobContents;\n}\n\nexport const getSnapshotTreeAndBlobsFromSerializedContainer = (\n\tdetachedContainerSnapshot: ISummaryTree,\n): SnapshotWithBlobs => {\n\tassert(\n\t\tisCombinedAppAndProtocolSummary(detachedContainerSnapshot),\n\t\t0x8e6 /* Protocol and App summary trees should be present */,\n\t);\n\tconst protocolSummaryTree = detachedContainerSnapshot.tree[\".protocol\"];\n\tconst appSummaryTree = detachedContainerSnapshot.tree[\".app\"];\n\tconst snapshotTreeWithBlobContents = convertProtocolAndAppSummaryToSnapshotAndBlobs(\n\t\tprotocolSummaryTree,\n\t\tappSummaryTree,\n\t);\n\treturn snapshotTreeWithBlobContents;\n};\n\nexport function getProtocolSnapshotTree(snapshot: ISnapshotTree): ISnapshotTree {\n\treturn \".protocol\" in snapshot.trees ? snapshot.trees[\".protocol\"] : snapshot;\n}\n\nexport const combineSnapshotTreeAndSnapshotBlobs = (\n\tbaseSnapshot: ISnapshotTree,\n\tsnapshotBlobs: ISerializableBlobContents,\n): ISnapshotTreeWithBlobContents => {\n\tconst blobsContents: { [path: string]: ArrayBufferLike } = {};\n\n\t// Process blobs in the current level\n\tfor (const [, id] of Object.entries(baseSnapshot.blobs)) {\n\t\tif (snapshotBlobs[id]) {\n\t\t\tblobsContents[id] = stringToBuffer(snapshotBlobs[id], \"utf8\");\n\t\t}\n\t}\n\n\t// Recursively process trees in the current level\n\tconst trees: { [path: string]: ISnapshotTreeWithBlobContents } = {};\n\tfor (const [path, tree] of Object.entries(baseSnapshot.trees)) {\n\t\ttrees[path] = combineSnapshotTreeAndSnapshotBlobs(tree, snapshotBlobs);\n\t}\n\n\t// Create a new snapshot tree with blob contents and processed trees\n\tconst snapshotTreeWithBlobContents: ISnapshotTreeWithBlobContents = {\n\t\t...baseSnapshot,\n\t\tblobsContents,\n\t\ttrees,\n\t};\n\n\treturn snapshotTreeWithBlobContents;\n};\n\nexport function isDeltaStreamConnectionForbiddenError(\n\terror: any,\n): error is DeltaStreamConnectionForbiddenError {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\terror?.errorType === DriverErrorTypes.deltaStreamConnectionForbidden\n\t);\n}\n\n/**\n * Validates format in parsed string get from detached container\n * serialization using IPendingDetachedContainerState format.\n */\nfunction isPendingDetachedContainerState(\n\tdetachedContainerState: IPendingDetachedContainerState,\n): detachedContainerState is IPendingDetachedContainerState {\n\tif (\n\t\tdetachedContainerState?.attached === undefined ||\n\t\tdetachedContainerState?.baseSnapshot === undefined ||\n\t\tdetachedContainerState?.snapshotBlobs === undefined ||\n\t\tdetachedContainerState?.hasAttachmentBlobs === undefined\n\t) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nexport function getDetachedContainerStateFromSerializedContainer(\n\tserializedContainer: string,\n): IPendingDetachedContainerState {\n\tconst hasBlobsSummaryTree = \".hasAttachmentBlobs\";\n\tconst parsedContainerState = JSON.parse(serializedContainer);\n\tif (isPendingDetachedContainerState(parsedContainerState)) {\n\t\treturn parsedContainerState;\n\t} else if (isCombinedAppAndProtocolSummary(parsedContainerState)) {\n\t\tconst { baseSnapshot, snapshotBlobs } =\n\t\t\tgetSnapshotTreeAndBlobsFromSerializedContainer(parsedContainerState);\n\t\tconst detachedContainerState: IPendingDetachedContainerState = {\n\t\t\tattached: false,\n\t\t\tbaseSnapshot,\n\t\t\tsnapshotBlobs,\n\t\t\thasAttachmentBlobs: parsedContainerState.tree[hasBlobsSummaryTree] !== undefined,\n\t\t};\n\t\treturn detachedContainerState;\n\t} else {\n\t\tthrow new UsageError(\"Cannot rehydrate detached container. Incorrect format\");\n\t}\n}\n\n/**\n * Ensures only a single instance of the provided async function is running.\n * If there are multiple calls they will all get the same promise to wait on.\n */\nexport const runSingle = <A extends any[], R>(func: (...args: A) => Promise<R>) => {\n\tlet running:\n\t\t| {\n\t\t\t\targs: A;\n\t\t\t\tresult: Promise<R>;\n\t\t }\n\t\t| undefined;\n\t// don't mark this function async, so we return the same promise,\n\t// rather than one that is wrapped due to async\n\t// eslint-disable-next-line @typescript-eslint/promise-function-async\n\treturn (...args: A) => {\n\t\tif (running !== undefined) {\n\t\t\tif (!compareArrays(running.args, args)) {\n\t\t\t\treturn Promise.reject(\n\t\t\t\t\tnew UsageError(\"Subsequent calls cannot use different arguments.\"),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn running.result;\n\t\t}\n\t\trunning = { args, result: func(...args).finally(() => (running = undefined)) };\n\t\treturn running.result;\n\t};\n};\n\nexport async function getDocumentAttributes(\n\tstorage: Pick<IDocumentStorageService, \"readBlob\">,\n\ttree: ISnapshotTree | undefined,\n): Promise<IDocumentAttributes> {\n\tif (tree === undefined) {\n\t\treturn {\n\t\t\tminimumSequenceNumber: 0,\n\t\t\tsequenceNumber: 0,\n\t\t};\n\t}\n\n\t// Backward compatibility: old docs would have \".attributes\" instead of \"attributes\"\n\tconst attributesHash =\n\t\t\".protocol\" in tree.trees\n\t\t\t? tree.trees[\".protocol\"].blobs.attributes\n\t\t\t: tree.blobs[\".attributes\"];\n\n\tconst attributes = await readAndParse<IDocumentAttributes>(storage, attributesHash);\n\n\treturn attributes;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.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 { Uint8ArrayToString, bufferToString, stringToBuffer } from \"@fluid-internal/client-utils\";\nimport { assert, compareArrays, unreachableCase } from \"@fluidframework/core-utils/internal\";\nimport { DriverErrorTypes } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tIDocumentStorageService,\n\ttype ISnapshot,\n} from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tCombinedAppAndProtocolSummary,\n\tDeltaStreamConnectionForbiddenError,\n\tisCombinedAppAndProtocolSummary,\n\treadAndParse,\n} from \"@fluidframework/driver-utils/internal\";\nimport {\n\tIDocumentAttributes,\n\tISnapshotTree,\n\tISummaryTree,\n\tSummaryType,\n} from \"@fluidframework/protocol-definitions\";\nimport { LoggingError, UsageError } from \"@fluidframework/telemetry-utils/internal\";\nimport { v4 as uuid } from \"uuid\";\n\nimport { ISerializableBlobContents } from \"./containerStorageAdapter.js\";\nimport type {\n\tIPendingContainerState,\n\tIPendingDetachedContainerState,\n\tISnapshotInfo,\n\tSnapshotWithBlobs,\n} from \"./serializedStateManager.js\";\n\n// This is used when we rehydrate a container from the snapshot. Here we put the blob contents\n// in separate property: blobContents.\nexport interface ISnapshotTreeWithBlobContents extends ISnapshotTree {\n\tblobsContents: { [path: string]: ArrayBufferLike };\n\ttrees: { [path: string]: ISnapshotTreeWithBlobContents };\n}\n\n/**\n * Interface to represent the parsed parts of IResolvedUrl.url to help\n * in getting info about different parts of the url.\n * May not be compatible or relevant for any Url Resolver\n * @alpha\n */\nexport interface IParsedUrl {\n\t/**\n\t * It is combination of tenantid/docId part of the url.\n\t */\n\tid: string;\n\t/**\n\t * It is the deep link path in the url.\n\t */\n\tpath: string;\n\t/**\n\t * Query string part of the url.\n\t */\n\tquery: string;\n\t/**\n\t * Undefined means load latest snapshot, otherwise it's version ID passed to IDocumentStorageService.getVersions()\n\t * to figure out what snapshot to use.\n\t */\n\tversion: string | undefined;\n}\n\n/**\n * Utility api to parse the IResolvedUrl.url into specific parts like querystring, path to get\n * deep link info etc.\n * Warning - This function may not be compatible with any Url Resolver's resolved url. It works\n * with urls of type: protocol://<string>/.../..?<querystring>\n * @param url - This is the IResolvedUrl.url part of the resolved url.\n * @returns The IParsedUrl representing the input URL, or undefined if the format was not supported\n * @alpha\n */\nexport function tryParseCompatibleResolvedUrl(url: string): IParsedUrl | undefined {\n\tconst parsed = new URL(url);\n\tif (typeof parsed.pathname !== \"string\") {\n\t\tthrow new LoggingError(\"Failed to parse pathname\");\n\t}\n\tconst query = parsed.search ?? \"\";\n\tconst regex = /^\\/([^/]*\\/[^/]*)(\\/?.*)$/;\n\tconst match = regex.exec(parsed.pathname);\n\treturn match?.length === 3\n\t\t? {\n\t\t\t\tid: match[1],\n\t\t\t\tpath: match[2],\n\t\t\t\tquery,\n\t\t\t\t// URLSearchParams returns null if the param is not provided.\n\t\t\t\tversion: parsed.searchParams.get(\"version\") ?? undefined,\n\t\t }\n\t\t: undefined;\n}\n\n/**\n * Combine the app summary and protocol summary in 1 tree.\n * @param appSummary - Summary of the app.\n * @param protocolSummary - Summary of the protocol.\n * @internal\n */\nexport function combineAppAndProtocolSummary(\n\tappSummary: ISummaryTree,\n\tprotocolSummary: ISummaryTree,\n): CombinedAppAndProtocolSummary {\n\tassert(\n\t\t!isCombinedAppAndProtocolSummary(appSummary),\n\t\t0x5a8 /* app summary is already a combined tree! */,\n\t);\n\tassert(\n\t\t!isCombinedAppAndProtocolSummary(protocolSummary),\n\t\t0x5a9 /* protocol summary is already a combined tree! */,\n\t);\n\tconst createNewSummary: CombinedAppAndProtocolSummary = {\n\t\ttype: SummaryType.Tree,\n\t\ttree: {\n\t\t\t\".protocol\": protocolSummary,\n\t\t\t\".app\": appSummary,\n\t\t},\n\t};\n\treturn createNewSummary;\n}\n\n/**\n * Converts a summary to snapshot tree and separate its blob contents\n * to align detached container format with IPendingContainerState\n * @param summary - ISummaryTree\n */\nfunction convertSummaryToSnapshotAndBlobs(summary: ISummaryTree): SnapshotWithBlobs {\n\tlet blobContents: ISerializableBlobContents = {};\n\tconst treeNode: ISnapshotTree = {\n\t\tblobs: {},\n\t\ttrees: {},\n\t\tid: uuid(),\n\t\tunreferenced: summary.unreferenced,\n\t\tgroupId: summary.groupId,\n\t};\n\tconst keys = Object.keys(summary.tree);\n\tfor (const key of keys) {\n\t\tconst summaryObject = summary.tree[key];\n\n\t\tswitch (summaryObject.type) {\n\t\t\tcase SummaryType.Tree: {\n\t\t\t\tconst innerSnapshot = convertSummaryToSnapshotAndBlobs(summaryObject);\n\t\t\t\ttreeNode.trees[key] = innerSnapshot.baseSnapshot;\n\t\t\t\tblobContents = { ...blobContents, ...innerSnapshot.snapshotBlobs };\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SummaryType.Attachment:\n\t\t\t\ttreeNode.blobs[key] = summaryObject.id;\n\t\t\t\tbreak;\n\t\t\tcase SummaryType.Blob: {\n\t\t\t\tconst blobId = uuid();\n\t\t\t\ttreeNode.blobs[key] = blobId;\n\t\t\t\tconst contentString: string =\n\t\t\t\t\tsummaryObject.content instanceof Uint8Array\n\t\t\t\t\t\t? Uint8ArrayToString(summaryObject.content)\n\t\t\t\t\t\t: summaryObject.content;\n\t\t\t\tblobContents[blobId] = contentString;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase SummaryType.Handle:\n\t\t\t\tthrow new LoggingError(\n\t\t\t\t\t\"No handles should be there in summary in detached container!!\",\n\t\t\t\t);\n\t\t\tdefault: {\n\t\t\t\tunreachableCase(summaryObject, `Unknown tree type ${(summaryObject as any).type}`);\n\t\t\t}\n\t\t}\n\t}\n\tconst pendingSnapshot = { baseSnapshot: treeNode, snapshotBlobs: blobContents };\n\treturn pendingSnapshot;\n}\n\n/**\n * Converts a snapshot to snapshotInfo with its blob contents\n * to align detached container format with IPendingContainerState\n *\n * Note, this assumes the ISnapshot sequence number is defined. Otherwise an assert will be thrown\n * @param snapshot - ISnapshot\n */\nexport function convertSnapshotToSnapshotInfo(snapshot: ISnapshot): ISnapshotInfo {\n\tassert(snapshot.sequenceNumber !== undefined, 0x93a /* Snapshot sequence number is missing */);\n\tconst snapshotBlobs: ISerializableBlobContents = {};\n\tfor (const [blobId, arrayBufferLike] of snapshot.blobContents.entries()) {\n\t\tsnapshotBlobs[blobId] = bufferToString(arrayBufferLike, \"utf8\");\n\t}\n\treturn {\n\t\tbaseSnapshot: snapshot.snapshotTree,\n\t\tsnapshotBlobs,\n\t\tsnapshotSequenceNumber: snapshot.sequenceNumber,\n\t};\n}\n\n/**\n * Converts a snapshot to snapshotInfo with its blob contents\n * to align detached container format with IPendingContainerState\n *\n * Note, this assumes the ISnapshot sequence number is defined. Otherwise an assert will be thrown\n * @param snapshot - ISnapshot\n */\nexport function convertSnapshotInfoToSnapshot(\n\tsnapshotInfo: ISnapshotInfo,\n\tsnapshotSequenceNumber: number,\n): ISnapshot {\n\tconst blobContents = new Map<string, ArrayBufferLike>();\n\tfor (const [blobId, serializedContent] of Object.entries(snapshotInfo.snapshotBlobs)) {\n\t\tblobContents.set(blobId, stringToBuffer(serializedContent, \"utf8\"));\n\t}\n\treturn {\n\t\tsnapshotTree: snapshotInfo.baseSnapshot,\n\t\tblobContents,\n\t\tops: [],\n\t\tsequenceNumber: snapshotSequenceNumber,\n\t\tlatestSequenceNumber: undefined,\n\t\tsnapshotFormatV: 1,\n\t};\n}\n\n/**\n * Converts summary parts into a SnapshotTree and its blob contents.\n * @param protocolSummaryTree - Protocol Summary Tree\n * @param appSummaryTree - App Summary Tree\n */\nfunction convertProtocolAndAppSummaryToSnapshotAndBlobs(\n\tprotocolSummaryTree: ISummaryTree,\n\tappSummaryTree: ISummaryTree,\n): SnapshotWithBlobs {\n\tconst combinedSummary: ISummaryTree = {\n\t\ttype: SummaryType.Tree,\n\t\ttree: { ...appSummaryTree.tree },\n\t};\n\n\tcombinedSummary.tree[\".protocol\"] = protocolSummaryTree;\n\tconst snapshotTreeWithBlobContents = convertSummaryToSnapshotAndBlobs(combinedSummary);\n\treturn snapshotTreeWithBlobContents;\n}\n\nexport const getSnapshotTreeAndBlobsFromSerializedContainer = (\n\tdetachedContainerSnapshot: ISummaryTree,\n): SnapshotWithBlobs => {\n\tassert(\n\t\tisCombinedAppAndProtocolSummary(detachedContainerSnapshot),\n\t\t0x8e6 /* Protocol and App summary trees should be present */,\n\t);\n\tconst protocolSummaryTree = detachedContainerSnapshot.tree[\".protocol\"];\n\tconst appSummaryTree = detachedContainerSnapshot.tree[\".app\"];\n\tconst snapshotTreeWithBlobContents = convertProtocolAndAppSummaryToSnapshotAndBlobs(\n\t\tprotocolSummaryTree,\n\t\tappSummaryTree,\n\t);\n\treturn snapshotTreeWithBlobContents;\n};\n\nexport function getProtocolSnapshotTree(snapshot: ISnapshotTree): ISnapshotTree {\n\treturn \".protocol\" in snapshot.trees ? snapshot.trees[\".protocol\"] : snapshot;\n}\n\nexport const combineSnapshotTreeAndSnapshotBlobs = (\n\tbaseSnapshot: ISnapshotTree,\n\tsnapshotBlobs: ISerializableBlobContents,\n): ISnapshotTreeWithBlobContents => {\n\tconst blobsContents: { [path: string]: ArrayBufferLike } = {};\n\n\t// Process blobs in the current level\n\tfor (const [, id] of Object.entries(baseSnapshot.blobs)) {\n\t\tif (snapshotBlobs[id]) {\n\t\t\tblobsContents[id] = stringToBuffer(snapshotBlobs[id], \"utf8\");\n\t\t}\n\t}\n\n\t// Recursively process trees in the current level\n\tconst trees: { [path: string]: ISnapshotTreeWithBlobContents } = {};\n\tfor (const [path, tree] of Object.entries(baseSnapshot.trees)) {\n\t\ttrees[path] = combineSnapshotTreeAndSnapshotBlobs(tree, snapshotBlobs);\n\t}\n\n\t// Create a new snapshot tree with blob contents and processed trees\n\tconst snapshotTreeWithBlobContents: ISnapshotTreeWithBlobContents = {\n\t\t...baseSnapshot,\n\t\tblobsContents,\n\t\ttrees,\n\t};\n\n\treturn snapshotTreeWithBlobContents;\n};\n\nexport function isDeltaStreamConnectionForbiddenError(\n\terror: any,\n): error is DeltaStreamConnectionForbiddenError {\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\terror?.errorType === DriverErrorTypes.deltaStreamConnectionForbidden\n\t);\n}\n\n/**\n * Validates format in parsed string get from detached container\n * serialization using IPendingDetachedContainerState format.\n */\nfunction isPendingDetachedContainerState(\n\tdetachedContainerState: IPendingDetachedContainerState,\n): detachedContainerState is IPendingDetachedContainerState {\n\tif (\n\t\tdetachedContainerState?.attached === undefined ||\n\t\tdetachedContainerState?.baseSnapshot === undefined ||\n\t\tdetachedContainerState?.snapshotBlobs === undefined ||\n\t\tdetachedContainerState?.hasAttachmentBlobs === undefined\n\t) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\n/**\n * Parses the given string into {@link IPendingDetachedContainerState} format,\n * with validation (if invalid, throws a UsageError).\n * This is the inverse of the JSON.stringify call in {@link Container.serialize}\n */\nexport function getDetachedContainerStateFromSerializedContainer(\n\tserializedContainer: string,\n): IPendingDetachedContainerState {\n\tconst hasBlobsSummaryTree = \".hasAttachmentBlobs\";\n\tconst parsedContainerState = JSON.parse(serializedContainer);\n\tif (isPendingDetachedContainerState(parsedContainerState)) {\n\t\treturn parsedContainerState;\n\t} else if (isCombinedAppAndProtocolSummary(parsedContainerState)) {\n\t\tconst { baseSnapshot, snapshotBlobs } =\n\t\t\tgetSnapshotTreeAndBlobsFromSerializedContainer(parsedContainerState);\n\t\tconst detachedContainerState: IPendingDetachedContainerState = {\n\t\t\tattached: false,\n\t\t\tbaseSnapshot,\n\t\t\tsnapshotBlobs,\n\t\t\thasAttachmentBlobs: parsedContainerState.tree[hasBlobsSummaryTree] !== undefined,\n\t\t};\n\t\treturn detachedContainerState;\n\t} else {\n\t\tthrow new UsageError(\"Cannot rehydrate detached container. Incorrect format\");\n\t}\n}\n\n/**\n * Blindly parses the given string into {@link IPendingContainerState} format.\n * This is the inverse of the JSON.stringify call in {@link SerializedStateManager.getPendingLocalState}\n */\nexport function getAttachedContainerStateFromSerializedContainer(\n\tserializedContainer: string | undefined,\n): IPendingContainerState | undefined {\n\treturn serializedContainer !== undefined\n\t\t? (JSON.parse(serializedContainer) as IPendingContainerState)\n\t\t: undefined;\n}\n\n/**\n * Ensures only a single instance of the provided async function is running.\n * If there are multiple calls they will all get the same promise to wait on.\n */\nexport const runSingle = <A extends any[], R>(func: (...args: A) => Promise<R>) => {\n\tlet running:\n\t\t| {\n\t\t\t\targs: A;\n\t\t\t\tresult: Promise<R>;\n\t\t }\n\t\t| undefined;\n\t// don't mark this function async, so we return the same promise,\n\t// rather than one that is wrapped due to async\n\t// eslint-disable-next-line @typescript-eslint/promise-function-async\n\treturn (...args: A) => {\n\t\tif (running !== undefined) {\n\t\t\tif (!compareArrays(running.args, args)) {\n\t\t\t\treturn Promise.reject(\n\t\t\t\t\tnew UsageError(\"Subsequent calls cannot use different arguments.\"),\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn running.result;\n\t\t}\n\t\trunning = { args, result: func(...args).finally(() => (running = undefined)) };\n\t\treturn running.result;\n\t};\n};\n\nexport async function getDocumentAttributes(\n\tstorage: Pick<IDocumentStorageService, \"readBlob\">,\n\ttree: ISnapshotTree | undefined,\n): Promise<IDocumentAttributes> {\n\tif (tree === undefined) {\n\t\treturn {\n\t\t\tminimumSequenceNumber: 0,\n\t\t\tsequenceNumber: 0,\n\t\t};\n\t}\n\n\t// Backward compatibility: old docs would have \".attributes\" instead of \"attributes\"\n\tconst attributesHash =\n\t\t\".protocol\" in tree.trees\n\t\t\t? tree.trees[\".protocol\"].blobs.attributes\n\t\t\t: tree.blobs[\".attributes\"];\n\n\tconst attributes = await readAndParse<IDocumentAttributes>(storage, attributesHash);\n\n\treturn attributes;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/container-loader",
|
|
3
|
-
"version": "2.0.0-rc.
|
|
3
|
+
"version": "2.0.0-rc.4.0.0",
|
|
4
4
|
"description": "Fluid container loader",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -117,15 +117,15 @@
|
|
|
117
117
|
"temp-directory": "nyc/.nyc_output"
|
|
118
118
|
},
|
|
119
119
|
"dependencies": {
|
|
120
|
-
"@fluid-internal/client-utils": ">=2.0.0-rc.
|
|
121
|
-
"@fluidframework/container-definitions": ">=2.0.0-rc.
|
|
122
|
-
"@fluidframework/core-interfaces": ">=2.0.0-rc.
|
|
123
|
-
"@fluidframework/core-utils": ">=2.0.0-rc.
|
|
124
|
-
"@fluidframework/driver-definitions": ">=2.0.0-rc.
|
|
125
|
-
"@fluidframework/driver-utils": ">=2.0.0-rc.
|
|
120
|
+
"@fluid-internal/client-utils": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
121
|
+
"@fluidframework/container-definitions": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
122
|
+
"@fluidframework/core-interfaces": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
123
|
+
"@fluidframework/core-utils": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
124
|
+
"@fluidframework/driver-definitions": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
125
|
+
"@fluidframework/driver-utils": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
126
126
|
"@fluidframework/protocol-base": "^4.0.0",
|
|
127
127
|
"@fluidframework/protocol-definitions": "^3.2.0",
|
|
128
|
-
"@fluidframework/telemetry-utils": ">=2.0.0-rc.
|
|
128
|
+
"@fluidframework/telemetry-utils": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
129
129
|
"@ungap/structured-clone": "^1.2.0",
|
|
130
130
|
"debug": "^4.3.4",
|
|
131
131
|
"double-ended-queue": "^2.1.0-0",
|
|
@@ -134,14 +134,14 @@
|
|
|
134
134
|
"devDependencies": {
|
|
135
135
|
"@arethetypeswrong/cli": "^0.15.2",
|
|
136
136
|
"@biomejs/biome": "^1.6.2",
|
|
137
|
-
"@fluid-internal/mocha-test-setup": ">=2.0.0-rc.
|
|
138
|
-
"@fluid-private/test-loader-utils": ">=2.0.0-rc.
|
|
139
|
-
"@fluid-tools/build-cli": "^0.
|
|
137
|
+
"@fluid-internal/mocha-test-setup": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
138
|
+
"@fluid-private/test-loader-utils": ">=2.0.0-rc.4.0.0 <2.0.0-rc.4.1.0",
|
|
139
|
+
"@fluid-tools/build-cli": "^0.38.0",
|
|
140
140
|
"@fluidframework/build-common": "^2.0.3",
|
|
141
|
-
"@fluidframework/build-tools": "^0.
|
|
142
|
-
"@fluidframework/container-loader-previous": "npm:@fluidframework/container-loader@2.0.0-
|
|
141
|
+
"@fluidframework/build-tools": "^0.38.0",
|
|
142
|
+
"@fluidframework/container-loader-previous": "npm:@fluidframework/container-loader@2.0.0-rc.3.0.0",
|
|
143
143
|
"@fluidframework/eslint-config-fluid": "^5.1.0",
|
|
144
|
-
"@microsoft/api-extractor": "^7.
|
|
144
|
+
"@microsoft/api-extractor": "^7.43.1",
|
|
145
145
|
"@types/debug": "^4.1.5",
|
|
146
146
|
"@types/double-ended-queue": "^2.1.0",
|
|
147
147
|
"@types/mocha": "^9.1.1",
|
|
@@ -164,11 +164,13 @@
|
|
|
164
164
|
},
|
|
165
165
|
"typeValidation": {
|
|
166
166
|
"broken": {
|
|
167
|
-
"
|
|
168
|
-
"forwardCompat": false
|
|
167
|
+
"InterfaceDeclaration_IProtocolHandler": {
|
|
168
|
+
"forwardCompat": false,
|
|
169
|
+
"backCompat": false
|
|
169
170
|
},
|
|
170
|
-
"
|
|
171
|
-
"forwardCompat": false
|
|
171
|
+
"InterfaceDeclaration_IContainerExperimental": {
|
|
172
|
+
"forwardCompat": false,
|
|
173
|
+
"backCompat": false
|
|
172
174
|
}
|
|
173
175
|
}
|
|
174
176
|
},
|
|
@@ -196,15 +198,16 @@
|
|
|
196
198
|
"format:prettier": "prettier --write . --cache --ignore-path ../../../.prettierignore",
|
|
197
199
|
"lint": "fluid-build . --task lint",
|
|
198
200
|
"lint:fix": "fluid-build . --task eslint:fix --task format",
|
|
201
|
+
"place:cjs:package-stub": "copyfiles -f ../../../common/build/build-common/src/cjs/package.json ./dist",
|
|
199
202
|
"test": "npm run test:mocha",
|
|
200
203
|
"test:coverage": "c8 npm test",
|
|
201
204
|
"test:mocha": "npm run test:mocha:esm && echo skipping cjs to avoid overhead - npm run test:mocha:cjs",
|
|
202
205
|
"test:mocha:cjs": "mocha --recursive \"dist/test/**/*.spec.*js\" --exit",
|
|
203
206
|
"test:mocha:esm": "mocha --recursive \"lib/test/**/*.spec.*js\" --exit",
|
|
204
207
|
"test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
|
|
205
|
-
"tsc": "fluid-tsc commonjs --project ./tsconfig.cjs.json &&
|
|
206
|
-
"tsc:watch": "tsc --watch",
|
|
207
|
-
"typetests:gen": "
|
|
208
|
+
"tsc": "fluid-tsc commonjs --project ./tsconfig.cjs.json && npm run place:cjs:package-stub",
|
|
209
|
+
"tsc:watch": "npm run place:cjs:package-stub && fluid-tsc commonjs --project ./tsconfig.cjs.json --watch",
|
|
210
|
+
"typetests:gen": "flub generate typetests --dir . -v --publicFallback",
|
|
208
211
|
"typetests:prepare": "flub typetests --dir . --reset --previous --normalize"
|
|
209
212
|
}
|
|
210
213
|
}
|
package/src/attachment.ts
CHANGED
|
@@ -132,19 +132,18 @@ export interface AttachProcessProps {
|
|
|
132
132
|
* This method is retriable on failure. Based on the provided initialAttachmentData
|
|
133
133
|
* this method will resume the attachment process and attempt to complete it.
|
|
134
134
|
*
|
|
135
|
-
* @param
|
|
135
|
+
* @param AttachProcessProps - The data and services necessary to run the attachment process
|
|
136
|
+
* @returns - The attach summary (only if offline load is enabled), or undefined
|
|
136
137
|
*/
|
|
137
|
-
export const runRetriableAttachProcess = async (
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
} = props;
|
|
147
|
-
let currentData: AttachmentData = props.initialAttachmentData;
|
|
138
|
+
export const runRetriableAttachProcess = async ({
|
|
139
|
+
detachedBlobStorage,
|
|
140
|
+
createOrGetStorageService,
|
|
141
|
+
setAttachmentData,
|
|
142
|
+
createAttachmentSummary,
|
|
143
|
+
offlineLoadEnabled,
|
|
144
|
+
initialAttachmentData,
|
|
145
|
+
}: AttachProcessProps): Promise<SnapshotWithBlobs | undefined> => {
|
|
146
|
+
let currentData: AttachmentData = initialAttachmentData;
|
|
148
147
|
|
|
149
148
|
if (currentData.blobs === undefined) {
|
|
150
149
|
// If attachment blobs were uploaded in detached state we will go through a different attach flow
|
|
@@ -161,7 +160,7 @@ export const runRetriableAttachProcess = async (
|
|
|
161
160
|
}
|
|
162
161
|
: {
|
|
163
162
|
state: AttachState.Attaching,
|
|
164
|
-
summary:
|
|
163
|
+
summary: createAttachmentSummary(),
|
|
165
164
|
blobs: "none",
|
|
166
165
|
};
|
|
167
166
|
setAttachmentData(currentData);
|
package/src/audience.ts
CHANGED
|
@@ -3,16 +3,21 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
7
|
+
import {
|
|
8
|
+
IAudienceEvents,
|
|
9
|
+
IAudienceOwner,
|
|
10
|
+
ISelf,
|
|
11
|
+
} from "@fluidframework/container-definitions/internal";
|
|
8
12
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
9
13
|
import { IClient } from "@fluidframework/protocol-definitions";
|
|
10
14
|
|
|
11
15
|
/**
|
|
12
16
|
* Audience represents all clients connected to the op stream.
|
|
13
17
|
*/
|
|
14
|
-
export class Audience extends
|
|
18
|
+
export class Audience extends TypedEventEmitter<IAudienceEvents> implements IAudienceOwner {
|
|
15
19
|
private readonly members = new Map<string, IClient>();
|
|
20
|
+
private _currentClientId: string | undefined;
|
|
16
21
|
|
|
17
22
|
constructor() {
|
|
18
23
|
super();
|
|
@@ -20,12 +25,28 @@ export class Audience extends EventEmitter implements IAudienceOwner {
|
|
|
20
25
|
super.setMaxListeners(0);
|
|
21
26
|
}
|
|
22
27
|
|
|
23
|
-
public
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
public getSelf(): ISelf | undefined {
|
|
29
|
+
return this._currentClientId === undefined
|
|
30
|
+
? undefined
|
|
31
|
+
: {
|
|
32
|
+
clientId: this._currentClientId,
|
|
33
|
+
client: this.getMember(this._currentClientId),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public setCurrentClientId(clientId: string): void {
|
|
38
|
+
if (this._currentClientId !== clientId) {
|
|
39
|
+
const oldId = this._currentClientId;
|
|
40
|
+
this._currentClientId = clientId;
|
|
41
|
+
// this.getMember(clientId) could resolve to undefined in these two cases:
|
|
42
|
+
// 1) Feature gates controlling ConnectionStateHandler() behavior are off
|
|
43
|
+
// 2) we are loading from stashed state and audience is empty, but we remember and set prior clientId
|
|
44
|
+
this.emit(
|
|
45
|
+
"selfChanged",
|
|
46
|
+
oldId === undefined ? undefined : ({ clientId: oldId } satisfies ISelf),
|
|
47
|
+
{ clientId, client: this.getMember(clientId) } satisfies ISelf,
|
|
48
|
+
);
|
|
49
|
+
}
|
|
29
50
|
}
|
|
30
51
|
|
|
31
52
|
/**
|
package/src/catchUpMonitor.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { IDeltaManager } from "@fluidframework/container-definitions";
|
|
6
|
+
import { IDeltaManager } from "@fluidframework/container-definitions/internal";
|
|
7
7
|
import { IDisposable } from "@fluidframework/core-interfaces";
|
|
8
8
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
9
9
|
import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
|
package/src/connectionManager.ts
CHANGED
|
@@ -8,14 +8,15 @@ import {
|
|
|
8
8
|
ICriticalContainerError,
|
|
9
9
|
IDeltaQueue,
|
|
10
10
|
ReadOnlyInfo,
|
|
11
|
-
} from "@fluidframework/container-definitions";
|
|
11
|
+
} from "@fluidframework/container-definitions/internal";
|
|
12
12
|
import { IDisposable, ITelemetryBaseProperties, LogLevel } from "@fluidframework/core-interfaces";
|
|
13
13
|
import { assert } from "@fluidframework/core-utils/internal";
|
|
14
|
-
import { DriverErrorTypes, IAnyDriverError } from "@fluidframework/driver-definitions";
|
|
15
14
|
import {
|
|
16
15
|
IDocumentDeltaConnection,
|
|
17
16
|
IDocumentDeltaConnectionEvents,
|
|
18
17
|
IDocumentService,
|
|
18
|
+
DriverErrorTypes,
|
|
19
|
+
IAnyDriverError,
|
|
19
20
|
} from "@fluidframework/driver-definitions/internal";
|
|
20
21
|
import {
|
|
21
22
|
calculateMaxWaitTime,
|
|
@@ -42,11 +43,12 @@ import {
|
|
|
42
43
|
MessageType,
|
|
43
44
|
ScopeType,
|
|
44
45
|
} from "@fluidframework/protocol-definitions";
|
|
45
|
-
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
|
|
46
46
|
import {
|
|
47
|
+
ITelemetryLoggerExt,
|
|
47
48
|
GenericError,
|
|
48
49
|
UsageError,
|
|
49
50
|
formatTick,
|
|
51
|
+
generateStack,
|
|
50
52
|
isFluidError,
|
|
51
53
|
normalizeError,
|
|
52
54
|
} from "@fluidframework/telemetry-utils/internal";
|
|
@@ -203,6 +205,9 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
203
205
|
private pendingConnection: IPendingConnection | undefined;
|
|
204
206
|
private connection: IDocumentDeltaConnection | undefined;
|
|
205
207
|
|
|
208
|
+
/** Details about connection. undefined if there is no active connection. */
|
|
209
|
+
private _connectionDetails?: IConnectionDetailsInternal;
|
|
210
|
+
|
|
206
211
|
/** file ACL - whether user has only read-only access to a file */
|
|
207
212
|
private _readonlyPermissions: boolean | undefined;
|
|
208
213
|
|
|
@@ -255,6 +260,12 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
255
260
|
public get clientId() {
|
|
256
261
|
return this.connection?.clientId;
|
|
257
262
|
}
|
|
263
|
+
|
|
264
|
+
/** Details about connection. undefined if there is no active connection. */
|
|
265
|
+
public get connectionDetails() {
|
|
266
|
+
return this._connectionDetails;
|
|
267
|
+
}
|
|
268
|
+
|
|
258
269
|
/**
|
|
259
270
|
* Automatic reconnecting enabled or disabled.
|
|
260
271
|
* If set to Never, then reconnecting will never be allowed.
|
|
@@ -505,21 +516,7 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
505
516
|
): Promise<void> {
|
|
506
517
|
assert(!this._disposed, 0x26a /* "not closed" */);
|
|
507
518
|
|
|
508
|
-
|
|
509
|
-
return; // Connection attempt already completed successfully
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
let pendingConnectionMode;
|
|
513
|
-
if (this.pendingConnection !== undefined) {
|
|
514
|
-
pendingConnectionMode = this.pendingConnection.connectionMode;
|
|
515
|
-
this.cancelConnection(reason); // Throw out in-progress connection attempt in favor of new attempt
|
|
516
|
-
assert(
|
|
517
|
-
this.pendingConnection === undefined,
|
|
518
|
-
0x344 /* this.pendingConnection should be undefined */,
|
|
519
|
-
);
|
|
520
|
-
}
|
|
521
|
-
// If there is no specified ConnectionMode, try the previous mode, if there is no previous mode use default
|
|
522
|
-
let requestedMode = connectionMode ?? pendingConnectionMode ?? this.defaultReconnectionMode;
|
|
519
|
+
let requestedMode = connectionMode ?? this.defaultReconnectionMode;
|
|
523
520
|
|
|
524
521
|
// if we have any non-acked ops from last connection, reconnect as "write".
|
|
525
522
|
// without that we would connect in view-only mode, which will result in immediate
|
|
@@ -530,6 +527,28 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
530
527
|
requestedMode = "write";
|
|
531
528
|
}
|
|
532
529
|
|
|
530
|
+
if (this.connection !== undefined || this.pendingConnection !== undefined) {
|
|
531
|
+
// Connection attempt already completed successfully or is in progress
|
|
532
|
+
// In general, there should be no issues if the modes do not match:
|
|
533
|
+
// If at some point it was Ok to connect as "read" (i.e. there were no pending ops we had to track),
|
|
534
|
+
// then it should be Ok to use "read" connection even if for some reason request came in to connect as "write"
|
|
535
|
+
// (though that should never happen)
|
|
536
|
+
// The opposite should be fine as well: we may have had idle "write" connection, and request to reconnect came in,
|
|
537
|
+
// using default "read" mode.
|
|
538
|
+
// That all said, let's understand better where such mismatches are coming from.
|
|
539
|
+
const mode = this.connection?.mode ?? this.pendingConnection?.connectionMode;
|
|
540
|
+
if (mode !== requestedMode) {
|
|
541
|
+
this.logger.sendTelemetryEvent({
|
|
542
|
+
eventName: "ConnectionModeMismatch",
|
|
543
|
+
connected: this.connection !== undefined,
|
|
544
|
+
mode,
|
|
545
|
+
requestedMode,
|
|
546
|
+
stack: generateStack(),
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
|
|
533
552
|
const docService = this.serviceProvider();
|
|
534
553
|
assert(docService !== undefined, 0x2a7 /* "Container is not attached" */);
|
|
535
554
|
|
|
@@ -758,6 +777,7 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
758
777
|
const connection = this.connection;
|
|
759
778
|
// Avoid any re-entrancy - clear object reference
|
|
760
779
|
this.connection = undefined;
|
|
780
|
+
this._connectionDetails = undefined;
|
|
761
781
|
|
|
762
782
|
// Remove listeners first so we don't try to retrigger this flow accidentally through reconnectOnError
|
|
763
783
|
connection.off("op", this.opHandler);
|
|
@@ -789,7 +809,10 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
789
809
|
);
|
|
790
810
|
this.pendingConnection.abort();
|
|
791
811
|
this.pendingConnection = undefined;
|
|
792
|
-
this.logger.sendTelemetryEvent({
|
|
812
|
+
this.logger.sendTelemetryEvent({
|
|
813
|
+
eventName: "ConnectionCancelReceived",
|
|
814
|
+
reason: reason.text,
|
|
815
|
+
});
|
|
793
816
|
this.props.cancelConnectionHandler({
|
|
794
817
|
text: `Cancel Pending Connection due to ${reason.text}`,
|
|
795
818
|
error: reason.error,
|
|
@@ -910,9 +933,9 @@ export class ConnectionManager implements IConnectionManager {
|
|
|
910
933
|
this.connectFirstConnection ? "InitialOps" : "ReconnectOps",
|
|
911
934
|
);
|
|
912
935
|
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
this.props.connectHandler(
|
|
936
|
+
this._connectionDetails = ConnectionManager.detailsFromConnection(connection, reason);
|
|
937
|
+
this._connectionDetails.checkpointSequenceNumber = checkpointSequenceNumber;
|
|
938
|
+
this.props.connectHandler(this._connectionDetails);
|
|
916
939
|
|
|
917
940
|
this.connectFirstConnection = false;
|
|
918
941
|
|