@fluidframework/routerlicious-driver 1.4.0-115997 → 2.0.0-dev-rc.1.0.0.224419
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/.eslintrc.js +10 -12
- package/.mocharc.js +12 -0
- package/CHANGELOG.md +156 -0
- package/README.md +39 -1
- package/api-extractor-lint.json +4 -0
- package/api-extractor.json +2 -2
- package/api-report/routerlicious-driver.api.md +108 -0
- package/dist/cache.cjs +30 -0
- package/dist/cache.cjs.map +1 -0
- package/dist/cache.d.ts +7 -0
- package/dist/cache.d.ts.map +1 -1
- package/dist/{definitions.js → contracts.cjs} +1 -1
- package/dist/contracts.cjs.map +1 -0
- package/dist/contracts.d.ts +42 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/{createNewUtils.js → createNewUtils.cjs} +7 -5
- package/dist/createNewUtils.cjs.map +1 -0
- package/dist/createNewUtils.d.ts +1 -1
- package/dist/createNewUtils.d.ts.map +1 -1
- package/dist/{defaultTokenProvider.js → defaultTokenProvider.cjs} +2 -1
- package/dist/defaultTokenProvider.cjs.map +1 -0
- package/dist/defaultTokenProvider.d.ts +1 -0
- package/dist/defaultTokenProvider.d.ts.map +1 -1
- package/dist/definitions.cjs +7 -0
- package/dist/definitions.cjs.map +1 -0
- package/dist/definitions.d.ts.map +1 -1
- package/dist/deltaStorageService.cjs +122 -0
- package/dist/deltaStorageService.cjs.map +1 -0
- package/dist/deltaStorageService.d.ts +7 -6
- package/dist/deltaStorageService.d.ts.map +1 -1
- package/dist/{documentDeltaConnection.js → documentDeltaConnection.cjs} +8 -13
- package/dist/documentDeltaConnection.cjs.map +1 -0
- package/dist/documentDeltaConnection.d.ts +3 -4
- package/dist/documentDeltaConnection.d.ts.map +1 -1
- package/dist/{documentService.js → documentService.cjs} +61 -64
- package/dist/documentService.cjs.map +1 -0
- package/dist/documentService.d.ts +12 -4
- package/dist/documentService.d.ts.map +1 -1
- package/dist/{documentServiceFactory.js → documentServiceFactory.cjs} +87 -33
- package/dist/documentServiceFactory.cjs.map +1 -0
- package/dist/documentServiceFactory.d.ts +5 -3
- package/dist/documentServiceFactory.d.ts.map +1 -1
- package/dist/{documentStorageService.js → documentStorageService.cjs} +18 -16
- package/dist/documentStorageService.cjs.map +1 -0
- package/dist/documentStorageService.d.ts +4 -3
- package/dist/documentStorageService.d.ts.map +1 -1
- package/dist/errorUtils.cjs +87 -0
- package/dist/errorUtils.cjs.map +1 -0
- package/dist/errorUtils.d.ts +56 -10
- package/dist/errorUtils.d.ts.map +1 -1
- package/dist/gitManager.cjs +46 -0
- package/dist/gitManager.cjs.map +1 -0
- package/dist/gitManager.d.ts +27 -0
- package/dist/gitManager.d.ts.map +1 -0
- package/dist/historian.cjs +72 -0
- package/dist/historian.cjs.map +1 -0
- package/dist/historian.d.ts +34 -0
- package/dist/historian.d.ts.map +1 -0
- package/dist/index.cjs +19 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +5 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/mapWithExpiration.cjs +105 -0
- package/dist/mapWithExpiration.cjs.map +1 -0
- package/dist/mapWithExpiration.d.ts +34 -0
- package/dist/mapWithExpiration.d.ts.map +1 -0
- package/dist/{nullBlobStorageService.js → nullBlobStorageService.cjs} +5 -5
- package/dist/nullBlobStorageService.cjs.map +1 -0
- package/dist/nullBlobStorageService.d.ts.map +1 -1
- package/dist/{packageVersion.js → packageVersion.cjs} +2 -2
- package/dist/packageVersion.cjs.map +1 -0
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/{policies.js → policies.cjs} +1 -1
- package/dist/policies.cjs.map +1 -0
- package/dist/policies.d.ts +22 -9
- package/dist/policies.d.ts.map +1 -1
- package/dist/r11sSnapshotParser.cjs +73 -0
- package/dist/r11sSnapshotParser.cjs.map +1 -0
- package/dist/r11sSnapshotParser.d.ts +14 -0
- package/dist/r11sSnapshotParser.d.ts.map +1 -0
- package/dist/restWrapper.cjs +249 -0
- package/dist/restWrapper.cjs.map +1 -0
- package/dist/restWrapper.d.ts +32 -12
- package/dist/restWrapper.d.ts.map +1 -1
- package/dist/restWrapperBase.cjs +89 -0
- package/dist/restWrapperBase.cjs.map +1 -0
- package/dist/restWrapperBase.d.ts +26 -0
- package/dist/restWrapperBase.d.ts.map +1 -0
- package/dist/retriableGitManager.cjs +40 -0
- package/dist/retriableGitManager.cjs.map +1 -0
- package/dist/retriableGitManager.d.ts +13 -23
- package/dist/retriableGitManager.d.ts.map +1 -1
- package/dist/routerlicious-driver-alpha.d.ts +92 -0
- package/dist/routerlicious-driver-beta.d.ts +98 -0
- package/dist/routerlicious-driver-public.d.ts +98 -0
- package/dist/routerlicious-driver-untrimmed.d.ts +261 -0
- package/dist/{shreddedSummaryDocumentStorageService.js → shreddedSummaryDocumentStorageService.cjs} +41 -34
- package/dist/shreddedSummaryDocumentStorageService.cjs.map +1 -0
- package/dist/shreddedSummaryDocumentStorageService.d.ts +6 -5
- package/dist/shreddedSummaryDocumentStorageService.d.ts.map +1 -1
- package/dist/storageContracts.cjs +7 -0
- package/dist/storageContracts.cjs.map +1 -0
- package/dist/storageContracts.d.ts +45 -0
- package/dist/storageContracts.d.ts.map +1 -0
- package/dist/summaryTreeUploadManager.cjs +110 -0
- package/dist/summaryTreeUploadManager.cjs.map +1 -0
- package/dist/summaryTreeUploadManager.d.ts +23 -0
- package/dist/summaryTreeUploadManager.d.ts.map +1 -0
- package/dist/{tokens.js → tokens.cjs} +1 -1
- package/dist/tokens.cjs.map +1 -0
- package/dist/tokens.d.ts +34 -5
- package/dist/tokens.d.ts.map +1 -1
- package/dist/treeUtils.cjs +107 -0
- package/dist/treeUtils.cjs.map +1 -0
- package/dist/treeUtils.d.ts +58 -0
- package/dist/treeUtils.d.ts.map +1 -0
- package/dist/tsdoc-metadata.json +11 -0
- package/dist/{urlUtils.js → urlUtils.cjs} +21 -25
- package/dist/urlUtils.cjs.map +1 -0
- package/dist/urlUtils.d.ts +2 -2
- package/dist/urlUtils.d.ts.map +1 -1
- package/dist/wholeSummaryDocumentStorageService.cjs +253 -0
- package/dist/wholeSummaryDocumentStorageService.cjs.map +1 -0
- package/dist/wholeSummaryDocumentStorageService.d.ts +10 -8
- package/dist/wholeSummaryDocumentStorageService.d.ts.map +1 -1
- package/dist/wholeSummaryUploadManager.cjs +37 -0
- package/dist/wholeSummaryUploadManager.cjs.map +1 -0
- package/dist/wholeSummaryUploadManager.d.ts +16 -0
- package/dist/wholeSummaryUploadManager.d.ts.map +1 -0
- package/lib/{cache.d.ts → cache.d.mts} +7 -0
- package/lib/cache.d.mts.map +1 -0
- package/lib/cache.mjs +25 -0
- package/lib/cache.mjs.map +1 -0
- package/lib/contracts.d.mts +42 -0
- package/lib/contracts.d.mts.map +1 -0
- package/lib/{definitions.js → contracts.mjs} +1 -1
- package/lib/contracts.mjs.map +1 -0
- package/lib/{createNewUtils.d.ts → createNewUtils.d.mts} +1 -1
- package/lib/{createNewUtils.d.ts.map → createNewUtils.d.mts.map} +1 -1
- package/lib/{createNewUtils.js → createNewUtils.mjs} +7 -5
- package/lib/createNewUtils.mjs.map +1 -0
- package/lib/{defaultTokenProvider.d.ts → defaultTokenProvider.d.mts} +2 -1
- package/lib/defaultTokenProvider.d.mts.map +1 -0
- package/lib/{defaultTokenProvider.js → defaultTokenProvider.mjs} +2 -1
- package/lib/defaultTokenProvider.mjs.map +1 -0
- package/lib/definitions.d.mts.map +1 -0
- package/lib/definitions.mjs +6 -0
- package/{dist/definitions.js.map → lib/definitions.mjs.map} +1 -1
- package/lib/{deltaStorageService.d.ts → deltaStorageService.d.mts} +8 -7
- package/lib/deltaStorageService.d.mts.map +1 -0
- package/lib/deltaStorageService.mjs +117 -0
- package/lib/deltaStorageService.mjs.map +1 -0
- package/lib/{documentDeltaConnection.d.ts → documentDeltaConnection.d.mts} +3 -4
- package/lib/documentDeltaConnection.d.mts.map +1 -0
- package/lib/{documentDeltaConnection.js → documentDeltaConnection.mjs} +8 -13
- package/lib/documentDeltaConnection.mjs.map +1 -0
- package/lib/{documentService.d.ts → documentService.d.mts} +16 -8
- package/lib/documentService.d.mts.map +1 -0
- package/lib/{documentService.js → documentService.mjs} +60 -44
- package/lib/documentService.mjs.map +1 -0
- package/lib/{documentServiceFactory.d.ts → documentServiceFactory.d.mts} +7 -5
- package/lib/documentServiceFactory.d.mts.map +1 -0
- package/lib/{documentServiceFactory.js → documentServiceFactory.mjs} +88 -34
- package/lib/documentServiceFactory.mjs.map +1 -0
- package/lib/{documentStorageService.d.ts → documentStorageService.d.mts} +7 -6
- package/lib/documentStorageService.d.mts.map +1 -0
- package/lib/{documentStorageService.js → documentStorageService.mjs} +19 -17
- package/lib/documentStorageService.mjs.map +1 -0
- package/lib/errorUtils.d.mts +93 -0
- package/lib/errorUtils.d.mts.map +1 -0
- package/lib/errorUtils.mjs +81 -0
- package/lib/errorUtils.mjs.map +1 -0
- package/lib/gitManager.d.mts +27 -0
- package/lib/gitManager.d.mts.map +1 -0
- package/lib/gitManager.mjs +42 -0
- package/lib/gitManager.mjs.map +1 -0
- package/lib/historian.d.mts +34 -0
- package/lib/historian.d.mts.map +1 -0
- package/lib/historian.mjs +67 -0
- package/lib/historian.mjs.map +1 -0
- package/lib/index.d.mts +10 -0
- package/lib/index.d.mts.map +1 -0
- package/lib/index.mjs +8 -0
- package/lib/index.mjs.map +1 -0
- package/lib/mapWithExpiration.d.mts +34 -0
- package/lib/mapWithExpiration.d.mts.map +1 -0
- package/lib/mapWithExpiration.mjs +101 -0
- package/lib/mapWithExpiration.mjs.map +1 -0
- package/lib/nullBlobStorageService.d.mts.map +1 -0
- package/lib/{nullBlobStorageService.js → nullBlobStorageService.mjs} +5 -5
- package/lib/nullBlobStorageService.mjs.map +1 -0
- package/lib/{packageVersion.d.ts → packageVersion.d.mts} +1 -1
- package/lib/{packageVersion.d.ts.map → packageVersion.d.mts.map} +1 -1
- package/lib/{packageVersion.js → packageVersion.mjs} +2 -2
- package/lib/packageVersion.mjs.map +1 -0
- package/lib/{policies.d.ts → policies.d.mts} +22 -9
- package/lib/policies.d.mts.map +1 -0
- package/lib/{policies.js → policies.mjs} +1 -1
- package/lib/policies.mjs.map +1 -0
- package/lib/r11sSnapshotParser.d.mts +14 -0
- package/lib/r11sSnapshotParser.d.mts.map +1 -0
- package/lib/r11sSnapshotParser.mjs +69 -0
- package/lib/r11sSnapshotParser.mjs.map +1 -0
- package/lib/restWrapper.d.mts +53 -0
- package/lib/restWrapper.d.mts.map +1 -0
- package/lib/restWrapper.mjs +236 -0
- package/lib/restWrapper.mjs.map +1 -0
- package/lib/restWrapperBase.d.mts +26 -0
- package/lib/restWrapperBase.d.mts.map +1 -0
- package/lib/restWrapperBase.mjs +84 -0
- package/lib/restWrapperBase.mjs.map +1 -0
- package/lib/retriableGitManager.d.mts +24 -0
- package/lib/retriableGitManager.d.mts.map +1 -0
- package/lib/retriableGitManager.mjs +36 -0
- package/lib/retriableGitManager.mjs.map +1 -0
- package/lib/routerlicious-driver-alpha.d.mts +92 -0
- package/lib/routerlicious-driver-beta.d.mts +98 -0
- package/lib/routerlicious-driver-public.d.mts +98 -0
- package/lib/routerlicious-driver-untrimmed.d.mts +261 -0
- package/lib/{shreddedSummaryDocumentStorageService.d.ts → shreddedSummaryDocumentStorageService.d.mts} +9 -8
- package/lib/shreddedSummaryDocumentStorageService.d.mts.map +1 -0
- package/lib/{shreddedSummaryDocumentStorageService.js → shreddedSummaryDocumentStorageService.mjs} +41 -34
- package/lib/shreddedSummaryDocumentStorageService.mjs.map +1 -0
- package/lib/storageContracts.d.mts +45 -0
- package/lib/storageContracts.d.mts.map +1 -0
- package/lib/storageContracts.mjs +6 -0
- package/lib/storageContracts.mjs.map +1 -0
- package/lib/summaryTreeUploadManager.d.mts +23 -0
- package/lib/summaryTreeUploadManager.d.mts.map +1 -0
- package/lib/summaryTreeUploadManager.mjs +106 -0
- package/lib/summaryTreeUploadManager.mjs.map +1 -0
- package/lib/{tokens.d.ts → tokens.d.mts} +34 -5
- package/lib/tokens.d.mts.map +1 -0
- package/lib/{tokens.js → tokens.mjs} +1 -1
- package/lib/tokens.mjs.map +1 -0
- package/lib/treeUtils.d.mts +58 -0
- package/lib/treeUtils.d.mts.map +1 -0
- package/lib/treeUtils.mjs +100 -0
- package/lib/treeUtils.mjs.map +1 -0
- package/lib/{urlUtils.d.ts → urlUtils.d.mts} +2 -2
- package/lib/urlUtils.d.mts.map +1 -0
- package/lib/urlUtils.mjs +38 -0
- package/lib/urlUtils.mjs.map +1 -0
- package/lib/{wholeSummaryDocumentStorageService.d.ts → wholeSummaryDocumentStorageService.d.mts} +12 -10
- package/lib/wholeSummaryDocumentStorageService.d.mts.map +1 -0
- package/lib/wholeSummaryDocumentStorageService.mjs +249 -0
- package/lib/wholeSummaryDocumentStorageService.mjs.map +1 -0
- package/lib/wholeSummaryUploadManager.d.mts +16 -0
- package/lib/wholeSummaryUploadManager.d.mts.map +1 -0
- package/lib/wholeSummaryUploadManager.mjs +33 -0
- package/lib/wholeSummaryUploadManager.mjs.map +1 -0
- package/package.json +104 -68
- package/prettier.config.cjs +8 -0
- package/src/cache.ts +25 -9
- package/src/contracts.ts +60 -0
- package/src/createNewUtils.ts +26 -24
- package/src/defaultTokenProvider.ts +14 -15
- package/src/definitions.ts +2 -2
- package/src/deltaStorageService.ts +145 -91
- package/src/documentDeltaConnection.ts +54 -52
- package/src/documentService.ts +272 -242
- package/src/documentServiceFactory.ts +338 -237
- package/src/documentStorageService.ts +92 -84
- package/src/errorUtils.ts +117 -79
- package/src/gitManager.ts +67 -0
- package/src/historian.ts +121 -0
- package/src/index.ts +15 -8
- package/src/mapWithExpiration.ts +124 -0
- package/src/nullBlobStorageService.ts +24 -21
- package/src/packageVersion.ts +1 -1
- package/src/policies.ts +51 -38
- package/src/r11sSnapshotParser.ts +82 -0
- package/src/restWrapper.ts +400 -216
- package/src/restWrapperBase.ts +146 -0
- package/src/retriableGitManager.ts +76 -153
- package/src/shreddedSummaryDocumentStorageService.ts +214 -195
- package/src/storageContracts.ts +63 -0
- package/src/summaryTreeUploadManager.ts +155 -0
- package/src/tokens.ts +74 -39
- package/src/treeUtils.ts +138 -0
- package/src/urlUtils.ts +27 -28
- package/src/wholeSummaryDocumentStorageService.ts +352 -252
- package/src/wholeSummaryUploadManager.ts +64 -0
- package/tsc-multi.test.json +4 -0
- package/tsconfig.json +10 -13
- package/dist/cache.js +0 -20
- package/dist/cache.js.map +0 -1
- package/dist/createNewUtils.js.map +0 -1
- package/dist/defaultTokenProvider.js.map +0 -1
- package/dist/deltaStorageService.js +0 -82
- package/dist/deltaStorageService.js.map +0 -1
- package/dist/documentDeltaConnection.js.map +0 -1
- package/dist/documentService.js.map +0 -1
- package/dist/documentServiceFactory.js.map +0 -1
- package/dist/documentStorageService.js.map +0 -1
- package/dist/errorUtils.js +0 -56
- package/dist/errorUtils.js.map +0 -1
- package/dist/index.js +0 -25
- package/dist/index.js.map +0 -1
- package/dist/nullBlobStorageService.js.map +0 -1
- package/dist/packageVersion.js.map +0 -1
- package/dist/policies.js.map +0 -1
- package/dist/restWrapper.js +0 -153
- package/dist/restWrapper.js.map +0 -1
- package/dist/retriableGitManager.js +0 -76
- package/dist/retriableGitManager.js.map +0 -1
- package/dist/shreddedSummaryDocumentStorageService.js.map +0 -1
- package/dist/tokens.js.map +0 -1
- package/dist/urlUtils.js.map +0 -1
- package/dist/wholeSummaryDocumentStorageService.js +0 -191
- package/dist/wholeSummaryDocumentStorageService.js.map +0 -1
- package/lib/cache.d.ts.map +0 -1
- package/lib/cache.js +0 -16
- package/lib/cache.js.map +0 -1
- package/lib/createNewUtils.js.map +0 -1
- package/lib/defaultTokenProvider.d.ts.map +0 -1
- package/lib/defaultTokenProvider.js.map +0 -1
- package/lib/definitions.d.ts.map +0 -1
- package/lib/definitions.js.map +0 -1
- package/lib/deltaStorageService.d.ts.map +0 -1
- package/lib/deltaStorageService.js +0 -77
- package/lib/deltaStorageService.js.map +0 -1
- package/lib/documentDeltaConnection.d.ts.map +0 -1
- package/lib/documentDeltaConnection.js.map +0 -1
- package/lib/documentService.d.ts.map +0 -1
- package/lib/documentService.js.map +0 -1
- package/lib/documentServiceFactory.d.ts.map +0 -1
- package/lib/documentServiceFactory.js.map +0 -1
- package/lib/documentStorageService.d.ts.map +0 -1
- package/lib/documentStorageService.js.map +0 -1
- package/lib/errorUtils.d.ts +0 -47
- package/lib/errorUtils.d.ts.map +0 -1
- package/lib/errorUtils.js +0 -50
- package/lib/errorUtils.js.map +0 -1
- package/lib/index.d.ts +0 -13
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js +0 -13
- package/lib/index.js.map +0 -1
- package/lib/nullBlobStorageService.d.ts.map +0 -1
- package/lib/nullBlobStorageService.js.map +0 -1
- package/lib/packageVersion.js.map +0 -1
- package/lib/policies.d.ts.map +0 -1
- package/lib/policies.js.map +0 -1
- package/lib/restWrapper.d.ts +0 -33
- package/lib/restWrapper.d.ts.map +0 -1
- package/lib/restWrapper.js +0 -144
- package/lib/restWrapper.js.map +0 -1
- package/lib/retriableGitManager.d.ts +0 -34
- package/lib/retriableGitManager.d.ts.map +0 -1
- package/lib/retriableGitManager.js +0 -72
- package/lib/retriableGitManager.js.map +0 -1
- package/lib/shreddedSummaryDocumentStorageService.d.ts.map +0 -1
- package/lib/shreddedSummaryDocumentStorageService.js.map +0 -1
- package/lib/tokens.d.ts.map +0 -1
- package/lib/tokens.js.map +0 -1
- package/lib/urlUtils.d.ts.map +0 -1
- package/lib/urlUtils.js +0 -42
- package/lib/urlUtils.js.map +0 -1
- package/lib/wholeSummaryDocumentStorageService.d.ts.map +0 -1
- package/lib/wholeSummaryDocumentStorageService.js +0 -187
- package/lib/wholeSummaryDocumentStorageService.js.map +0 -1
- package/tsconfig.esnext.json +0 -7
- /package/lib/{definitions.d.ts → definitions.d.mts} +0 -0
- /package/lib/{nullBlobStorageService.d.ts → nullBlobStorageService.d.mts} +0 -0
package/src/restWrapper.ts
CHANGED
|
@@ -2,235 +2,419 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
5
|
+
|
|
6
|
+
import { ITelemetryProperties } from "@fluidframework/core-interfaces";
|
|
7
|
+
import {
|
|
8
|
+
ITelemetryLoggerExt,
|
|
9
|
+
PerformanceEvent,
|
|
10
|
+
numberFromString,
|
|
11
|
+
} from "@fluidframework/telemetry-utils";
|
|
12
|
+
import { assert } from "@fluidframework/core-utils";
|
|
13
|
+
import { fromUtf8ToBase64, performance } from "@fluid-internal/client-utils";
|
|
14
|
+
import { GenericNetworkError, NonRetryableError, RateLimiter } from "@fluidframework/driver-utils";
|
|
9
15
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
CorrelationIdHeaderName,
|
|
17
|
+
DriverVersionHeaderName,
|
|
18
|
+
getAuthorizationTokenFromCredentials,
|
|
19
|
+
RestLessClient,
|
|
13
20
|
} from "@fluidframework/server-services-client";
|
|
14
|
-
import { PerformanceEvent } from "@fluidframework/telemetry-utils";
|
|
15
21
|
import fetch from "cross-fetch";
|
|
16
|
-
import type { AxiosRequestConfig,
|
|
22
|
+
import type { AxiosRequestConfig, RawAxiosRequestHeaders } from "axios";
|
|
17
23
|
import safeStringify from "json-stringify-safe";
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import { ITokenProvider } from "./tokens";
|
|
24
|
+
import { RouterliciousErrorTypes, throwR11sNetworkError } from "./errorUtils";
|
|
25
|
+
import { ITokenProvider, ITokenResponse } from "./tokens";
|
|
21
26
|
import { pkgVersion as driverVersion } from "./packageVersion";
|
|
27
|
+
import { QueryStringType, RestWrapper } from "./restWrapperBase";
|
|
28
|
+
|
|
29
|
+
type AuthorizationHeaderGetter = (token: ITokenResponse) => string;
|
|
30
|
+
export type TokenFetcher = (refresh?: boolean) => Promise<ITokenResponse>;
|
|
22
31
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
const axiosRequestConfigToFetchRequestConfig = (
|
|
33
|
+
requestConfig: AxiosRequestConfig,
|
|
34
|
+
): [RequestInfo, RequestInit] => {
|
|
35
|
+
const requestInfo: string =
|
|
36
|
+
requestConfig.baseURL !== undefined
|
|
37
|
+
? `${requestConfig.baseURL}${requestConfig.url ?? ""}`
|
|
38
|
+
: requestConfig.url ?? "";
|
|
39
|
+
const requestInit: RequestInit = {
|
|
40
|
+
method: requestConfig.method,
|
|
41
|
+
// NOTE: I believe that although the Axios type permits non-string values in the header, here we are
|
|
42
|
+
// guaranteed the requestConfig only has string values in its header.
|
|
43
|
+
headers: requestConfig.headers as Record<string, string>,
|
|
44
|
+
body: requestConfig.data,
|
|
45
|
+
};
|
|
46
|
+
return [requestInfo, requestInit];
|
|
37
47
|
};
|
|
38
48
|
|
|
49
|
+
export interface IR11sResponse<T> {
|
|
50
|
+
content: T;
|
|
51
|
+
headers: Map<string, string>;
|
|
52
|
+
propsToLog: ITelemetryProperties;
|
|
53
|
+
requestUrl: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* A utility function to create a Routerlicious response without any additional props as we might not have them always.
|
|
58
|
+
* @param content - Response which is equivalent to content.
|
|
59
|
+
* @returns A Routerlicious response without any extra props.
|
|
60
|
+
*/
|
|
61
|
+
export function createR11sResponseFromContent<T>(content: T): IR11sResponse<T> {
|
|
62
|
+
return {
|
|
63
|
+
content,
|
|
64
|
+
headers: new Map(),
|
|
65
|
+
propsToLog: {},
|
|
66
|
+
requestUrl: "",
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function headersToMap(headers: Headers) {
|
|
71
|
+
const newHeaders = new Map<string, string>();
|
|
72
|
+
for (const [key, value] of headers.entries()) {
|
|
73
|
+
newHeaders.set(key, value);
|
|
74
|
+
}
|
|
75
|
+
return newHeaders;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function getPropsToLogFromResponse(headers: {
|
|
79
|
+
// eslint-disable-next-line @rushstack/no-new-null
|
|
80
|
+
get: (id: string) => string | undefined | null;
|
|
81
|
+
}) {
|
|
82
|
+
interface LoggingHeader {
|
|
83
|
+
headerName: string;
|
|
84
|
+
logName: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// We rename headers so that otel doesn't scrub them away. Otel doesn't allow
|
|
88
|
+
// certain characters in headers including '-'
|
|
89
|
+
const headersToLog: LoggingHeader[] = [
|
|
90
|
+
{ headerName: CorrelationIdHeaderName, logName: "requestCorrelationId" },
|
|
91
|
+
{ headerName: "content-encoding", logName: "contentEncoding" },
|
|
92
|
+
{ headerName: "content-type", logName: "contentType" },
|
|
93
|
+
];
|
|
94
|
+
const additionalProps: ITelemetryProperties = {
|
|
95
|
+
contentsize: numberFromString(headers.get("content-length")),
|
|
96
|
+
};
|
|
97
|
+
headersToLog.forEach((header) => {
|
|
98
|
+
const headerValue = headers.get(header.headerName);
|
|
99
|
+
if (headerValue !== undefined && headerValue !== null) {
|
|
100
|
+
additionalProps[header.logName] = headerValue;
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
return additionalProps;
|
|
105
|
+
}
|
|
106
|
+
|
|
39
107
|
export class RouterliciousRestWrapper extends RestWrapper {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
108
|
+
private readonly restLess = new RestLessClient();
|
|
109
|
+
private token: ITokenResponse | undefined;
|
|
110
|
+
|
|
111
|
+
constructor(
|
|
112
|
+
logger: ITelemetryLoggerExt,
|
|
113
|
+
private readonly rateLimiter: RateLimiter,
|
|
114
|
+
private readonly fetchRefreshedToken: TokenFetcher,
|
|
115
|
+
private readonly getAuthorizationHeader: AuthorizationHeaderGetter,
|
|
116
|
+
private readonly useRestLess: boolean,
|
|
117
|
+
baseurl?: string,
|
|
118
|
+
private tokenP?: Promise<ITokenResponse>,
|
|
119
|
+
defaultQueryString: QueryStringType = {},
|
|
120
|
+
) {
|
|
121
|
+
super(baseurl, defaultQueryString);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
protected async request<T>(
|
|
125
|
+
requestConfig: AxiosRequestConfig,
|
|
126
|
+
statusCode: number,
|
|
127
|
+
canRetry = true,
|
|
128
|
+
): Promise<IR11sResponse<T>> {
|
|
129
|
+
const config = {
|
|
130
|
+
...requestConfig,
|
|
131
|
+
headers: await this.generateHeaders(requestConfig.headers),
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const translatedConfig = this.useRestLess ? this.restLess.translate(config) : config;
|
|
135
|
+
const fetchRequestConfig = axiosRequestConfigToFetchRequestConfig(translatedConfig);
|
|
136
|
+
|
|
137
|
+
const res = await this.rateLimiter.schedule(async () => {
|
|
138
|
+
const perfStart = performance.now();
|
|
139
|
+
const result = await fetch(...fetchRequestConfig).catch(async (error) => {
|
|
140
|
+
// Browser Fetch throws a TypeError on network error, `node-fetch` throws a FetchError
|
|
141
|
+
const isNetworkError = ["TypeError", "FetchError"].includes(error?.name);
|
|
142
|
+
const errorMessage = isNetworkError
|
|
143
|
+
? `NetworkError: ${error.message}`
|
|
144
|
+
: safeStringify(error);
|
|
145
|
+
// If a service is temporarily down or a browser resource limit is reached, RestWrapper will throw
|
|
146
|
+
// a network error with no status code (e.g. err:ERR_CONN_REFUSED or err:ERR_FAILED) and
|
|
147
|
+
// the error message will start with NetworkError as defined in restWrapper.ts
|
|
148
|
+
// If there exists a self-signed SSL certificates error, throw a NonRetryableError
|
|
149
|
+
// TODO: instead of relying on string matching, filter error based on the error code like we do for websocket connections
|
|
150
|
+
const err = errorMessage.includes("failed, reason: self signed certificate")
|
|
151
|
+
? new NonRetryableError(errorMessage, RouterliciousErrorTypes.sslCertError, {
|
|
152
|
+
driverVersion,
|
|
153
|
+
})
|
|
154
|
+
: new GenericNetworkError(
|
|
155
|
+
errorMessage,
|
|
156
|
+
errorMessage.startsWith("NetworkError"),
|
|
157
|
+
{ driverVersion },
|
|
158
|
+
);
|
|
159
|
+
throw err;
|
|
160
|
+
});
|
|
161
|
+
return {
|
|
162
|
+
response: result,
|
|
163
|
+
duration: performance.now() - perfStart,
|
|
164
|
+
};
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const response = res.response;
|
|
168
|
+
|
|
169
|
+
let start = performance.now();
|
|
170
|
+
const text = await response.text();
|
|
171
|
+
const receiveContentTime = performance.now() - start;
|
|
172
|
+
|
|
173
|
+
const bodySize = text.length;
|
|
174
|
+
start = performance.now();
|
|
175
|
+
const responseBody: any = response.headers.get("content-type")?.includes("application/json")
|
|
176
|
+
? JSON.parse(text)
|
|
177
|
+
: text;
|
|
178
|
+
const parseTime = performance.now() - start;
|
|
179
|
+
|
|
180
|
+
// Success
|
|
181
|
+
if (response.ok || response.status === statusCode) {
|
|
182
|
+
const result = responseBody as T;
|
|
183
|
+
const headers = headersToMap(response.headers);
|
|
184
|
+
return {
|
|
185
|
+
content: result,
|
|
186
|
+
headers,
|
|
187
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
188
|
+
requestUrl: fetchRequestConfig[0].toString(),
|
|
189
|
+
propsToLog: {
|
|
190
|
+
...getPropsToLogFromResponse(headers),
|
|
191
|
+
bodySize,
|
|
192
|
+
receiveContentTime,
|
|
193
|
+
parseTime,
|
|
194
|
+
fetchTime: res.duration,
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
// Failure
|
|
199
|
+
if (response.status === 401 && canRetry) {
|
|
200
|
+
// Refresh Authorization header and retry once
|
|
201
|
+
this.token = await this.fetchRefreshedToken(true /* refreshToken */);
|
|
202
|
+
return this.request<T>(config, statusCode, false);
|
|
203
|
+
}
|
|
204
|
+
if (response.status === 429 && responseBody?.retryAfter > 0) {
|
|
205
|
+
// Retry based on retryAfter[Seconds]
|
|
206
|
+
return new Promise<IR11sResponse<T>>((resolve, reject) =>
|
|
207
|
+
setTimeout(() => {
|
|
208
|
+
this.request<T>(config, statusCode).then(resolve).catch(reject);
|
|
209
|
+
}, responseBody.retryAfter * 1000),
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const responseSummary =
|
|
214
|
+
responseBody !== undefined
|
|
215
|
+
? typeof responseBody === "string"
|
|
216
|
+
? responseBody
|
|
217
|
+
: safeStringify(responseBody)
|
|
218
|
+
: response.statusText;
|
|
219
|
+
throwR11sNetworkError(
|
|
220
|
+
`R11s fetch error: ${responseSummary}`,
|
|
221
|
+
response.status,
|
|
222
|
+
responseBody?.retryAfter,
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private async generateHeaders(
|
|
227
|
+
requestHeaders?: RawAxiosRequestHeaders | undefined,
|
|
228
|
+
): Promise<RawAxiosRequestHeaders> {
|
|
229
|
+
const token = await this.getToken();
|
|
230
|
+
assert(token !== undefined, 0x679 /* token should be present */);
|
|
231
|
+
const headers: RawAxiosRequestHeaders = {
|
|
232
|
+
...requestHeaders,
|
|
233
|
+
[DriverVersionHeaderName]: driverVersion,
|
|
234
|
+
// NOTE: If this.authorizationHeader is undefined, should "Authorization" be removed entirely?
|
|
235
|
+
Authorization: this.getAuthorizationHeader(token),
|
|
236
|
+
};
|
|
237
|
+
return headers;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
public async getToken(): Promise<ITokenResponse> {
|
|
241
|
+
if (this.token !== undefined) {
|
|
242
|
+
return this.token;
|
|
243
|
+
}
|
|
244
|
+
const token = await (this.tokenP ?? this.fetchRefreshedToken());
|
|
245
|
+
this.setToken(token);
|
|
246
|
+
this.tokenP = undefined;
|
|
247
|
+
return token;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
public setToken(token: ITokenResponse) {
|
|
251
|
+
this.token = token;
|
|
252
|
+
}
|
|
122
253
|
}
|
|
123
254
|
|
|
124
255
|
export class RouterliciousStorageRestWrapper extends RouterliciousRestWrapper {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
256
|
+
private constructor(
|
|
257
|
+
logger: ITelemetryLoggerExt,
|
|
258
|
+
rateLimiter: RateLimiter,
|
|
259
|
+
fetchToken: TokenFetcher,
|
|
260
|
+
getAuthorizationHeader: AuthorizationHeaderGetter,
|
|
261
|
+
useRestLess: boolean,
|
|
262
|
+
baseurl?: string,
|
|
263
|
+
initialTokenP?: Promise<ITokenResponse>,
|
|
264
|
+
defaultQueryString: QueryStringType = {},
|
|
265
|
+
) {
|
|
266
|
+
super(
|
|
267
|
+
logger,
|
|
268
|
+
rateLimiter,
|
|
269
|
+
fetchToken,
|
|
270
|
+
getAuthorizationHeader,
|
|
271
|
+
useRestLess,
|
|
272
|
+
baseurl,
|
|
273
|
+
initialTokenP,
|
|
274
|
+
defaultQueryString,
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
public static async load(
|
|
279
|
+
tenantId: string,
|
|
280
|
+
tokenFetcher: TokenFetcher,
|
|
281
|
+
logger: ITelemetryLoggerExt,
|
|
282
|
+
rateLimiter: RateLimiter,
|
|
283
|
+
useRestLess: boolean,
|
|
284
|
+
baseurl?: string,
|
|
285
|
+
initialTokenP?: Promise<ITokenResponse>,
|
|
286
|
+
): Promise<RouterliciousStorageRestWrapper> {
|
|
287
|
+
const defaultQueryString = {
|
|
288
|
+
token: `${fromUtf8ToBase64(tenantId)}`,
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
const getAuthorizationHeader: AuthorizationHeaderGetter = (
|
|
292
|
+
token: ITokenResponse,
|
|
293
|
+
): string => {
|
|
294
|
+
const credentials = {
|
|
295
|
+
password: token.jwt,
|
|
296
|
+
user: tenantId,
|
|
297
|
+
};
|
|
298
|
+
return getAuthorizationTokenFromCredentials(credentials);
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
const restWrapper = new RouterliciousStorageRestWrapper(
|
|
302
|
+
logger,
|
|
303
|
+
rateLimiter,
|
|
304
|
+
tokenFetcher,
|
|
305
|
+
getAuthorizationHeader,
|
|
306
|
+
useRestLess,
|
|
307
|
+
baseurl,
|
|
308
|
+
initialTokenP,
|
|
309
|
+
defaultQueryString,
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
return restWrapper;
|
|
313
|
+
}
|
|
183
314
|
}
|
|
184
315
|
|
|
185
316
|
export class RouterliciousOrdererRestWrapper extends RouterliciousRestWrapper {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
317
|
+
private constructor(
|
|
318
|
+
logger: ITelemetryLoggerExt,
|
|
319
|
+
rateLimiter: RateLimiter,
|
|
320
|
+
fetchToken: TokenFetcher,
|
|
321
|
+
getAuthorizationHeader: AuthorizationHeaderGetter,
|
|
322
|
+
useRestLess: boolean,
|
|
323
|
+
baseurl?: string,
|
|
324
|
+
initialTokenP?: Promise<ITokenResponse>,
|
|
325
|
+
defaultQueryString: QueryStringType = {},
|
|
326
|
+
) {
|
|
327
|
+
super(
|
|
328
|
+
logger,
|
|
329
|
+
rateLimiter,
|
|
330
|
+
fetchToken,
|
|
331
|
+
getAuthorizationHeader,
|
|
332
|
+
useRestLess,
|
|
333
|
+
baseurl,
|
|
334
|
+
initialTokenP,
|
|
335
|
+
defaultQueryString,
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
public static async load(
|
|
340
|
+
tokenFetcher: TokenFetcher,
|
|
341
|
+
logger: ITelemetryLoggerExt,
|
|
342
|
+
rateLimiter: RateLimiter,
|
|
343
|
+
useRestLess: boolean,
|
|
344
|
+
baseurl?: string,
|
|
345
|
+
initialTokenP?: Promise<ITokenResponse>,
|
|
346
|
+
): Promise<RouterliciousOrdererRestWrapper> {
|
|
347
|
+
const getAuthorizationHeader: AuthorizationHeaderGetter = (
|
|
348
|
+
token: ITokenResponse,
|
|
349
|
+
): string => {
|
|
350
|
+
return `Basic ${token.jwt}`;
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
const restWrapper = new RouterliciousOrdererRestWrapper(
|
|
354
|
+
logger,
|
|
355
|
+
rateLimiter,
|
|
356
|
+
tokenFetcher,
|
|
357
|
+
getAuthorizationHeader,
|
|
358
|
+
useRestLess,
|
|
359
|
+
baseurl,
|
|
360
|
+
initialTokenP,
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
return restWrapper;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
export function toInstrumentedR11sOrdererTokenFetcher(
|
|
368
|
+
tenantId: string,
|
|
369
|
+
documentId: string | undefined,
|
|
370
|
+
tokenProvider: ITokenProvider,
|
|
371
|
+
logger: ITelemetryLoggerExt,
|
|
372
|
+
): TokenFetcher {
|
|
373
|
+
const fetchOrdererToken = async (refreshToken?: boolean): Promise<ITokenResponse> => {
|
|
374
|
+
return PerformanceEvent.timedExecAsync(
|
|
375
|
+
logger,
|
|
376
|
+
{
|
|
377
|
+
eventName: "FetchOrdererToken",
|
|
378
|
+
docId: documentId,
|
|
379
|
+
},
|
|
380
|
+
async () => {
|
|
381
|
+
const ordererToken = await tokenProvider.fetchOrdererToken(
|
|
382
|
+
tenantId,
|
|
383
|
+
documentId,
|
|
384
|
+
refreshToken,
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
return ordererToken;
|
|
388
|
+
},
|
|
389
|
+
);
|
|
390
|
+
};
|
|
391
|
+
return fetchOrdererToken;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
export function toInstrumentedR11sStorageTokenFetcher(
|
|
395
|
+
tenantId: string,
|
|
396
|
+
documentId: string,
|
|
397
|
+
tokenProvider: ITokenProvider,
|
|
398
|
+
logger: ITelemetryLoggerExt,
|
|
399
|
+
): TokenFetcher {
|
|
400
|
+
const fetchStorageToken = async (refreshToken?: boolean): Promise<ITokenResponse> => {
|
|
401
|
+
return PerformanceEvent.timedExecAsync(
|
|
402
|
+
logger,
|
|
403
|
+
{
|
|
404
|
+
eventName: "FetchStorageToken",
|
|
405
|
+
docId: documentId,
|
|
406
|
+
},
|
|
407
|
+
async () => {
|
|
408
|
+
// Craft credentials using tenant id and token
|
|
409
|
+
const storageToken = await tokenProvider.fetchStorageToken(
|
|
410
|
+
tenantId,
|
|
411
|
+
documentId,
|
|
412
|
+
refreshToken,
|
|
413
|
+
);
|
|
414
|
+
|
|
415
|
+
return storageToken;
|
|
416
|
+
},
|
|
417
|
+
);
|
|
418
|
+
};
|
|
419
|
+
return fetchStorageToken;
|
|
236
420
|
}
|