@fluidframework/routerlicious-driver 2.0.0-dev.4.1.0.148229 → 2.0.0-dev.4.3.0.157531

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 (163) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +38 -0
  3. package/dist/contracts.d.ts +15 -0
  4. package/dist/contracts.d.ts.map +1 -0
  5. package/dist/contracts.js +7 -0
  6. package/dist/contracts.js.map +1 -0
  7. package/dist/deltaStorageService.d.ts +1 -1
  8. package/dist/deltaStorageService.d.ts.map +1 -1
  9. package/dist/deltaStorageService.js +7 -4
  10. package/dist/deltaStorageService.js.map +1 -1
  11. package/dist/documentService.d.ts +4 -2
  12. package/dist/documentService.d.ts.map +1 -1
  13. package/dist/documentService.js +11 -9
  14. package/dist/documentService.js.map +1 -1
  15. package/dist/documentServiceFactory.d.ts +2 -1
  16. package/dist/documentServiceFactory.d.ts.map +1 -1
  17. package/dist/documentServiceFactory.js +18 -8
  18. package/dist/documentServiceFactory.js.map +1 -1
  19. package/dist/documentStorageService.d.ts +3 -2
  20. package/dist/documentStorageService.d.ts.map +1 -1
  21. package/dist/documentStorageService.js +4 -4
  22. package/dist/documentStorageService.js.map +1 -1
  23. package/dist/gitManager.d.ts +30 -0
  24. package/dist/gitManager.d.ts.map +1 -0
  25. package/dist/gitManager.js +89 -0
  26. package/dist/gitManager.js.map +1 -0
  27. package/dist/historian.d.ts +33 -0
  28. package/dist/historian.d.ts.map +1 -0
  29. package/dist/historian.js +65 -0
  30. package/dist/historian.js.map +1 -0
  31. package/dist/packageVersion.d.ts +1 -1
  32. package/dist/packageVersion.js +1 -1
  33. package/dist/packageVersion.js.map +1 -1
  34. package/dist/r11sSnapshotParser.d.ts +15 -0
  35. package/dist/r11sSnapshotParser.d.ts.map +1 -0
  36. package/dist/r11sSnapshotParser.js +75 -0
  37. package/dist/r11sSnapshotParser.js.map +1 -0
  38. package/dist/restWrapper.d.ts +21 -8
  39. package/dist/restWrapper.d.ts.map +1 -1
  40. package/dist/restWrapper.js +93 -25
  41. package/dist/restWrapper.js.map +1 -1
  42. package/dist/restWrapperBase.d.ts +26 -0
  43. package/dist/restWrapperBase.d.ts.map +1 -0
  44. package/dist/restWrapperBase.js +55 -0
  45. package/dist/restWrapperBase.js.map +1 -0
  46. package/dist/retriableGitManager.d.ts +10 -21
  47. package/dist/retriableGitManager.d.ts.map +1 -1
  48. package/dist/retriableGitManager.js +0 -36
  49. package/dist/retriableGitManager.js.map +1 -1
  50. package/dist/shreddedSummaryDocumentStorageService.d.ts +1 -1
  51. package/dist/shreddedSummaryDocumentStorageService.d.ts.map +1 -1
  52. package/dist/shreddedSummaryDocumentStorageService.js +6 -6
  53. package/dist/shreddedSummaryDocumentStorageService.js.map +1 -1
  54. package/dist/storageContracts.d.ts +44 -0
  55. package/dist/storageContracts.d.ts.map +1 -0
  56. package/dist/storageContracts.js +7 -0
  57. package/dist/storageContracts.js.map +1 -0
  58. package/dist/summaryTreeUploadManager.d.ts +23 -0
  59. package/dist/summaryTreeUploadManager.d.ts.map +1 -0
  60. package/dist/summaryTreeUploadManager.js +110 -0
  61. package/dist/summaryTreeUploadManager.js.map +1 -0
  62. package/dist/treeUtils.d.ts +7 -0
  63. package/dist/treeUtils.d.ts.map +1 -1
  64. package/dist/treeUtils.js +23 -1
  65. package/dist/treeUtils.js.map +1 -1
  66. package/dist/wholeSummaryDocumentStorageService.d.ts +5 -4
  67. package/dist/wholeSummaryDocumentStorageService.d.ts.map +1 -1
  68. package/dist/wholeSummaryDocumentStorageService.js +74 -42
  69. package/dist/wholeSummaryDocumentStorageService.js.map +1 -1
  70. package/dist/wholeSummaryUploadManager.d.ts +16 -0
  71. package/dist/wholeSummaryUploadManager.d.ts.map +1 -0
  72. package/dist/wholeSummaryUploadManager.js +38 -0
  73. package/dist/wholeSummaryUploadManager.js.map +1 -0
  74. package/lib/contracts.d.ts +15 -0
  75. package/lib/contracts.d.ts.map +1 -0
  76. package/lib/contracts.js +6 -0
  77. package/lib/contracts.js.map +1 -0
  78. package/lib/deltaStorageService.d.ts +1 -1
  79. package/lib/deltaStorageService.d.ts.map +1 -1
  80. package/lib/deltaStorageService.js +7 -4
  81. package/lib/deltaStorageService.js.map +1 -1
  82. package/lib/documentService.d.ts +4 -2
  83. package/lib/documentService.d.ts.map +1 -1
  84. package/lib/documentService.js +9 -7
  85. package/lib/documentService.js.map +1 -1
  86. package/lib/documentServiceFactory.d.ts +2 -1
  87. package/lib/documentServiceFactory.d.ts.map +1 -1
  88. package/lib/documentServiceFactory.js +18 -8
  89. package/lib/documentServiceFactory.js.map +1 -1
  90. package/lib/documentStorageService.d.ts +3 -2
  91. package/lib/documentStorageService.d.ts.map +1 -1
  92. package/lib/documentStorageService.js +4 -4
  93. package/lib/documentStorageService.js.map +1 -1
  94. package/lib/gitManager.d.ts +30 -0
  95. package/lib/gitManager.d.ts.map +1 -0
  96. package/lib/gitManager.js +85 -0
  97. package/lib/gitManager.js.map +1 -0
  98. package/lib/historian.d.ts +33 -0
  99. package/lib/historian.d.ts.map +1 -0
  100. package/lib/historian.js +60 -0
  101. package/lib/historian.js.map +1 -0
  102. package/lib/packageVersion.d.ts +1 -1
  103. package/lib/packageVersion.js +1 -1
  104. package/lib/packageVersion.js.map +1 -1
  105. package/lib/r11sSnapshotParser.d.ts +15 -0
  106. package/lib/r11sSnapshotParser.d.ts.map +1 -0
  107. package/lib/r11sSnapshotParser.js +71 -0
  108. package/lib/r11sSnapshotParser.js.map +1 -0
  109. package/lib/restWrapper.d.ts +21 -8
  110. package/lib/restWrapper.d.ts.map +1 -1
  111. package/lib/restWrapper.js +92 -26
  112. package/lib/restWrapper.js.map +1 -1
  113. package/lib/restWrapperBase.d.ts +26 -0
  114. package/lib/restWrapperBase.d.ts.map +1 -0
  115. package/lib/restWrapperBase.js +50 -0
  116. package/lib/restWrapperBase.js.map +1 -0
  117. package/lib/retriableGitManager.d.ts +10 -21
  118. package/lib/retriableGitManager.d.ts.map +1 -1
  119. package/lib/retriableGitManager.js +0 -36
  120. package/lib/retriableGitManager.js.map +1 -1
  121. package/lib/shreddedSummaryDocumentStorageService.d.ts +1 -1
  122. package/lib/shreddedSummaryDocumentStorageService.d.ts.map +1 -1
  123. package/lib/shreddedSummaryDocumentStorageService.js +5 -5
  124. package/lib/shreddedSummaryDocumentStorageService.js.map +1 -1
  125. package/lib/storageContracts.d.ts +44 -0
  126. package/lib/storageContracts.d.ts.map +1 -0
  127. package/lib/storageContracts.js +6 -0
  128. package/lib/storageContracts.js.map +1 -0
  129. package/lib/summaryTreeUploadManager.d.ts +23 -0
  130. package/lib/summaryTreeUploadManager.d.ts.map +1 -0
  131. package/lib/summaryTreeUploadManager.js +106 -0
  132. package/lib/summaryTreeUploadManager.js.map +1 -0
  133. package/lib/treeUtils.d.ts +7 -0
  134. package/lib/treeUtils.d.ts.map +1 -1
  135. package/lib/treeUtils.js +20 -0
  136. package/lib/treeUtils.js.map +1 -1
  137. package/lib/wholeSummaryDocumentStorageService.d.ts +5 -4
  138. package/lib/wholeSummaryDocumentStorageService.d.ts.map +1 -1
  139. package/lib/wholeSummaryDocumentStorageService.js +74 -42
  140. package/lib/wholeSummaryDocumentStorageService.js.map +1 -1
  141. package/lib/wholeSummaryUploadManager.d.ts +16 -0
  142. package/lib/wholeSummaryUploadManager.d.ts.map +1 -0
  143. package/lib/wholeSummaryUploadManager.js +34 -0
  144. package/lib/wholeSummaryUploadManager.js.map +1 -0
  145. package/package.json +9 -10
  146. package/src/contracts.ts +16 -0
  147. package/src/deltaStorageService.ts +11 -3
  148. package/src/documentService.ts +11 -11
  149. package/src/documentServiceFactory.ts +35 -16
  150. package/src/documentStorageService.ts +8 -4
  151. package/src/gitManager.ts +116 -0
  152. package/src/historian.ts +121 -0
  153. package/src/packageVersion.ts +1 -1
  154. package/src/r11sSnapshotParser.ts +83 -0
  155. package/src/restWrapper.ts +114 -38
  156. package/src/restWrapperBase.ts +146 -0
  157. package/src/retriableGitManager.ts +17 -95
  158. package/src/shreddedSummaryDocumentStorageService.ts +7 -9
  159. package/src/storageContracts.ts +63 -0
  160. package/src/summaryTreeUploadManager.ts +160 -0
  161. package/src/treeUtils.ts +30 -0
  162. package/src/wholeSummaryDocumentStorageService.ts +117 -58
  163. package/src/wholeSummaryUploadManager.ts +64 -0
