@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.
- package/.eslintrc.cjs +1 -4
- package/CHANGELOG.md +4 -0
- package/api-report/{runtime-utils.legacy.alpha.api.md → runtime-utils.legacy.beta.api.md} +12 -12
- package/dist/compatibilityBase.d.ts +1 -3
- package/dist/compatibilityBase.d.ts.map +1 -1
- package/dist/compatibilityBase.js +3 -0
- package/dist/compatibilityBase.js.map +1 -1
- package/dist/dataStoreHandleContextUtils.d.ts +1 -1
- package/dist/dataStoreHandleContextUtils.d.ts.map +1 -1
- package/dist/dataStoreHandleContextUtils.js.map +1 -1
- package/dist/dataStoreHelpers.d.ts +18 -6
- package/dist/dataStoreHelpers.d.ts.map +1 -1
- package/dist/dataStoreHelpers.js +39 -11
- package/dist/dataStoreHelpers.js.map +1 -1
- package/dist/deltaManager.d.ts +1 -2
- package/dist/deltaManager.d.ts.map +1 -1
- package/dist/deltaManager.js +3 -2
- package/dist/deltaManager.js.map +1 -1
- package/dist/handles.d.ts +8 -12
- package/dist/handles.d.ts.map +1 -1
- package/dist/handles.js +14 -12
- package/dist/handles.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/objectstoragepartition.d.ts +1 -1
- package/dist/objectstoragepartition.d.ts.map +1 -1
- package/dist/objectstoragepartition.js.map +1 -1
- package/dist/objectstorageutils.d.ts +9 -1
- package/dist/objectstorageutils.d.ts.map +1 -1
- package/dist/objectstorageutils.js +15 -6
- package/dist/objectstorageutils.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/remoteFluidObjectHandle.d.ts +2 -2
- package/dist/remoteFluidObjectHandle.d.ts.map +1 -1
- package/dist/remoteFluidObjectHandle.js +1 -0
- package/dist/remoteFluidObjectHandle.js.map +1 -1
- package/dist/requestParser.d.ts +2 -3
- package/dist/requestParser.d.ts.map +1 -1
- package/dist/requestParser.js +9 -11
- package/dist/requestParser.js.map +1 -1
- package/dist/runtimeFactoryHelper.d.ts +3 -4
- package/dist/runtimeFactoryHelper.d.ts.map +1 -1
- package/dist/runtimeFactoryHelper.js +1 -2
- package/dist/runtimeFactoryHelper.js.map +1 -1
- package/dist/summaryUtils.d.ts +29 -20
- package/dist/summaryUtils.d.ts.map +1 -1
- package/dist/summaryUtils.js +49 -21
- package/dist/summaryUtils.js.map +1 -1
- package/dist/unpackUsedRoutes.d.ts.map +1 -1
- package/dist/unpackUsedRoutes.js +3 -3
- package/dist/unpackUsedRoutes.js.map +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js.map +1 -1
- package/lib/compatibilityBase.d.ts +1 -3
- package/lib/compatibilityBase.d.ts.map +1 -1
- package/lib/compatibilityBase.js +3 -0
- package/lib/compatibilityBase.js.map +1 -1
- package/lib/dataStoreHandleContextUtils.d.ts +1 -1
- package/lib/dataStoreHandleContextUtils.d.ts.map +1 -1
- package/lib/dataStoreHandleContextUtils.js.map +1 -1
- package/lib/dataStoreHelpers.d.ts +18 -6
- package/lib/dataStoreHelpers.d.ts.map +1 -1
- package/lib/dataStoreHelpers.js +39 -11
- package/lib/dataStoreHelpers.js.map +1 -1
- package/lib/deltaManager.d.ts +1 -2
- package/lib/deltaManager.d.ts.map +1 -1
- package/lib/deltaManager.js +3 -2
- package/lib/deltaManager.js.map +1 -1
- package/lib/handles.d.ts +8 -12
- package/lib/handles.d.ts.map +1 -1
- package/lib/handles.js +14 -12
- package/lib/handles.js.map +1 -1
- package/lib/index.d.ts +6 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/objectstoragepartition.d.ts +1 -1
- package/lib/objectstoragepartition.d.ts.map +1 -1
- package/lib/objectstoragepartition.js.map +1 -1
- package/lib/objectstorageutils.d.ts +9 -1
- package/lib/objectstorageutils.d.ts.map +1 -1
- package/lib/objectstorageutils.js +15 -6
- package/lib/objectstorageutils.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/remoteFluidObjectHandle.d.ts +2 -2
- package/lib/remoteFluidObjectHandle.d.ts.map +1 -1
- package/lib/remoteFluidObjectHandle.js +1 -0
- package/lib/remoteFluidObjectHandle.js.map +1 -1
- package/lib/requestParser.d.ts +2 -3
- package/lib/requestParser.d.ts.map +1 -1
- package/lib/requestParser.js +9 -11
- package/lib/requestParser.js.map +1 -1
- package/lib/runtimeFactoryHelper.d.ts +3 -4
- package/lib/runtimeFactoryHelper.d.ts.map +1 -1
- package/lib/runtimeFactoryHelper.js +1 -2
- package/lib/runtimeFactoryHelper.js.map +1 -1
- package/lib/summaryUtils.d.ts +29 -20
- package/lib/summaryUtils.d.ts.map +1 -1
- package/lib/summaryUtils.js +51 -23
- package/lib/summaryUtils.js.map +1 -1
- package/lib/unpackUsedRoutes.d.ts.map +1 -1
- package/lib/unpackUsedRoutes.js +3 -3
- package/lib/unpackUsedRoutes.js.map +1 -1
- package/lib/utils.d.ts +1 -1
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js.map +1 -1
- package/package.json +13 -13
- package/src/compatibilityBase.ts +4 -3
- package/src/dataStoreHandleContextUtils.ts +1 -1
- package/src/dataStoreHelpers.ts +49 -16
- package/src/deltaManager.ts +3 -2
- package/src/handles.ts +14 -13
- package/src/index.ts +6 -4
- package/src/objectstoragepartition.ts +2 -2
- package/src/objectstorageutils.ts +17 -8
- package/src/packageVersion.ts +1 -1
- package/src/remoteFluidObjectHandle.ts +4 -3
- package/src/requestParser.ts +15 -15
- package/src/runtimeFactoryHelper.ts +4 -5
- package/src/summaryUtils.ts +70 -43
- package/src/unpackUsedRoutes.ts +7 -5
- 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.
|
|
18
|
+
normalizePath = normalizePath.slice(1);
|
|
15
19
|
}
|
|
16
20
|
if (normalizePath.endsWith("/")) {
|
|
17
|
-
normalizePath = normalizePath.
|
|
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 ===
|
|
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 ===
|
|
52
|
+
tree = treeEntry?.type === TreeEntry.Tree ? treeEntry.value : undefined;
|
|
44
53
|
}
|
|
45
|
-
if (tree?.entries === undefined || pathParts.length
|
|
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 ===
|
|
57
|
+
return tree.entries.filter((e) => e.type === TreeEntry.Blob).map((e) => e.path);
|
|
49
58
|
}
|
package/src/packageVersion.ts
CHANGED
|
@@ -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
|
}
|
package/src/requestParser.ts
CHANGED
|
@@ -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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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.
|
|
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
|
|
package/src/summaryUtils.ts
CHANGED
|
@@ -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 {
|
|
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.
|
|
69
|
-
if (code
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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:
|
|
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 |
|
|
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
|
-
|
|
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.
|
|
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:
|
|
538
|
-
public get gcNodes():
|
|
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:
|
|
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:
|
|
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
|
}
|
package/src/unpackUsedRoutes.ts
CHANGED
|
@@ -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(
|
|
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
|
|
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
|
|
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
|
}
|