@fluidframework/routerlicious-driver 2.0.0-dev.2.2.0.111723 → 2.0.0-dev.3.1.0.125672

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/.eslintrc.js +10 -12
  2. package/.mocharc.js +2 -2
  3. package/README.md +1 -1
  4. package/api-extractor.json +2 -2
  5. package/dist/cache.d.ts +3 -0
  6. package/dist/cache.d.ts.map +1 -1
  7. package/dist/cache.js +6 -4
  8. package/dist/cache.js.map +1 -1
  9. package/dist/createNewUtils.d.ts.map +1 -1
  10. package/dist/createNewUtils.js +4 -2
  11. package/dist/createNewUtils.js.map +1 -1
  12. package/dist/defaultTokenProvider.d.ts.map +1 -1
  13. package/dist/defaultTokenProvider.js.map +1 -1
  14. package/dist/definitions.d.ts.map +1 -1
  15. package/dist/definitions.js.map +1 -1
  16. package/dist/deltaStorageService.d.ts.map +1 -1
  17. package/dist/deltaStorageService.js +4 -1
  18. package/dist/deltaStorageService.js.map +1 -1
  19. package/dist/documentDeltaConnection.d.ts.map +1 -1
  20. package/dist/documentDeltaConnection.js.map +1 -1
  21. package/dist/documentService.d.ts +4 -2
  22. package/dist/documentService.d.ts.map +1 -1
  23. package/dist/documentService.js +22 -41
  24. package/dist/documentService.js.map +1 -1
  25. package/dist/documentServiceFactory.d.ts.map +1 -1
  26. package/dist/documentServiceFactory.js +23 -9
  27. package/dist/documentServiceFactory.js.map +1 -1
  28. package/dist/documentStorageService.d.ts +1 -1
  29. package/dist/documentStorageService.d.ts.map +1 -1
  30. package/dist/documentStorageService.js +8 -6
  31. package/dist/documentStorageService.js.map +1 -1
  32. package/dist/errorUtils.d.ts +2 -1
  33. package/dist/errorUtils.d.ts.map +1 -1
  34. package/dist/errorUtils.js +6 -0
  35. package/dist/errorUtils.js.map +1 -1
  36. package/dist/index.d.ts +1 -1
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/nullBlobStorageService.d.ts.map +1 -1
  40. package/dist/nullBlobStorageService.js.map +1 -1
  41. package/dist/packageVersion.d.ts +1 -1
  42. package/dist/packageVersion.js +1 -1
  43. package/dist/packageVersion.js.map +1 -1
  44. package/dist/policies.d.ts.map +1 -1
  45. package/dist/policies.js.map +1 -1
  46. package/dist/restWrapper.d.ts +10 -7
  47. package/dist/restWrapper.d.ts.map +1 -1
  48. package/dist/restWrapper.js +42 -44
  49. package/dist/restWrapper.js.map +1 -1
  50. package/dist/retriableGitManager.d.ts.map +1 -1
  51. package/dist/retriableGitManager.js.map +1 -1
  52. package/dist/shreddedSummaryDocumentStorageService.d.ts +1 -1
  53. package/dist/shreddedSummaryDocumentStorageService.d.ts.map +1 -1
  54. package/dist/shreddedSummaryDocumentStorageService.js +9 -5
  55. package/dist/shreddedSummaryDocumentStorageService.js.map +1 -1
  56. package/dist/tokens.d.ts.map +1 -1
  57. package/dist/tokens.js.map +1 -1
  58. package/dist/urlUtils.d.ts.map +1 -1
  59. package/dist/urlUtils.js.map +1 -1
  60. package/dist/wholeSummaryDocumentStorageService.d.ts +1 -1
  61. package/dist/wholeSummaryDocumentStorageService.d.ts.map +1 -1
  62. package/dist/wholeSummaryDocumentStorageService.js +25 -11
  63. package/dist/wholeSummaryDocumentStorageService.js.map +1 -1
  64. package/lib/cache.d.ts +3 -0
  65. package/lib/cache.d.ts.map +1 -1
  66. package/lib/cache.js +6 -4
  67. package/lib/cache.js.map +1 -1
  68. package/lib/createNewUtils.d.ts.map +1 -1
  69. package/lib/createNewUtils.js +4 -2
  70. package/lib/createNewUtils.js.map +1 -1
  71. package/lib/defaultTokenProvider.d.ts.map +1 -1
  72. package/lib/defaultTokenProvider.js.map +1 -1
  73. package/lib/definitions.d.ts.map +1 -1
  74. package/lib/definitions.js.map +1 -1
  75. package/lib/deltaStorageService.d.ts.map +1 -1
  76. package/lib/deltaStorageService.js +4 -1
  77. package/lib/deltaStorageService.js.map +1 -1
  78. package/lib/documentDeltaConnection.d.ts.map +1 -1
  79. package/lib/documentDeltaConnection.js.map +1 -1
  80. package/lib/documentService.d.ts +4 -2
  81. package/lib/documentService.d.ts.map +1 -1
  82. package/lib/documentService.js +22 -22
  83. package/lib/documentService.js.map +1 -1
  84. package/lib/documentServiceFactory.d.ts.map +1 -1
  85. package/lib/documentServiceFactory.js +23 -9
  86. package/lib/documentServiceFactory.js.map +1 -1
  87. package/lib/documentStorageService.d.ts +1 -1
  88. package/lib/documentStorageService.d.ts.map +1 -1
  89. package/lib/documentStorageService.js +9 -7
  90. package/lib/documentStorageService.js.map +1 -1
  91. package/lib/errorUtils.d.ts +2 -1
  92. package/lib/errorUtils.d.ts.map +1 -1
  93. package/lib/errorUtils.js +6 -0
  94. package/lib/errorUtils.js.map +1 -1
  95. package/lib/index.d.ts +1 -1
  96. package/lib/index.d.ts.map +1 -1
  97. package/lib/index.js +1 -1
  98. package/lib/index.js.map +1 -1
  99. package/lib/nullBlobStorageService.d.ts.map +1 -1
  100. package/lib/nullBlobStorageService.js.map +1 -1
  101. package/lib/packageVersion.d.ts +1 -1
  102. package/lib/packageVersion.js +1 -1
  103. package/lib/packageVersion.js.map +1 -1
  104. package/lib/policies.d.ts.map +1 -1
  105. package/lib/policies.js.map +1 -1
  106. package/lib/restWrapper.d.ts +10 -7
  107. package/lib/restWrapper.d.ts.map +1 -1
  108. package/lib/restWrapper.js +42 -44
  109. package/lib/restWrapper.js.map +1 -1
  110. package/lib/retriableGitManager.d.ts.map +1 -1
  111. package/lib/retriableGitManager.js.map +1 -1
  112. package/lib/shreddedSummaryDocumentStorageService.d.ts +1 -1
  113. package/lib/shreddedSummaryDocumentStorageService.d.ts.map +1 -1
  114. package/lib/shreddedSummaryDocumentStorageService.js +10 -6
  115. package/lib/shreddedSummaryDocumentStorageService.js.map +1 -1
  116. package/lib/tokens.d.ts.map +1 -1
  117. package/lib/tokens.js.map +1 -1
  118. package/lib/urlUtils.d.ts.map +1 -1
  119. package/lib/urlUtils.js.map +1 -1
  120. package/lib/wholeSummaryDocumentStorageService.d.ts +1 -1
  121. package/lib/wholeSummaryDocumentStorageService.d.ts.map +1 -1
  122. package/lib/wholeSummaryDocumentStorageService.js +27 -13
  123. package/lib/wholeSummaryDocumentStorageService.js.map +1 -1
  124. package/package.json +19 -15
  125. package/prettier.config.cjs +1 -1
  126. package/src/cache.ts +21 -14
  127. package/src/createNewUtils.ts +24 -22
  128. package/src/defaultTokenProvider.ts +13 -15
  129. package/src/definitions.ts +2 -2
  130. package/src/deltaStorageService.ts +99 -95
  131. package/src/documentDeltaConnection.ts +53 -47
  132. package/src/documentService.ts +243 -239
  133. package/src/documentServiceFactory.ts +267 -237
  134. package/src/documentStorageService.ts +87 -83
  135. package/src/errorUtils.ts +78 -75
  136. package/src/index.ts +4 -1
  137. package/src/nullBlobStorageService.ts +24 -21
  138. package/src/packageVersion.ts +1 -1
  139. package/src/policies.ts +44 -44
  140. package/src/restWrapper.ts +275 -209
  141. package/src/retriableGitManager.ts +152 -151
  142. package/src/shreddedSummaryDocumentStorageService.ts +202 -194
  143. package/src/tokens.ts +51 -43
  144. package/src/urlUtils.ts +26 -23
  145. package/src/wholeSummaryDocumentStorageService.ts +246 -228
  146. package/tsconfig.esnext.json +6 -6
  147. package/tsconfig.json +9 -13
