@fluidframework/runtime-utils 2.53.1 → 2.60.0

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 (127) hide show
  1. package/.eslintrc.cjs +1 -4
  2. package/CHANGELOG.md +4 -0
  3. package/api-report/{runtime-utils.legacy.alpha.api.md → runtime-utils.legacy.beta.api.md} +12 -12
  4. package/dist/compatibilityBase.d.ts +1 -3
  5. package/dist/compatibilityBase.d.ts.map +1 -1
  6. package/dist/compatibilityBase.js +3 -0
  7. package/dist/compatibilityBase.js.map +1 -1
  8. package/dist/dataStoreHandleContextUtils.d.ts +1 -1
  9. package/dist/dataStoreHandleContextUtils.d.ts.map +1 -1
  10. package/dist/dataStoreHandleContextUtils.js.map +1 -1
  11. package/dist/dataStoreHelpers.d.ts +18 -6
  12. package/dist/dataStoreHelpers.d.ts.map +1 -1
  13. package/dist/dataStoreHelpers.js +39 -11
  14. package/dist/dataStoreHelpers.js.map +1 -1
  15. package/dist/deltaManager.d.ts +1 -2
  16. package/dist/deltaManager.d.ts.map +1 -1
  17. package/dist/deltaManager.js +3 -2
  18. package/dist/deltaManager.js.map +1 -1
  19. package/dist/handles.d.ts +8 -12
  20. package/dist/handles.d.ts.map +1 -1
  21. package/dist/handles.js +14 -12
  22. package/dist/handles.js.map +1 -1
  23. package/dist/index.d.ts +6 -3
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/objectstoragepartition.d.ts +1 -1
  27. package/dist/objectstoragepartition.d.ts.map +1 -1
  28. package/dist/objectstoragepartition.js.map +1 -1
  29. package/dist/objectstorageutils.d.ts +9 -1
  30. package/dist/objectstorageutils.d.ts.map +1 -1
  31. package/dist/objectstorageutils.js +15 -6
  32. package/dist/objectstorageutils.js.map +1 -1
  33. package/dist/packageVersion.d.ts +1 -1
  34. package/dist/packageVersion.js +1 -1
  35. package/dist/packageVersion.js.map +1 -1
  36. package/dist/remoteFluidObjectHandle.d.ts +2 -2
  37. package/dist/remoteFluidObjectHandle.d.ts.map +1 -1
  38. package/dist/remoteFluidObjectHandle.js +1 -0
  39. package/dist/remoteFluidObjectHandle.js.map +1 -1
  40. package/dist/requestParser.d.ts +2 -3
  41. package/dist/requestParser.d.ts.map +1 -1
  42. package/dist/requestParser.js +9 -11
  43. package/dist/requestParser.js.map +1 -1
  44. package/dist/runtimeFactoryHelper.d.ts +3 -4
  45. package/dist/runtimeFactoryHelper.d.ts.map +1 -1
  46. package/dist/runtimeFactoryHelper.js +1 -2
  47. package/dist/runtimeFactoryHelper.js.map +1 -1
  48. package/dist/summaryUtils.d.ts +29 -20
  49. package/dist/summaryUtils.d.ts.map +1 -1
  50. package/dist/summaryUtils.js +49 -21
  51. package/dist/summaryUtils.js.map +1 -1
  52. package/dist/unpackUsedRoutes.d.ts.map +1 -1
  53. package/dist/unpackUsedRoutes.js +3 -3
  54. package/dist/unpackUsedRoutes.js.map +1 -1
  55. package/dist/utils.d.ts +1 -1
  56. package/dist/utils.d.ts.map +1 -1
  57. package/dist/utils.js.map +1 -1
  58. package/lib/compatibilityBase.d.ts +1 -3
  59. package/lib/compatibilityBase.d.ts.map +1 -1
  60. package/lib/compatibilityBase.js +3 -0
  61. package/lib/compatibilityBase.js.map +1 -1
  62. package/lib/dataStoreHandleContextUtils.d.ts +1 -1
  63. package/lib/dataStoreHandleContextUtils.d.ts.map +1 -1
  64. package/lib/dataStoreHandleContextUtils.js.map +1 -1
  65. package/lib/dataStoreHelpers.d.ts +18 -6
  66. package/lib/dataStoreHelpers.d.ts.map +1 -1
  67. package/lib/dataStoreHelpers.js +39 -11
  68. package/lib/dataStoreHelpers.js.map +1 -1
  69. package/lib/deltaManager.d.ts +1 -2
  70. package/lib/deltaManager.d.ts.map +1 -1
  71. package/lib/deltaManager.js +3 -2
  72. package/lib/deltaManager.js.map +1 -1
  73. package/lib/handles.d.ts +8 -12
  74. package/lib/handles.d.ts.map +1 -1
  75. package/lib/handles.js +14 -12
  76. package/lib/handles.js.map +1 -1
  77. package/lib/index.d.ts +6 -3
  78. package/lib/index.d.ts.map +1 -1
  79. package/lib/index.js.map +1 -1
  80. package/lib/objectstoragepartition.d.ts +1 -1
  81. package/lib/objectstoragepartition.d.ts.map +1 -1
  82. package/lib/objectstoragepartition.js.map +1 -1
  83. package/lib/objectstorageutils.d.ts +9 -1
  84. package/lib/objectstorageutils.d.ts.map +1 -1
  85. package/lib/objectstorageutils.js +15 -6
  86. package/lib/objectstorageutils.js.map +1 -1
  87. package/lib/packageVersion.d.ts +1 -1
  88. package/lib/packageVersion.js +1 -1
  89. package/lib/packageVersion.js.map +1 -1
  90. package/lib/remoteFluidObjectHandle.d.ts +2 -2
  91. package/lib/remoteFluidObjectHandle.d.ts.map +1 -1
  92. package/lib/remoteFluidObjectHandle.js +1 -0
  93. package/lib/remoteFluidObjectHandle.js.map +1 -1
  94. package/lib/requestParser.d.ts +2 -3
  95. package/lib/requestParser.d.ts.map +1 -1
  96. package/lib/requestParser.js +9 -11
  97. package/lib/requestParser.js.map +1 -1
  98. package/lib/runtimeFactoryHelper.d.ts +3 -4
  99. package/lib/runtimeFactoryHelper.d.ts.map +1 -1
  100. package/lib/runtimeFactoryHelper.js +1 -2
  101. package/lib/runtimeFactoryHelper.js.map +1 -1
  102. package/lib/summaryUtils.d.ts +29 -20
  103. package/lib/summaryUtils.d.ts.map +1 -1
  104. package/lib/summaryUtils.js +51 -23
  105. package/lib/summaryUtils.js.map +1 -1
  106. package/lib/unpackUsedRoutes.d.ts.map +1 -1
  107. package/lib/unpackUsedRoutes.js +3 -3
  108. package/lib/unpackUsedRoutes.js.map +1 -1
  109. package/lib/utils.d.ts +1 -1
  110. package/lib/utils.d.ts.map +1 -1
  111. package/lib/utils.js.map +1 -1
  112. package/package.json +13 -13
  113. package/src/compatibilityBase.ts +4 -3
  114. package/src/dataStoreHandleContextUtils.ts +1 -1
  115. package/src/dataStoreHelpers.ts +49 -16
  116. package/src/deltaManager.ts +3 -2
  117. package/src/handles.ts +14 -13
  118. package/src/index.ts +6 -4
  119. package/src/objectstoragepartition.ts +2 -2
  120. package/src/objectstorageutils.ts +17 -8
  121. package/src/packageVersion.ts +1 -1
  122. package/src/remoteFluidObjectHandle.ts +4 -3
  123. package/src/requestParser.ts +15 -15
  124. package/src/runtimeFactoryHelper.ts +4 -5
  125. package/src/summaryUtils.ts +70 -43
  126. package/src/unpackUsedRoutes.ts +7 -5
  127. package/src/utils.ts +2 -2
