@fluidframework/odsp-driver 2.0.0-internal.1.0.0.83139 → 2.0.0-internal.1.1.1

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 (94) hide show
  1. package/.mocharc.js +12 -0
  2. package/README.md +19 -0
  3. package/dist/contracts.d.ts +1 -0
  4. package/dist/contracts.d.ts.map +1 -1
  5. package/dist/contracts.js.map +1 -1
  6. package/dist/createFile.d.ts +1 -1
  7. package/dist/createFile.d.ts.map +1 -1
  8. package/dist/createFile.js +53 -16
  9. package/dist/createFile.js.map +1 -1
  10. package/dist/createOdspCreateContainerRequest.d.ts +4 -3
  11. package/dist/createOdspCreateContainerRequest.d.ts.map +1 -1
  12. package/dist/createOdspCreateContainerRequest.js +6 -3
  13. package/dist/createOdspCreateContainerRequest.js.map +1 -1
  14. package/dist/fetchSnapshot.d.ts +1 -2
  15. package/dist/fetchSnapshot.d.ts.map +1 -1
  16. package/dist/fetchSnapshot.js +14 -16
  17. package/dist/fetchSnapshot.js.map +1 -1
  18. package/dist/odspDeltaStorageService.d.ts +1 -1
  19. package/dist/odspDeltaStorageService.js +1 -1
  20. package/dist/odspDeltaStorageService.js.map +1 -1
  21. package/dist/odspDocumentService.d.ts.map +1 -1
  22. package/dist/odspDocumentService.js +2 -2
  23. package/dist/odspDocumentService.js.map +1 -1
  24. package/dist/odspDocumentServiceFactoryCore.d.ts.map +1 -1
  25. package/dist/odspDocumentServiceFactoryCore.js +29 -6
  26. package/dist/odspDocumentServiceFactoryCore.js.map +1 -1
  27. package/dist/odspDocumentStorageManager.d.ts +1 -2
  28. package/dist/odspDocumentStorageManager.d.ts.map +1 -1
  29. package/dist/odspDocumentStorageManager.js +22 -11
  30. package/dist/odspDocumentStorageManager.js.map +1 -1
  31. package/dist/odspDocumentStorageServiceBase.d.ts +1 -1
  32. package/dist/odspDocumentStorageServiceBase.d.ts.map +1 -1
  33. package/dist/odspDocumentStorageServiceBase.js +4 -2
  34. package/dist/odspDocumentStorageServiceBase.js.map +1 -1
  35. package/dist/odspUtils.d.ts +11 -2
  36. package/dist/odspUtils.d.ts.map +1 -1
  37. package/dist/odspUtils.js +21 -1
  38. package/dist/odspUtils.js.map +1 -1
  39. package/dist/packageVersion.d.ts +1 -1
  40. package/dist/packageVersion.d.ts.map +1 -1
  41. package/dist/packageVersion.js +1 -1
  42. package/dist/packageVersion.js.map +1 -1
  43. package/lib/contracts.d.ts +1 -0
  44. package/lib/contracts.d.ts.map +1 -1
  45. package/lib/contracts.js.map +1 -1
  46. package/lib/createFile.d.ts +1 -1
  47. package/lib/createFile.d.ts.map +1 -1
  48. package/lib/createFile.js +54 -17
  49. package/lib/createFile.js.map +1 -1
  50. package/lib/createOdspCreateContainerRequest.d.ts +4 -3
  51. package/lib/createOdspCreateContainerRequest.d.ts.map +1 -1
  52. package/lib/createOdspCreateContainerRequest.js +6 -3
  53. package/lib/createOdspCreateContainerRequest.js.map +1 -1
  54. package/lib/fetchSnapshot.d.ts +1 -2
  55. package/lib/fetchSnapshot.d.ts.map +1 -1
  56. package/lib/fetchSnapshot.js +14 -16
  57. package/lib/fetchSnapshot.js.map +1 -1
  58. package/lib/odspDeltaStorageService.d.ts +1 -1
  59. package/lib/odspDeltaStorageService.js +1 -1
  60. package/lib/odspDeltaStorageService.js.map +1 -1
  61. package/lib/odspDocumentService.d.ts.map +1 -1
  62. package/lib/odspDocumentService.js +2 -2
  63. package/lib/odspDocumentService.js.map +1 -1
  64. package/lib/odspDocumentServiceFactoryCore.d.ts.map +1 -1
  65. package/lib/odspDocumentServiceFactoryCore.js +29 -6
  66. package/lib/odspDocumentServiceFactoryCore.js.map +1 -1
  67. package/lib/odspDocumentStorageManager.d.ts +1 -2
  68. package/lib/odspDocumentStorageManager.d.ts.map +1 -1
  69. package/lib/odspDocumentStorageManager.js +22 -11
  70. package/lib/odspDocumentStorageManager.js.map +1 -1
  71. package/lib/odspDocumentStorageServiceBase.d.ts +1 -1
  72. package/lib/odspDocumentStorageServiceBase.d.ts.map +1 -1
  73. package/lib/odspDocumentStorageServiceBase.js +4 -2
  74. package/lib/odspDocumentStorageServiceBase.js.map +1 -1
  75. package/lib/odspUtils.d.ts +11 -2
  76. package/lib/odspUtils.d.ts.map +1 -1
  77. package/lib/odspUtils.js +19 -0
  78. package/lib/odspUtils.js.map +1 -1
  79. package/lib/packageVersion.d.ts +1 -1
  80. package/lib/packageVersion.d.ts.map +1 -1
  81. package/lib/packageVersion.js +1 -1
  82. package/lib/packageVersion.js.map +1 -1
  83. package/package.json +15 -15
  84. package/src/contracts.ts +2 -0
  85. package/src/createFile.ts +75 -15
  86. package/src/createOdspCreateContainerRequest.ts +7 -4
  87. package/src/fetchSnapshot.ts +12 -17
  88. package/src/odspDeltaStorageService.ts +1 -1
  89. package/src/odspDocumentService.ts +1 -2
  90. package/src/odspDocumentServiceFactoryCore.ts +40 -4
  91. package/src/odspDocumentStorageManager.ts +19 -13
  92. package/src/odspDocumentStorageServiceBase.ts +4 -2
  93. package/src/odspUtils.ts +24 -1
  94. package/src/packageVersion.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/odsp-driver",