@@ -3,19 +3,14 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
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
-
10
- import { ITelemetryLogger } from "@fluidframework/common-definitions";
11
- import { fromUtf8ToBase64 } from "@fluidframework/common-utils";
6
+ import { ITelemetryLogger, ITelemetryProperties } from "@fluidframework/common-definitions";
7
+ import { assert, fromUtf8ToBase64, performance } from "@fluidframework/common-utils";
12
8
  import { RateLimiter } from "@fluidframework/driver-utils";
13
9
  import {
14
10
  getAuthorizationTokenFromCredentials,
15
11
  RestLessClient,
16
- RestWrapper,
17
12
  } from "@fluidframework/server-services-client";
18
- import { PerformanceEvent } from "@fluidframework/telemetry-utils";
13
+ import { PerformanceEvent, TelemetryLogger } from "@fluidframework/telemetry-utils";
19
14
  import fetch from "cross-fetch";
20
15
  import type { AxiosRequestConfig, AxiosRequestHeaders } from "axios";
21
16
  import safeStringify from "json-stringify-safe";
@@ -23,6 +18,7 @@ import { v4 as uuid } from "uuid";
23
18
  import { throwR11sNetworkError } from "./errorUtils";
24
19
  import { ITokenProvider, ITokenResponse } from "./tokens";