@@ -2,14 +2,18 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import * as querystring from "querystring";
5
+
6
+ // Just using the type from a node.js module does not introduce a runtime dependency.
7
+ // eslint-disable-next-line import/no-nodejs-modules
8
+ import type { ParsedUrlQueryInput } from "querystring";
9
+
6
10
  import { ITelemetryLogger } from "@fluidframework/common-definitions";
7
11
  import { fromUtf8ToBase64 } from "@fluidframework/common-utils";
8
12
  import { RateLimiter } from "@fluidframework/driver-utils";
9
13
  import {
10
- getAuthorizationTokenFromCredentials,
11
- RestLessClient,
12
- RestWrapper,
14
+ getAuthorizationTokenFromCredentials,
15
+ RestLessClient,
16
+ RestWrapper,
13
17
  } from "@fluidframework/server-services-client";
14
18
  import { PerformanceEvent } from "@fluidframework/telemetry-utils";
15
19
  import fetch from "cross-fetch";
@@ -17,220 +21,282 @@ import type { AxiosRequestConfig, AxiosRequestHeaders } from "axios";
17
21
  import safeStringify from "json-stringify-safe";
18
22
  import { v4 as uuid } from "uuid";
19
23
  import { throwR11sNetworkError } from "./errorUtils";
20
- import { ITokenProvider } from "./tokens";
24
+ import { ITokenProvider, ITokenResponse } from "./tokens";
21
25
  import { pkgVersion as driverVersion } from "./packageVersion";