3
- "version": "2.0.0-internal.1.0.0.83139",
3
+ "version": "2.0.0-internal.1.1.1",
4
4
  "description": "Socket storage implementation for SPO and ODC",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -61,17 +61,17 @@
61
61
  },
62
62
  "dependencies": {
63
63
  "@fluidframework/common-definitions": "^0.20.1",
64
- "@fluidframework/common-utils": "^0.32.1",
65
- "@fluidframework/core-interfaces": "2.0.0-internal.1.0.0.83139",
66
- "@fluidframework/driver-base": "2.0.0-internal.1.0.0.83139",
67
- "@fluidframework/driver-definitions": "2.0.0-internal.1.0.0.83139",
68
- "@fluidframework/driver-utils": "2.0.0-internal.1.0.0.83139",
69
- "@fluidframework/gitresources": "^0.1037.1000-0",
70
- "@fluidframework/odsp-doclib-utils": "2.0.0-internal.1.0.0.83139",
71
- "@fluidframework/odsp-driver-definitions": "2.0.0-internal.1.0.0.83139",
72
- "@fluidframework/protocol-base": "^0.1037.1000-0",
73
- "@fluidframework/protocol-definitions": "^0.1029.1000-0",
74
- "@fluidframework/telemetry-utils": "2.0.0-internal.1.0.0.83139",
64
+ "@fluidframework/common-utils": "^1.0.0",
65
+ "@fluidframework/core-interfaces": "^2.0.0-internal.1.1.1",
66
+ "@fluidframework/driver-base": "^2.0.0-internal.1.1.1",
67
+ "@fluidframework/driver-definitions": "^2.0.0-internal.1.1.1",
68
+ "@fluidframework/driver-utils": "^2.0.0-internal.1.1.1",
69
+ "@fluidframework/gitresources": "^0.1037.1000",
70
+ "@fluidframework/odsp-doclib-utils": "^2.0.0-internal.1.1.1",
71
+ "@fluidframework/odsp-driver-definitions": "^2.0.0-internal.1.1.1",
72
+ "@fluidframework/protocol-base": "^0.1037.1000",
73
+ "@fluidframework/protocol-definitions": "^1.0.0",
74
+ "@fluidframework/telemetry-utils": "^2.0.0-internal.1.1.1",
75
75
  "abort-controller": "^3.0.0",
76
76
  "node-fetch": "^2.6.1",
77
77
  "socket.io-client": "^4.4.1",
@@ -79,9 +79,9 @@
79
79
  },