25
20
  import { pkgVersion as driverVersion } from "./packageVersion";
21
+ import { QueryStringType, RestWrapper } from "./restWrapperBase";
26
22
 
27
23
  type AuthorizationHeaderGetter = (token: ITokenResponse) => string;
28
24
  type TokenFetcher = (refresh?: boolean) => Promise<ITokenResponse>;
@@ -44,18 +40,75 @@ const axiosRequestConfigToFetchRequestConfig = (
44
40
  return [requestInfo, requestInit];
45
41
  };
46
42
 
43
+ export interface IR11sResponse<T> {
44
+ content: T;
45
+ headers: Map<string, string>;
46
+ propsToLog: ITelemetryProperties;
47
+ requestUrl: string;
48
+ }
49
+
50
+ /**
51
+ * A utility function to create a r11s response without any additional props as we might not have them always.
52
+ * @param content - response which is equivalent to content.
53
+ * @returns - a r11s response without any extra props.
54
+ */
55
+ export function createR11sResponseFromContent<T>(content: T): IR11sResponse<T> {
56
+ return {
57
+ content,
58
+ headers: new Map(),
59
+ propsToLog: {},
60
+ requestUrl: "",
61
+ };
62
+ }
63
+
64
+ function headersToMap(headers: Headers) {
65
+ const newHeaders = new Map<string, string>();
66
+ for (const [key, value] of headers.entries()) {
67
+ newHeaders.set(key, value);
68
+ }
69
+ return newHeaders;
70
+ }
71
+
72
+ export function getPropsToLogFromResponse(headers: {
73
+ get: (id: string) => string | undefined | null;
74
+ }) {
75
+ interface LoggingHeader {
76
+ headerName: string;
77
+ logName: string;
78
+ }
79
+
80
+ // We rename headers so that otel doesn't scrub them away. Otel doesn't allow
81
+ // certain characters in headers including '-'
82
+ const headersToLog: LoggingHeader[] = [
83
+ { headerName: "x-correlation-id", logName: "requestCorrelationId" },
84
+ { headerName: "content-encoding", logName: "contentEncoding" },
85
+ { headerName: "content-type", logName: "contentType" },
86
+ ];
87
+ const additionalProps: ITelemetryProperties = {
88
+ contentsize: TelemetryLogger.numberFromString(headers.get("content-length")),
89
+ };
90
+ headersToLog.forEach((header) => {
91
+ const headerValue = headers.get(header.headerName);
92
+ if (headerValue !== undefined && headerValue !== null) {
93
+ additionalProps[header.logName] = headerValue;
94
+ }
95
+ });
96
+
97
+ return additionalProps;
98
+ }
99
+
47
100
  export class RouterliciousRestWrapper extends RestWrapper {
48
101
  private readonly restLess = new RestLessClient();
102
+ private token: ITokenResponse | undefined;
49
103
 
50
104
  constructor(
51
105
  logger: ITelemetryLogger,
52
106
  private readonly rateLimiter: RateLimiter,
53
- private token: ITokenResponse,
54
107
  private readonly fetchRefreshedToken: TokenFetcher,
55
108
  private readonly getAuthorizationHeader: AuthorizationHeaderGetter,
56
109
  private readonly useRestLess: boolean,
57
110
  baseurl?: string,
58
- defaultQueryString: ParsedUrlQueryInput = {},
111
+ defaultQueryString: QueryStringType = {},
59
112
  ) {
60
113
  super(baseurl, defaultQueryString);
61
114
  }
@@ -64,33 +117,59 @@ export class RouterliciousRestWrapper extends RestWrapper {
64
117
  requestConfig: AxiosRequestConfig,
65
118
  statusCode: number,
66
119
  canRetry = true,
67
- ): Promise<T> {
120
+ ): Promise<IR11sResponse<T>> {
68
121
  const config = {
69
122
  ...requestConfig,
70
- headers: this.generateHeaders(requestConfig.headers),
123
+ headers: await this.generateHeaders(requestConfig.headers),
71
124
  };
72
125
 
73
126
  const translatedConfig = this.useRestLess ? this.restLess.translate(config) : config;
74
127
  const fetchRequestConfig = axiosRequestConfigToFetchRequestConfig(translatedConfig);
75
128
 
76
- const response: Response = await this.rateLimiter.schedule(async () =>
77
- fetch(...fetchRequestConfig).catch(async (error) => {
129
+ const res = await this.rateLimiter.schedule(async () => {
130
+ const perfStart = performance.now();
131
+ const result = await fetch(...fetchRequestConfig).catch(async (error) => {
78
132
  // Browser Fetch throws a TypeError on network error, `node-fetch` throws a FetchError
79
133
  const isNetworkError = ["TypeError", "FetchError"].includes(error?.name);
80
134
  throwR11sNetworkError(
81
135
  isNetworkError ? `NetworkError: ${error.message}` : safeStringify(error),
82
136
  );
83
- }),
84
- );
137
+ });
138
+ return {
139
+ response: result,
140
+ duration: performance.now() - perfStart,
141
+ };
142
+ });
143
+
144
+ const response = res.response;
85
145
 
146
+ let start = performance.now();
147
+ const text = await response.text();
148
+ const receiveContentTime = performance.now() - start;
149
+
150
+ const bodySize = text.length;
151
+ start = performance.now();
86
152
  const responseBody: any = response.headers.get("content-type")?.includes("application/json")
87
- ? await response.json()
88
- : await response.text();
153
+ ? JSON.parse(text)
154
+ : text;
155
+ const parseTime = performance.now() - start;
89
156
 
90
157
  // Success
91
158
  if (response.ok || response.status === statusCode) {
92
- const result: T = responseBody;
93
- return result;
159
+ const result = responseBody as T;
160
+ const headers = headersToMap(response.headers);
161
+ return {
162
+ content: result,
163
+ headers,
164
+ requestUrl: fetchRequestConfig[0].toString(),
165
+ propsToLog: {
166
+ ...getPropsToLogFromResponse(headers),
167
+ bodySize,
168
+ receiveContentTime,
169
+ parseTime,
170
+ fetchTime: res.duration,
171
+ },
172
+ };
94
173
  }
95
174
  // Failure
96
175
  if (response.status === 401 && canRetry) {
@@ -100,7 +179,7 @@ export class RouterliciousRestWrapper extends RestWrapper {
100
179
  }
101
180
  if (response.status === 429 && responseBody?.retryAfter > 0) {
102
181
  // Retry based on retryAfter[Seconds]
103
- return new Promise<T>((resolve, reject) =>
182
+ return new Promise<IR11sResponse<T>>((resolve, reject) =>
104
183
  setTimeout(() => {
105
184
  this.request<T>(config, statusCode).then(resolve).catch(reject);
106
185
  }, responseBody.retryAfter * 1000),
@@ -120,9 +199,11 @@ export class RouterliciousRestWrapper extends RestWrapper {
120
199
  );
121
200
  }
122
201
 
123
- private generateHeaders(
202
+ private async generateHeaders(
124
203
  requestHeaders?: AxiosRequestHeaders | undefined,
125
- ): Record<string, string> {
204
+ ): Promise<Record<string, string>> {
205
+ const token = await this.getToken();
206
+ assert(token !== undefined, 0x679 /* token should be present */);
126
207
  const correlationId = requestHeaders?.["x-correlation-id"] ?? uuid();
127
208
 
128
209
  return {
@@ -132,12 +213,17 @@ export class RouterliciousRestWrapper extends RestWrapper {
132
213
  "x-correlation-id": correlationId as string,
133
214
  "x-driver-version": driverVersion,
134
215
  // NOTE: If this.authorizationHeader is undefined, should "Authorization" be removed entirely?
135
- "Authorization": this.getAuthorizationHeader(this.token),
216
+ "Authorization": this.getAuthorizationHeader(token),
136
217
  };
137
218
  }
138
219
 
139
- public getToken(): ITokenResponse {
140
- return this.token;
220
+ public async getToken(): Promise<ITokenResponse> {
221
+ if (this.token !== undefined) {
222
+ return this.token;
223
+ }
224
+ const token = await this.fetchRefreshedToken();
225
+ this.setToken(token);
226
+ return token;
141
227
  }
142
228
 
143
229
  public setToken(token: ITokenResponse) {
@@ -149,17 +235,15 @@ export class RouterliciousStorageRestWrapper extends RouterliciousRestWrapper {
149
235
  private constructor(
150
236
  logger: ITelemetryLogger,
151
237
  rateLimiter: RateLimiter,
152
- token: ITokenResponse,
153
238
  fetchToken: TokenFetcher,
154
239
  getAuthorizationHeader: AuthorizationHeaderGetter,
155
240
  useRestLess: boolean,
156
241
  baseurl?: string,
157
- defaultQueryString: ParsedUrlQueryInput = {},
242
+ defaultQueryString: QueryStringType = {},
158
243
  ) {
159
244
  super(
160
245
  logger,
161
246
  rateLimiter,
162
- token,
163
247
  fetchToken,
164
248
  getAuthorizationHeader,
165
249
  useRestLess,
@@ -211,12 +295,9 @@ export class RouterliciousStorageRestWrapper extends RouterliciousRestWrapper {
211
295
  return getAuthorizationTokenFromCredentials(credentials);
212
296
  };
213
297
 
214
- const storagetoken = await fetchStorageToken();
215
-
216
298
  const restWrapper = new RouterliciousStorageRestWrapper(
217
299
  logger,
218
300
  rateLimiter,
219
- storagetoken,
220
301
  fetchStorageToken,
221
302
  getAuthorizationHeader,
222
303
  useRestLess,
@@ -232,17 +313,15 @@ export class RouterliciousOrdererRestWrapper extends RouterliciousRestWrapper {
232
313
  private constructor(
233
314
  logger: ITelemetryLogger,
234
315
  rateLimiter: RateLimiter,
235
- token: ITokenResponse,
236
316
  fetchToken: TokenFetcher,
237
317
  getAuthorizationHeader: AuthorizationHeaderGetter,
238
318
  useRestLess: boolean,
239
319
  baseurl?: string,
240
- defaultQueryString: ParsedUrlQueryInput = {},
320
+ defaultQueryString: QueryStringType = {},
241
321
  ) {
242
322
  super(
243
323
  logger,
244
324
  rateLimiter,
245
- token,
246
325
  fetchToken,
247
326
  getAuthorizationHeader,
248
327
  useRestLess,
@@ -285,12 +364,9 @@ export class RouterliciousOrdererRestWrapper extends RouterliciousRestWrapper {
285
364
  );
286
365
  };
287
366
 
288
- const newtoken = await fetchOrdererToken();
289
-
290
367
  const restWrapper = new RouterliciousOrdererRestWrapper(
291
368
  logger,
292
369
  rateLimiter,
293
- newtoken,
294
370
  fetchOrdererToken,
295
371
  getAuthorizationHeader,
296
372
  useRestLess,
@@ -0,0 +1,146 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import type { AxiosRequestConfig, AxiosRequestHeaders } from "axios";
7
+ import { IR11sResponse } from "./restWrapper";
8
+
9
+ export abstract class RestWrapper {
10
+ constructor(
11
+ protected readonly baseurl?: string,
12
+ protected defaultQueryString: QueryStringType = {},
13
+ protected readonly maxBodyLength = 1000 * 1024 * 1024,
14
+ protected readonly maxContentLength = 1000 * 1024 * 1024,
15
+ ) {}
16
+
17
+ public async get<T>(
18
+ url: string,
19
+ queryString?: QueryStringType,
20
+ headers?: AxiosRequestHeaders,
21
+ additionalOptions?: Partial<
22
+ Omit<
23
+ AxiosRequestConfig,
24
+ "baseURL" | "headers" | "maxBodyLength" | "maxContentLength" | "method" | "url"
25
+ >
26
+ >,
27
+ ): Promise<IR11sResponse<T>> {
28
+ const options: AxiosRequestConfig = {
29
+ ...additionalOptions,
30
+ baseURL: this.baseurl,
31
+ headers,
32
+ maxBodyLength: this.maxBodyLength,
33
+ maxContentLength: this.maxContentLength,
34
+ method: "GET",
35
+ url: `${url}${this.generateQueryString(queryString)}`,
36
+ };
37
+ return this.request<T>(options, 200);
38
+ }
39
+
40
+ public async post<T>(
41
+ url: string,
42
+ requestBody: any,
43
+ queryString?: QueryStringType,
44
+ headers?: AxiosRequestHeaders,
45
+ additionalOptions?: Partial<
46
+ Omit<
47
+ AxiosRequestConfig,
48
+ "baseURL" | "headers" | "maxBodyLength" | "maxContentLength" | "method" | "url"
49
+ >
50
+ >,
51
+ ): Promise<IR11sResponse<T>> {
52
+ const options: AxiosRequestConfig = {
53
+ ...additionalOptions,
54
+ baseURL: this.baseurl,
55
+ data: requestBody,
56
+ headers,
57
+ maxBodyLength: this.maxBodyLength,
58
+ maxContentLength: this.maxContentLength,
59
+ method: "POST",
60
+ url: `${url}${this.generateQueryString(queryString)}`,
61
+ };
62
+ return this.request<T>(options, 201);
63
+ }
64
+
65
+ public async delete<T>(
66
+ url: string,
67
+ queryString?: QueryStringType,
68
+ headers?: AxiosRequestHeaders,
69
+ additionalOptions?: Partial<
70
+ Omit<
71
+ AxiosRequestConfig,
72
+ "baseURL" | "headers" | "maxBodyLength" | "maxContentLength" | "method" | "url"
73
+ >
74
+ >,
75
+ ): Promise<IR11sResponse<T>> {
76
+ const options: AxiosRequestConfig = {
77
+ ...additionalOptions,
78
+ baseURL: this.baseurl,
79
+ headers,
80
+ maxBodyLength: this.maxBodyLength,
81
+ maxContentLength: this.maxContentLength,
82
+ method: "DELETE",
83
+ url: `${url}${this.generateQueryString(queryString)}`,
84
+ };
85
+ return this.request<T>(options, 204);
86
+ }
87
+
88
+ public async patch<T>(
89
+ url: string,
90
+ requestBody: any,
91
+ queryString?: QueryStringType,
92
+ headers?: AxiosRequestHeaders,
93
+ additionalOptions?: Partial<
94
+ Omit<
95
+ AxiosRequestConfig,
96
+ "baseURL" | "headers" | "maxBodyLength" | "maxContentLength" | "method" | "url"
97
+ >
98
+ >,
99
+ ): Promise<IR11sResponse<T>> {
100
+ const options: AxiosRequestConfig = {
101
+ ...additionalOptions,
102
+ baseURL: this.baseurl,
103
+ data: requestBody,
104
+ headers,
105
+ maxBodyLength: this.maxBodyLength,
106
+ maxContentLength: this.maxContentLength,
107
+ method: "PATCH",
108
+ url: `${url}${this.generateQueryString(queryString)}`,
109
+ };
110
+ return this.request<T>(options, 200);
111
+ }
112
+
113
+ protected abstract request<T>(
114
+ options: AxiosRequestConfig,
115
+ statusCode: number,
116
+ addNetworkCallProps?: boolean,
117
+ ): Promise<IR11sResponse<T>>;
118
+
119
+ protected generateQueryString(queryStringValues?: QueryStringType) {
120
+ if (this.defaultQueryString || queryStringValues) {
121
+ const queryStringMap = { ...this.defaultQueryString, ...queryStringValues };
122
+
123
+ return getQueryString(queryStringMap);
124
+ }
125
+
126
+ return "";
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Generates query string from the given query parameters.
132
+ * @param queryParams - Query parameters from which to create a query.
133
+ */
134
+ export function getQueryString(queryParams: QueryStringType): string {
135
+ let queryString = "";
136
+ for (const key of Object.keys(queryParams)) {
137
+ if (queryParams[key] !== undefined) {
138
+ const startChar = queryString === "" ? "?" : "&";
139
+ queryString += `${startChar}${key}=${encodeURIComponent(queryParams[key])}`;
140
+ }
141
+ }
142
+
143
+ return queryString;
144
+ }
145
+
146
+ export type QueryStringType = Record<string, string | number | boolean>;
@@ -4,15 +4,15 @@
4
4
  */
5
5
 
6
6
  import type * as git from "@fluidframework/gitresources";
7
- import type * as protocol from "@fluidframework/protocol-definitions";
8
7
  import {
9
- IGitManager,
10
8
  IWholeFlatSummary,
11
9
  IWholeSummaryPayload,
12
10
  IWriteSummaryResponse,
13
11
  } from "@fluidframework/server-services-client";
14
12
  import { runWithRetry } from "@fluidframework/driver-utils";
15
13
  import { ITelemetryLogger } from "@fluidframework/common-definitions";
14
+ import { IGitManager } from "./storageContracts";
15
+ import { IR11sResponse } from "./restWrapper";
16
16
 
17
17
  export class RetriableGitManager implements IGitManager {
18
18
  constructor(
@@ -20,135 +20,57 @@ export class RetriableGitManager implements IGitManager {
20
20
  private readonly logger: ITelemetryLogger,
21
21
  ) {}
22
22
 
23
- public async getHeader(id: string, sha: string): Promise<protocol.ISnapshotTree> {
24
- return this.runWithRetry(
25
- async () => this.internalGitManager.getHeader(id, sha),
26
- "gitManager_getHeader",
27
- );
28
- }
29
-
30
- public async getFullTree(sha: string): Promise<any> {
31
- return this.runWithRetry(
32
- async () => this.internalGitManager.getFullTree(sha),
33
- "gitManager_getFullTree",
34
- );
35
- }
36
-
37
- public async getCommit(sha: string): Promise<git.ICommit> {
38
- return this.runWithRetry(
39
- async () => this.internalGitManager.getCommit(sha),
40
- "gitManager_getCommit",
41
- );
42
- }
43
-
44
- public async getCommits(sha: string, count: number): Promise<git.ICommitDetails[]> {
23
+ public async getCommits(
24
+ sha: string,
25
+ count: number,
26
+ ): Promise<IR11sResponse<git.ICommitDetails[]>> {
45
27
  return this.runWithRetry(
46
28
  async () => this.internalGitManager.getCommits(sha, count),
47
29
  "gitManager_getCommits",
48
30
  );
49
31
  }
50
32
 
51
- public async getTree(root: string, recursive: boolean): Promise<git.ITree> {
33
+ public async getTree(root: string, recursive: boolean): Promise<IR11sResponse<git.ITree>> {
52
34
  return this.runWithRetry(
53
35
  async () => this.internalGitManager.getTree(root, recursive),
54
36
  "gitManager_getTree",
55
37
  );
56
38
  }
57
39
 
58
- public async getBlob(sha: string): Promise<git.IBlob> {
40
+ public async getBlob(sha: string): Promise<IR11sResponse<git.IBlob>> {
59
41
  return this.runWithRetry(
60
42
  async () => this.internalGitManager.getBlob(sha),
61
43
  "gitManager_getBlob",
62
44
  );
63
45
  }
64
46
 
65
- public getRawUrl(sha: string): string {
66
- return this.internalGitManager.getRawUrl(sha);
67
- }
68
-
69
- public async getContent(commit: string, path: string): Promise<git.IBlob> {
70
- return this.runWithRetry(
71
- async () => this.internalGitManager.getContent(commit, path),
72
- "gitManager_getContent",
73
- );
74
- }
75
-
76
- public async createBlob(content: string, encoding: string): Promise<git.ICreateBlobResponse> {
47
+ public async createBlob(
48
+ content: string,
49
+ encoding: string,
50
+ ): Promise<IR11sResponse<git.ICreateBlobResponse>> {
77
51
  return this.runWithRetry(
78
52
  async () => this.internalGitManager.createBlob(content, encoding),
79
53
  "gitManager_createBlob",
80
54
  );
81
55
  }
82
56
 
83
- public async createGitTree(params: git.ICreateTreeParams): Promise<git.ITree> {
57
+ public async createGitTree(params: git.ICreateTreeParams): Promise<IR11sResponse<git.ITree>> {
84
58
  return this.runWithRetry(
85
59
  async () => this.internalGitManager.createGitTree(params),
86
60
  "gitManager_createGitTree",
87
61
  );
88
62
  }
89
63
 
90
- public async createTree(files: protocol.ITree): Promise<git.ITree> {
91
- return this.runWithRetry(
92
- async () => this.internalGitManager.createTree(files),
93
- "gitManager_createTree",
94
- );
95
- }
96
-
97
- public async createCommit(commit: git.ICreateCommitParams): Promise<git.ICommit> {
98
- return this.runWithRetry(
99
- async () => this.internalGitManager.createCommit(commit),
100
- "gitManager_createCommit",
101
- );
102
- }
103
-
104
- public async getRef(ref: string): Promise<git.IRef> {
105
- return this.runWithRetry(
106
- async () => this.internalGitManager.getRef(ref),
107
- "gitManager_getRef",
108
- );
109
- }
110
-
111
- public async createRef(branch: string, sha: string): Promise<git.IRef> {
112
- return this.runWithRetry(
113
- async () => this.internalGitManager.createRef(branch, sha),
114
- "gitManager_createRef",
115
- );
116
- }
117
-
118
- public async upsertRef(branch: string, commitSha: string): Promise<git.IRef> {
119
- return this.runWithRetry(
120
- async () => this.internalGitManager.upsertRef(branch, commitSha),
121
- "gitManager_upsertRef",
122
- );
123
- }
124
-
125
- public async write(
126
- branch: string,
127
- inputTree: protocol.ITree,
128
- parents: string[],
129
- message: string,
130
- ): Promise<git.ICommit> {
131
- return this.runWithRetry(
132
- async () => this.internalGitManager.write(branch, inputTree, parents, message),
133
- "gitManager_write",
134
- );
135
- }
136
-
137
- public async createSummary(summary: IWholeSummaryPayload): Promise<IWriteSummaryResponse> {
64
+ public async createSummary(
65
+ summary: IWholeSummaryPayload,
66
+ ): Promise<IR11sResponse<IWriteSummaryResponse>> {
138
67
  return this.runWithRetry(
139
68
  async () => this.internalGitManager.createSummary(summary),
140
69
  "gitManager_createSummary",
141
70
  );
142
71
  }
143
72
 
144
- public async deleteSummary(softDelete: boolean): Promise<void> {
145
- return this.runWithRetry(
146
- async () => this.internalGitManager.deleteSummary(softDelete),
147
- "gitManager_deleteSummary",
148
- );
149
- }
150
-
151
- public async getSummary(sha: string): Promise<IWholeFlatSummary> {
73
+ public async getSummary(sha: string): Promise<IR11sResponse<IWholeFlatSummary>> {
152
74
  return this.runWithRetry(
153
75
  async () => this.internalGitManager.getSummary(sha),
154
76
  "gitManager_getSummary",
@@ -18,16 +18,14 @@ import {
18
18
  ISummaryTree,
19
19
  IVersion,
20
20
  } from "@fluidframework/protocol-definitions";
21
- import {
22
- GitManager,
23
- ISummaryUploadManager,
24
- SummaryTreeUploadManager,
25
- } from "@fluidframework/server-services-client";
26
21
  import { PerformanceEvent } from "@fluidframework/telemetry-utils";
27
22
  import { IRouterliciousDriverPolicies } from "./policies";
28
23
  import { ICache, InMemoryCache } from "./cache";
29
24
  import { RetriableGitManager } from "./retriableGitManager";
30
25
  import { ISnapshotTreeVersion } from "./definitions";
26
+ import { GitManager } from "./gitManager";
27
+ import { ISummaryUploadManager } from "./storageContracts";
28
+ import { SummaryTreeUploadManager } from "./summaryTreeUploadManager";
31
29
 
32
30
  const isNode = typeof window === "undefined";
33
31
 
@@ -85,7 +83,7 @@ export class ShreddedSummaryDocumentStorageService implements IDocumentStorageSe
85
83
  },
86
84
  async () => {
87
85
  const manager = await this.getStorageManager();
88
- return manager.getCommits(id, count);
86
+ return (await manager.getCommits(id, count)).content;
89
87
  },
90
88
  );
91
89
  return commits.map((commit) => ({
@@ -121,7 +119,7 @@ export class ShreddedSummaryDocumentStorageService implements IDocumentStorageSe
121
119
  },
122
120
  async (event) => {
123
121
  const manager = await this.getStorageManager();
124
- const response = await manager.getTree(requestVersion!.treeId);
122
+ const response = (await manager.getTree(requestVersion!.treeId)).content;
125
123
  event.end({
126
124
  size: response.tree.length,
127
125
  });
@@ -150,7 +148,7 @@ export class ShreddedSummaryDocumentStorageService implements IDocumentStorageSe
150
148
  },
151
149
  async (event) => {
152
150
  const manager = await this.getStorageManager();
153
- const response = await manager.getBlob(blobId);
151
+ const response = (await manager.getBlob(blobId)).content;
154
152
  event.end({
155
153
  size: response.size,
156
154
  });
@@ -203,7 +201,7 @@ export class ShreddedSummaryDocumentStorageService implements IDocumentStorageSe
203
201
  const manager = await this.getStorageManager();
204
202
  const response = await manager
205
203
  .createBlob(Uint8ArrayToString(uint8ArrayFile, "base64"), "base64")
206
- .then((r) => ({ id: r.sha, url: r.url }));
204
+ .then((r) => ({ id: r.content.sha, url: r.content.url }));
207
205
  event.end({
208
206
  blobId: response.id,
209
207
  });