@fluidframework/odsp-driver 0.58.2001 → 0.59.2000-61729

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 (101) hide show
  1. package/dist/compactSnapshotParser.d.ts +1 -0
  2. package/dist/compactSnapshotParser.d.ts.map +1 -1
  3. package/dist/compactSnapshotParser.js +8 -7
  4. package/dist/compactSnapshotParser.js.map +1 -1
  5. package/dist/createNewUtils.js +0 -1
  6. package/dist/createNewUtils.js.map +1 -1
  7. package/dist/epochTracker.d.ts +12 -0
  8. package/dist/epochTracker.d.ts.map +1 -1
  9. package/dist/epochTracker.js +18 -22
  10. package/dist/epochTracker.js.map +1 -1
  11. package/dist/fetchSnapshot.d.ts +11 -0
  12. package/dist/fetchSnapshot.d.ts.map +1 -1
  13. package/dist/fetchSnapshot.js +56 -70
  14. package/dist/fetchSnapshot.js.map +1 -1
  15. package/dist/odspDocumentService.d.ts +2 -1
  16. package/dist/odspDocumentService.d.ts.map +1 -1
  17. package/dist/odspDocumentService.js +14 -7
  18. package/dist/odspDocumentService.js.map +1 -1
  19. package/dist/odspDocumentServiceFactoryCore.d.ts +2 -2
  20. package/dist/odspDocumentServiceFactoryCore.d.ts.map +1 -1
  21. package/dist/odspDocumentServiceFactoryCore.js +6 -6
  22. package/dist/odspDocumentServiceFactoryCore.js.map +1 -1
  23. package/dist/odspDocumentStorageManager.d.ts +0 -6
  24. package/dist/odspDocumentStorageManager.d.ts.map +1 -1
  25. package/dist/odspDocumentStorageManager.js +9 -58
  26. package/dist/odspDocumentStorageManager.js.map +1 -1
  27. package/dist/odspDriverUrlResolver.d.ts +2 -6
  28. package/dist/odspDriverUrlResolver.d.ts.map +1 -1
  29. package/dist/odspDriverUrlResolver.js +15 -10
  30. package/dist/odspDriverUrlResolver.js.map +1 -1
  31. package/dist/odspDriverUrlResolverForShareLink.d.ts +2 -6
  32. package/dist/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
  33. package/dist/odspDriverUrlResolverForShareLink.js +12 -9
  34. package/dist/odspDriverUrlResolverForShareLink.js.map +1 -1
  35. package/dist/odspSnapshotParser.d.ts.map +1 -1
  36. package/dist/odspSnapshotParser.js +1 -5
  37. package/dist/odspSnapshotParser.js.map +1 -1
  38. package/dist/odspSummaryUploadManager.d.ts.map +1 -1
  39. package/dist/odspSummaryUploadManager.js +9 -6
  40. package/dist/odspSummaryUploadManager.js.map +1 -1
  41. package/dist/packageVersion.d.ts +1 -1
  42. package/dist/packageVersion.d.ts.map +1 -1
  43. package/dist/packageVersion.js +1 -1
  44. package/dist/packageVersion.js.map +1 -1
  45. package/lib/compactSnapshotParser.d.ts +1 -0
  46. package/lib/compactSnapshotParser.d.ts.map +1 -1
  47. package/lib/compactSnapshotParser.js +7 -6
  48. package/lib/compactSnapshotParser.js.map +1 -1
  49. package/lib/createNewUtils.js +0 -1
  50. package/lib/createNewUtils.js.map +1 -1
  51. package/lib/epochTracker.d.ts +12 -0
  52. package/lib/epochTracker.d.ts.map +1 -1
  53. package/lib/epochTracker.js +19 -23
  54. package/lib/epochTracker.js.map +1 -1
  55. package/lib/fetchSnapshot.d.ts +11 -0
  56. package/lib/fetchSnapshot.d.ts.map +1 -1
  57. package/lib/fetchSnapshot.js +58 -72
  58. package/lib/fetchSnapshot.js.map +1 -1
  59. package/lib/odspDocumentService.d.ts +2 -1
  60. package/lib/odspDocumentService.d.ts.map +1 -1
  61. package/lib/odspDocumentService.js +14 -7
  62. package/lib/odspDocumentService.js.map +1 -1
  63. package/lib/odspDocumentServiceFactoryCore.d.ts +2 -2
  64. package/lib/odspDocumentServiceFactoryCore.d.ts.map +1 -1
  65. package/lib/odspDocumentServiceFactoryCore.js +6 -6
  66. package/lib/odspDocumentServiceFactoryCore.js.map +1 -1
  67. package/lib/odspDocumentStorageManager.d.ts +0 -6
  68. package/lib/odspDocumentStorageManager.d.ts.map +1 -1
  69. package/lib/odspDocumentStorageManager.js +9 -58
  70. package/lib/odspDocumentStorageManager.js.map +1 -1
  71. package/lib/odspDriverUrlResolver.d.ts +2 -6
  72. package/lib/odspDriverUrlResolver.d.ts.map +1 -1
  73. package/lib/odspDriverUrlResolver.js +14 -9
  74. package/lib/odspDriverUrlResolver.js.map +1 -1
  75. package/lib/odspDriverUrlResolverForShareLink.d.ts +2 -6
  76. package/lib/odspDriverUrlResolverForShareLink.d.ts.map +1 -1
  77. package/lib/odspDriverUrlResolverForShareLink.js +10 -7
  78. package/lib/odspDriverUrlResolverForShareLink.js.map +1 -1
  79. package/lib/odspSnapshotParser.d.ts.map +1 -1
  80. package/lib/odspSnapshotParser.js +1 -5
  81. package/lib/odspSnapshotParser.js.map +1 -1
  82. package/lib/odspSummaryUploadManager.d.ts.map +1 -1
  83. package/lib/odspSummaryUploadManager.js +9 -6
  84. package/lib/odspSummaryUploadManager.js.map +1 -1
  85. package/lib/packageVersion.d.ts +1 -1
  86. package/lib/packageVersion.d.ts.map +1 -1
  87. package/lib/packageVersion.js +1 -1
  88. package/lib/packageVersion.js.map +1 -1
  89. package/package.json +19 -14
  90. package/src/compactSnapshotParser.ts +14 -12
  91. package/src/createNewUtils.ts +0 -1
  92. package/src/epochTracker.ts +34 -25
  93. package/src/fetchSnapshot.ts +59 -89
  94. package/src/odspDocumentService.ts +8 -5
  95. package/src/odspDocumentServiceFactoryCore.ts +7 -2
  96. package/src/odspDocumentStorageManager.ts +10 -64
  97. package/src/odspDriverUrlResolver.ts +18 -9
  98. package/src/odspDriverUrlResolverForShareLink.ts +11 -8
  99. package/src/odspSnapshotParser.ts +1 -4
  100. package/src/odspSummaryUploadManager.ts +7 -6
  101. package/src/packageVersion.ts +1 -1