@@ -4,14 +4,14 @@
4
4
  */
5
5
 
6
6
  import { assert } from "@fluidframework/core-utils/internal";
7
- import { IChannelStorageService } from "@fluidframework/datastore-definitions/internal";
7
+ import type { IChannelStorageService } from "@fluidframework/datastore-definitions/internal";
8
8
 
9
9
  /**
10
10
  * Returns a new IChannelStorageService that resolves the given `path` as root.
11
11
  * @internal
12
12
  */
13
13
  export class ObjectStoragePartition implements IChannelStorageService {
14
- constructor(
14
+ public constructor(
15
15
  private readonly storage: IChannelStorageService,
16
16
  private readonly path: string,
17
17
  ) {
@@ -3,18 +3,22 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { ITree } from "@fluidframework/driver-definitions/internal";
6
+ import type { ITree } from "@fluidframework/driver-definitions/internal";
7
+ import { TreeEntry } from "@fluidframework/driver-definitions/internal";
7
8
 
8
9
  /**
10
+ * Normalizes a storage path by removing leading and trailing slashes and splitting into parts
11
+ * @param path - The storage path to normalize (e.g. "/foo/bar/")
12
+ * @returns Array of path segments (e.g. ["foo", "bar"])
9
13
  * @internal
10
14
  */
11
- export function getNormalizedObjectStoragePathParts(path: string) {
15
+ export function getNormalizedObjectStoragePathParts(path: string): string[] {
12
16
  let normalizePath = path;
13
17
  if (normalizePath.startsWith("/")) {
14
- normalizePath = normalizePath.substr(1);
18
+ normalizePath = normalizePath.slice(1);
15
19
  }
16
20
  if (normalizePath.endsWith("/")) {
17
- normalizePath = normalizePath.substr(0, normalizePath.length - 1);
21
+ normalizePath = normalizePath.slice(0, -1);
18
22
  }
19
23
  if (normalizePath.length > 0) {
20
24
  return normalizePath.split("/");
@@ -23,6 +27,11 @@ export function getNormalizedObjectStoragePathParts(path: string) {
23
27
  }
24
28
 
25
29
  /**
30
+ * Lists all blobs at the specified path in the given tree
31
+ * @param inputTree - The tree to search within
32
+ * @param path - The path to search at (e.g. "foo/bar")
33
+ * @returns Promise that resolves to an array of blob names at that path
34
+ * @throws Error if the path does not exist in the tree
26
35
  * @internal
27
36
  */
28
37
  export async function listBlobsAtTreePath(
@@ -34,16 +43,16 @@ export async function listBlobsAtTreePath(
34
43
  while (tree?.entries !== undefined && pathParts.length > 0) {
35
44
  const part = pathParts.shift();
36
45
  const treeEntry = tree.entries.find((value) => {
37
- return value.type === "Tree" && value.path === part ? true : false;
46
+ return value.type === TreeEntry.Tree && value.path === part ? true : false;
38
47
  });
39
48
 
40
49
  // this check is largely superfluous due to the same check being done
41
50
  // immediately above. the type system, however, is not aware of this.
42
51
  // so we must redundantly determine that the entry's type is "Tree"
43
- tree = treeEntry?.type === "Tree" ? treeEntry.value : undefined;
52
+ tree = treeEntry?.type === TreeEntry.Tree ? treeEntry.value : undefined;
44
53
  }
45
- if (tree?.entries === undefined || pathParts.length !== 0) {
54
+ if (tree?.entries === undefined || pathParts.length > 0) {
46
55
  throw new Error("path does not exist");
47
56
  }
48
- return tree.entries.filter((e) => e.type === "Blob").map((e) => e.path);
57
+ return tree.entries.filter((e) => e.type === TreeEntry.Blob).map((e) => e.path);
49
58
  }
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/runtime-utils";
9
- export const pkgVersion = "2.53.1";
9
+ export const pkgVersion = "2.60.0";
@@ -3,8 +3,8 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { FluidObject, IRequest } from "@fluidframework/core-interfaces";
7
- import { IFluidHandleContext } from "@fluidframework/core-interfaces/internal";
6
+ import type { FluidObject, IRequest } from "@fluidframework/core-interfaces";
7
+ import type { IFluidHandleContext } from "@fluidframework/core-interfaces/internal";
8
8
  import { assert } from "@fluidframework/core-utils/internal";
9
9
 
10
10
  import { responseToException } from "./dataStoreHelpers.js";
@@ -30,7 +30,7 @@ export class RemoteFluidObjectHandle extends FluidHandleBase<FluidObject> {
30
30
  * @param routeContext - The root IFluidHandleContext that has a route to this handle.
31
31
  * @param payloadPending - Whether the handle may have a pending payload that is not yet available.
32
32
  */
33
- constructor(
33
+ public constructor(
34
34
  public readonly absolutePath: string,
35
35
  public readonly routeContext: IFluidHandleContext,
36
36
  public readonly payloadPending: boolean,
@@ -54,6 +54,7 @@ export class RemoteFluidObjectHandle extends FluidHandleBase<FluidObject> {
54
54
  };
55
55
  this.objectP = this.routeContext.resolveHandle(request).then<FluidObject>((response) => {
56
56
  if (response.mimeType === "fluid/object") {
57
+ // Responses with mimeType == "fluid/object" are produced by Fluid, and thus they can reasonably be expected to always be a FluidObject
57
58
  const fluidObject: FluidObject = response.value as FluidObject;
58
59
  return fluidObject;
59
60
  }
@@ -3,12 +3,11 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { IRequest, IRequestHeader } from "@fluidframework/core-interfaces";
6
+ import type { IRequest, IRequestHeader } from "@fluidframework/core-interfaces";
7
7
 
8
8
  /**
9
9
  * The Request Parser takes an IRequest provides parsing and sub request creation
10
- * @legacy
11
- * @alpha
10
+ * @legacy @beta
12
11
  */
13
12
  export class RequestParser implements IRequest {
14
13
  /**
@@ -17,21 +16,22 @@ export class RequestParser implements IRequest {
17
16
  */
18
17
  public static getPathParts(url: string): readonly string[] {
19
18
  const queryStartIndex = url.indexOf("?");
20
- return url
21
- .substring(0, queryStartIndex < 0 ? url.length : queryStartIndex)
22
- .split("/")
23
- .reduce<string[]>((pv, cv) => {
24
- if (cv !== undefined && cv.length > 0) {
25
- pv.push(decodeURIComponent(cv));
26
- }
27
- return pv;
28
- }, []);
19
+ const pathParts: string[] = [];
20
+ const urlPath = url.slice(0, queryStartIndex < 0 ? url.length : queryStartIndex);
21
+
22
+ for (const part of urlPath.split("/")) {
23
+ if (part !== undefined && part.length > 0) {
24
+ pathParts.push(decodeURIComponent(part));
25
+ }
26
+ }
27
+
28
+ return pathParts;
29
29
  }
30
30
 
31
31
  private requestPathParts: readonly string[] | undefined;
32
32
  public readonly query: string;
33
33
 
34
- public static create(request: Readonly<IRequest>) {
34
+ public static create(request: Readonly<IRequest>): RequestParser {
35
35
  // Perf optimizations.
36
36
  if (request instanceof RequestParser) {
37
37
  return request;
@@ -41,7 +41,7 @@ export class RequestParser implements IRequest {
41
41
 
42
42
  protected constructor(private readonly request: Readonly<IRequest>) {
43
43
  const queryStartIndex = this.request.url.indexOf("?");
44
- this.query = queryStartIndex >= 0 ? this.request.url.substring(queryStartIndex) : "";
44
+ this.query = queryStartIndex >= 0 ? this.request.url.slice(queryStartIndex) : "";
45
45
  if (request.headers !== undefined) {
46
46
  this.headers = request.headers;
47
47
  }
@@ -67,7 +67,7 @@ export class RequestParser implements IRequest {
67
67
  * Returns true if it's a terminating path, i.e. no more elements after `elements` entries and empty query.
68
68
  * @param elements - number of elements in path
69
69
  */
70
- public isLeaf(elements: number) {
70
+ public isLeaf(elements: number): boolean {
71
71
  return this.query === "" && this.pathParts.length === elements;
72
72
  }
73
73
 
@@ -3,19 +3,18 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import {
6
+ import type {
7
7
  IContainerContext,
8
8
  IRuntime,
9
9
  IRuntimeFactory,
10
10
  } from "@fluidframework/container-definitions/internal";
11
- import { IContainerRuntime } from "@fluidframework/container-runtime-definitions/internal";
11
+ import type { IContainerRuntime } from "@fluidframework/container-runtime-definitions/internal";
12
12
 
13
13
  /**
14
- * @legacy
15
- * @alpha
14
+ * @legacy @beta
16
15
  */
17
16
  export abstract class RuntimeFactoryHelper<T = IContainerRuntime> implements IRuntimeFactory {
18
- public get IRuntimeFactory() {
17
+ public get IRuntimeFactory(): this {
19
18
  return this;
20
19
  }
21
20
 
@@ -9,29 +9,30 @@ import {
9
9
  bufferToString,
10
10
  fromBase64ToUtf8,
11
11
  } from "@fluid-internal/client-utils";
12
- import { ISnapshotTreeWithBlobContents } from "@fluidframework/container-definitions/internal";
12
+ import type { ISnapshotTreeWithBlobContents } from "@fluidframework/container-definitions/internal";
13
13
  import { assert, unreachableCase } from "@fluidframework/core-utils/internal";
14
- import {
14
+ import type {
15
15
  ISummaryBlob,
16
16
  ISummaryTree,
17
17
  SummaryObject,
18
- SummaryType,
19
18
  } from "@fluidframework/driver-definitions";
20
- import { ITree, ITreeEntry, TreeEntry } from "@fluidframework/driver-definitions/internal";
19
+ import { SummaryType } from "@fluidframework/driver-definitions";
20
+ import type { ITree, ITreeEntry } from "@fluidframework/driver-definitions/internal";
21
+ import { TreeEntry } from "@fluidframework/driver-definitions/internal";
21
22
  import {
22
23
  AttachmentTreeEntry,
23
24
  BlobTreeEntry,
24
25
  TreeTreeEntry,
25
26
  } from "@fluidframework/driver-utils/internal";
26
- import {
27
+ import type {
27
28
  ISummaryStats,
28
29
  ISummaryTreeWithStats,
29
30
  ITelemetryContext,
30
31
  IGarbageCollectionData,
31
32
  ISummarizeResult,
32
33
  ITelemetryContextExt,
33
- gcDataBlobKey,
34
34
  } from "@fluidframework/runtime-definitions/internal";
35
+ import { gcDataBlobKey } from "@fluidframework/runtime-definitions/internal";
35
36
  import type { TelemetryEventPropertyTypeExt } from "@fluidframework/telemetry-utils/internal";
36
37
 
37
38
  /**
@@ -59,26 +60,34 @@ export function mergeStats(...stats: ISummaryStats[]): ISummaryStats {
59
60
  }
60
61
 
61
62
  /**
63
+ * Calculates the byte length of an UTF-8 encoded string
64
+ * @param str - The string to calculate the byte length of
65
+ * @returns The byte length of the string
62
66
  * @internal
63
67
  */
64
68
  export function utf8ByteLength(str: string): number {
65
69
  // returns the byte length of an utf8 string
66
70
  let s = str.length;
67
71
  for (let i = str.length - 1; i >= 0; i--) {
68
- const code = str.charCodeAt(i);
69
- if (code > 0x7f && code <= 0x7ff) {
70
- s++;
71
- } else if (code > 0x7ff && code <= 0xffff) {
72
- s += 2;
73
- }
74
- if (code >= 0xdc00 && code <= 0xdfff) {
75
- i--; // trail surrogate
72
+ const code = str.codePointAt(i);
73
+ if (code !== undefined) {
74
+ if (code > 0x7f && code <= 0x7ff) {
75
+ s++;
76
+ } else if (code > 0x7ff && code <= 0xffff) {
77
+ s += 2;
78
+ }
79
+ if (code >= 0xdc00 && code <= 0xdfff) {
80
+ i--; // trail surrogate
81
+ }
76
82
  }
77
83
  }
78
84
  return s;
79
85
  }
80
86
 
81
87
  /**
88
+ * Gets the size of a blob
89
+ * @param content - The content of the blob
90
+ * @returns The size of the blob in bytes
82
91
  * @internal
83
92
  */
84
93
  export function getBlobSize(content: ISummaryBlob["content"]): number {
@@ -103,12 +112,16 @@ function calculateStatsCore(summaryObject: SummaryObject, stats: ISummaryStats):
103
112
  stats.totalBlobSize += getBlobSize(summaryObject.content);
104
113
  return;
105
114
  }
106
- default:
115
+ default: {
107
116
  return;
117
+ }
108
118
  }
109
119
  }
110
120
 
111
121
  /**
122
+ * Calculates the stats for a summary object
123
+ * @param summary - The summary object to calculate stats for
124
+ * @returns The calculated stats
112
125
  * @internal
113
126
  */
114
127
  export function calculateStats(summary: SummaryObject): ISummaryStats {
@@ -118,6 +131,10 @@ export function calculateStats(summary: SummaryObject): ISummaryStats {
118
131
  }
119
132
 
120
133
  /**
134
+ * Adds a blob to the summary tree
135
+ * @param summary - The summary tree to add the blob to
136
+ * @param key - The key to store the blob at
137
+ * @param content - The content of the blob to be added
121
138
  * @internal
122
139
  */
123
140
  export function addBlobToSummary(
@@ -135,6 +152,10 @@ export function addBlobToSummary(
135
152
  }
136
153
 
137
154
  /**
155
+ * Adds a summarize result to the summary tree
156
+ * @param summary - The summary tree to add the summarize result to
157
+ * @param key - The key to store the summarize result at
158
+ * @param summarizeResult - The summarize result to be added
138
159
  * @internal
139
160
  */
140
161
  export function addSummarizeResultToSummary(
@@ -148,8 +169,7 @@ export function addSummarizeResultToSummary(
148
169
 
149
170
  /**
150
171
  * An object who's properties are used to initialize a {@link SummaryTreeBuilder}
151
- * @legacy
152
- * @alpha
172
+ * @legacy @beta
153
173
  */
154
174
  export interface SummaryTreeBuilderParams {
155
175
  /**
@@ -161,8 +181,7 @@ export interface SummaryTreeBuilderParams {
161
181
  /**
162
182
  * A helper class for building summary trees.
163
183
  * @remarks Uses the builder pattern.
164
- * @legacy
165
- * @alpha
184
+ * @legacy @beta
166
185
  */
167
186
  export class SummaryTreeBuilder implements ISummaryTreeWithStats {
168
187
  private attachmentCounter: number = 0;
@@ -183,13 +202,13 @@ export class SummaryTreeBuilder implements ISummaryTreeWithStats {
183
202
  return { ...this.summaryStats };
184
203
  }
185
204
 
186
- constructor(params?: { groupId?: string }) {
205
+ public constructor(params?: { groupId?: string }) {
187
206
  this.summaryStats = mergeStats();
188
207
  this.summaryStats.treeNodeCount++;
189
208
  this.groupId = params?.groupId;
190
209
  }
191
210
 
192
- private readonly summaryTree: { [path: string]: SummaryObject } = {};
211
+ private readonly summaryTree: Record<string, SummaryObject> = {};
193
212
  private summaryStats: ISummaryStats;
194
213
 
195
214
  /**
@@ -247,7 +266,7 @@ export class SummaryTreeBuilder implements ISummaryTreeWithStats {
247
266
  * Adds an {@link @fluidframework/driver-definitions#ISummaryAttachment} to the summary. This blob needs to already be uploaded to storage.
248
267
  * @param id - The id of the uploaded attachment to be added to the summary tree.
249
268
  */
250
- public addAttachment(id: string) {
269
+ public addAttachment(id: string): void {
251
270
  this.summaryTree[this.attachmentCounter++] = { id, type: SummaryType.Attachment };
252
271
  }
253
272
 
@@ -267,8 +286,7 @@ export class SummaryTreeBuilder implements ISummaryTreeWithStats {
267
286
  * Converts snapshot ITree to ISummaryTree format and tracks stats.
268
287
  * @param snapshot - snapshot in ITree format
269
288
  * @param fullTree - true to never use handles, even if id is specified
270
- * @legacy
271
- * @alpha
289
+ * @legacy @beta
272
290
  */
273
291
  export function convertToSummaryTreeWithStats(
274
292
  snapshot: ITree,
@@ -299,8 +317,9 @@ export function convertToSummaryTreeWithStats(
299
317
  break;
300
318
  }
301
319
 
302
- default:
320
+ default: {
303
321
  throw new Error("Unexpected TreeEntry type");
322
+ }
304
323
  }
305
324
  }
306
325
 
@@ -354,6 +373,8 @@ export function convertSnapshotTreeToSummaryTree(
354
373
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
355
374
  const content: ArrayBufferLike = snapshot.blobsContents[id]!;
356
375
  if (content !== undefined) {
376
+ // Cannot change "utf-8" to "utf8" as this encoding value is stored in summaries and would be a breaking change which needs to be done first before changing to utf8.
377
+ // eslint-disable-next-line unicorn/text-encoding-identifier-case -- External on-disk format is 'utf-8'.
357
378
  decoded = bufferToString(content, "utf-8");
358
379
  }
359
380
  // 0.44 back-compat We still put contents in same blob for back-compat so need to add blob
@@ -390,6 +411,8 @@ export function convertSummaryTreeToITree(summaryTree: ISummaryTree): ITree {
390
411
  switch (value.type) {
391
412
  case SummaryType.Blob: {
392
413
  let parsedContent: string;
414
+ // Cannot change "utf-8" to "utf8" as this encoding value is stored in summaries and would be a breaking change which needs to be done first before changing to utf8.
415
+ // eslint-disable-next-line unicorn/text-encoding-identifier-case -- external contract uses 'utf-8'.
393
416
  let encoding: "utf-8" | "base64" = "utf-8";
394
417
  if (typeof value.content === "string") {
395
418
  parsedContent = value.content;
@@ -415,8 +438,9 @@ export function convertSummaryTreeToITree(summaryTree: ISummaryTree): ITree {
415
438
  throw new Error("Should not have Handle type in summary tree");
416
439
  }
417
440
 
418
- default:
441
+ default: {
419
442
  unreachableCase(value, "Unexpected summary tree type");
443
+ }
420
444
  }
421
445
  }
422
446
  return {
@@ -440,7 +464,7 @@ export function convertSummaryTreeToITree(summaryTree: ISummaryTree): ITree {
440
464
  * @internal
441
465
  */
442
466
  export function processAttachMessageGCData(
443
- snapshot: ITree | null,
467
+ snapshot: ITree | undefined,
444
468
  addedGCOutboundRoute: (fromNodeId: string, toPath: string) => void,
445
469
  ): boolean {
446
470
  const gcDataEntry = snapshot?.entries.find((e) => e.path === gcDataBlobKey);
@@ -452,15 +476,18 @@ export function processAttachMessageGCData(
452
476
  }
453
477
 
454
478
  assert(
479
+ // Cannot change "utf-8" to "utf8" as this encoding value is stored in summaries and would be a breaking change which needs to be done first before changing to utf8.
480
+ // eslint-disable-next-line unicorn/text-encoding-identifier-case -- external contract uses 'utf-8'.
455
481
  gcDataEntry.type === TreeEntry.Blob && gcDataEntry.value.encoding === "utf-8",
456
482
  0x8ff /* GC data should be a utf-8-encoded blob */,
457
483
  );
458
484
 
485
+ // Type assertion is safe as we expect the GC data to conform to IGarbageCollectionData schema
459
486
  const gcData = JSON.parse(gcDataEntry.value.contents) as IGarbageCollectionData;
460
487
  for (const [nodeId, outboundRoutes] of Object.entries(gcData.gcNodes)) {
461
- outboundRoutes.forEach((toPath) => {
488
+ for (const toPath of outboundRoutes) {
462
489
  addedGCOutboundRoute(nodeId, toPath);
463
- });
490
+ }
464
491
  }
465
492
  return true;
466
493
  }
@@ -474,14 +501,14 @@ export class TelemetryContext implements ITelemetryContext, ITelemetryContextExt
474
501
  /**
475
502
  * {@inheritDoc @fluidframework/runtime-definitions#ITelemetryContext.set}
476
503
  */
477
- set(prefix: string, property: string, value: TelemetryEventPropertyTypeExt): void {
504
+ public set(prefix: string, property: string, value: TelemetryEventPropertyTypeExt): void {
478
505
  this.telemetry.set(`${prefix}${property}`, value);
479
506
  }
480
507
 
481
508
  /**
482
509
  * {@inheritDoc @fluidframework/runtime-definitions#ITelemetryContext.setMultiple}
483
510
  */
484
- setMultiple(
511
+ public setMultiple(
485
512
  prefix: string,
486
513
  property: string,
487
514
  values: Record<string, TelemetryEventPropertyTypeExt>,
@@ -495,18 +522,18 @@ export class TelemetryContext implements ITelemetryContext, ITelemetryContextExt
495
522
  /**
496
523
  * {@inheritDoc @fluidframework/runtime-definitions#ITelemetryContext.get}
497
524
  */
498
- get(prefix: string, property: string): TelemetryEventPropertyTypeExt {
525
+ public get(prefix: string, property: string): TelemetryEventPropertyTypeExt {
499
526
  return this.telemetry.get(`${prefix}${property}`);
500
527
  }
501
528
 
502
529
  /**
503
530
  * {@inheritDoc @fluidframework/runtime-definitions#ITelemetryContext.serialize}
504
531
  */
505
- serialize(): string {
532
+ public serialize(): string {
506
533
  const jsonObject = {};
507
- this.telemetry.forEach((value, key) => {
534
+ for (const [key, value] of this.telemetry.entries()) {
508
535
  jsonObject[key] = value;
509
- });
536
+ }
510
537
  return JSON.stringify(jsonObject);
511
538
  }
512
539
  }
@@ -516,7 +543,7 @@ export class TelemetryContext implements ITelemetryContext, ITelemetryContextExt
516
543
  * @param str - A string that may contain leading slashes.
517
544
  * @returns A new string without leading slashes.
518
545
  */
519
- function trimLeadingSlashes(str: string) {
546
+ function trimLeadingSlashes(str: string): string {
520
547
  return str.replace(/^\/+/g, "");
521
548
  }
522
549
 
@@ -525,7 +552,7 @@ function trimLeadingSlashes(str: string) {
525
552
  * @param str - A string that may contain trailing slashes.
526
553
  * @returns A new string without trailing slashes.
527
554
  */
528
- function trimTrailingSlashes(str: string) {
555
+ function trimTrailingSlashes(str: string): string {
529
556
  return str.replace(/\/+$/g, "");
530
557
  }
531
558
 
@@ -534,8 +561,8 @@ function trimTrailingSlashes(str: string) {
534
561
  * @internal
535
562
  */
536
563
  export class GCDataBuilder implements IGarbageCollectionData {
537
- private readonly gcNodesSet: { [id: string]: Set<string> } = {};
538
- public get gcNodes(): { [id: string]: string[] } {
564
+ private readonly gcNodesSet: Record<string, Set<string>> = {};
565
+ public get gcNodes(): Record<string, string[]> {
539
566
  const gcNodes = {};
540
567
  for (const [nodeId, outboundRoutes] of Object.entries(this.gcNodesSet)) {
541
568
  gcNodes[nodeId] = [...outboundRoutes];
@@ -543,7 +570,7 @@ export class GCDataBuilder implements IGarbageCollectionData {
543
570
  return gcNodes;
544
571
  }
545
572
 
546
- public addNode(id: string, outboundRoutes: string[]) {
573
+ public addNode(id: string, outboundRoutes: string[]): void {
547
574
  this.gcNodesSet[id] = new Set(outboundRoutes);
548
575
  }
549
576
 
@@ -553,7 +580,7 @@ export class GCDataBuilder implements IGarbageCollectionData {
553
580
  * - Prefixes the given `prefixId` to the given nodes' ids.
554
581
  * - Adds the outbound routes of the nodes against the normalized and prefixed id.
555
582
  */
556
- public prefixAndAddNodes(prefixId: string, gcNodes: { [id: string]: string[] }) {
583
+ public prefixAndAddNodes(prefixId: string, gcNodes: Record<string, string[]>): void {
557
584
  for (const [id, outboundRoutes] of Object.entries(gcNodes)) {
558
585
  // Remove any leading slashes from the id.
559
586
  let normalizedId = trimLeadingSlashes(id);
@@ -568,7 +595,7 @@ export class GCDataBuilder implements IGarbageCollectionData {
568
595
  }
569
596
  }
570
597
 
571
- public addNodes(gcNodes: { [id: string]: string[] }) {
598
+ public addNodes(gcNodes: Record<string, string[]>): void {
572
599
  for (const [id, outboundRoutes] of Object.entries(gcNodes)) {
573
600
  this.gcNodesSet[id] = new Set(outboundRoutes);
574
601
  }
@@ -577,7 +604,7 @@ export class GCDataBuilder implements IGarbageCollectionData {
577
604
  /**
578
605
  * Adds the given outbound route to the outbound routes of all GC nodes.
579
606
  */
580
- public addRouteToAllNodes(outboundRoute: string) {
607
+ public addRouteToAllNodes(outboundRoute: string): void {
581
608
  for (const outboundRoutes of Object.values(this.gcNodesSet)) {
582
609
  outboundRoutes.add(outboundRoute);
583
610
  }
@@ -11,10 +11,12 @@ import { assert } from "@fluidframework/core-utils/internal";
11
11
  * @returns A map of used routes of each children of the the given node.
12
12
  * @internal
13
13
  */
14
- export function unpackChildNodesUsedRoutes(usedRoutes: readonly string[]) {
14
+ export function unpackChildNodesUsedRoutes(
15
+ usedRoutes: readonly string[],
16
+ ): Map<string, string[]> {
15
17
  // Remove the node's self used route, if any, and generate the children used routes.
16
18
  const filteredUsedRoutes = usedRoutes.filter((route) => route !== "" && route !== "/");
17
- const childUsedRoutesMap: Map<string, string[]> = new Map();
19
+ const childUsedRoutesMap = new Map<string, string[]>();
18
20
  for (const route of filteredUsedRoutes) {
19
21
  assert(route.startsWith("/"), 0x5e0 /* Used route should always be an absolute route */);
20
22
  const childId = route.split("/")[1];
@@ -25,10 +27,10 @@ export function unpackChildNodesUsedRoutes(usedRoutes: readonly string[]) {
25
27
  const childUsedRoute = route.slice(childId.length + 1);
26
28
 
27
29
  const childUsedRoutes = childUsedRoutesMap.get(childId);
28
- if (childUsedRoutes !== undefined) {
29
- childUsedRoutes.push(childUsedRoute);
30
- } else {
30
+ if (childUsedRoutes === undefined) {
31
31
  childUsedRoutesMap.set(childId, [childUsedRoute]);
32
+ } else {
33
+ childUsedRoutes.push(childUsedRoute);
32
34
  }
33
35
  }
34
36
  return childUsedRoutesMap;
package/src/utils.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { assert } from "@fluidframework/core-utils/internal";
7
- import {
7
+ import type {
8
8
  IDocumentAttributes,
9
9
  ISnapshotTree,
10
10
  } from "@fluidframework/driver-definitions/internal";
@@ -77,7 +77,7 @@ export const charSetForEncodingIds =
77
77
  * @returns A string - representation of an input
78
78
  * @internal
79
79
  */
80
- export function encodeCompactIdToString(idArg: number | string, prefix = "") {
80
+ export function encodeCompactIdToString(idArg: number | string, prefix = ""): string {
81
81
  if (typeof idArg === "string") {
82
82
  return idArg;
83
83
  }