80
80
  "devDependencies": {
81
81
  "@fluidframework/build-common": "^0.24.0",
82
- "@fluidframework/build-tools": "^0.3.0-0",
82
+ "@fluidframework/build-tools": "^0.3.1000",
83
83
  "@fluidframework/eslint-config-fluid": "^0.28.2000",
84
- "@fluidframework/mocha-test-setup": "2.0.0-internal.1.0.0.83139",
84
+ "@fluidframework/mocha-test-setup": "^2.0.0-internal.1.1.1",
85
85
  "@fluidframework/odsp-driver-previous": "npm:@fluidframework/odsp-driver@^1.0.0",
86
86
  "@microsoft/api-extractor": "^7.22.2",
87
87
  "@rushstack/eslint-config": "^2.5.1",
@@ -89,7 +89,7 @@
89
89
  "@types/node-fetch": "^2.5.10",
90
90
  "@types/sha.js": "^2.4.0",
91
91
  "concurrently": "^6.2.0",
92
- "copyfiles": "^2.1.0",
92
+ "copyfiles": "^2.4.1",
93
93
  "cross-env": "^7.0.2",
94
94
  "eslint": "~8.6.0",
95
95
  "mocha": "^10.0.0",
package/src/contracts.ts CHANGED
@@ -216,6 +216,8 @@ export interface ICreateFileResponse {
216
216
  itemId: string;
217
217
  itemUrl: string;
218
218
  sequenceNumber: number;
219
+ // sharing object contains shareId, sharingLink data or error in the response
220
+ sharing?: any;
219
221
  sharingLink?: string;
220
222
  sharingLinkErrorReason?: string;
221
223
  }
package/src/createFile.ts CHANGED
@@ -15,6 +15,9 @@ import {
15
15
  InstrumentedStorageTokenFetcher,
16
16
  IOdspResolvedUrl,
17
17
  OdspErrorType,
18
+ ShareLinkInfoType,
19
+ ISharingLinkKind,
20
+ ShareLinkTypes,
18
21
  } from "@fluidframework/odsp-driver-definitions";
19
22
  import { DriverErrorType } from "@fluidframework/driver-definitions";
20
23
  import {
@@ -26,6 +29,7 @@ import {
26
29
  } from "./contracts";
27
30
  import { getUrlAndHeadersWithAuth } from "./getUrlAndHeadersWithAuth";
28
31
  import {
32
+ buildOdspShareLinkReqParams,
29
33
  createCacheSnapshotKey,
30
34
  getWithRetryForTokenRefresh,
31
35
  INewFileInfo,
@@ -61,6 +65,8 @@ export async function createNewFluidFile(
61
65
  createNewCaching: boolean,
62
66
  forceAccessTokenViaAuthorizationHeader: boolean,
63
67
  isClpCompliantApp?: boolean,
68
+ enableSingleRequestForShareLinkWithCreate?: boolean,
69
+ enableShareLinkWithCreate?: boolean,
64
70
  ): Promise<IOdspResolvedUrl> {
65
71
  // Check for valid filename before the request to create file is actually made.
66
72
  if (isInvalidFileName(newFileInfo.filename)) {
@@ -71,8 +77,7 @@ export async function createNewFluidFile(
71
77
 
72
78
  let itemId: string;
73
79
  let summaryHandle: string = "";
74
- let sharingLink: string | undefined;
75
- let sharingLinkErrorReason: string | undefined;
80
+ let shareLinkInfo: ShareLinkInfoType | undefined;
76
81
  if (createNewSummary === undefined) {
77
82
  itemId = await createNewEmptyFluidFile(
78
83
  getStorageToken, newFileInfo, logger, epochTracker, forceAccessTokenViaAuthorizationHeader);
@@ -87,8 +92,12 @@ export async function createNewFluidFile(
87
92
  );
88
93
  itemId = content.itemId;
89
94
  summaryHandle = content.id;
90
- sharingLink = content.sharingLink;
91
- sharingLinkErrorReason = content.sharingLinkErrorReason;
95
+
96
+ shareLinkInfo = extractShareLinkData(
97
+ newFileInfo.createLinkType,
98
+ content,
99
+ enableSingleRequestForShareLinkWithCreate,
100
+ enableShareLinkWithCreate);
92
101
  }
93
102
 
94
103
  const odspUrl = createOdspUrl({ ...newFileInfo, itemId, dataStorePath: "/" });
@@ -100,15 +109,7 @@ export async function createNewFluidFile(
100
109
  fileEntry.docId = odspResolvedUrl.hashedDocumentId;
101
110
  fileEntry.resolvedUrl = odspResolvedUrl;
102
111
 
103
- if (sharingLink || sharingLinkErrorReason) {
104
- odspResolvedUrl.shareLinkInfo = {
105
- createLink: {
106
- type: newFileInfo.createLinkType,
107
- link: sharingLink,
108
- error: sharingLinkErrorReason,
109
- },
110
- };
111
- }
112
+ odspResolvedUrl.shareLinkInfo = shareLinkInfo;
112
113
 
113
114
  if (createNewSummary !== undefined && createNewCaching) {
114
115
  assert(summaryHandle !== undefined, 0x203 /* "Summary handle is undefined" */);
@@ -120,6 +121,61 @@ export async function createNewFluidFile(
120
121
  return odspResolvedUrl;
121
122
  }
122
123
 
124
+ /**
125
+ * If user requested creation of a sharing link along with the creation of the file by providing either
126
+ * createLinkType (now deprecated) or createLinkScope in the request parameters, extract and save
127
+ * sharing link information from the response if it is available.
128
+ * In case there was an error in creation of the sharing link, error is provided back in the response,
129
+ * and does not impact the creation of file in ODSP.
130
+ * @param requestedSharingLinkKind - Kind of sharing link requested to be created along with the creation of file.
131
+ * @param response - Response object received from the /snapshot api call
132
+ * @returns Sharing link information received in the response from a successful creation of a file.
133
+ */
134
+ function extractShareLinkData(
135
+ requestedSharingLinkKind: ShareLinkTypes | ISharingLinkKind | undefined,
136
+ response: ICreateFileResponse,
137
+ enableSingleRequestForShareLinkWithCreate?: boolean,
138
+ enableShareLinkWithCreate?: boolean,
139
+ ): ShareLinkInfoType | undefined {
140
+ if (!requestedSharingLinkKind) {
141
+ return;
142
+ }
143
+ let shareLinkInfo: ShareLinkInfoType | undefined;
144
+ if (enableSingleRequestForShareLinkWithCreate) {
145
+ const { sharing } = response;
146
+ if (!sharing) {
147
+ return;
148
+ }
149
+ shareLinkInfo = {
150
+ createLink: {
151
+ type: requestedSharingLinkKind,
152
+ link: sharing.sharingLink ? {
153
+ scope: sharing.sharingLink.scope,
154
+ role: sharing.sharingLink.type,
155
+ webUrl: sharing.sharingLink.webUrl,
156
+ ...sharing.sharingLink,
157
+ } : undefined,
158
+ error: sharing.error,
159
+ shareId: sharing.shareId,
160
+ },
161
+ };
162
+ } else if (enableShareLinkWithCreate) {
163
+ const { sharing, sharingLink, sharingLinkErrorReason } = response;
164
+ if (!sharingLink && !sharingLinkErrorReason) {
165
+ return;
166
+ }
167
+ shareLinkInfo = {
168
+ createLink: {
169
+ type: requestedSharingLinkKind,
170
+ link: sharingLink,
171
+ error: sharingLinkErrorReason,
172
+ shareId: sharing?.shareId,
173
+ },
174
+ };
175
+ }
176
+ return shareLinkInfo;
177
+ }
178
+
123
179
  export async function createNewEmptyFluidFile(
124
180
  getStorageToken: InstrumentedStorageTokenFetcher,
125
181
  newFileInfo: INewFileInfo,
@@ -192,8 +248,12 @@ export async function createNewFluidFileFromSummary(
192
248
  `${filePath}/${encodedFilename}`;
193
249
 
194
250
  const containerSnapshot = convertSummaryIntoContainerSnapshot(createNewSummary);
195
- const initialUrl = `${baseUrl}:/opStream/snapshots/snapshot${newFileInfo.createLinkType ?
196
- `?createLinkType=${newFileInfo.createLinkType}` : ""}`;
251
+
252
+ // Build share link parameter based on the createLinkType provided so that the
253
+ // snapshot api can create and return the share link along with creation of file in the response.
254
+ const createShareLinkParam = buildOdspShareLinkReqParams(newFileInfo.createLinkType);
255
+ const initialUrl =
256
+ `${baseUrl}:/opStream/snapshots/snapshot${createShareLinkParam ? `?${createShareLinkParam}` : ""}`;
197
257
 
198
258
  return getWithRetryForTokenRefresh(async (options) => {
199
259
  const storageToken = await getStorageToken(options, "CreateNewFile");
@@ -4,7 +4,8 @@
4
4
  */
5
5
  import { IRequest } from "@fluidframework/core-interfaces";
6
6
  import { DriverHeader } from "@fluidframework/driver-definitions";
7
- import { ShareLinkTypes } from "@fluidframework/odsp-driver-definitions";
7
+ import { ShareLinkTypes, ISharingLinkKind } from "@fluidframework/odsp-driver-definitions";
8
+ import { buildOdspShareLinkReqParams } from "./odspUtils";
8
9
 
9
10
  /**
10
11
  * Create the request object with url and headers for creating a new file on OneDrive Sharepoint
@@ -12,19 +13,21 @@ import { ShareLinkTypes } from "@fluidframework/odsp-driver-definitions";
12
13
  * @param driveId - drive identifier
13
14
  * @param filePath - path where file needs to be created
14
15
  * @param fileName - name of the new file to be created
15
- * @param createLinkType - type of sharing link you would like to create for this file
16
+ * @param createShareLinkType - type of sharing link you would like to create for this file. ShareLinkTypes
17
+ * will be deprecated soon, so for any new implementation please provide createShareLinkType of type ShareLink
16
18
  */
17
19
  export function createOdspCreateContainerRequest(
18
20
  siteUrl: string,
19
21
  driveId: string,
20
22
  filePath: string,
21
23
  fileName: string,
22
- createLinkType?: ShareLinkTypes,
24
+ createShareLinkType?: ShareLinkTypes | ISharingLinkKind,
23
25
  ): IRequest {
26
+ const shareLinkRequestParams = buildOdspShareLinkReqParams(createShareLinkType);
24
27
  const createNewRequest: IRequest = {
25
28
  url: `${siteUrl}?driveId=${encodeURIComponent(
26
29
  driveId,
27
- )}&path=${encodeURIComponent(filePath)}${createLinkType ? `&createLinkType=${createLinkType}` : ""}`,
30
+ )}&path=${encodeURIComponent(filePath)}${shareLinkRequestParams ? `&${shareLinkRequestParams}` : ""}`,
28
31
  headers: {
29
32
  [DriverHeader.createNew]: {
30
33
  fileName,
@@ -49,7 +49,6 @@ export enum SnapshotFormatSupportType {
49
49
  * @param token - token used for authorization in the request
50
50
  * @param storageFetchWrapper - Implementation of the get/post methods used to fetch the snapshot
51
51
  * @param versionId - id of specific snapshot to be fetched
52
- * @param fetchFullSnapshot - whether we want to fetch full snapshot(with blobs)
53
52
  * @param forceAccessTokenViaAuthorizationHeader - whether to force passing given token via authorization header
54
53
  * @returns A promise of the snapshot and the status code of the response
55
54
  */
@@ -57,22 +56,14 @@ export async function fetchSnapshot(
57
56
  snapshotUrl: string,
58
57
  token: string | null,
59
58
  versionId: string,
60
- fetchFullSnapshot: boolean,
61
59
  forceAccessTokenViaAuthorizationHeader: boolean,
62
60
  logger: ITelemetryLogger,
63
61
  snapshotDownloader: (url: string, fetchOptions: { [index: string]: any; }) => Promise<IOdspResponse<unknown>>,
64
62
  ): Promise<ISnapshotContents> {
65
63
  const path = `/trees/${versionId}`;
66
- let queryParams: ISnapshotOptions = {};
67
-
68
- if (fetchFullSnapshot) {
69
- if (versionId !== "latest") {
70
- queryParams = { channels: 1, blobs: 2 };
71
- } else {
72
- queryParams = { deltas: 1, channels: 1, blobs: 2 };
73
- }
74
- }
75
-
64
+ // We just want to fetch tree here. So explicitly set to not fetch blobs and deltas
65
+ // as by default server will send that.
66
+ const queryParams: ISnapshotOptions = { deltas: 0, blobs: 0 };
76
67
  const queryString = getQueryString(queryParams);
77
68
  const { url, headers } = getUrlAndHeadersWithAuth(
78
69
  `${snapshotUrl}${path}${queryString}`, token, forceAccessTokenViaAuthorizationHeader);
@@ -252,9 +243,15 @@ async function fetchLatestSnapshotCore(
252
243
  });
253
244
 
254
245
  let parsedSnapshotContents: IOdspResponse<ISnapshotContents> | undefined;
246
+ let contentTypeToRead: string | undefined;
247
+ if (contentType?.indexOf("application/ms-fluid") !== -1) {
248
+ contentTypeToRead = "application/ms-fluid";
249
+ } else if (contentType?.indexOf("application/json") !== -1) {
250
+ contentTypeToRead = "application/json";
251
+ }
255
252
 
256
253
  try {
257
- switch (contentType) {
254
+ switch (contentTypeToRead) {
258
255
  case "application/json": {
259
256
  const text = await odspResponse.content.text();
260
257
  propsToLog.bodySize = text.length;
@@ -549,14 +546,12 @@ export async function downloadSnapshot(
549
546
  };
550
547
  // Decide what snapshot format to fetch as per the feature gate.
551
548
  switch (snapshotFormatFetchType) {
552
- case SnapshotFormatSupportType.JsonAndBinary:
553
- headers.accept = `application/json, application/ms-fluid; v=${currentReadVersion}`;
554
- break;
555
549
  case SnapshotFormatSupportType.Binary:
556
550
  headers.accept = `application/ms-fluid; v=${currentReadVersion}`;
557
551
  break;
558
552
  default:
559
- headers.accept = "application/json";
553
+ // By default ask both versions and let the server decide the format.
554
+ headers.accept = `application/json, application/ms-fluid; v=${currentReadVersion}`;
560
555
  }
561
556
 
562
557
  const odspResponse = await (epochTracker?.fetch(url, fetchOptions, "treesLatest", true, scenarioName) ??
@@ -31,7 +31,7 @@ export class OdspDeltaStorageService {
31
31
  }
32
32
 
33
33
  /**
34
- * Retrieves ops from cache
34
+ * Retrieves ops from storage
35
35
  * @param from - inclusive
36
36
  * @param to - exclusive
37
37
  * @param telemetryProps - properties to add when issuing telemetry events
@@ -176,7 +176,6 @@ export class OdspDocumentService implements IDocumentService {
176
176
  this.odspResolvedUrl,
177
177
  this.getStorageToken,
178
178
  this.mc.logger,
179
- true,
180
179
  this.cache,
181
180
  this.hostPolicy,
182
181
  this.epochTracker,
@@ -189,7 +188,7 @@ export class OdspDocumentService implements IDocumentService {
189
188
  },
190
189
  () => {
191
190
  assert(this.relayServiceTenantAndSessionId !== undefined,
192
- "relayServiceTenantAndSessionId should be present");
191
+ 0x37b /* relayServiceTenantAndSessionId should be present */);
193
192
  return this.relayServiceTenantAndSessionId;
194
193
  },
195
194
  this.mc.config.getNumber("Fluid.Driver.Odsp.snapshotFormatFetchType"),
@@ -26,6 +26,10 @@ import {
26
26
  HostStoragePolicy,
27
27
  IFileEntry,
28
28
  IOdspUrlParts,
29
+ SharingLinkScope,
30
+ SharingLinkRole,
31
+ ShareLinkTypes,
32
+ ISharingLinkKind,
29
33
  } from "@fluidframework/odsp-driver-definitions";
30
34
  import type { io as SocketIOClientStatic } from "socket.io-client";
31
35
  import { v4 as uuid } from "uuid";
@@ -84,15 +88,13 @@ export class OdspDocumentServiceFactoryCore implements IDocumentServiceFactory {
84
88
  }
85
89
  }
86
90
 
91
+ const createShareLinkParam = getSharingLinkParams(this.hostPolicy, searchParams);
87
92
  const newFileInfo: INewFileInfo = {
88
93
  driveId: odspResolvedUrl.driveId,
89
94
  siteUrl: odspResolvedUrl.siteUrl,
90
95
  filePath,
91
96
  filename: odspResolvedUrl.fileName,
92
- // set createLinkType to undefined if enableShareLinkWithCreate is set to false,
93
- // so that share link creation with create file can be enabled
94
- createLinkType: this.hostPolicy.enableShareLinkWithCreate ?
95
- odspResolvedUrl.shareLinkInfo?.createLink?.type : undefined,
97
+ createLinkType: createShareLinkParam,
96
98
  };
97
99
 
98
100
  const odspLogger = createOdspLogger(logger);
@@ -110,6 +112,10 @@ export class OdspDocumentServiceFactoryCore implements IDocumentServiceFactory {
110
112
  {
111
113
  eventName: "CreateNew",
112
114
  isWithSummaryUpload: true,
115
+ createShareLinkParam: JSON.stringify(createShareLinkParam),
116
+ enableShareLinkWithCreate: this.hostPolicy.enableShareLinkWithCreate,
117
+ enableSingleRequestForShareLinkWithCreate:
118
+ this.hostPolicy.enableSingleRequestForShareLinkWithCreate,
113
119
  },
114
120
  async (event) => {
115
121
  odspResolvedUrl = await createNewFluidFile(
@@ -127,6 +133,8 @@ export class OdspDocumentServiceFactoryCore implements IDocumentServiceFactory {
127
133
  this.hostPolicy.cacheCreateNewSummary ?? true,
128
134
  !!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,
129
135
  odspResolvedUrl.isClpCompliantApp,
136
+ this.hostPolicy.enableSingleRequestForShareLinkWithCreate,
137
+ this.hostPolicy.enableShareLinkWithCreate,
130
138
  );
131
139
  const docService = this.createDocumentServiceCore(odspResolvedUrl, odspLogger,
132
140
  cacheAndTracker, clientIsSummarizer);
@@ -223,3 +231,31 @@ export class OdspDocumentServiceFactoryCore implements IDocumentServiceFactory {
223
231
  );
224
232
  }
225
233
  }
234
+
235
+ /**
236
+ * Extract the sharing link kind from the resolved URL's query paramerters
237
+ */
238
+ function getSharingLinkParams(
239
+ hostPolicy: HostStoragePolicy,
240
+ searchParams: URLSearchParams,
241
+ ): ShareLinkTypes | ISharingLinkKind | undefined {
242
+ // extract request parameters for creation of sharing link (if provided) if the feature is enabled
243
+ let createShareLinkParam: ShareLinkTypes | ISharingLinkKind | undefined;
244
+ if (hostPolicy.enableSingleRequestForShareLinkWithCreate) {
245
+ const createLinkScope = searchParams.get("createLinkScope");
246
+ const createLinkRole = searchParams.get("createLinkRole");
247
+ if (createLinkScope && SharingLinkScope[createLinkScope]) {
248
+ createShareLinkParam = {
249
+ scope: SharingLinkScope[createLinkScope],
250
+ ...(createLinkRole && SharingLinkRole[createLinkRole] ?
251
+ { role: SharingLinkRole[createLinkRole] } : {}),
252
+ };
253
+ }
254
+ } else if (hostPolicy.enableShareLinkWithCreate) {
255
+ const createLinkType = searchParams.get("createLinkType");
256
+ if (createLinkType && ShareLinkTypes[createLinkType]) {
257
+ createShareLinkParam = ShareLinkTypes[createLinkType || ""];
258
+ }
259
+ }
260
+ return createShareLinkParam;
261
+ }
@@ -88,7 +88,6 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
88
88
  private readonly odspResolvedUrl: IOdspResolvedUrl,
89
89
  private readonly getStorageToken: InstrumentedStorageTokenFetcher,
90
90
  private readonly logger: ITelemetryLogger,
91
- private readonly fetchFullSnapshot: boolean,
92
91
  private readonly cache: IOdspCache,
93
92
  private readonly hostPolicy: HostStoragePolicyInternal,
94
93
  private readonly epochTracker: EpochTracker,
@@ -228,8 +227,7 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
228
227
  }
229
228
 
230
229
  // If count is one, we can use the trees/latest API, which returns the latest version and trees in a single request for better performance
231
- // Do it only once - we might get more here due to summarizer - it needs only container tree, not full snapshot.
232
- if (this.firstVersionCall && count === 1 && (blobid === null || blobid === this.documentId)) {
230
+ if (count === 1 && (blobid === null || blobid === this.documentId)) {
233
231
  const hostSnapshotOptions = this.hostPolicy.snapshotOptions;
234
232
  const odspSnapshotCacheValue: ISnapshotContents = await PerformanceEvent.timedExecAsync(
235
233
  this.logger,
@@ -275,7 +273,10 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
275
273
  // Based on the concurrentSnapshotFetch policy:
276
274
  // Either retrieve both the network and cache snapshots concurrently and pick the first to return,
277
275
  // or grab the cache value and then the network value if the cache value returns undefined.
278
- if (this.hostPolicy.concurrentSnapshotFetch && !this.hostPolicy.summarizerClient) {
276
+ // For summarizer which could call this during refreshing of summary parent, always use the cache
277
+ // first. Also for other clients, if it is not critical path which is determined by firstVersionCall,
278
+ // then also check the cache first.
279
+ if (this.firstVersionCall && this.hostPolicy.concurrentSnapshotFetch && !this.hostPolicy.summarizerClient) {
279
280
  const networkSnapshotP = this.fetchSnapshot(hostSnapshotOptions, scenarioName);
280
281
 
281
282
  // Ensure that failures on both paths are ignored initially.
@@ -306,11 +307,18 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
306
307
  // while the first caller is awaiting later async code in this block.
307
308
 
308
309
  retrievedSnapshot = await cachedSnapshotP;
309
-
310
- method = retrievedSnapshot !== undefined ? "cache" : "network";
311
-
312
- if (retrievedSnapshot === undefined) {
313
- retrievedSnapshot = await this.fetchSnapshot(hostSnapshotOptions, scenarioName);
310
+ if (retrievedSnapshot !== undefined) {
311
+ method = "cache";
312
+ } else {
313
+ method = "network";
314
+ const options: ISnapshotOptions = { ...hostSnapshotOptions };
315
+ // Don't fetch the blobs/deltas if it is not the first call. By default server will add
316
+ // blobs and deltas to the response.
317
+ if (!this.firstVersionCall) {
318
+ options.blobs = 0;
319
+ options.deltas = 0;
320
+ }
321
+ retrievedSnapshot = await this.fetchSnapshot(options, scenarioName);
314
322
  }
315
323
  }
316
324
  }
@@ -322,10 +330,9 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
322
330
  },
323
331
  );
324
332
 
325
- // Successful call, make network calls only
333
+ // Don't override ops which were fetched during initial load, since we could still need them.
334
+ const id = this.initializeFromSnapshot(odspSnapshotCacheValue, this.firstVersionCall);
326
335
  this.firstVersionCall = false;
327
- const id = this.initializeFromSnapshot(odspSnapshotCacheValue);
328
-
329
336
  return id ? [{ id, treeId: undefined! }] : [];
330
337
  }
331
338
 
@@ -545,7 +552,6 @@ export class OdspDocumentStorageService extends OdspDocumentStorageServiceBase {
545
552
  this.snapshotUrl!,
546
553
  storageToken,
547
554
  id,
548
- this.fetchFullSnapshot,
549
555
  !!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,
550
556
  this.logger,
551
557
  snapshotDownloader,
@@ -244,7 +244,7 @@ export abstract class OdspDocumentStorageServiceBase implements IDocumentStorage
244
244
  return summarySnapshotTree;
245
245
  }
246
246
 
247
- protected initializeFromSnapshot(odspSnapshotCacheValue: ISnapshotContents): string | undefined {
247
+ protected initializeFromSnapshot(odspSnapshotCacheValue: ISnapshotContents, cacheOps: boolean = true): string | undefined {
248
248
  this._snapshotSequenceNumber = odspSnapshotCacheValue.sequenceNumber;
249
249
  const { snapshotTree, blobs, ops } = odspSnapshotCacheValue;
250
250
 
@@ -260,7 +260,9 @@ export abstract class OdspDocumentStorageServiceBase implements IDocumentStorage
260
260
  this.initBlobsCache(blobs);
261
261
  }
262
262
 
263
- this.ops = ops;
263
+ if (cacheOps) {
264
+ this.ops = ops;
265
+ }
264
266
  return id;
265
267
  }
266
268
  }
package/src/odspUtils.ts CHANGED
@@ -27,6 +27,7 @@ import {
27
27
  isTokenFromCache,
28
28
  OdspResourceTokenFetchOptions,
29
29
  ShareLinkTypes,
30
+ ISharingLinkKind,
30
31
  TokenFetcher,
31
32
  ICacheEntry,
32
33
  snapshotKey,
@@ -233,8 +234,10 @@ export interface INewFileInfo {
233
234
  * application can request creation of a share link along with the creation of a new file
234
235
  * by passing in an optional param to specify the kind of sharing link
235
236
  * (at the time of adding this comment Sept/2021), odsp only supports csl
237
+ * ShareLinkTypes will deprecated in future. Use ISharingLinkKind instead which specifies both
238
+ * share link type and the role type.
236
239
  */
237
- createLinkType?: ShareLinkTypes;
240
+ createLinkType?: ShareLinkTypes | ISharingLinkKind;
238
241
  }
239
242
 
240
243
  export function getOdspResolvedUrl(resolvedUrl: IResolvedUrl): IOdspResolvedUrl {
@@ -348,3 +351,23 @@ export function createCacheSnapshotKey(odspResolvedUrl: IOdspResolvedUrl): ICach
348
351
  // 80KB is the max body size that we can put in ump post body for server to be able to accept it.
349
352
  // Keeping it 78KB to be a little cautious. As per the telemetry 99p is less than 78KB.
350
353
  export const maxUmpPostBodySize = 79872;
354
+
355
+ /**
356
+ * Build request parameters to request for the creation of a sharing link along with the creation of the file
357
+ * through the /snapshot api call.
358
+ * @param shareLinkType - Kind of sharing link requested
359
+ * @returns A string of request parameters that can be concatenated with the base URI
360
+ */
361
+ export function buildOdspShareLinkReqParams(shareLinkType: ShareLinkTypes | ISharingLinkKind | undefined) {
362
+ if (!shareLinkType) {
363
+ return;
364
+ }
365
+ const scope = (shareLinkType as ISharingLinkKind).scope;
366
+ if (!scope) {
367
+ return `createLinkType=${shareLinkType}`;
368
+ }
369
+ let shareLinkRequestParams = `createLinkScope=${scope}`;
370
+ const role = (shareLinkType as ISharingLinkKind).role;
371
+ shareLinkRequestParams = role ? `${shareLinkRequestParams}&createLinkRole=${role}` : shareLinkRequestParams;
372
+ return shareLinkRequestParams;
373
+ }
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/odsp-driver";
9
- export const pkgVersion = "2.0.0-internal.1.0.0.83139";
9
+ export const pkgVersion = "2.0.0-internal.1.1.1";