22
26
 
23
- type AuthorizationHeaderGetter = (refresh?: boolean) => Promise<string | undefined>;
24
-
25
- const axiosRequestConfigToFetchRequestConfig = (requestConfig: AxiosRequestConfig): [RequestInfo, RequestInit] => {
26
- const requestInfo: string = requestConfig.baseURL !== undefined
27
- ? `${requestConfig.baseURL}${requestConfig.url ?? ""}`
28
- : requestConfig.url ?? "";
29
- const requestInit: RequestInit = {
30
- method: requestConfig.method,
31
- // NOTE: I believe that although the Axios type permits non-string values in the header, here we are
32
- // guaranteed the requestConfig only has string values in its header.
33
- headers: requestConfig.headers as Record<string, string>,
34
- body: requestConfig.data,
35
- };
36
- return [requestInfo, requestInit];
27
+ type AuthorizationHeaderGetter = (token: ITokenResponse) => string;
28
+ type TokenFetcher = (refresh?: boolean) => Promise<ITokenResponse>;
29
+
30
+ const axiosRequestConfigToFetchRequestConfig = (
31
+ requestConfig: AxiosRequestConfig,
32
+ ): [RequestInfo, RequestInit] => {
33
+ const requestInfo: string =
34
+ requestConfig.baseURL !== undefined
35
+ ? `${requestConfig.baseURL}${requestConfig.url ?? ""}`
36
+ : requestConfig.url ?? "";
37
+ const requestInit: RequestInit = {
38
+ method: requestConfig.method,
39
+ // NOTE: I believe that although the Axios type permits non-string values in the header, here we are
40
+ // guaranteed the requestConfig only has string values in its header.
41
+ headers: requestConfig.headers as Record<string, string>,
42
+ body: requestConfig.data,
43
+ };
44
+ return [requestInfo, requestInit];
37
45
  };
38
46
 
39
47
  export class RouterliciousRestWrapper extends RestWrapper {
40
- private authorizationHeader: string | undefined;
41
- private readonly restLess = new RestLessClient();
42
-
43
- constructor(
44
- logger: ITelemetryLogger,
45
- private readonly rateLimiter: RateLimiter,
46
- private readonly getAuthorizationHeader: AuthorizationHeaderGetter,
47
- private readonly useRestLess: boolean,
48
- baseurl?: string,
49
- defaultQueryString: querystring.ParsedUrlQueryInput = {},
50
- ) {
51
- super(baseurl, defaultQueryString);
52
- }
53
-
54
- public async load() {
55
- this.authorizationHeader = await this.getAuthorizationHeader();
56
- }
57
-
58
- protected async request<T>(requestConfig: AxiosRequestConfig, statusCode: number, canRetry = true): Promise<T> {
59
- const config = {
60
- ...requestConfig,
61
- headers: this.generateHeaders(requestConfig.headers),
62
- };
63
-
64
- const translatedConfig = this.useRestLess ? this.restLess.translate(config) : config;
65
- const fetchRequestConfig = axiosRequestConfigToFetchRequestConfig(translatedConfig);
66
-
67
- const response: Response = await this.rateLimiter.schedule(async () => fetch(...fetchRequestConfig)
68
- .catch(async (error) => {
69
- // Browser Fetch throws a TypeError on network error, `node-fetch` throws a FetchError
70
- const isNetworkError = ["TypeError", "FetchError"].includes(error?.name);
71
- throwR11sNetworkError(
72
- isNetworkError ? `NetworkError: ${error.message}` : safeStringify(error));
73
- }));
74
-
75
- const responseBody: any = response.headers.get("content-type")?.includes("application/json")
76
- ? await response.json()
77
- : await response.text();
78
-
79
- // Success
80
- if (response.ok || response.status === statusCode) {
81
- const result: T = responseBody;
82
- return result;
83
- }
84
- // Failure
85
- if (response.status === 401 && canRetry) {
86
- // Refresh Authorization header and retry once
87
- this.authorizationHeader = await this.getAuthorizationHeader(true /* refreshToken */);
88
- return this.request<T>(config, statusCode, false);
89
- }
90
- if (response.status === 429 && responseBody?.retryAfter > 0) {
91
- // Retry based on retryAfter[Seconds]
92
- return new Promise<T>((resolve, reject) => setTimeout(() => {
93
- this.request<T>(config, statusCode)
94
- .then(resolve)
95
- .catch(reject);
96
- }, responseBody.retryAfter * 1000));
97
- }
98
-
99
- const responseSummary = responseBody !== undefined
100
- ? typeof responseBody === "string" ? responseBody : safeStringify(responseBody)
101
- : response.statusText;
102
- throwR11sNetworkError(
103
- `R11s fetch error: ${responseSummary}`,
104
- response.status,
105
- responseBody?.retryAfter,
106
- );
107
- }
108
-
109
- private generateHeaders(requestHeaders?: AxiosRequestHeaders | undefined): Record<string, string> {
110
- const correlationId = requestHeaders?.["x-correlation-id"] ?? uuid();
111
-
112
- return {
113
- ...requestHeaders,
114
- // TODO: replace header names with CorrelationIdHeaderName and DriverVersionHeaderName from services-client
115
- // NOTE: Can correlationId actually be number | true?
116
- "x-correlation-id": correlationId as string,
117
- "x-driver-version": driverVersion,
118
- // NOTE: If this.authorizationHeader is undefined, should "Authorization" be removed entirely?
119
- "Authorization": this.authorizationHeader!,
120
- };
121
- }
48
+ private readonly restLess = new RestLessClient();
49
+
50
+ constructor(
51
+ logger: ITelemetryLogger,
52
+ private readonly rateLimiter: RateLimiter,
53
+ private token: ITokenResponse,
54
+ private readonly fetchRefreshedToken: TokenFetcher,
55
+ private readonly getAuthorizationHeader: AuthorizationHeaderGetter,
56
+ private readonly useRestLess: boolean,
57
+ baseurl?: string,
58
+ defaultQueryString: ParsedUrlQueryInput = {},
59
+ ) {
60
+ super(baseurl, defaultQueryString);
61
+ }
62
+
63
+ protected async request<T>(
64
+ requestConfig: AxiosRequestConfig,
65
+ statusCode: number,
66
+ canRetry = true,
67
+ ): Promise<T> {
68
+ const config = {
69
+ ...requestConfig,
70
+ headers: this.generateHeaders(requestConfig.headers),
71
+ };
72
+
73
+ const translatedConfig = this.useRestLess ? this.restLess.translate(config) : config;
74
+ const fetchRequestConfig = axiosRequestConfigToFetchRequestConfig(translatedConfig);
75
+
76
+ const response: Response = await this.rateLimiter.schedule(async () =>
77
+ fetch(...fetchRequestConfig).catch(async (error) => {
78
+ // Browser Fetch throws a TypeError on network error, `node-fetch` throws a FetchError
79
+ const isNetworkError = ["TypeError", "FetchError"].includes(error?.name);
80
+ throwR11sNetworkError(
81
+ isNetworkError ? `NetworkError: ${error.message}` : safeStringify(error),
82
+ );
83
+ }),
84
+ );
85
+
86
+ const responseBody: any = response.headers.get("content-type")?.includes("application/json")
87
+ ? await response.json()
88
+ : await response.text();
89
+
90
+ // Success
91
+ if (response.ok || response.status === statusCode) {
92
+ const result: T = responseBody;
93
+ return result;
94
+ }
95
+ // Failure
96
+ if (response.status === 401 && canRetry) {
97
+ // Refresh Authorization header and retry once
98
+ this.token = await this.fetchRefreshedToken(true /* refreshToken */);
99
+ return this.request<T>(config, statusCode, false);
100
+ }
101
+ if (response.status === 429 && responseBody?.retryAfter > 0) {
102
+ // Retry based on retryAfter[Seconds]
103
+ return new Promise<T>((resolve, reject) =>
104
+ setTimeout(() => {
105
+ this.request<T>(config, statusCode).then(resolve).catch(reject);
106
+ }, responseBody.retryAfter * 1000),
107
+ );
108
+ }
109
+
110
+ const responseSummary =
111
+ responseBody !== undefined
112
+ ? typeof responseBody === "string"
113
+ ? responseBody
114
+ : safeStringify(responseBody)
115
+ : response.statusText;
116
+ throwR11sNetworkError(
117
+ `R11s fetch error: ${responseSummary}`,
118
+ response.status,
119
+ responseBody?.retryAfter,
120
+ );
121
+ }
122
+
123
+ private generateHeaders(
124
+ requestHeaders?: AxiosRequestHeaders | undefined,
125
+ ): Record<string, string> {
126
+ const correlationId = requestHeaders?.["x-correlation-id"] ?? uuid();
127
+
128
+ return {
129
+ ...requestHeaders,
130
+ // TODO: replace header names with CorrelationIdHeaderName and DriverVersionHeaderName from services-client
131
+ // NOTE: Can correlationId actually be number | true?
132
+ "x-correlation-id": correlationId as string,
133
+ "x-driver-version": driverVersion,
134
+ // NOTE: If this.authorizationHeader is undefined, should "Authorization" be removed entirely?
135
+ "Authorization": this.getAuthorizationHeader(this.token),
136
+ };
137
+ }
138
+
139
+ public getToken(): ITokenResponse {
140
+ return this.token;
141
+ }
142
+
143
+ public setToken(token: ITokenResponse) {
144
+ this.token = token;
145
+ }
122
146
  }
123
147
 
124
148
  export class RouterliciousStorageRestWrapper extends RouterliciousRestWrapper {
125
- private constructor(
126
- logger: ITelemetryLogger,
127
- rateLimiter: RateLimiter,
128
- getAuthorizationHeader: AuthorizationHeaderGetter,
129
- useRestLess: boolean,
130
- baseurl?: string,
131
- defaultQueryString: querystring.ParsedUrlQueryInput = {},
132
- ) {
133
- super(logger, rateLimiter, getAuthorizationHeader, useRestLess, baseurl, defaultQueryString);
134
- }
135
-
136
- public static async load(
137
- tenantId: string,
138
- documentId: string,
139
- tokenProvider: ITokenProvider,
140
- logger: ITelemetryLogger,
141
- rateLimiter: RateLimiter,
142
- useRestLess: boolean,
143
- baseurl?: string,
144
- ): Promise<RouterliciousStorageRestWrapper> {
145
- const defaultQueryString = {
146
- token: `${fromUtf8ToBase64(tenantId)}`,
147
- };
148
- const getAuthorizationHeader: AuthorizationHeaderGetter = async (refreshToken?: boolean): Promise<string> => {
149
- return PerformanceEvent.timedExecAsync(
150
- logger,
151
- {
152
- eventName: "FetchStorageToken",
153
- docId: documentId,
154
- },
155
- async () => {
156
- // Craft credentials using tenant id and token
157
- const storageToken = await tokenProvider.fetchStorageToken(
158
- tenantId,
159
- documentId,
160
- refreshToken
161
- );
162
- const credentials = {
163
- password: storageToken.jwt,
164
- user: tenantId,
165
- };
166
- return getAuthorizationTokenFromCredentials(credentials);
167
- }
168
- );
169
- };
170
-
171
- const restWrapper = new RouterliciousStorageRestWrapper(
172
- logger, rateLimiter, getAuthorizationHeader, useRestLess, baseurl, defaultQueryString);
173
- try {
174
- await restWrapper.load();
175
- } catch (e) {
176
- logger.sendErrorEvent({
177
- eventName: "R11sRestWrapperLoadFailure",
178
- }, e);
179
- await restWrapper.load();
180
- }
181
- return restWrapper;
182
- }
149
+ private constructor(
150
+ logger: ITelemetryLogger,
151
+ rateLimiter: RateLimiter,
152
+ token: ITokenResponse,
153
+ fetchToken: TokenFetcher,
154
+ getAuthorizationHeader: AuthorizationHeaderGetter,
155
+ useRestLess: boolean,
156
+ baseurl?: string,
157
+ defaultQueryString: ParsedUrlQueryInput = {},
158
+ ) {
159
+ super(
160
+ logger,
161
+ rateLimiter,
162
+ token,
163
+ fetchToken,
164
+ getAuthorizationHeader,
165
+ useRestLess,
166
+ baseurl,
167
+ defaultQueryString,
168
+ );
169
+ }
170
+
171
+ public static async load(
172
+ tenantId: string,
173
+ documentId: string,
174
+ tokenProvider: ITokenProvider,
175
+ logger: ITelemetryLogger,
176
+ rateLimiter: RateLimiter,
177
+ useRestLess: boolean,
178
+ baseurl?: string,
179
+ ): Promise<RouterliciousStorageRestWrapper> {
180
+ const defaultQueryString = {
181
+ token: `${fromUtf8ToBase64(tenantId)}`,
182
+ };
183
+
184
+ const fetchStorageToken = async (refreshToken?: boolean): Promise<ITokenResponse> => {
185
+ return PerformanceEvent.timedExecAsync(
186
+ logger,
187
+ {
188
+ eventName: "FetchStorageToken",
189
+ docId: documentId,
190
+ },
191
+ async () => {
192
+ // Craft credentials using tenant id and token
193
+ const storageToken = await tokenProvider.fetchStorageToken(
194
+ tenantId,
195
+ documentId,
196
+ refreshToken,
197
+ );
198
+
199
+ return storageToken;
200
+ },
201
+ );
202
+ };
203
+
204
+ const getAuthorizationHeader: AuthorizationHeaderGetter = (
205
+ token: ITokenResponse,
206
+ ): string => {
207
+ const credentials = {
208
+ password: token.jwt,
209
+ user: tenantId,
210
+ };
211
+ return getAuthorizationTokenFromCredentials(credentials);
212
+ };
213
+
214
+ const storagetoken = await fetchStorageToken();
215
+
216
+ const restWrapper = new RouterliciousStorageRestWrapper(
217
+ logger,
218
+ rateLimiter,
219
+ storagetoken,
220
+ fetchStorageToken,
221
+ getAuthorizationHeader,
222
+ useRestLess,
223
+ baseurl,
224
+ defaultQueryString,
225
+ );
226
+
227
+ return restWrapper;
228
+ }
183
229
  }
184
230
 
185
231
  export class RouterliciousOrdererRestWrapper extends RouterliciousRestWrapper {
186
- private constructor(
187
- logger: ITelemetryLogger,
188
- rateLimiter: RateLimiter,
189
- getAuthorizationHeader: AuthorizationHeaderGetter,
190
- useRestLess: boolean,
191
- baseurl?: string,
192
- defaultQueryString: querystring.ParsedUrlQueryInput = {},
193
- ) {
194
- super(logger, rateLimiter, getAuthorizationHeader, useRestLess, baseurl, defaultQueryString);
195
- }
196
-
197
- public static async load(
198
- tenantId: string,
199
- documentId: string | undefined,
200
- tokenProvider: ITokenProvider,
201
- logger: ITelemetryLogger,
202
- rateLimiter: RateLimiter,
203
- useRestLess: boolean,
204
- baseurl?: string,
205
- ): Promise<RouterliciousOrdererRestWrapper> {
206
- const getAuthorizationHeader: AuthorizationHeaderGetter = async (refreshToken?: boolean): Promise<string> => {
207
- return PerformanceEvent.timedExecAsync(
208
- logger,
209
- {
210
- eventName: "FetchOrdererToken",
211
- docId: documentId,
212
- },
213
- async () => {
214
- const ordererToken = await tokenProvider.fetchOrdererToken(
215
- tenantId,
216
- documentId,
217
- refreshToken,
218
- );
219
- return `Basic ${ordererToken.jwt}`;
220
- }
221
- );
222
- };
223
-
224
- const restWrapper = new RouterliciousOrdererRestWrapper(
225
- logger, rateLimiter, getAuthorizationHeader, useRestLess, baseurl);
226
- try {
227
- await restWrapper.load();
228
- } catch (e) {
229
- logger.sendErrorEvent({
230
- eventName: "R11sRestWrapperLoadFailure",
231
- }, e);
232
- await restWrapper.load();
233
- }
234
- return restWrapper;
235
- }
232
+ private constructor(
233
+ logger: ITelemetryLogger,
234
+ rateLimiter: RateLimiter,
235
+ token: ITokenResponse,
236
+ fetchToken: TokenFetcher,
237
+ getAuthorizationHeader: AuthorizationHeaderGetter,
238
+ useRestLess: boolean,
239
+ baseurl?: string,
240
+ defaultQueryString: ParsedUrlQueryInput = {},
241
+ ) {
242
+ super(
243
+ logger,
244
+ rateLimiter,
245
+ token,
246
+ fetchToken,
247
+ getAuthorizationHeader,
248
+ useRestLess,
249
+ baseurl,
250
+ defaultQueryString,
251
+ );
252
+ }
253
+
254
+ public static async load(
255
+ tenantId: string,
256
+ documentId: string | undefined,
257
+ tokenProvider: ITokenProvider,
258
+ logger: ITelemetryLogger,
259
+ rateLimiter: RateLimiter,
260
+ useRestLess: boolean,
261
+ baseurl?: string,
262
+ ): Promise<RouterliciousOrdererRestWrapper> {
263
+ const getAuthorizationHeader: AuthorizationHeaderGetter = (
264
+ token: ITokenResponse,
265
+ ): string => {
266
+ return `Basic ${token.jwt}`;
267
+ };
268
+
269
+ const fetchOrdererToken = async (refreshToken?: boolean): Promise<ITokenResponse> => {
270
+ return PerformanceEvent.timedExecAsync(
271
+ logger,
272
+ {
273
+ eventName: "FetchOrdererToken",
274
+ docId: documentId,
275
+ },
276
+ async () => {
277
+ const ordererToken = await tokenProvider.fetchOrdererToken(
278
+ tenantId,
279
+ documentId,
280
+ refreshToken,
281
+ );
282
+
283
+ return ordererToken;
284
+ },
285
+ );
286
+ };
287
+
288
+ const newtoken = await fetchOrdererToken();
289
+
290
+ const restWrapper = new RouterliciousOrdererRestWrapper(
291
+ logger,
292
+ rateLimiter,
293
+ newtoken,
294
+ fetchOrdererToken,
295
+ getAuthorizationHeader,
296
+ useRestLess,
297
+ baseurl,
298
+ );
299
+
300
+ return restWrapper;
301
+ }
236
302
  }