@fluidframework/odsp-driver 0.55.0 → 0.56.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 (134) hide show
  1. package/dist/checkUrl.d.ts.map +1 -1
  2. package/dist/checkUrl.js +0 -1
  3. package/dist/checkUrl.js.map +1 -1
  4. package/dist/contractsPublic.d.ts +7 -1
  5. package/dist/contractsPublic.d.ts.map +1 -1
  6. package/dist/contractsPublic.js +7 -1
  7. package/dist/contractsPublic.js.map +1 -1
  8. package/dist/createFile.d.ts +3 -3
  9. package/dist/createFile.d.ts.map +1 -1
  10. package/dist/createFile.js +7 -7
  11. package/dist/createFile.js.map +1 -1
  12. package/dist/epochTracker.d.ts +3 -3
  13. package/dist/epochTracker.d.ts.map +1 -1
  14. package/dist/epochTracker.js +20 -8
  15. package/dist/epochTracker.js.map +1 -1
  16. package/dist/fetchSnapshot.d.ts +3 -2
  17. package/dist/fetchSnapshot.d.ts.map +1 -1
  18. package/dist/fetchSnapshot.js +28 -16
  19. package/dist/fetchSnapshot.js.map +1 -1
  20. package/dist/getFileLink.js +4 -4
  21. package/dist/getFileLink.js.map +1 -1
  22. package/dist/getUrlAndHeadersWithAuth.d.ts +1 -1
  23. package/dist/getUrlAndHeadersWithAuth.d.ts.map +1 -1
  24. package/dist/getUrlAndHeadersWithAuth.js +20 -33
  25. package/dist/getUrlAndHeadersWithAuth.js.map +1 -1
  26. package/dist/odspDeltaStorageService.d.ts.map +1 -1
  27. package/dist/odspDeltaStorageService.js +1 -4
  28. package/dist/odspDeltaStorageService.js.map +1 -1
  29. package/dist/odspDocumentServiceFactoryCore.d.ts.map +1 -1
  30. package/dist/odspDocumentServiceFactoryCore.js +2 -2
  31. package/dist/odspDocumentServiceFactoryCore.js.map +1 -1
  32. package/dist/odspDocumentStorageManager.d.ts +1 -0
  33. package/dist/odspDocumentStorageManager.d.ts.map +1 -1
  34. package/dist/odspDocumentStorageManager.js +16 -9
  35. package/dist/odspDocumentStorageManager.js.map +1 -1
  36. package/dist/odspDriverUrlResolver.d.ts.map +1 -1
  37. package/dist/odspDriverUrlResolver.js +5 -2
  38. package/dist/odspDriverUrlResolver.js.map +1 -1
  39. package/dist/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
  40. package/dist/odspDriverUrlResolverForShareLink.js +1 -2
  41. package/dist/odspDriverUrlResolverForShareLink.js.map +1 -1
  42. package/dist/odspSummaryUploadManager.d.ts +2 -1
  43. package/dist/odspSummaryUploadManager.d.ts.map +1 -1
  44. package/dist/odspSummaryUploadManager.js +3 -2
  45. package/dist/odspSummaryUploadManager.js.map +1 -1
  46. package/dist/odspUtils.d.ts.map +1 -1
  47. package/dist/odspUtils.js +4 -1
  48. package/dist/odspUtils.js.map +1 -1
  49. package/dist/packageVersion.d.ts +1 -1
  50. package/dist/packageVersion.js +1 -1
  51. package/dist/packageVersion.js.map +1 -1
  52. package/dist/prefetchLatestSnapshot.d.ts +2 -1
  53. package/dist/prefetchLatestSnapshot.d.ts.map +1 -1
  54. package/dist/prefetchLatestSnapshot.js +3 -2
  55. package/dist/prefetchLatestSnapshot.js.map +1 -1
  56. package/dist/retryErrorsStorageAdapter.d.ts +1 -1
  57. package/dist/retryErrorsStorageAdapter.d.ts.map +1 -1
  58. package/dist/retryErrorsStorageAdapter.js.map +1 -1
  59. package/lib/checkUrl.d.ts.map +1 -1
  60. package/lib/checkUrl.js +0 -1
  61. package/lib/checkUrl.js.map +1 -1
  62. package/lib/contractsPublic.d.ts +7 -1
  63. package/lib/contractsPublic.d.ts.map +1 -1
  64. package/lib/contractsPublic.js +6 -0
  65. package/lib/contractsPublic.js.map +1 -1
  66. package/lib/createFile.d.ts +3 -3
  67. package/lib/createFile.d.ts.map +1 -1
  68. package/lib/createFile.js +7 -7
  69. package/lib/createFile.js.map +1 -1
  70. package/lib/epochTracker.d.ts +3 -3
  71. package/lib/epochTracker.d.ts.map +1 -1
  72. package/lib/epochTracker.js +21 -9
  73. package/lib/epochTracker.js.map +1 -1
  74. package/lib/fetchSnapshot.d.ts +3 -2
  75. package/lib/fetchSnapshot.d.ts.map +1 -1
  76. package/lib/fetchSnapshot.js +28 -16
  77. package/lib/fetchSnapshot.js.map +1 -1
  78. package/lib/getFileLink.js +4 -4
  79. package/lib/getFileLink.js.map +1 -1
  80. package/lib/getUrlAndHeadersWithAuth.d.ts +1 -1
  81. package/lib/getUrlAndHeadersWithAuth.d.ts.map +1 -1
  82. package/lib/getUrlAndHeadersWithAuth.js +20 -33
  83. package/lib/getUrlAndHeadersWithAuth.js.map +1 -1
  84. package/lib/odspDeltaStorageService.d.ts.map +1 -1
  85. package/lib/odspDeltaStorageService.js +1 -4
  86. package/lib/odspDeltaStorageService.js.map +1 -1
  87. package/lib/odspDocumentServiceFactoryCore.d.ts.map +1 -1
  88. package/lib/odspDocumentServiceFactoryCore.js +2 -2
  89. package/lib/odspDocumentServiceFactoryCore.js.map +1 -1
  90. package/lib/odspDocumentStorageManager.d.ts +1 -0
  91. package/lib/odspDocumentStorageManager.d.ts.map +1 -1
  92. package/lib/odspDocumentStorageManager.js +16 -9
  93. package/lib/odspDocumentStorageManager.js.map +1 -1
  94. package/lib/odspDriverUrlResolver.d.ts.map +1 -1
  95. package/lib/odspDriverUrlResolver.js +5 -2
  96. package/lib/odspDriverUrlResolver.js.map +1 -1
  97. package/lib/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
  98. package/lib/odspDriverUrlResolverForShareLink.js +1 -2
  99. package/lib/odspDriverUrlResolverForShareLink.js.map +1 -1
  100. package/lib/odspSummaryUploadManager.d.ts +2 -1
  101. package/lib/odspSummaryUploadManager.d.ts.map +1 -1
  102. package/lib/odspSummaryUploadManager.js +3 -2
  103. package/lib/odspSummaryUploadManager.js.map +1 -1
  104. package/lib/odspUtils.d.ts.map +1 -1
  105. package/lib/odspUtils.js +5 -2
  106. package/lib/odspUtils.js.map +1 -1
  107. package/lib/packageVersion.d.ts +1 -1
  108. package/lib/packageVersion.js +1 -1
  109. package/lib/packageVersion.js.map +1 -1
  110. package/lib/prefetchLatestSnapshot.d.ts +2 -1
  111. package/lib/prefetchLatestSnapshot.d.ts.map +1 -1
  112. package/lib/prefetchLatestSnapshot.js +3 -2
  113. package/lib/prefetchLatestSnapshot.js.map +1 -1
  114. package/lib/retryErrorsStorageAdapter.d.ts +1 -1
  115. package/lib/retryErrorsStorageAdapter.d.ts.map +1 -1
  116. package/lib/retryErrorsStorageAdapter.js.map +1 -1
  117. package/package.json +9 -9
  118. package/src/checkUrl.ts +0 -1
  119. package/src/contractsPublic.ts +11 -1
  120. package/src/createFile.ts +16 -4
  121. package/src/epochTracker.ts +21 -6
  122. package/src/fetchSnapshot.ts +33 -16
  123. package/src/getFileLink.ts +7 -2
  124. package/src/getUrlAndHeadersWithAuth.ts +24 -38
  125. package/src/odspDeltaStorageService.ts +1 -3
  126. package/src/odspDocumentServiceFactoryCore.ts +1 -0
  127. package/src/odspDocumentStorageManager.ts +39 -8
  128. package/src/odspDriverUrlResolver.ts +3 -0
  129. package/src/odspDriverUrlResolverForShareLink.ts +1 -2
  130. package/src/odspSummaryUploadManager.ts +6 -1
  131. package/src/odspUtils.ts +13 -3
  132. package/src/packageVersion.ts +1 -1
  133. package/src/prefetchLatestSnapshot.ts +3 -0
  134. package/src/retryErrorsStorageAdapter.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"retryErrorsStorageAdapter.d.ts","sourceRoot":"","sources":["../src/retryErrorsStorageAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACH,uBAAuB,EACvB,+BAA+B,EAC/B,eAAe,EAClB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACH,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,KAAK,EACL,QAAQ,EACX,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAGnF,qBAAa,yBAA0B,YAAW,uBAAuB,EAAE,WAAW;IAG9E,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAH3B,OAAO,CAAC,SAAS,CAAS;gBAEL,sBAAsB,EAAE,uBAAuB,EAC/C,MAAM,EAAE,gBAAgB;IAI7C,IAAW,QAAQ,IAAI,+BAA+B,GAAG,SAAS,CAEjE;IACD,IAAW,QAAQ,YAA2B;IACvC,OAAO;IAId,IAAW,aAAa,IAAI,MAAM,CAEjC;IAEY,eAAe,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAOlE,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAO9C,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAOlE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAOtF,wBAAwB,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAQ1F,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;IAO9D,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAO5E,OAAO,CAAC,oBAAoB;YAMd,YAAY;CAQ7B"}
