@fluid-tools/fetch-tool 0.59.2001 → 0.59.3000
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.js +0 -1
- package/dist/fluidAnalyzeMessages.js +14 -11
- package/dist/fluidAnalyzeMessages.js.map +1 -1
- package/dist/fluidFetch.js +7 -7
- package/dist/fluidFetch.js.map +1 -1
- package/dist/fluidFetchArgs.d.ts +0 -1
- package/dist/fluidFetchArgs.d.ts.map +1 -1
- package/dist/fluidFetchArgs.js +1 -6
- package/dist/fluidFetchArgs.js.map +1 -1
- package/dist/fluidFetchInit.d.ts.map +1 -1
- package/dist/fluidFetchInit.js +5 -31
- package/dist/fluidFetchInit.js.map +1 -1
- package/dist/fluidFetchMessages.js +6 -6
- package/dist/fluidFetchMessages.js.map +1 -1
- package/dist/fluidFetchSharePoint.js +7 -7
- package/dist/fluidFetchSharePoint.js.map +1 -1
- package/dist/fluidFetchSnapshot.js +11 -11
- package/dist/fluidFetchSnapshot.js.map +1 -1
- package/package.json +17 -18
- package/src/fluidAnalyzeMessages.ts +63 -59
- package/src/fluidFetch.ts +1 -1
- package/src/fluidFetchArgs.ts +7 -13
- package/src/fluidFetchInit.ts +3 -41
- package/src/fluidFetchSharePoint.ts +1 -1
- package/src/fluidFetchSnapshot.ts +4 -4
|
@@ -226,7 +226,7 @@ class DataStructureAnalyzer implements IMessageAnalyzer {
|
|
|
226
226
|
private readonly dataType = new Map<string, string>();
|
|
227
227
|
private readonly dataTypeStats = new Map<string, [number, number]>();
|
|
228
228
|
private readonly objectStats = new Map<string, [number, number]>();
|
|
229
|
-
private readonly chunkMap = new Map<string, {chunks: string[]
|
|
229
|
+
private readonly chunkMap = new Map<string, { chunks: string[]; totalSize: number; }>();
|
|
230
230
|
|
|
231
231
|
public processOp(message: ISequencedDocumentMessage, msgSize: number, skipMessage: boolean): void {
|
|
232
232
|
if (!skipMessage) {
|
|
@@ -479,7 +479,7 @@ function processOp(
|
|
|
479
479
|
msgSize: number,
|
|
480
480
|
dataTypeStats: Map<string, [number, number]>,
|
|
481
481
|
messageTypeStats: Map<string, [number, number]>,
|
|
482
|
-
chunkMap: Map<string, {chunks: string[]
|
|
482
|
+
chunkMap: Map<string, { chunks: string[]; totalSize: number; }>) {
|
|
483
483
|
let type = message.type;
|
|
484
484
|
let recorded = false;
|
|
485
485
|
let totalMsgSize = msgSize;
|
|
@@ -500,7 +500,11 @@ function processOp(
|
|
|
500
500
|
case RuntimeMessage.ChunkedOp: {
|
|
501
501
|
const chunk = runtimeMessage.contents as IChunkedOp;
|
|
502
502
|
if (!chunkMap.has(runtimeMessage.clientId)) {
|
|
503
|
-
chunkMap.set(
|
|
503
|
+
chunkMap.set(
|
|
504
|
+
runtimeMessage.clientId, {
|
|
505
|
+
chunks: new Array<string>(chunk.totalChunks),
|
|
506
|
+
totalSize: 0,
|
|
507
|
+
});
|
|
504
508
|
}
|
|
505
509
|
const value = chunkMap.get(runtimeMessage.clientId);
|
|
506
510
|
assert(value !== undefined, 0x2b8 /* "Chunk should be set in map" */);
|
|
@@ -528,68 +532,68 @@ function processOp(
|
|
|
528
532
|
case RuntimeMessage.Alias:
|
|
529
533
|
case RuntimeMessage.Rejoin:
|
|
530
534
|
case RuntimeMessage.Operation:
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
}
|
|
537
|
-
const innerContent = envelope.contents as {
|
|
538
|
-
content: any;
|
|
539
|
-
type: string;
|
|
540
|
-
};
|
|
541
|
-
const address = envelope.address;
|
|
542
|
-
type = `${type}/${innerContent.type}`;
|
|
543
|
-
switch (innerContent.type) {
|
|
544
|
-
case DataStoreMessageType.Attach: {
|
|
545
|
-
const attachMessage = innerContent.content as IAttachMessage;
|
|
546
|
-
let objectType = attachMessage.type;
|
|
547
|
-
if (objectType.startsWith(objectTypePrefix)) {
|
|
548
|
-
objectType = objectType.substring(objectTypePrefix.length);
|
|
549
|
-
}
|
|
550
|
-
dataType.set(getObjectId(address, attachMessage.id), objectType);
|
|
551
|
-
break;
|
|
535
|
+
{
|
|
536
|
+
let envelope = runtimeMessage.contents as IEnvelope;
|
|
537
|
+
// TODO: Legacy?
|
|
538
|
+
if (envelope && typeof envelope === "string") {
|
|
539
|
+
envelope = JSON.parse(envelope);
|
|
552
540
|
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
// Somehow we do not have data...
|
|
566
|
-
dataType.set(objectId, objectId);
|
|
567
|
-
objectType = objectId;
|
|
568
|
-
}
|
|
569
|
-
incr(dataTypeStats, objectType, totalMsgSize, opCount);
|
|
570
|
-
recorded = true;
|
|
571
|
-
|
|
572
|
-
let subType = innerContent2.type;
|
|
573
|
-
if (innerContent2.type === "set" &&
|
|
574
|
-
typeof innerContent2.value === "object" &&
|
|
575
|
-
innerContent2.value !== null) {
|
|
576
|
-
type = `${type}/${subType}`;
|
|
577
|
-
subType = innerContent2.value.type;
|
|
578
|
-
} else if (objectType === "mergeTree" && subType !== undefined) {
|
|
579
|
-
const types = ["insert", "remove", "annotate", "group"];
|
|
580
|
-
if (types[subType]) {
|
|
581
|
-
subType = types[subType];
|
|
541
|
+
const innerContent = envelope.contents as {
|
|
542
|
+
content: any;
|
|
543
|
+
type: string;
|
|
544
|
+
};
|
|
545
|
+
const address = envelope.address;
|
|
546
|
+
type = `${type}/${innerContent.type}`;
|
|
547
|
+
switch (innerContent.type) {
|
|
548
|
+
case DataStoreMessageType.Attach: {
|
|
549
|
+
const attachMessage = innerContent.content as IAttachMessage;
|
|
550
|
+
let objectType = attachMessage.type;
|
|
551
|
+
if (objectType.startsWith(objectTypePrefix)) {
|
|
552
|
+
objectType = objectType.substring(objectTypePrefix.length);
|
|
582
553
|
}
|
|
554
|
+
dataType.set(getObjectId(address, attachMessage.id), objectType);
|
|
555
|
+
break;
|
|
583
556
|
}
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
557
|
+
case DataStoreMessageType.ChannelOp:
|
|
558
|
+
default: {
|
|
559
|
+
const innerEnvelope = innerContent.content as IEnvelope;
|
|
560
|
+
const innerContent2 = innerEnvelope.contents as {
|
|
561
|
+
type?: string;
|
|
562
|
+
value?: any;
|
|
563
|
+
};
|
|
564
|
+
|
|
565
|
+
const objectId = getObjectId(address, innerEnvelope.address);
|
|
566
|
+
incr(objectStats, objectId, totalMsgSize, opCount);
|
|
567
|
+
let objectType = dataType.get(objectId);
|
|
568
|
+
if (objectType === undefined) {
|
|
569
|
+
// Somehow we do not have data...
|
|
570
|
+
dataType.set(objectId, objectId);
|
|
571
|
+
objectType = objectId;
|
|
572
|
+
}
|
|
573
|
+
incr(dataTypeStats, objectType, totalMsgSize, opCount);
|
|
574
|
+
recorded = true;
|
|
575
|
+
|
|
576
|
+
let subType = innerContent2.type;
|
|
577
|
+
if (innerContent2.type === "set" &&
|
|
578
|
+
typeof innerContent2.value === "object" &&
|
|
579
|
+
innerContent2.value !== null) {
|
|
580
|
+
type = `${type}/${subType}`;
|
|
581
|
+
subType = innerContent2.value.type;
|
|
582
|
+
} else if (objectType === "mergeTree" && subType !== undefined) {
|
|
583
|
+
const types = ["insert", "remove", "annotate", "group"];
|
|
584
|
+
if (types[subType]) {
|
|
585
|
+
subType = types[subType];
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
if (subType !== undefined) {
|
|
589
|
+
type = `${type}/${subType}`;
|
|
590
|
+
}
|
|
587
591
|
|
|
588
|
-
|
|
592
|
+
type = `${type} (${objectType})`;
|
|
593
|
+
}
|
|
589
594
|
}
|
|
595
|
+
break;
|
|
590
596
|
}
|
|
591
|
-
break;
|
|
592
|
-
}
|
|
593
597
|
default:
|
|
594
598
|
unreachableCase(messageType, "Message type not recognized!");
|
|
595
599
|
}
|
package/src/fluidFetch.ts
CHANGED
|
@@ -37,7 +37,7 @@ async function tryFluidFetchOneSharePointFile(server: string, driveItem: IOdspDr
|
|
|
37
37
|
await fluidFetchOneFile(`https://${server}/_api/v2.1/drives/${driveId}/items/${itemId}`, name);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
function getSharePointSpecificDriveItem(url: URL): { driveId: string; itemId: string } | undefined {
|
|
40
|
+
function getSharePointSpecificDriveItem(url: URL): { driveId: string; itemId: string; } | undefined {
|
|
41
41
|
if (url.searchParams.has("driveId") && url.searchParams.has("itemId")) {
|
|
42
42
|
return {
|
|
43
43
|
driveId: url.searchParams.get("driveId") as string,
|
package/src/fluidFetchArgs.ts
CHANGED
|
@@ -31,7 +31,6 @@ export const messageTypeFilter = new Set<string>();
|
|
|
31
31
|
|
|
32
32
|
export let paramURL: string | undefined;
|
|
33
33
|
export let paramJWT: string;
|
|
34
|
-
export let paramAzureKey: string;
|
|
35
34
|
|
|
36
35
|
export let connectToWebSocket = false;
|
|
37
36
|
|
|
@@ -50,7 +49,6 @@ const optionsArray =
|
|
|
50
49
|
["--stat", "Show both messages & snapshot stats"],
|
|
51
50
|
["--filter:messageType <type>", "filter message by <type>"],
|
|
52
51
|
["--jwt <token>", "token to be used for routerlicious URLs"],
|
|
53
|
-
["--azureKey <key>", "secret key for Azure Fluid Relay instance"],
|
|
54
52
|
["--numSnapshotVersions <number>", "Number of versions to load (default:10)"],
|
|
55
53
|
["--noUnpack", "Do not unpack aggregated blobs"],
|
|
56
54
|
["--actualPayload", "Do not format json payloads nicely, preserve actual bytes / formatting in storage"],
|
|
@@ -72,13 +70,13 @@ export function printUsage() {
|
|
|
72
70
|
// Can be used in unit test to pass in customized argument values
|
|
73
71
|
// More argument options can be added when needed
|
|
74
72
|
export function setArguments(values: {
|
|
75
|
-
saveDir: string
|
|
76
|
-
paramURL: string
|
|
77
|
-
dumpMessages?: boolean
|
|
78
|
-
dumpMessageStats?: boolean
|
|
79
|
-
dumpSnapshotStats?: boolean
|
|
80
|
-
dumpSnapshotTrees?: boolean
|
|
81
|
-
overWrite?: boolean }) {
|
|
73
|
+
saveDir: string;
|
|
74
|
+
paramURL: string;
|
|
75
|
+
dumpMessages?: boolean;
|
|
76
|
+
dumpMessageStats?: boolean;
|
|
77
|
+
dumpSnapshotStats?: boolean;
|
|
78
|
+
dumpSnapshotTrees?: boolean;
|
|
79
|
+
overWrite?: boolean; }) {
|
|
82
80
|
paramSaveDir = values.saveDir;
|
|
83
81
|
paramURL = values.paramURL;
|
|
84
82
|
dumpMessages = values.dumpMessages ?? dumpMessages;
|
|
@@ -121,13 +119,9 @@ export function parseArguments() {
|
|
|
121
119
|
case "--help":
|
|
122
120
|
printUsage();
|
|
123
121
|
process.exit(0);
|
|
124
|
-
// fallthrough
|
|
125
122
|
case "--jwt":
|
|
126
123
|
paramJWT = parseStrArg(i++, "jwt token");
|
|
127
124
|
break;
|
|
128
|
-
case "--azureKey":
|
|
129
|
-
paramAzureKey = parseStrArg(i++, "Azure Fluid Relay key");
|
|
130
|
-
break;
|
|
131
125
|
case "--forceTokenReauth":
|
|
132
126
|
paramForceTokenReauth = true;
|
|
133
127
|
break;
|
package/src/fluidFetchInit.ts
CHANGED
|
@@ -5,11 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
import { URL } from "url";
|
|
7
7
|
import child_process from "child_process";
|
|
8
|
-
import { AzureUrlResolver } from "@fluidframework/azure-client/dist/AzureUrlResolver";
|
|
9
|
-
import {
|
|
10
|
-
generateTestUser,
|
|
11
|
-
InsecureTokenProvider,
|
|
12
|
-
} from "@fluidframework/test-client-utils";
|
|
13
8
|
import { IFluidResolvedUrl, IResolvedUrl, IUrlResolver } from "@fluidframework/driver-definitions";
|
|
14
9
|
import { configurableUrlResolver } from "@fluidframework/driver-utils";
|
|
15
10
|
import { FluidAppOdspUrlResolver } from "@fluid-tools/fluidapp-odsp-urlresolver";
|
|
@@ -20,7 +15,7 @@ import { OdspUrlResolver } from "@fluidframework/odsp-urlresolver";
|
|
|
20
15
|
import * as r11s from "@fluidframework/routerlicious-driver";
|
|
21
16
|
import { RouterliciousUrlResolver } from "@fluidframework/routerlicious-urlresolver";
|
|
22
17
|
import { getMicrosoftConfiguration } from "@fluidframework/tool-utils";
|
|
23
|
-
import { localDataOnly,
|
|
18
|
+
import { localDataOnly, paramJWT } from "./fluidFetchArgs";
|
|
24
19
|
import { resolveWrapper } from "./fluidFetchSharePoint";
|
|
25
20
|
|
|
26
21
|
export let latestVersionsId: string = "";
|
|
@@ -84,11 +79,7 @@ async function initializeODSPCore(
|
|
|
84
79
|
opsBatchSize: 20000,
|
|
85
80
|
concurrentOpsBatches: 4,
|
|
86
81
|
});
|
|
87
|
-
return odspDocumentServiceFactory.createDocumentService(
|
|
88
|
-
odspResolvedUrl,
|
|
89
|
-
undefined, // logger
|
|
90
|
-
false, // clientIsSummrizer
|
|
91
|
-
);
|
|
82
|
+
return odspDocumentServiceFactory.createDocumentService(odspResolvedUrl);
|
|
92
83
|
}
|
|
93
84
|
|
|
94
85
|
async function initializeR11s(server: string, pathname: string, r11sResolvedUrl: IFluidResolvedUrl) {
|
|
@@ -119,28 +110,7 @@ async function initializeR11s(server: string, pathname: string, r11sResolvedUrl:
|
|
|
119
110
|
console.log(`Connecting to r11s: tenantId=${tenantId} id:${documentId}`);
|
|
120
111
|
const tokenProvider = new r11s.DefaultTokenProvider(paramJWT);
|
|
121
112
|
const r11sDocumentServiceFactory = new r11s.RouterliciousDocumentServiceFactory(tokenProvider);
|
|
122
|
-
return r11sDocumentServiceFactory.createDocumentService(
|
|
123
|
-
r11sResolvedUrl,
|
|
124
|
-
undefined, // logger
|
|
125
|
-
false, // clientIsSummarizer
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
async function initializeAzure(resolvedUrl: IFluidResolvedUrl, tenantId: string) {
|
|
130
|
-
connectionInfo = {
|
|
131
|
-
server: resolvedUrl.endpoints.ordererUrl,
|
|
132
|
-
tenantId,
|
|
133
|
-
id: resolvedUrl.id,
|
|
134
|
-
};
|
|
135
|
-
console.log(`Connecting to Azure Fluid Relay: tenantId=${tenantId} id:${resolvedUrl.id}`);
|
|
136
|
-
const user = generateTestUser();
|
|
137
|
-
const tokenProvider = new InsecureTokenProvider(paramAzureKey, user);
|
|
138
|
-
const r11sDocumentServiceFactory = new r11s.RouterliciousDocumentServiceFactory(tokenProvider);
|
|
139
|
-
return r11sDocumentServiceFactory.createDocumentService(
|
|
140
|
-
resolvedUrl,
|
|
141
|
-
undefined, // logger
|
|
142
|
-
false, // clientIsSummarizer
|
|
143
|
-
);
|
|
113
|
+
return r11sDocumentServiceFactory.createDocumentService(r11sResolvedUrl);
|
|
144
114
|
}
|
|
145
115
|
|
|
146
116
|
async function resolveUrl(url: string): Promise<IResolvedUrl | undefined> {
|
|
@@ -149,7 +119,6 @@ async function resolveUrl(url: string): Promise<IResolvedUrl | undefined> {
|
|
|
149
119
|
new FluidAppOdspUrlResolver(),
|
|
150
120
|
// eslint-disable-next-line @typescript-eslint/promise-function-async
|
|
151
121
|
new RouterliciousUrlResolver(undefined, () => Promise.resolve(paramJWT), ""),
|
|
152
|
-
new AzureUrlResolver(),
|
|
153
122
|
];
|
|
154
123
|
const resolved = await configurableUrlResolver(resolversList, { url });
|
|
155
124
|
return resolved;
|
|
@@ -168,13 +137,6 @@ export async function fluidFetchInit(urlStr: string) {
|
|
|
168
137
|
const url = new URL(urlStr);
|
|
169
138
|
const server = url.hostname.toLowerCase();
|
|
170
139
|
return initializeR11s(server, url.pathname, resolvedUrl);
|
|
171
|
-
} else if (resolvedUrl.url.includes("fluidrelay.azure.com")) {
|
|
172
|
-
const url = new URL(urlStr);
|
|
173
|
-
const tenantId = url.searchParams.get("tenantId");
|
|
174
|
-
if (tenantId === null) {
|
|
175
|
-
throw new Error("Azure URL did not contain tenantId");
|
|
176
|
-
}
|
|
177
|
-
return initializeAzure(resolvedUrl, tenantId);
|
|
178
140
|
}
|
|
179
141
|
return Promise.reject(new Error(`Unknown resolved protocol ${protocol}`));
|
|
180
142
|
}
|
|
@@ -97,7 +97,7 @@ export async function getSharepointFiles(server: string, serverRelativePath: str
|
|
|
97
97
|
|
|
98
98
|
const fileInfo = await resolveDriveItemByServerRelativePath(server, serverRelativePath, clientConfig);
|
|
99
99
|
console.log(fileInfo);
|
|
100
|
-
const pendingFolder: { path: string
|
|
100
|
+
const pendingFolder: { path: string; folder: IOdspDriveItem; }[] = [];
|
|
101
101
|
const files: IOdspDriveItem[] = [];
|
|
102
102
|
if (fileInfo.isFolder) {
|
|
103
103
|
pendingFolder.push({ path: serverRelativePath, folder: fileInfo });
|
|
@@ -104,7 +104,7 @@ function fetchBlobs(prefix: string,
|
|
|
104
104
|
|
|
105
105
|
function createTreeBlob(tree: ISnapshotTree, prefix: string, patched: boolean): IFetchedTree {
|
|
106
106
|
const id = tree.id ?? "original";
|
|
107
|
-
const blob = stringToBuffer(JSON.stringify(tree),"utf8");
|
|
107
|
+
const blob = stringToBuffer(JSON.stringify(tree), "utf8");
|
|
108
108
|
const filename = patched ? "tree" : `tree-${id}`;
|
|
109
109
|
const treePath = `${prefix}${filename}`;
|
|
110
110
|
return { treePath, blobId: "original tree $id", filename, blob, patched, reused: false };
|
|
@@ -172,7 +172,7 @@ async function dumpSnapshotTreeVerbose(name: string, fetchedData: IFetchedData[]
|
|
|
172
172
|
if (buffer === undefined) {
|
|
173
173
|
continue;
|
|
174
174
|
}
|
|
175
|
-
const blob = bufferToString(buffer,"utf8");
|
|
175
|
+
const blob = bufferToString(buffer, "utf8");
|
|
176
176
|
// eslint-disable-next-line max-len
|
|
177
177
|
console.log(`${item.treePath.padEnd(nameLength)} | ${item.reused ? "X" : " "} | ${formatNumber(blob.length).padStart(10)}`);
|
|
178
178
|
size += blob.length;
|
|
@@ -222,7 +222,7 @@ async function saveSnapshot(name: string, fetchedData: IFetchedData[], saveDir:
|
|
|
222
222
|
|
|
223
223
|
// we assume that the buffer is utf8 here, which currently is true for
|
|
224
224
|
// all of our snapshot blobs. It doesn't necessary be true in the future
|
|
225
|
-
let decoded = bufferToString(buffer,"utf8");
|
|
225
|
+
let decoded = bufferToString(buffer, "utf8");
|
|
226
226
|
try {
|
|
227
227
|
if (!paramActualFormatting) {
|
|
228
228
|
decoded = JSON.stringify(JSON.parse(decoded), undefined, 2);
|
|
@@ -233,7 +233,7 @@ async function saveSnapshot(name: string, fetchedData: IFetchedData[], saveDir:
|
|
|
233
233
|
`${outDir}/decoded/${item.filename}.json`, decoded);
|
|
234
234
|
} else {
|
|
235
235
|
// Write out same data for tree decoded or not, except for formatting
|
|
236
|
-
const treeString = bufferToString(buffer,"utf8");
|
|
236
|
+
const treeString = bufferToString(buffer, "utf8");
|
|
237
237
|
fs.writeFileSync(`${outDir}/${item.filename}.json`, treeString);
|
|
238
238
|
fs.writeFileSync(`${outDir}/decoded/${item.filename}.json`,
|
|
239
239
|
paramActualFormatting ? treeString : JSON.stringify(JSON.parse(treeString), undefined, 2));
|