@@ -13,7 +13,7 @@ import { assert, stringToBuffer } from "@fluidframework/common-utils";
13
13
  function buildHierarchy(flatTree) {
14
14
  const lookup = {};
15
15
  // id is required for root tree as it will be used to determine the version we loaded from.
16
- const root = { id: flatTree.id, blobs: {}, commits: {}, trees: {} };
16
+ const root = { id: flatTree.id, blobs: {}, trees: {} };
17
17
  lookup[""] = root;
18
18
  for (const entry of flatTree.entries) {
19
19
  const lastIndex = entry.path.lastIndexOf("/");
@@ -25,7 +25,6 @@ function buildHierarchy(flatTree) {
25
25
  if (entry.type === "tree") {
26
26
  const newTree = {
27
27
  blobs: {},
28
- commits: {},
29
28
  trees: {},
30
29
  unreferenced: entry.unreferenced,
31
30
  };
@@ -35,9 +34,6 @@ function buildHierarchy(flatTree) {
35
34
  else if (entry.type === "blob") {
36
35
  node.blobs[decodeURIComponent(entryPathBase)] = entry.id;
37
36
  }
38
- else if (entry.type === "commit") {
39
- node.commits[decodeURIComponent(entryPathBase)] = entry.id;
40
- }
41
37
  }
42
38
  return root;
43
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"odspSnapshotParser.js","sourceRoot":"","sources":["../src/odspSnapshotParser.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 { assert, stringToBuffer } from \"@fluidframework/common-utils\";\nimport * as api from \"@fluidframework/protocol-definitions\";\nimport { IOdspSnapshot, IOdspSnapshotCommit } from \"./contracts\";\nimport { ISnapshotContents } from \"./odspUtils\";\n\n/**\n * Build a tree hierarchy base on a flat tree\n *\n * @param flatTree - a flat tree\n * @param blobsShaToPathCache - Map with blobs sha as keys and values as path of the blob.\n * @returns the hierarchical tree\n */\nfunction buildHierarchy(flatTree: IOdspSnapshotCommit): api.ISnapshotTree {\n const lookup: { [path: string]: api.ISnapshotTree } = {};\n // id is required for root tree as it will be used to determine the version we loaded from.\n const root: api.ISnapshotTree = { id: flatTree.id, blobs: {}, commits: {}, trees: {} };\n lookup[\"\"] = root;\n\n for (const entry of flatTree.entries) {\n const lastIndex = entry.path.lastIndexOf(\"/\");\n const entryPathDir = entry.path.slice(0, Math.max(0, lastIndex));\n const entryPathBase = entry.path.slice(lastIndex + 1);\n\n // ODSP snapshots are created breadth-first so we can assume we see tree nodes prior to their contents\n const node = lookup[entryPathDir];\n\n // Add in either the blob or tree\n if (entry.type === \"tree\") {\n const newTree: api.ISnapshotTree = {\n blobs: {},\n commits: {},\n trees: {},\n unreferenced: entry.unreferenced,\n };\n node.trees[decodeURIComponent(entryPathBase)] = newTree;\n lookup[entry.path] = newTree;\n } else if (entry.type === \"blob\") {\n node.blobs[decodeURIComponent(entryPathBase)] = entry.id;\n } else if (entry.type === \"commit\") {\n node.commits[decodeURIComponent(entryPathBase)] = entry.id;\n }\n }\n\n return root;\n}\n\n/**\n * Converts existing IOdspSnapshot to snapshot tree, blob array and ops\n * @param odspSnapshot - snapshot\n */\nexport function convertOdspSnapshotToSnapsohtTreeAndBlobs(\n odspSnapshot: IOdspSnapshot,\n): ISnapshotContents {\n const blobsWithBufferContent = new Map<string, ArrayBuffer>();\n if (odspSnapshot.blobs) {\n odspSnapshot.blobs.forEach((blob) => {\n assert(blob.encoding === \"base64\" || blob.encoding === undefined,\n 0x0a4 /* `Unexpected blob encoding type: '${blob.encoding}'` */);\n blobsWithBufferContent.set(blob.id, stringToBuffer(blob.content, blob.encoding ?? \"utf8\"));\n });\n }\n const val: ISnapshotContents = {\n blobs: blobsWithBufferContent,\n ops: odspSnapshot.ops?.map((op) => op.op) ?? [],\n sequenceNumber: odspSnapshot.trees && (odspSnapshot.trees[0]).sequenceNumber,\n snapshotTree: buildHierarchy(odspSnapshot.trees[0]),\n };\n return val;\n}\n"]}
1
+ {"version":3,"file":"odspSnapshotParser.js","sourceRoot":"","sources":["../src/odspSnapshotParser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAKtE;;;;;;GAMG;AACH,SAAS,cAAc,CAAC,QAA6B;IACjD,MAAM,MAAM,GAA0C,EAAE,CAAC;IACzD,2FAA2F;IAC3F,MAAM,IAAI,GAAsB,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IAC1E,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;IAElB,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,OAAO,EAAE;QAClC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAC9C,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;QACjE,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;QAEtD,sGAAsG;QACtG,MAAM,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;QAElC,iCAAiC;QACjC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE;YACvB,MAAM,OAAO,GAAsB;gBAC/B,KAAK,EAAE,EAAE;gBACT,KAAK,EAAE,EAAE;gBACT,YAAY,EAAE,KAAK,CAAC,YAAY;aACnC,CAAC;YACF,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC,GAAG,OAAO,CAAC;YACxD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;SAChC;aAAM,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE;YAC9B,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC;SAC5D;KACJ;IAED,OAAO,IAAI,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yCAAyC,CACrD,YAA2B;;IAE3B,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC9D,IAAI,YAAY,CAAC,KAAK,EAAE;QACpB,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;;YAChC,MAAM,CAAC,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAC5D,KAAK,CAAC,yDAAyD,CAAC,CAAC;YACrE,sBAAsB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,cAAc,CAAC,IAAI,CAAC,OAAO,QAAE,IAAI,CAAC,QAAQ,mCAAI,MAAM,CAAC,CAAC,CAAC;QAC/F,CAAC,CAAC,CAAC;KACN;IACD,MAAM,GAAG,GAAsB;QAC3B,KAAK,EAAE,sBAAsB;QAC7B,GAAG,cAAE,YAAY,CAAC,GAAG,0CAAE,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,oCAAK,EAAE;QAC/C,cAAc,EAAE,YAAY,CAAC,KAAK,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc;QAC5E,YAAY,EAAE,cAAc,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;KACtD,CAAC;IACF,OAAO,GAAG,CAAC;AACf,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert, stringToBuffer } from \"@fluidframework/common-utils\";\nimport * as api from \"@fluidframework/protocol-definitions\";\nimport { IOdspSnapshot, IOdspSnapshotCommit } from \"./contracts\";\nimport { ISnapshotContents } from \"./odspUtils\";\n\n/**\n * Build a tree hierarchy base on a flat tree\n *\n * @param flatTree - a flat tree\n * @param blobsShaToPathCache - Map with blobs sha as keys and values as path of the blob.\n * @returns the hierarchical tree\n */\nfunction buildHierarchy(flatTree: IOdspSnapshotCommit): api.ISnapshotTree {\n const lookup: { [path: string]: api.ISnapshotTree } = {};\n // id is required for root tree as it will be used to determine the version we loaded from.\n const root: api.ISnapshotTree = { id: flatTree.id, blobs: {}, trees: {} };\n lookup[\"\"] = root;\n\n for (const entry of flatTree.entries) {\n const lastIndex = entry.path.lastIndexOf(\"/\");\n const entryPathDir = entry.path.slice(0, Math.max(0, lastIndex));\n const entryPathBase = entry.path.slice(lastIndex + 1);\n\n // ODSP snapshots are created breadth-first so we can assume we see tree nodes prior to their contents\n const node = lookup[entryPathDir];\n\n // Add in either the blob or tree\n if (entry.type === \"tree\") {\n const newTree: api.ISnapshotTree = {\n blobs: {},\n trees: {},\n unreferenced: entry.unreferenced,\n };\n node.trees[decodeURIComponent(entryPathBase)] = newTree;\n lookup[entry.path] = newTree;\n } else if (entry.type === \"blob\") {\n node.blobs[decodeURIComponent(entryPathBase)] = entry.id;\n }\n }\n\n return root;\n}\n\n/**\n * Converts existing IOdspSnapshot to snapshot tree, blob array and ops\n * @param odspSnapshot - snapshot\n */\nexport function convertOdspSnapshotToSnapsohtTreeAndBlobs(\n odspSnapshot: IOdspSnapshot,\n): ISnapshotContents {\n const blobsWithBufferContent = new Map<string, ArrayBuffer>();\n if (odspSnapshot.blobs) {\n odspSnapshot.blobs.forEach((blob) => {\n assert(blob.encoding === \"base64\" || blob.encoding === undefined,\n 0x0a4 /* `Unexpected blob encoding type: '${blob.encoding}'` */);\n blobsWithBufferContent.set(blob.id, stringToBuffer(blob.content, blob.encoding ?? \"utf8\"));\n });\n }\n const val: ISnapshotContents = {\n blobs: blobsWithBufferContent,\n ops: odspSnapshot.ops?.map((op) => op.op) ?? [],\n sequenceNumber: odspSnapshot.trees && (odspSnapshot.trees[0]).sequenceNumber,\n snapshotTree: buildHierarchy(odspSnapshot.trees[0]),\n };\n return val;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"odspSummaryUploadManager.d.ts","sourceRoot":"","sources":["../src/odspSummaryUploadManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAErE,OAAO,KAAK,GAAG,MAAM,sCAAsC,CAAC;AAC5D,OAAO,EAAE,+BAA+B,EAAE,MAAM,yCAAyC,CAAC;AAU1F,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAM9C;;;GAGG;AACH,qBAAa,wBAAwB;IAM7B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAEhC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,sCAAsC;IAR3D,OAAO,CAAC,yBAAyB,CAAqB;IACtD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAoB;gBAGlB,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,+BAA+B,EACjE,MAAM,EAAE,gBAAgB,EACP,YAAY,EAAE,YAAY,EAC1B,sCAAsC,EAAE,OAAO;IAKvD,gBAAgB,CAAC,IAAI,EAAE,GAAG,CAAC,YAAY,EAAE,OAAO,EAAE,eAAe;YAqBhE,oBAAoB;IA4DlC;;;;;;;;OAQG;YACW,4BAA4B;CAuG7C"}
1
+ {"version":3,"file":"odspSummaryUploadManager.d.ts","sourceRoot":"","sources":["../src/odspSummaryUploadManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAErE,OAAO,KAAK,GAAG,MAAM,sCAAsC,CAAC;AAC5D,OAAO,EAAE,+BAA+B,EAAE,MAAM,yCAAyC,CAAC;AAU1F,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAM9C;;;GAGG;AACH,qBAAa,wBAAwB;IAM7B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAEhC,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,sCAAsC;IAR3D,OAAO,CAAC,yBAAyB,CAAqB;IACtD,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAoB;gBAGlB,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,+BAA+B,EACjE,MAAM,EAAE,gBAAgB,EACP,YAAY,EAAE,YAAY,EAC1B,sCAAsC,EAAE,OAAO;IAKvD,gBAAgB,CAAC,IAAI,EAAE,GAAG,CAAC,YAAY,EAAE,OAAO,EAAE,eAAe;YAqBhE,oBAAoB;IAgElC;;;;;;;;OAQG;YACW,4BAA4B;CAoG7C"}
@@ -42,14 +42,17 @@ export class OdspSummaryUploadManager {
42
42
  return id;
43
43
  }
44
44
  async writeSummaryTreeCore(parentHandle, referenceSequenceNumber, tree) {
45
- const { snapshotTree, blobs } = await this.convertSummaryToSnapshotTree(parentHandle, tree, ".app", "");
45
+ const enableContainerTypeSummaryUpload = this.mc.config.getBoolean("Fluid.Driver.Odsp.EnableContainerTypeSummaryUpload");
46
+ const containsProtocolTree = enableContainerTypeSummaryUpload &&
47
+ Object.keys(tree.tree).includes(".protocol");
48
+ const { snapshotTree, blobs } = await this.convertSummaryToSnapshotTree(parentHandle, tree, ".app");
46
49
  const snapshot = {
47
50
  entries: snapshotTree.entries,
48
51
  message: "app",
49
52
  sequenceNumber: referenceSequenceNumber,
50
53
  // no ack handle implies this is initial summary after empty file creation.
51
54
  // send container payload so server will use it without a summary op
52
- type: parentHandle === undefined ? "container" : "channel",
55
+ type: containsProtocolTree || parentHandle === undefined ? "container" : "channel",
53
56
  };
54
57
  return getWithRetryForTokenRefresh(async (options) => {
55
58
  const storageToken = await this.getStorageToken(options, "WriteSummaryTree");
@@ -68,6 +71,8 @@ export class OdspSummaryUploadManager {
68
71
  blobs,
69
72
  size: postBody.length,
70
73
  referenceSequenceNumber,
74
+ type: snapshot.type,
75
+ enableContainerTypeSummaryUpload,
71
76
  }, async () => {
72
77
  const response = await this.epochTracker.fetchAndParseAsJSON(url, {
73
78
  body: postBody,
@@ -87,9 +92,8 @@ export class OdspSummaryUploadManager {
87
92
  * @param path - Current path of node which is getting evaluated.
88
93
  * @param markUnreferencedNodes - True if we should mark unreferenced nodes.
89
94
  */
90
- async convertSummaryToSnapshotTree(parentHandle, tree, rootNodeName, path, markUnreferencedNodes) {
95
+ async convertSummaryToSnapshotTree(parentHandle, tree, rootNodeName, markUnreferencedNodes) {
91
96
  var _a;
92
- if (path === void 0) { path = ""; }
93
97
  if (markUnreferencedNodes === void 0) { markUnreferencedNodes = (_a = this.mc.config.getBoolean("Fluid.Driver.Odsp.MarkUnreferencedNodes")) !== null && _a !== void 0 ? _a : true; }
94
98
  const snapshotTree = {
95
99
  type: "tree",
@@ -105,10 +109,9 @@ export class OdspSummaryUploadManager {
105
109
  // property is not present, the tree entry is considered referenced. If the property is present and is
106
110
  // true (which is the only value it can have), the tree entry is considered unreferenced.
107
111
  let unreferenced;
108
- const currentPath = path === "" ? `${rootNodeName}/${key}` : `${path}/${key}`;
109
112
  switch (summaryObject.type) {
110
113
  case api.SummaryType.Tree: {
111
- const result = await this.convertSummaryToSnapshotTree(parentHandle, summaryObject, rootNodeName, currentPath);
114
+ const result = await this.convertSummaryToSnapshotTree(parentHandle, summaryObject, rootNodeName);
112
115
  value = result.snapshotTree;
113
116
  unreferenced = markUnreferencedNodes ? summaryObject.unreferenced : undefined;
114
117
  blobs += result.blobs;
@@ -1 +1 @@
1
- {"version":3,"file":"odspSummaryUploadManager.js","sourceRoot":"","sources":["../src/odspSummaryUploadManager.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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, Uint8ArrayToString, unreachableCase } from \"@fluidframework/common-utils\";\nimport { ISummaryContext } from \"@fluidframework/driver-definitions\";\nimport { getGitType } from \"@fluidframework/protocol-base\";\nimport * as api from \"@fluidframework/protocol-definitions\";\nimport { InstrumentedStorageTokenFetcher } from \"@fluidframework/odsp-driver-definitions\";\nimport { loggerToMonitoringContext, MonitoringContext, PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport {\n IOdspSummaryPayload,\n IWriteSummaryResponse,\n IOdspSummaryTree,\n IOdspSummaryTreeBaseEntry,\n OdspSummaryTreeEntry,\n OdspSummaryTreeValue,\n} from \"./contracts\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport { getWithRetryForTokenRefresh } from \"./odspUtils\";\n\n/* eslint-disable max-len */\n\n/**\n * This class manages a summary upload. When it receives a call to upload summary, it converts the summary tree into\n * a snapshot tree and then uploads that to the server.\n */\nexport class OdspSummaryUploadManager {\n // Last proposed handle of the uploaded app summary.\n private lastSummaryProposalHandle: string | undefined;\n private readonly mc: MonitoringContext;\n\n constructor(\n private readonly snapshotUrl: string,\n private readonly getStorageToken: InstrumentedStorageTokenFetcher,\n logger: ITelemetryLogger,\n private readonly epochTracker: EpochTracker,\n private readonly forceAccessTokenViaAuthorizationHeader: boolean,\n ) {\n this.mc = loggerToMonitoringContext(logger);\n }\n\n public async writeSummaryTree(tree: api.ISummaryTree, context: ISummaryContext) {\n // If the last proposed handle is not the proposed handle of the acked summary(could happen when the last summary get nacked),\n // then re-initialize the caches with the previous ones else just update the previous caches with the caches from acked summary.\n // Don't bother logging if lastSummaryProposalHandle hasn't been set before; only log on a positive mismatch.\n if (this.lastSummaryProposalHandle !== undefined &&\n this.lastSummaryProposalHandle !== context.proposalHandle) {\n this.mc.logger.sendTelemetryEvent({\n eventName: \"LastSummaryProposedHandleMismatch\",\n ackedSummaryProposedHandle: context.proposalHandle,\n lastSummaryProposalHandle: this.lastSummaryProposalHandle,\n });\n }\n const result = await this.writeSummaryTreeCore(context.ackHandle, context.referenceSequenceNumber, tree);\n const id = result ? result.id : undefined;\n if (!result || !id) {\n throw new Error(`Failed to write summary tree`);\n }\n this.lastSummaryProposalHandle = id;\n return id;\n }\n\n private async writeSummaryTreeCore(\n parentHandle: string | undefined,\n referenceSequenceNumber: number,\n tree: api.ISummaryTree,\n ): Promise<IWriteSummaryResponse> {\n const { snapshotTree, blobs } = await this.convertSummaryToSnapshotTree(\n parentHandle,\n tree,\n \".app\",\n \"\",\n );\n const snapshot: IOdspSummaryPayload = {\n entries: snapshotTree.entries!,\n message: \"app\",\n sequenceNumber: referenceSequenceNumber,\n // no ack handle implies this is initial summary after empty file creation.\n // send container payload so server will use it without a summary op\n type: parentHandle === undefined ? \"container\" : \"channel\",\n };\n\n return getWithRetryForTokenRefresh(async (options) => {\n const storageToken = await this.getStorageToken(options, \"WriteSummaryTree\");\n\n const { url, headers } = getUrlAndHeadersWithAuth(\n `${this.snapshotUrl}/snapshot`,\n storageToken,\n this.forceAccessTokenViaAuthorizationHeader,\n );\n headers[\"Content-Type\"] = \"application/json\";\n if (parentHandle) {\n headers[\"If-Match\"] = `fluid:containerid=${parentHandle}`;\n }\n\n const postBody = JSON.stringify(snapshot);\n\n return PerformanceEvent.timedExecAsync(this.mc.logger,\n {\n eventName: \"uploadSummary\",\n attempt: options.refresh ? 2 : 1,\n hasClaims: !!options.claims,\n hasTenantId: !!options.tenantId,\n headers: Object.keys(headers).length !== 0 ? true : undefined,\n blobs,\n size: postBody.length,\n referenceSequenceNumber,\n },\n async () => {\n const response = await this.epochTracker.fetchAndParseAsJSON<IWriteSummaryResponse>(\n url,\n {\n body: postBody,\n headers,\n method: \"POST\",\n },\n \"uploadSummary\");\n return response.content;\n });\n });\n }\n\n /**\n * Following are the goals of this function.\n * a.) Converts the summary tree to a snapshot/odsp tree to be uploaded. Always upload full snapshot tree.\n * @param parentHandle - Handle of the last uploaded summary or detach new summary.\n * @param tree - Summary Tree which will be converted to snapshot tree to be uploaded.\n * @param rootNodeName - Root node name of the summary tree.\n * @param path - Current path of node which is getting evaluated.\n * @param markUnreferencedNodes - True if we should mark unreferenced nodes.\n */\n private async convertSummaryToSnapshotTree(\n parentHandle: string | undefined,\n tree: api.ISummaryTree,\n rootNodeName: string,\n path: string = \"\",\n markUnreferencedNodes: boolean = this.mc.config.getBoolean(\"Fluid.Driver.Odsp.MarkUnreferencedNodes\") ?? true,\n ) {\n const snapshotTree: IOdspSummaryTree = {\n type: \"tree\",\n entries: [] as OdspSummaryTreeEntry[],\n };\n\n let blobs = 0;\n const keys = Object.keys(tree.tree);\n for (const key of keys) {\n const summaryObject = tree.tree[key];\n\n let id: string | undefined;\n let value: OdspSummaryTreeValue | undefined;\n\n // Tracks if an entry is unreferenced. Currently, only tree entries can be marked as unreferenced. If the\n // property is not present, the tree entry is considered referenced. If the property is present and is\n // true (which is the only value it can have), the tree entry is considered unreferenced.\n let unreferenced: true | undefined;\n const currentPath = path === \"\" ? `${rootNodeName}/${key}` : `${path}/${key}`;\n switch (summaryObject.type) {\n case api.SummaryType.Tree: {\n const result = await this.convertSummaryToSnapshotTree(\n parentHandle,\n summaryObject,\n rootNodeName,\n currentPath);\n value = result.snapshotTree;\n unreferenced = markUnreferencedNodes ? summaryObject.unreferenced : undefined;\n blobs += result.blobs;\n break;\n }\n case api.SummaryType.Blob: {\n if (typeof summaryObject.content === \"string\") {\n value = {\n type: \"blob\",\n content: summaryObject.content,\n encoding: \"utf-8\",\n };\n } else {\n value = {\n type: \"blob\",\n content: Uint8ArrayToString(summaryObject.content, \"base64\"),\n encoding: \"base64\",\n };\n }\n blobs++;\n break;\n }\n case api.SummaryType.Handle: {\n if (!parentHandle) {\n throw Error(\"Parent summary does not exist to reference by handle.\");\n }\n let handlePath = summaryObject.handle;\n if (handlePath.length > 0 && !handlePath.startsWith(\"/\")) {\n handlePath = `/${handlePath}`;\n }\n const pathKey = `${rootNodeName}${handlePath}`;\n id = `${parentHandle}/${pathKey}`;\n break;\n }\n case api.SummaryType.Attachment: {\n id = summaryObject.id;\n break;\n }\n default: {\n unreachableCase(summaryObject, `Unknown type: ${(summaryObject as any).type}`);\n }\n }\n\n const baseEntry: IOdspSummaryTreeBaseEntry = {\n path: encodeURIComponent(key),\n type: getGitType(summaryObject),\n };\n\n let entry: OdspSummaryTreeEntry;\n\n if (value) {\n assert(id === undefined, 0x0ad /* \"Snapshot entry has both a tree value and a referenced id!\" */);\n entry = {\n value,\n ...baseEntry,\n unreferenced,\n };\n } else if (id) {\n entry = {\n ...baseEntry,\n id,\n };\n } else {\n throw new Error(`Invalid tree entry for ${summaryObject.type}`);\n }\n\n snapshotTree.entries!.push(entry);\n }\n\n return { snapshotTree, blobs };\n }\n}\n\n/* eslint-enable max-len */\n"]}
1
+ {"version":3,"file":"odspSummaryUploadManager.js","sourceRoot":"","sources":["../src/odspSummaryUploadManager.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 { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert, Uint8ArrayToString, unreachableCase } from \"@fluidframework/common-utils\";\nimport { ISummaryContext } from \"@fluidframework/driver-definitions\";\nimport { getGitType } from \"@fluidframework/protocol-base\";\nimport * as api from \"@fluidframework/protocol-definitions\";\nimport { InstrumentedStorageTokenFetcher } from \"@fluidframework/odsp-driver-definitions\";\nimport { loggerToMonitoringContext, MonitoringContext, PerformanceEvent } from \"@fluidframework/telemetry-utils\";\nimport {\n IOdspSummaryPayload,\n IWriteSummaryResponse,\n IOdspSummaryTree,\n IOdspSummaryTreeBaseEntry,\n OdspSummaryTreeEntry,\n OdspSummaryTreeValue,\n} from \"./contracts\";\nimport { EpochTracker } from \"./epochTracker\";\nimport { getUrlAndHeadersWithAuth } from \"./getUrlAndHeadersWithAuth\";\nimport { getWithRetryForTokenRefresh } from \"./odspUtils\";\n\n/* eslint-disable max-len */\n\n/**\n * This class manages a summary upload. When it receives a call to upload summary, it converts the summary tree into\n * a snapshot tree and then uploads that to the server.\n */\nexport class OdspSummaryUploadManager {\n // Last proposed handle of the uploaded app summary.\n private lastSummaryProposalHandle: string | undefined;\n private readonly mc: MonitoringContext;\n\n constructor(\n private readonly snapshotUrl: string,\n private readonly getStorageToken: InstrumentedStorageTokenFetcher,\n logger: ITelemetryLogger,\n private readonly epochTracker: EpochTracker,\n private readonly forceAccessTokenViaAuthorizationHeader: boolean,\n ) {\n this.mc = loggerToMonitoringContext(logger);\n }\n\n public async writeSummaryTree(tree: api.ISummaryTree, context: ISummaryContext) {\n // If the last proposed handle is not the proposed handle of the acked summary(could happen when the last summary get nacked),\n // then re-initialize the caches with the previous ones else just update the previous caches with the caches from acked summary.\n // Don't bother logging if lastSummaryProposalHandle hasn't been set before; only log on a positive mismatch.\n if (this.lastSummaryProposalHandle !== undefined &&\n this.lastSummaryProposalHandle !== context.proposalHandle) {\n this.mc.logger.sendTelemetryEvent({\n eventName: \"LastSummaryProposedHandleMismatch\",\n ackedSummaryProposedHandle: context.proposalHandle,\n lastSummaryProposalHandle: this.lastSummaryProposalHandle,\n });\n }\n const result = await this.writeSummaryTreeCore(context.ackHandle, context.referenceSequenceNumber, tree);\n const id = result ? result.id : undefined;\n if (!result || !id) {\n throw new Error(`Failed to write summary tree`);\n }\n this.lastSummaryProposalHandle = id;\n return id;\n }\n\n private async writeSummaryTreeCore(\n parentHandle: string | undefined,\n referenceSequenceNumber: number,\n tree: api.ISummaryTree,\n ): Promise<IWriteSummaryResponse> {\n const enableContainerTypeSummaryUpload = this.mc.config.getBoolean(\"Fluid.Driver.Odsp.EnableContainerTypeSummaryUpload\");\n const containsProtocolTree = enableContainerTypeSummaryUpload &&\n Object.keys(tree.tree).includes(\".protocol\");\n const { snapshotTree, blobs } = await this.convertSummaryToSnapshotTree(\n parentHandle,\n tree,\n \".app\",\n );\n const snapshot: IOdspSummaryPayload = {\n entries: snapshotTree.entries!,\n message: \"app\",\n sequenceNumber: referenceSequenceNumber,\n // no ack handle implies this is initial summary after empty file creation.\n // send container payload so server will use it without a summary op\n type: containsProtocolTree || parentHandle === undefined ? \"container\" : \"channel\",\n };\n\n return getWithRetryForTokenRefresh(async (options) => {\n const storageToken = await this.getStorageToken(options, \"WriteSummaryTree\");\n\n const { url, headers } = getUrlAndHeadersWithAuth(\n `${this.snapshotUrl}/snapshot`,\n storageToken,\n this.forceAccessTokenViaAuthorizationHeader,\n );\n headers[\"Content-Type\"] = \"application/json\";\n if (parentHandle) {\n headers[\"If-Match\"] = `fluid:containerid=${parentHandle}`;\n }\n\n const postBody = JSON.stringify(snapshot);\n\n return PerformanceEvent.timedExecAsync(this.mc.logger,\n {\n eventName: \"uploadSummary\",\n attempt: options.refresh ? 2 : 1,\n hasClaims: !!options.claims,\n hasTenantId: !!options.tenantId,\n headers: Object.keys(headers).length !== 0 ? true : undefined,\n blobs,\n size: postBody.length,\n referenceSequenceNumber,\n type: snapshot.type,\n enableContainerTypeSummaryUpload,\n },\n async () => {\n const response = await this.epochTracker.fetchAndParseAsJSON<IWriteSummaryResponse>(\n url,\n {\n body: postBody,\n headers,\n method: \"POST\",\n },\n \"uploadSummary\");\n return response.content;\n });\n });\n }\n\n /**\n * Following are the goals of this function.\n * a.) Converts the summary tree to a snapshot/odsp tree to be uploaded. Always upload full snapshot tree.\n * @param parentHandle - Handle of the last uploaded summary or detach new summary.\n * @param tree - Summary Tree which will be converted to snapshot tree to be uploaded.\n * @param rootNodeName - Root node name of the summary tree.\n * @param path - Current path of node which is getting evaluated.\n * @param markUnreferencedNodes - True if we should mark unreferenced nodes.\n */\n private async convertSummaryToSnapshotTree(\n parentHandle: string | undefined,\n tree: api.ISummaryTree,\n rootNodeName: string,\n markUnreferencedNodes: boolean = this.mc.config.getBoolean(\"Fluid.Driver.Odsp.MarkUnreferencedNodes\") ?? true,\n ) {\n const snapshotTree: IOdspSummaryTree = {\n type: \"tree\",\n entries: [] as OdspSummaryTreeEntry[],\n };\n\n let blobs = 0;\n const keys = Object.keys(tree.tree);\n for (const key of keys) {\n const summaryObject = tree.tree[key];\n\n let id: string | undefined;\n let value: OdspSummaryTreeValue | undefined;\n\n // Tracks if an entry is unreferenced. Currently, only tree entries can be marked as unreferenced. If the\n // property is not present, the tree entry is considered referenced. If the property is present and is\n // true (which is the only value it can have), the tree entry is considered unreferenced.\n let unreferenced: true | undefined;\n switch (summaryObject.type) {\n case api.SummaryType.Tree: {\n const result = await this.convertSummaryToSnapshotTree(\n parentHandle,\n summaryObject,\n rootNodeName);\n value = result.snapshotTree;\n unreferenced = markUnreferencedNodes ? summaryObject.unreferenced : undefined;\n blobs += result.blobs;\n break;\n }\n case api.SummaryType.Blob: {\n if (typeof summaryObject.content === \"string\") {\n value = {\n type: \"blob\",\n content: summaryObject.content,\n encoding: \"utf-8\",\n };\n } else {\n value = {\n type: \"blob\",\n content: Uint8ArrayToString(summaryObject.content, \"base64\"),\n encoding: \"base64\",\n };\n }\n blobs++;\n break;\n }\n case api.SummaryType.Handle: {\n if (!parentHandle) {\n throw Error(\"Parent summary does not exist to reference by handle.\");\n }\n let handlePath = summaryObject.handle;\n if (handlePath.length > 0 && !handlePath.startsWith(\"/\")) {\n handlePath = `/${handlePath}`;\n }\n const pathKey = `${rootNodeName}${handlePath}`;\n id = `${parentHandle}/${pathKey}`;\n break;\n }\n case api.SummaryType.Attachment: {\n id = summaryObject.id;\n break;\n }\n default: {\n unreachableCase(summaryObject, `Unknown type: ${(summaryObject as any).type}`);\n }\n }\n\n const baseEntry: IOdspSummaryTreeBaseEntry = {\n path: encodeURIComponent(key),\n type: getGitType(summaryObject),\n };\n\n let entry: OdspSummaryTreeEntry;\n\n if (value) {\n assert(id === undefined, 0x0ad /* \"Snapshot entry has both a tree value and a referenced id!\" */);\n entry = {\n value,\n ...baseEntry,\n unreferenced,\n };\n } else if (id) {\n entry = {\n ...baseEntry,\n id,\n };\n } else {\n throw new Error(`Invalid tree entry for ${summaryObject.type}`);\n }\n\n snapshotTree.entries!.push(entry);\n }\n\n return { snapshotTree, blobs };\n }\n}\n\n/* eslint-enable max-len */\n"]}
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export declare const pkgName = "@fluidframework/odsp-driver";
8
- export declare const pkgVersion = "0.58.2001";
8
+ export declare const pkgVersion = "0.59.2000-61729";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,gCAAgC,CAAC;AACrD,eAAO,MAAM,UAAU,cAAc,CAAC"}
1
+ {"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,gCAAgC,CAAC;AACrD,eAAO,MAAM,UAAU,oBAAoB,CAAC"}
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export const pkgName = "@fluidframework/odsp-driver";
8
- export const pkgVersion = "0.58.2001";
8
+ export const pkgVersion = "0.59.2000-61729";
9
9
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,6BAA6B,CAAC;AACrD,MAAM,CAAC,MAAM,UAAU,GAAG,WAAW,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/odsp-driver\";\nexport const pkgVersion = \"0.58.2001\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,6BAA6B,CAAC;AACrD,MAAM,CAAC,MAAM,UAAU,GAAG,iBAAiB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/odsp-driver\";\nexport const pkgVersion = \"0.59.2000-61729\";\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/odsp-driver",
3
- "version": "0.58.2001",
3
+ "version": "0.59.2000-61729",
4
4
  "description": "Socket storage implementation for SPO and ODC",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -32,7 +32,7 @@
32
32
  "lint:fix": "npm run eslint:fix",
33
33
  "test": "npm run test:mocha",
34
34
  "test:coverage": "nyc npm test -- --reporter xunit --reporter-option output=nyc/junit-report.xml",
35
- "test:mocha": "mocha --recursive dist/test -r node_modules/@fluidframework/mocha-test-setup --unhandled-rejections=strict",
35
+ "test:mocha": "mocha --ignore 'dist/test/types/*' --recursive dist/test -r node_modules/@fluidframework/mocha-test-setup --unhandled-rejections=strict",
36
36
  "test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
37
37
  "tsc": "tsc",
38
38
  "tsfmt": "tsfmt --verify",
@@ -61,16 +61,16 @@
61
61
  "dependencies": {
62
62
  "@fluidframework/common-definitions": "^0.20.1",
63
63
  "@fluidframework/common-utils": "^0.32.1",
64
- "@fluidframework/core-interfaces": "^0.42.0",
65
- "@fluidframework/driver-base": "^0.58.2001",
66
- "@fluidframework/driver-definitions": "^0.45.1000",
67
- "@fluidframework/driver-utils": "^0.58.2001",
68
- "@fluidframework/gitresources": "^0.1035.1000",
69
- "@fluidframework/odsp-doclib-utils": "^0.58.2001",
70
- "@fluidframework/odsp-driver-definitions": "^0.58.2001",
71
- "@fluidframework/protocol-base": "^0.1035.1000",
72
- "@fluidframework/protocol-definitions": "^0.1027.1000",
73
- "@fluidframework/telemetry-utils": "^0.58.2001",
64
+ "@fluidframework/core-interfaces": "^0.43.1000-0",
65
+ "@fluidframework/driver-base": "0.59.2000-61729",
66
+ "@fluidframework/driver-definitions": "^0.46.1000-0",
67
+ "@fluidframework/driver-utils": "0.59.2000-61729",
68
+ "@fluidframework/gitresources": "^0.1036.1000-0",
69
+ "@fluidframework/odsp-doclib-utils": "0.59.2000-61729",
70
+ "@fluidframework/odsp-driver-definitions": "0.59.2000-61729",
71
+ "@fluidframework/protocol-base": "^0.1036.1000-0",
72
+ "@fluidframework/protocol-definitions": "^0.1028.1000-0",
73
+ "@fluidframework/telemetry-utils": "0.59.2000-61729",
74
74
  "abort-controller": "^3.0.0",
75
75
  "node-fetch": "^2.6.1",
76
76
  "socket.io-client": "^4.4.1",
@@ -78,8 +78,9 @@
78
78
  },
79
79
  "devDependencies": {
80
80
  "@fluidframework/build-common": "^0.23.0",
81
- "@fluidframework/eslint-config-fluid": "^0.27.0",
82
- "@fluidframework/mocha-test-setup": "^0.58.2001",
81
+ "@fluidframework/eslint-config-fluid": "^0.28.1000-61189",
82
+ "@fluidframework/mocha-test-setup": "0.59.2000-61729",
83
+ "@fluidframework/odsp-driver-previous": "npm:@fluidframework/odsp-driver@^0.58.0",
83
84
  "@microsoft/api-extractor": "^7.16.1",
84
85
  "@rushstack/eslint-config": "^2.5.1",
85
86
  "@types/mocha": "^8.2.2",
@@ -103,5 +104,9 @@
103
104
  "sinon": "^7.4.2",
104
105
  "typescript": "~4.1.3",
105
106
  "typescript-formatter": "7.1.0"
107
+ },
108
+ "typeValidation": {
109
+ "version": "0.59.1000",
110
+ "broken": {}
106
111
  }
107
112
  }
@@ -14,10 +14,12 @@ import {
14
14
  assertNumberInstance,
15
15
  getAndValidateNodeProps,
16
16
  NodeCore,
17
+ NodeTypes,
17
18
  TreeBuilder,
18
19
  } from "./zipItDataRepresentationUtils";
19
20
 
20
21
  export const snapshotMinReadVersion = "1.0";
22
+ export const currentReadVersion = "1.0";
21
23
 
22
24
  interface ISnapshotSection {
23
25
  snapshotTree: ISnapshotTree,
@@ -28,7 +30,8 @@ interface ISnapshotSection {
28
30
  * Recreates blobs section of the tree.
29
31
  * @param node - tree node to read blob section from
30
32
  */
31
- function readBlobSection(node: NodeCore) {
33
+ function readBlobSection(node: NodeTypes) {
34
+ assertNodeCoreInstance(node, "TreeBlobs should be of type NodeCore");
32
35
  const blobs: Map<string, ArrayBuffer> = new Map();
33
36
  for (let count = 0; count < node.length; ++count) {
34
37
  const blob = node.getNode(count);
@@ -44,7 +47,8 @@ function readBlobSection(node: NodeCore) {
44
47
  * Recreates ops section of the tree.
45
48
  * @param node - tree node to read ops section from
46
49
  */
47
- function readOpsSection(node: NodeCore) {
50
+ function readOpsSection(node: NodeTypes) {
51
+ assertNodeCoreInstance(node, "Deltas should be of type NodeCore");
48
52
  const ops: ISequencedDocumentMessage[] = [];
49
53
  const records = getAndValidateNodeProps(node, ["firstSequenceNumber", "deltas"]);
50
54
  assertNumberInstance(records.firstSequenceNumber, "Seq number should be a number");
@@ -52,7 +56,8 @@ function readOpsSection(node: NodeCore) {
52
56
  for (let i = 0; i < records.deltas.length; ++i) {
53
57
  ops.push(JSON.parse(records.deltas.getString(i)));
54
58
  }
55
- assert(records.firstSequenceNumber.valueOf() === ops[0].sequenceNumber, 0x280 /* "Validate first op seq number" */);
59
+ assert(records.firstSequenceNumber.valueOf() === ops[0].sequenceNumber,
60
+ 0x280 /* "Validate first op seq number" */);
56
61
  return ops;
57
62
  }
58
63
 
@@ -63,7 +68,6 @@ function readOpsSection(node: NodeCore) {
63
68
  function readTreeSection(node: NodeCore) {
64
69
  const snapshotTree: ISnapshotTree = {
65
70
  blobs: {},
66
- commits: {},
67
71
  trees: {},
68
72
  };
69
73
  for (let count = 0; count < node.length; count++) {
@@ -93,7 +97,8 @@ function readTreeSection(node: NodeCore) {
93
97
  * Recreates snapshot tree out of tree representation.
94
98
  * @param node - tree node to de-serialize from
95
99
  */
96
- function readSnapshotSection(node: NodeCore): ISnapshotSection {
100
+ function readSnapshotSection(node: NodeTypes): ISnapshotSection {
101
+ assertNodeCoreInstance(node, "Snapshot should be of type NodeCore");
97
102
  const records = getAndValidateNodeProps(node,
98
103
  ["id", "sequenceNumber", "treeNodes"]);
99
104
 
@@ -120,7 +125,7 @@ export function parseCompactSnapshotResponse(buffer: ReadBuffer): ISnapshotConte
120
125
  const root = builder.getNode(0);
121
126
 
122
127
  const records = getAndValidateNodeProps(root,
123
- ["mrv", "cv", "snapshot", "blobs", "deltas"]);
128
+ ["mrv", "cv", "snapshot", "blobs", "deltas"], false);
124
129
 
125
130
  assertBlobCoreInstance(records.mrv, "minReadVersion should be of BlobCore type");
126
131
  assertBlobCoreInstance(records.cv, "createVersion should be of BlobCore type");
@@ -128,14 +133,11 @@ export function parseCompactSnapshotResponse(buffer: ReadBuffer): ISnapshotConte
128
133
  0x20f /* "Driver min read version should >= to server minReadVersion" */);
129
134
  assert(records.cv.toString() >= snapshotMinReadVersion,
130
135
  0x210 /* "Snapshot should be created with minReadVersion or above" */);
131
-
132
- assertNodeCoreInstance(records.snapshot, "Snapshot should be of type NodeCore");
133
- assertNodeCoreInstance(records.blobs, "TreeBlobs should be of type NodeCore");
134
- assertNodeCoreInstance(records.deltas, "Deltas should be of type NodeCore");
135
-
136
+ assert(currentReadVersion === records.cv.toString(),
137
+ 0x2c2 /* "Create Version should be equal to currentReadVersion" */);
136
138
  return {
137
139
  ...readSnapshotSection(records.snapshot),
138
140
  blobs: readBlobSection(records.blobs),
139
- ops: readOpsSection(records.deltas),
141
+ ops: records.deltas !== undefined ? readOpsSection(records.deltas) : [],
140
142
  };
141
143
  }
@@ -36,7 +36,6 @@ function convertCreateNewSummaryTreeToTreeAndBlobsCore(
36
36
  const treeNode: ISnapshotTree = {
37
37
  blobs: {},
38
38
  trees: {},
39
- commits: {},
40
39
  unreferenced: summary.unreferenced,
41
40
  };
42
41
  const keys = Object.keys(summary.tree);
@@ -18,7 +18,7 @@ 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, getOdspResolvedUrl, IOdspResponse } from "./odspUtils";
21
+ import { fetchAndParseAsJSONHelper, fetchArray, fetchHelper, getOdspResolvedUrl, IOdspResponse } from "./odspUtils";
22
22
  import {
23
23
  IOdspCache,
24
24
  INonPersistentCache,
@@ -166,6 +166,7 @@ export class EpochTracker implements IPersistedFileCache {
166
166
  * @param fetchOptions - fetch options for request containing body, headers etc.
167
167
  * @param fetchType - method for which fetch is called.
168
168
  * @param addInBody - Pass True if caller wants to add epoch in post body.
169
+ * @param fetchReason - fetch reason to add to the request.
169
170
  */
170
171
  public async fetchAndParseAsJSON<T>(
171
172
  url: string,
@@ -174,12 +175,41 @@ export class EpochTracker implements IPersistedFileCache {
174
175
  addInBody: boolean = false,
175
176
  fetchReason?: string,
176
177
  ): Promise<IOdspResponse<T>> {
178
+ return this.fetchCore<T>(url, fetchOptions, fetchAndParseAsJSONHelper, fetchType, addInBody, fetchReason);
179
+ }
180
+
181
+ /**
182
+ * Api to fetch the response for given request and parse it as json.
183
+ * @param url - url of the request
184
+ * @param fetchOptions - fetch options for request containing body, headers etc.
185
+ * @param fetchType - method for which fetch is called.
186
+ * @param addInBody - Pass True if caller wants to add epoch in post body.
187
+ * @param fetchReason - fetch reason to add to the request.
188
+ */
189
+ public async fetch(
190
+ url: string,
191
+ fetchOptions: RequestInit,
192
+ fetchType: FetchType,
193
+ addInBody: boolean = false,
194
+ fetchReason?: string,
195
+ ) {
196
+ return this.fetchCore<Response>(url, fetchOptions, fetchHelper, fetchType, addInBody, fetchReason);
197
+ }
198
+
199
+ private async fetchCore<T>(
200
+ url: string,
201
+ fetchOptions: {[index: string]: any},
202
+ fetcher: (url: string, fetchOptions: {[index: string]: any}) => Promise<IOdspResponse<T>>,
203
+ fetchType: FetchType,
204
+ addInBody: boolean = false,
205
+ fetchReason?: string,
206
+ ) {
177
207
  const clientCorrelationId = this.formatClientCorrelationId(fetchReason);
178
208
  // Add epoch in fetch request.
179
209
  this.addEpochInRequest(fetchOptions, addInBody, clientCorrelationId);
180
210
  let epochFromResponse: string | undefined;
181
211
  return this.rateLimiter.schedule(
182
- async () => fetchAndParseAsJSONHelper<T>(url, fetchOptions),
212
+ async () => fetcher(url, fetchOptions),
183
213
  ).then((response) => {
184
214
  epochFromResponse = response.headers.get("x-fluid-epoch");
185
215
  this.validateEpochFromResponse(epochFromResponse, fetchType);
@@ -205,6 +235,7 @@ export class EpochTracker implements IPersistedFileCache {
205
235
  * @param fetchOptions - fetch options for request containing body, headers etc.
206
236
  * @param fetchType - method for which fetch is called.
207
237
  * @param addInBody - Pass True if caller wants to add epoch in post body.
238
+ * @param fetchReason - fetch reason to add to the request.
208
239
  */
209
240
  public async fetchArray(
210
241
  url: string,
@@ -213,29 +244,7 @@ export class EpochTracker implements IPersistedFileCache {
213
244
  addInBody: boolean = false,
214
245
  fetchReason?: string,
215
246
  ) {
216
- const clientCorrelationId = this.formatClientCorrelationId(fetchReason);
217
- // Add epoch in fetch request.
218
- this.addEpochInRequest(fetchOptions, addInBody, clientCorrelationId);
219
- let epochFromResponse: string | undefined;
220
- return this.rateLimiter.schedule(
221
- async () => fetchArray(url, fetchOptions),
222
- ).then((response) => {
223
- epochFromResponse = response.headers.get("x-fluid-epoch");
224
- this.validateEpochFromResponse(epochFromResponse, fetchType);
225
- response.propsToLog.XRequestStatsHeader = clientCorrelationId;
226
- return response;
227
- }).catch(async (error) => {
228
- // Get the server epoch from error in case we don't have it as if undefined we won't be able
229
- // to mark it as epoch error.
230
- if (epochFromResponse === undefined) {
231
- epochFromResponse = (error as IOdspError).serverEpoch;
232
- }
233
- await this.checkForEpochError(error, epochFromResponse, fetchType);
234
- throw error;
235
- }).catch((error) => {
236
- const fluidError = normalizeError(error, { props: { XRequestStatsHeader: clientCorrelationId }});
237
- throw fluidError;
238
- });
247
+ return this.fetchCore<ArrayBuffer>(url, fetchOptions, fetchArray, fetchType, addInBody, fetchReason);
239
248
  }
240
249
 
241
250
  private addEpochInRequest(