1
+ {"version":3,"file":"retryErrorsStorageAdapter.d.ts","sourceRoot":"","sources":["../src/retryErrorsStorageAdapter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACH,uBAAuB,EACvB,+BAA+B,EAC/B,eAAe,EAClB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACH,mBAAmB,EACnB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,KAAK,EACL,QAAQ,EACX,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAGnF,qBAAa,yBAA0B,YAAW,uBAAuB,EAAE,WAAW;IAG9E,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAH3B,OAAO,CAAC,SAAS,CAAS;gBAEL,sBAAsB,EAAE,uBAAuB,EAC/C,MAAM,EAAE,gBAAgB;IAI7C,IAAW,QAAQ,IAAI,+BAA+B,GAAG,SAAS,CAEjE;IACD,IAAW,QAAQ,YAA2B;IACvC,OAAO;IAId,IAAW,aAAa,IAAI,MAAM,CAEjC;IAEY,eAAe,CAAC,OAAO,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAOlE,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAO9C,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAOzE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAOtF,wBAAwB,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC;IAQ1F,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC;IAO9D,UAAU,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAO5E,OAAO,CAAC,oBAAoB;YAMd,YAAY;CAQ7B"}
@@ -1 +1 @@
1
- {"version":3,"file":"retryErrorsStorageAdapter.js","sourceRoot":"","sources":["../src/retryErrorsStorageAdapter.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { LoggingError } from \"@fluidframework/telemetry-utils\";\nimport {\n IDocumentStorageService,\n IDocumentStorageServicePolicies,\n ISummaryContext,\n} from \"@fluidframework/driver-definitions\";\nimport {\n ICreateBlobResponse,\n ISnapshotTree,\n ISummaryHandle,\n ISummaryTree,\n ITree,\n IVersion,\n} from \"@fluidframework/protocol-definitions\";\nimport { IDisposable, ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { runWithRetry } from \"./retryUtils\";\n\nexport class RetryErrorsStorageAdapter implements IDocumentStorageService, IDisposable {\n private _disposed = false;\n constructor(\n private readonly internalStorageService: IDocumentStorageService,\n private readonly logger: ITelemetryLogger,\n ) {\n }\n\n public get policies(): IDocumentStorageServicePolicies | undefined {\n return this.internalStorageService.policies;\n }\n public get disposed() {return this._disposed;}\n public dispose() {\n this._disposed = true;\n }\n\n public get repositoryUrl(): string {\n return this.internalStorageService.repositoryUrl;\n }\n\n public async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n return this.runWithRetry(\n async () => this.internalStorageService.getSnapshotTree(version),\n \"storage_getSnapshotTree\",\n );\n }\n\n public async readBlob(id: string): Promise<ArrayBufferLike> {\n return this.runWithRetry(\n async () => this.internalStorageService.readBlob(id),\n \"storage_readBlob\",\n );\n }\n\n public async getVersions(versionId: string, count: number): Promise<IVersion[]> {\n return this.runWithRetry(\n async () => this.internalStorageService.getVersions(versionId, count),\n \"storage_getVersions\",\n );\n }\n\n public async write(tree: ITree, parents: string[], message: string, ref: string): Promise<IVersion> {\n return this.runWithRetry(\n async () => this.internalStorageService.write(tree, parents, message, ref),\n \"storage_write\",\n );\n }\n\n public async uploadSummaryWithContext(summary: ISummaryTree, context: ISummaryContext): Promise<string> {\n // Creation flow with attachment blobs - need to do retries!\n return this.runWithRetry(\n async () => this.internalStorageService.uploadSummaryWithContext(summary, context),\n \"storage_uploadSummaryWithContext\",\n );\n }\n\n public async downloadSummary(handle: ISummaryHandle): Promise<ISummaryTree> {\n return this.runWithRetry(\n async () => this.internalStorageService.downloadSummary(handle),\n \"storage_downloadSummary\",\n );\n }\n\n public async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n return this.runWithRetry(\n async () => this.internalStorageService.createBlob(file),\n \"storage_createBlob\",\n );\n }\n\n private checkStorageDisposed() {\n if (this._disposed) {\n throw new LoggingError(\"storageServiceDisposedCannotRetry\", { canRetry: false });\n }\n }\n\n private async runWithRetry<T>(api: () => Promise<T>, callName: string): Promise<T> {\n return runWithRetry(\n api,\n callName,\n this.logger,\n () => this.checkStorageDisposed(),\n );\n }\n}\n"]}
1
+ {"version":3,"file":"retryErrorsStorageAdapter.js","sourceRoot":"","sources":["../src/retryErrorsStorageAdapter.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { LoggingError } from \"@fluidframework/telemetry-utils\";\nimport {\n IDocumentStorageService,\n IDocumentStorageServicePolicies,\n ISummaryContext,\n} from \"@fluidframework/driver-definitions\";\nimport {\n ICreateBlobResponse,\n ISnapshotTree,\n ISummaryHandle,\n ISummaryTree,\n ITree,\n IVersion,\n} from \"@fluidframework/protocol-definitions\";\nimport { IDisposable, ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { runWithRetry } from \"./retryUtils\";\n\nexport class RetryErrorsStorageAdapter implements IDocumentStorageService, IDisposable {\n private _disposed = false;\n constructor(\n private readonly internalStorageService: IDocumentStorageService,\n private readonly logger: ITelemetryLogger,\n ) {\n }\n\n public get policies(): IDocumentStorageServicePolicies | undefined {\n return this.internalStorageService.policies;\n }\n public get disposed() {return this._disposed;}\n public dispose() {\n this._disposed = true;\n }\n\n public get repositoryUrl(): string {\n return this.internalStorageService.repositoryUrl;\n }\n\n public async getSnapshotTree(version?: IVersion): Promise<ISnapshotTree | null> {\n return this.runWithRetry(\n async () => this.internalStorageService.getSnapshotTree(version),\n \"storage_getSnapshotTree\",\n );\n }\n\n public async readBlob(id: string): Promise<ArrayBufferLike> {\n return this.runWithRetry(\n async () => this.internalStorageService.readBlob(id),\n \"storage_readBlob\",\n );\n }\n\n public async getVersions(versionId: string | null, count: number): Promise<IVersion[]> {\n return this.runWithRetry(\n async () => this.internalStorageService.getVersions(versionId, count),\n \"storage_getVersions\",\n );\n }\n\n public async write(tree: ITree, parents: string[], message: string, ref: string): Promise<IVersion> {\n return this.runWithRetry(\n async () => this.internalStorageService.write(tree, parents, message, ref),\n \"storage_write\",\n );\n }\n\n public async uploadSummaryWithContext(summary: ISummaryTree, context: ISummaryContext): Promise<string> {\n // Creation flow with attachment blobs - need to do retries!\n return this.runWithRetry(\n async () => this.internalStorageService.uploadSummaryWithContext(summary, context),\n \"storage_uploadSummaryWithContext\",\n );\n }\n\n public async downloadSummary(handle: ISummaryHandle): Promise<ISummaryTree> {\n return this.runWithRetry(\n async () => this.internalStorageService.downloadSummary(handle),\n \"storage_downloadSummary\",\n );\n }\n\n public async createBlob(file: ArrayBufferLike): Promise<ICreateBlobResponse> {\n return this.runWithRetry(\n async () => this.internalStorageService.createBlob(file),\n \"storage_createBlob\",\n );\n }\n\n private checkStorageDisposed() {\n if (this._disposed) {\n throw new LoggingError(\"storageServiceDisposedCannotRetry\", { canRetry: false });\n }\n }\n\n private async runWithRetry<T>(api: () => Promise<T>, callName: string): Promise<T> {\n return runWithRetry(\n api,\n callName,\n this.logger,\n () => this.checkStorageDisposed(),\n );\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/odsp-driver",
3
- "version": "0.55.0",
3
+ "version": "0.56.1",
4
4
  "description": "Socket storage implementation for SPO and ODC",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": "https://github.com/microsoft/FluidFramework",
@@ -57,16 +57,16 @@
57
57
  "dependencies": {
58
58
  "@fluidframework/common-definitions": "^0.20.1",
59
59
  "@fluidframework/common-utils": "^0.32.1",
60
- "@fluidframework/core-interfaces": "^0.41.0",
61
- "@fluidframework/driver-base": "^0.55.0",
62
- "@fluidframework/driver-definitions": "^0.43.0",
63
- "@fluidframework/driver-utils": "^0.55.0",
60
+ "@fluidframework/core-interfaces": "^0.42.0",
61
+ "@fluidframework/driver-base": "^0.56.1",
62
+ "@fluidframework/driver-definitions": "^0.44.0",
63
+ "@fluidframework/driver-utils": "^0.56.1",
64
64
  "@fluidframework/gitresources": "^0.1034.0",
65
- "@fluidframework/odsp-doclib-utils": "^0.55.0",
66
- "@fluidframework/odsp-driver-definitions": "^0.55.0",
65
+ "@fluidframework/odsp-doclib-utils": "^0.56.1",
66
+ "@fluidframework/odsp-driver-definitions": "^0.56.1",
67
67
  "@fluidframework/protocol-base": "^0.1034.0",
68
68
  "@fluidframework/protocol-definitions": "^0.1026.0",
69
- "@fluidframework/telemetry-utils": "^0.55.0",
69
+ "@fluidframework/telemetry-utils": "^0.56.1",
70
70
  "abort-controller": "^3.0.0",
71
71
  "node-fetch": "^2.6.1",
72
72
  "socket.io-client": "^2.4.0",
@@ -75,7 +75,7 @@
75
75
  "devDependencies": {
76
76
  "@fluidframework/build-common": "^0.23.0",
77
77
  "@fluidframework/eslint-config-fluid": "^0.25.0",
78
- "@fluidframework/mocha-test-setup": "^0.55.0",
78
+ "@fluidframework/mocha-test-setup": "^0.56.1",
79
79
  "@microsoft/api-extractor": "^7.16.1",
80
80
  "@rushstack/eslint-config": "^2.5.1",
81
81
  "@types/mocha": "^8.2.2",
package/src/checkUrl.ts CHANGED
@@ -27,7 +27,6 @@ export function checkUrl(documentUrl: URL): DriverPreCheckInfo | undefined {
27
27
  } catch {}
28
28
 
29
29
  return {
30
- containerPath: locator.dataStorePath,
31
30
  codeDetailsHint: locator?.containerPackageName,
32
31
  // Add the snapshot endpoint, which has the same domain as the site URL
33
32
  criticalBootDomains: siteOrigin ? [siteOrigin] : undefined,
@@ -22,7 +22,17 @@ export interface ISharingLinkHeader {
22
22
  [SharingLinkHeader.isSharingLinkToRedeem]: boolean;
23
23
  }
24
24
 
25
+ export enum ClpCompliantAppHeader {
26
+ // Can be used in request made to resolver, to tell the resolver that the host app is CLP compliant.
27
+ // Odsp will not return Classified, labeled, or protected documents if the host app cannot support them.
28
+ isClpCompliantApp = "X-CLP-Compliant-App",
29
+ }
30
+
31
+ export interface IClpCompliantAppHeader {
32
+ [ClpCompliantAppHeader.isClpCompliantApp]: boolean;
33
+ }
34
+
25
35
  declare module "@fluidframework/core-interfaces" {
26
36
  // eslint-disable-next-line @typescript-eslint/no-empty-interface
27
- export interface IRequestHeader extends Partial<ISharingLinkHeader> { }
37
+ export interface IRequestHeader extends Partial<ISharingLinkHeader>, Partial<IClpCompliantAppHeader> { }
28
38
  }
package/src/createFile.ts CHANGED
@@ -55,6 +55,7 @@ export async function createNewFluidFile(
55
55
  epochTracker: EpochTracker,
56
56
  fileEntry: IFileEntry,
57
57
  createNewCaching: boolean,
58
+ forceAccessTokenViaAuthorizationHeader: boolean,
58
59
  ): Promise<IOdspResolvedUrl> {
59
60
  // Check for valid filename before the request to create file is actually made.
60
61
  if (isInvalidFileName(newFileInfo.filename)) {
@@ -67,10 +68,17 @@ export async function createNewFluidFile(
67
68
  let sharingLink: string | undefined;
68
69
  let sharingLinkErrorReason: string | undefined;
69
70
  if (createNewSummary === undefined) {
70
- itemId = await createNewEmptyFluidFile(getStorageToken, newFileInfo, logger, epochTracker);
71
+ itemId = await createNewEmptyFluidFile(
72
+ getStorageToken, newFileInfo, logger, epochTracker, forceAccessTokenViaAuthorizationHeader);
71
73
  } else {
72
74
  const content = await createNewFluidFileFromSummary(
73
- getStorageToken, newFileInfo, logger, createNewSummary, epochTracker);
75
+ getStorageToken,
76
+ newFileInfo,
77
+ logger,
78
+ createNewSummary,
79
+ epochTracker,
80
+ forceAccessTokenViaAuthorizationHeader,
81
+ );
74
82
  itemId = content.itemId;
75
83
  summaryHandle = content.id;
76
84
  sharingLink = content.sharingLink;
@@ -108,6 +116,7 @@ export async function createNewEmptyFluidFile(
108
116
  newFileInfo: INewFileInfo,
109
117
  logger: ITelemetryLogger,
110
118
  epochTracker: EpochTracker,
119
+ forceAccessTokenViaAuthorizationHeader: boolean,
111
120
  ): Promise<string> {
112
121
  const filePath = newFileInfo.filePath ? encodeURIComponent(`/${newFileInfo.filePath}`) : "";
113
122
  // add .tmp extension to empty file (host is expected to rename)
@@ -123,7 +132,8 @@ export async function createNewEmptyFluidFile(
123
132
  logger,
124
133
  { eventName: "createNewEmptyFile" },
125
134
  async (event) => {
126
- const { url, headers } = getUrlAndHeadersWithAuth(initialUrl, storageToken);
135
+ const { url, headers } = getUrlAndHeadersWithAuth(
136
+ initialUrl, storageToken, forceAccessTokenViaAuthorizationHeader);
127
137
  headers["Content-Type"] = "application/json";
128
138
 
129
139
  const fetchResponse = await runWithRetry(
@@ -163,6 +173,7 @@ export async function createNewFluidFileFromSummary(
163
173
  logger: ITelemetryLogger,
164
174
  createNewSummary: ISummaryTree,
165
175
  epochTracker: EpochTracker,
176
+ forceAccessTokenViaAuthorizationHeader: boolean,
166
177
  ): Promise<ICreateFileResponse> {
167
178
  const filePath = newFileInfo.filePath ? encodeURIComponent(`/${newFileInfo.filePath}`) : "";
168
179
  const encodedFilename = encodeURIComponent(newFileInfo.filename);
@@ -181,7 +192,8 @@ export async function createNewFluidFileFromSummary(
181
192
  logger,
182
193
  { eventName: "createNewFile" },
183
194
  async (event) => {
184
- const { url, headers } = getUrlAndHeadersWithAuth(initialUrl, storageToken);
195
+ const { url, headers } = getUrlAndHeadersWithAuth(
196
+ initialUrl, storageToken, forceAccessTokenViaAuthorizationHeader);
185
197
  headers["Content-Type"] = "application/json";
186
198
 
187
199
  const fetchResponse = await runWithRetry(
@@ -18,13 +18,14 @@ import {
18
18
  } from "@fluidframework/odsp-driver-definitions";
19
19
  import { DriverErrorType } from "@fluidframework/driver-definitions";
20
20
  import { PerformanceEvent, isFluidError, normalizeError } from "@fluidframework/telemetry-utils";
21
- import { fetchAndParseAsJSONHelper, fetchArray, IOdspResponse } from "./odspUtils";
21
+ import { fetchAndParseAsJSONHelper, fetchArray, getOdspResolvedUrl, IOdspResponse } from "./odspUtils";
22
22
  import {
23
23
  IOdspCache,
24
24
  INonPersistentCache,
25
25
  IPersistedFileCache,
26
26
  } from "./odspCache";
27
27
  import { IVersionedValueWithEpoch, persistedCacheValueVersion } from "./contracts";
28
+ import { ClpCompliantAppHeader } from "./contractsPublic";
28
29
 
29
30
  export type FetchType = "blob" | "createBlob" | "createFile" | "joinSession" | "ops" | "test" | "snapshotTree" |
30
31
  "treesLatest" | "uploadSummary" | "push" | "versions";
@@ -170,8 +171,9 @@ export class EpochTracker implements IPersistedFileCache {
170
171
  fetchOptions: RequestInit,
171
172
  fetchType: FetchType,
172
173
  addInBody: boolean = false,
174
+ fetchReason?: string,
173
175
  ): Promise<IOdspResponse<T>> {
174
- const clientCorrelationId = this.formatClientCorrelationId();
176
+ const clientCorrelationId = this.formatClientCorrelationId(fetchReason);
175
177
  // Add epoch in fetch request.
176
178
  this.addEpochInRequest(fetchOptions, addInBody, clientCorrelationId);
177
179
  let epochFromResponse: string | undefined;
@@ -211,8 +213,9 @@ export class EpochTracker implements IPersistedFileCache {
211
213
  fetchOptions: {[index: string]: any},
212
214
  fetchType: FetchType,
213
215
  addInBody: boolean = false,
216
+ fetchReason?: string,
214
217
  ) {
215
- const clientCorrelationId = this.formatClientCorrelationId();
218
+ const clientCorrelationId = this.formatClientCorrelationId(fetchReason);
216
219
  // Add epoch in fetch request.
217
220
  this.addEpochInRequest(fetchOptions, addInBody, clientCorrelationId);
218
221
  let epochFromResponse: string | undefined;
@@ -245,12 +248,16 @@ export class EpochTracker implements IPersistedFileCache {
245
248
  addInBody: boolean,
246
249
  clientCorrelationId: string,
247
250
  ) {
251
+ const isClpCompliantApp = getOdspResolvedUrl(this.fileEntry.resolvedUrl).isClpCompliantApp;
248
252
  if (addInBody) {
249
253
  const headers: {[key: string]: string} = {};
250
254
  headers["X-RequestStats"] = clientCorrelationId;
251
255
  if (this.fluidEpoch !== undefined) {
252
256
  headers["x-fluid-epoch"] = this.fluidEpoch;
253
257
  }
258
+ if (isClpCompliantApp) {
259
+ headers[ClpCompliantAppHeader.isClpCompliantApp] = isClpCompliantApp.toString();
260
+ }
254
261
  this.addParamInBody(fetchOptions, headers);
255
262
  } else {
256
263
  const addHeader = (key: string, val: string) => {
@@ -264,6 +271,9 @@ export class EpochTracker implements IPersistedFileCache {
264
271
  if (this.fluidEpoch !== undefined) {
265
272
  addHeader("x-fluid-epoch", this.fluidEpoch);
266
273
  }
274
+ if (isClpCompliantApp) {
275
+ addHeader(ClpCompliantAppHeader.isClpCompliantApp, isClpCompliantApp.toString());
276
+ }
267
277
  }
268
278
  }
269
279
 
@@ -285,8 +295,12 @@ export class EpochTracker implements IPersistedFileCache {
285
295
  fetchOptions.body = formParams.join("\r\n");
286
296
  }
287
297
 
288
- private formatClientCorrelationId() {
289
- return `driverId=${this.driverId}, RequestNumber=${this.networkCallNumber++}`;
298
+ private formatClientCorrelationId(fetchReason?: string) {
299
+ const items: string[] = [`driverId=${this.driverId}`, `RequestNumber=${this.networkCallNumber++}`];
300
+ if (fetchReason !== undefined) {
301
+ items.push(`fetchReason=${fetchReason}`);
302
+ }
303
+ return items.join(", ");
290
304
  }
291
305
 
292
306
  protected validateEpochFromResponse(
@@ -395,13 +409,14 @@ export class EpochTrackerWithRedemption extends EpochTracker {
395
409
  fetchOptions: {[index: string]: any},
396
410
  fetchType: FetchType,
397
411
  addInBody: boolean = false,
412
+ fetchReason?: string,
398
413
  ): Promise<IOdspResponse<T>> {
399
414
  // Optimize the flow if we know that treesLatestDeferral was already completed by the timer we started
400
415
  // joinSession call. If we did - there is no reason to repeat the call as it will fail with same error.
401
416
  const completed = this.treesLatestDeferral.isCompleted;
402
417
 
403
418
  try {
404
- return await super.fetchAndParseAsJSON<T>(url, fetchOptions, fetchType, addInBody);
419
+ return await super.fetchAndParseAsJSON<T>(url, fetchOptions, fetchType, addInBody, fetchReason);
405
420
  } catch (error) {
406
421
  // Only handling here treesLatest. If createFile failed, we should never try to do joinSession.
407
422
  // Similar, if getVersions failed, we should not do any further storage calls.
@@ -39,6 +39,7 @@ import { EpochTracker } from "./epochTracker";
39
39
  * @param storageFetchWrapper - Implementation of the get/post methods used to fetch the snapshot
40
40
  * @param versionId - id of specific snapshot to be fetched
41
41
  * @param fetchFullSnapshot - whether we want to fetch full snapshot(with blobs)
42
+ * @param forceAccessTokenViaAuthorizationHeader - whether to force passing given token via authorization header
42
43
  * @returns A promise of the snapshot and the status code of the response
43
44
  */
44
45
  export async function fetchSnapshot(
@@ -46,6 +47,7 @@ export async function fetchSnapshot(
46
47
  token: string | null,
47
48
  versionId: string,
48
49
  fetchFullSnapshot: boolean,
50
+ forceAccessTokenViaAuthorizationHeader: boolean,
49
51
  logger: ITelemetryLogger,
50
52
  snapshotDownloader: (url: string, fetchOptions: {[index: string]: any}) => Promise<IOdspResponse<unknown>>,
51
53
  ): Promise<ISnapshotContents> {
@@ -61,7 +63,8 @@ export async function fetchSnapshot(
61
63
  }
62
64
 
63
65
  const queryString = getQueryString(queryParams);
64
- const { url, headers } = getUrlAndHeadersWithAuth(`${snapshotUrl}${path}${queryString}`, token);
66
+ const { url, headers } = getUrlAndHeadersWithAuth(
67
+ `${snapshotUrl}${path}${queryString}`, token, forceAccessTokenViaAuthorizationHeader);
65
68
  const response = await PerformanceEvent.timedExecAsync(
66
69
  logger,
67
70
  {
@@ -77,6 +80,7 @@ export async function fetchSnapshotWithRedeem(
77
80
  odspResolvedUrl: IOdspResolvedUrl,
78
81
  storageTokenFetcher: InstrumentedStorageTokenFetcher,
79
82
  snapshotOptions: ISnapshotOptions | undefined,
83
+ forceAccessTokenViaAuthorizationHeader: boolean,
80
84
  logger: ITelemetryLogger,
81
85
  snapshotDownloader: (
82
86
  finalOdspResolvedUrl: IOdspResolvedUrl,
@@ -88,6 +92,12 @@ export async function fetchSnapshotWithRedeem(
88
92
  removeEntries: () => Promise<void>,
89
93
  enableRedeemFallback?: boolean,
90
94
  ): Promise<ISnapshotContents> {
95
+ // back-compat: This block to be removed with #8784 when we only consume/consider odsp resolvers that are >= 0.51
96
+ const sharingLinkToRedeem = (odspResolvedUrl as any).sharingLinkToRedeem;
97
+ if(sharingLinkToRedeem) {
98
+ odspResolvedUrl.shareLinkInfo = {...odspResolvedUrl.shareLinkInfo, sharingLinkToRedeem}
99
+ }
100
+
91
101
  return fetchLatestSnapshotCore(
92
102
  odspResolvedUrl,
93
103
  storageTokenFetcher,
@@ -103,16 +113,15 @@ export async function fetchSnapshotWithRedeem(
103
113
  eventName: "RedeemFallback",
104
114
  errorType: error.errorType,
105
115
  }, error);
106
- await redeemSharingLink(odspResolvedUrl, storageTokenFetcher, logger);
116
+ await redeemSharingLink(
117
+ odspResolvedUrl, storageTokenFetcher, logger, forceAccessTokenViaAuthorizationHeader);
107
118
  const odspResolvedUrlWithoutShareLink: IOdspResolvedUrl =
108
- { ...odspResolvedUrl, sharingLinkToRedeem: undefined };
109
-
110
- if(odspResolvedUrlWithoutShareLink.shareLinkInfo) {
111
- odspResolvedUrlWithoutShareLink.shareLinkInfo = {
112
- ...odspResolvedUrlWithoutShareLink.shareLinkInfo,
113
- sharingLinkToRedeem: undefined,
119
+ { ...odspResolvedUrl,
120
+ shareLinkInfo: {
121
+ ...odspResolvedUrl.shareLinkInfo,
122
+ sharingLinkToRedeem: undefined
123
+ }
114
124
  };
115
- }
116
125
 
117
126
  return fetchLatestSnapshotCore(
118
127
  odspResolvedUrlWithoutShareLink,
@@ -141,6 +150,7 @@ async function redeemSharingLink(
141
150
  odspResolvedUrl: IOdspResolvedUrl,
142
151
  storageTokenFetcher: InstrumentedStorageTokenFetcher,
143
152
  logger: ITelemetryLogger,
153
+ forceAccessTokenViaAuthorizationHeader: boolean,
144
154
  ) {
145
155
  return PerformanceEvent.timedExecAsync(
146
156
  logger,
@@ -148,12 +158,13 @@ async function redeemSharingLink(
148
158
  eventName: "RedeemShareLink",
149
159
  },
150
160
  async () => getWithRetryForTokenRefresh(async (tokenFetchOptions) => {
151
- assert(!!odspResolvedUrl.sharingLinkToRedeem,
161
+ assert(!!odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem,
152
162
  0x1ed /* "Share link should be present" */);
153
163
  const storageToken = await storageTokenFetcher(tokenFetchOptions, "RedeemShareLink");
154
- const encodedShareUrl = getEncodedShareUrl(odspResolvedUrl.sharingLinkToRedeem);
164
+ const encodedShareUrl = getEncodedShareUrl(odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem);
155
165
  const redeemUrl = `${odspResolvedUrl.siteUrl}/_api/v2.0/shares/${encodedShareUrl}`;
156
- const { url, headers } = getUrlAndHeadersWithAuth(redeemUrl, storageToken);
166
+ const { url, headers } = getUrlAndHeadersWithAuth(
167
+ redeemUrl, storageToken, forceAccessTokenViaAuthorizationHeader);
157
168
  headers.prefer = "redeemSharingLink";
158
169
  return fetchAndParseAsJSONHelper(url, { headers });
159
170
  }),
@@ -189,7 +200,7 @@ async function fetchLatestSnapshotCore(
189
200
  const perfEvent = {
190
201
  eventName: "TreesLatest",
191
202
  attempts: tokenFetchOptions.refresh ? 2 : 1,
192
- shareLinkPresent: odspResolvedUrl.sharingLinkToRedeem !== undefined,
203
+ shareLinkPresent: odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem !== undefined,
193
204
  redeemFallbackEnabled: enableRedeemFallback,
194
205
  };
195
206
  if (snapshotOptions !== undefined) {
@@ -423,8 +434,8 @@ function getFormBodyAndHeaders(
423
434
  }
424
435
  });
425
436
  }
426
- if (odspResolvedUrl.sharingLinkToRedeem) {
427
- formParams.push(`sl: ${odspResolvedUrl.sharingLinkToRedeem}`);
437
+ if (odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem) {
438
+ formParams.push(`sl: ${odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem}`);
428
439
  }
429
440
  formParams.push(`_post: 1`);
430
441
  formParams.push(`\r\n--${formBoundary}--`);
@@ -467,6 +478,12 @@ export async function downloadSnapshot(
467
478
  controller?: AbortController,
468
479
  epochTracker?: EpochTracker,
469
480
  ): Promise<ISnapshotRequestAndResponseOptions> {
481
+ // back-compat: This block to be removed with #8784 when we only consume/consider odsp resolvers that are >= 0.51
482
+ const sharingLinkToRedeem = (odspResolvedUrl as any).sharingLinkToRedeem;
483
+ if(sharingLinkToRedeem) {
484
+ odspResolvedUrl.shareLinkInfo = {...odspResolvedUrl.shareLinkInfo, sharingLinkToRedeem}
485
+ }
486
+
470
487
  if (fetchBinarySnapshotFormat) {
471
488
  // Logging an event here as it is not supposed to be used in production yet and only in experimental mode.
472
489
  logger.sendTelemetryEvent({ eventName: "BinarySnapshotFetched" });
@@ -477,7 +494,7 @@ export async function downloadSnapshot(
477
494
  }
478
495
 
479
496
  function isRedeemSharingLinkError(odspResolvedUrl: IOdspResolvedUrl, error: any) {
480
- if (odspResolvedUrl.sharingLinkToRedeem !== undefined
497
+ if (odspResolvedUrl.shareLinkInfo?.sharingLinkToRedeem !== undefined
481
498
  && (typeof error === "object" && error !== null)
482
499
  && (error.errorType === DriverErrorType.authorizationError
483
500
  || error.errorType === DriverErrorType.fileNotFoundOrAccessDeniedError)) {
@@ -84,7 +84,7 @@ async function getFileLinkCore(
84
84
  identityType: IdentityType,
85
85
  logger: ITelemetryLogger,
86
86
  ): Promise<string> {
87
- const fileItem = await getFileItemLite(getToken, odspUrlParts, logger);
87
+ const fileItem = await getFileItemLite(getToken, odspUrlParts, logger, identityType === "Consumer");
88
88
 
89
89
  // ODC canonical link does not require any additional processing
90
90
  if (identityType === "Consumer") {
@@ -104,7 +104,10 @@ async function getFileLinkCore(
104
104
  const { url, headers } = getUrlAndHeadersWithAuth(
105
105
  `${odspUrlParts.siteUrl}/_api/web/GetFileByUrl(@a1)/ListItemAllFields/GetSharingInformation?@a1=${
106
106
  encodeURIComponent(`'${fileItem.webDavUrl}'`)
107
- }`, tokenFromResponse(token));
107
+ }`,
108
+ tokenFromResponse(token),
109
+ false,
110
+ );
108
111
  const requestInit = {
109
112
  method: "POST",
110
113
  headers: {
@@ -152,6 +155,7 @@ async function getFileItemLite(
152
155
  getToken: TokenFetcher<OdspResourceTokenFetchOptions>,
153
156
  odspUrlParts: IOdspUrlParts,
154
157
  logger: ITelemetryLogger,
158
+ forceAccessTokenViaAuthorizationHeader: boolean,
155
159
  ): Promise<FileItemLite> {
156
160
  return PerformanceEvent.timedExecAsync(
157
161
  logger,
@@ -166,6 +170,7 @@ async function getFileItemLite(
166
170
  const { url, headers } = getUrlAndHeadersWithAuth(
167
171
  `${siteUrl}/_api/v2.0/drives/${driveId}/items/${itemId}?select=webUrl,webDavUrl`,
168
172
  tokenFromResponse(token),
173
+ forceAccessTokenViaAuthorizationHeader,
169
174
  );
170
175
  const requestInit = { method: "GET", headers };
171
176
  const response = await fetchHelper(url, requestInit);
@@ -3,48 +3,34 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- /**
7
- * Gets the length of the query string portion of a url.
8
- * @param url The full url
9
- */
10
- function getQueryStringLength(url: string): number {
11
- const queryParamStart = url.indexOf("?");
12
-
13
- if (queryParamStart === -1) {
14
- return 0;
15
- }
16
-
17
- return url.length - queryParamStart - 1;
18
- }
19
-
20
- // eslint-disable-next-line max-len
21
- export function getUrlAndHeadersWithAuth(url: string, token: string | null): { url: string, headers: { [index: string]: string } } {
6
+ export function getUrlAndHeadersWithAuth(
7
+ url: string,
8
+ token: string | null,
9
+ forceAccessTokenViaAuthorizationHeader: boolean,
10
+ ): { url: string, headers: { [index: string]: string } } {
22
11
  if (!token || token.length === 0) {
23
12
  return { url, headers: {} };
24
13
  }
25
14
 
26
- const queryParamStart = url.indexOf("?");
27
-
28
- // Determine if we need to add ?, &, or nothing (if the url ends with ?)
29
- let tokenQueryParam = queryParamStart === -1 ? "?" : (queryParamStart !== url.length - 1 ? `&` : "");
30
-
31
- const tokenIsQueryParam = token.startsWith("?");
32
- if (tokenIsQueryParam) {
33
- // The token itself is a query param
34
- tokenQueryParam += token.substring(1);
35
- } else {
36
- tokenQueryParam += `access_token=${encodeURIComponent(token)}`;
37
- }
38
-
39
- // ODSP APIs have a limitation that the query string cannot exceed 2048 characters.
40
- // We try to stick the access token in the URL to make it a simple XHR request and avoid an options call.
41
- // If the query string exceeds 2048, we have to fall back to sending the access token as a header, which
42
- // has a negative performance implication as it adds a performance overhead.
43
- if (tokenIsQueryParam || getQueryStringLength(url + tokenQueryParam) <= 2048) {
44
- return {
45
- headers: {},
46
- url: url + tokenQueryParam,
47
- };
15
+ if (!forceAccessTokenViaAuthorizationHeader) {
16
+ // Pass access token via query string: this will make request be treated as 'simple' request
17
+ // which does not require OPTIONS call as part of CORS check.
18
+ const urlWithAccessTokenInQueryString = new URL(url);
19
+ // IMPORTANT: Do not apply encodeURIComponent to token, param value is automatically encoded
20
+ // when set via URLSearchParams class
21
+ urlWithAccessTokenInQueryString.searchParams.set("access_token", token);
22
+ // ODSP APIs have a limitation that the query string cannot exceed 2048 characters.
23
+ // If the query string exceeds 2048, we have to fall back to sending the access token as a header, which
24
+ // has a negative performance implication as it adds a performance overhead.
25
+ // NOTE: URL.search.length value includes '?' symbol and it is unclear whether backend logic which enforces
26
+ // query length limit accounts for it. This logic errs on side of caution and includes that key in overall
27
+ // query length.
28
+ if (urlWithAccessTokenInQueryString.search.length <= 2048) {
29
+ return {
30
+ headers: {},
31
+ url: urlWithAccessTokenInQueryString.href,
32
+ };
33
+ }
48
34
  }
49
35
 
50
36
  return {
@@ -53,9 +53,6 @@ export class OdspDeltaStorageService {
53
53
  let postBody = `--${formBoundary}\r\n`;
54
54
  postBody += `Authorization: Bearer ${storageToken}\r\n`;
55
55
  postBody += `X-HTTP-Method-Override: GET\r\n`;
56
- if (fetchReason !== undefined) {
57
- postBody += `fetchReason: ${fetchReason}\r\n`;
58
- }
59
56
 
60
57
  postBody += `_post: 1\r\n`;
61
58
  postBody += `\r\n--${formBoundary}--`;
@@ -81,6 +78,7 @@ export class OdspDeltaStorageService {
81
78
  },
82
79
  "ops",
83
80
  true,
81
+ fetchReason,
84
82
  );
85
83
  clearTimeout(timer);
86
84
  const deltaStorageResponse = response.content;
@@ -104,6 +104,7 @@ export class OdspDocumentServiceFactoryCore implements IDocumentServiceFactory {
104
104
  cacheAndTracker.epochTracker,
105
105
  fileEntry,
106
106
  this.hostPolicy.cacheCreateNewSummary ?? true,
107
+ !!this.hostPolicy.sessionOptions?.forceAccessTokenViaAuthorizationHeader,
107
108
  );
108
109
  const docService = this.createDocumentServiceCore(odspResolvedUrl, odspLogger, cacheAndTracker);
109
110
  event.end({