@fluidframework/tool-utils 2.0.2 → 2.1.0-276326
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 +2 -15
- package/api-report/tool-utils.alpha.api.md +0 -4
- package/api-report/tool-utils.beta.api.md +0 -4
- package/api-report/tool-utils.public.api.md +0 -4
- package/dist/debug.d.ts.map +1 -1
- package/dist/debug.js +2 -0
- package/dist/debug.js.map +1 -1
- package/dist/{fluidToolRC.d.ts → fluidToolRc.d.ts} +7 -9
- package/dist/fluidToolRc.d.ts.map +1 -0
- package/dist/{fluidToolRC.js → fluidToolRc.js} +16 -11
- package/dist/fluidToolRc.js.map +1 -0
- package/dist/httpHelpers.d.ts +2 -2
- package/dist/httpHelpers.d.ts.map +1 -1
- package/dist/httpHelpers.js +16 -4
- package/dist/httpHelpers.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/odspTokenManager.d.ts +2 -2
- package/dist/odspTokenManager.d.ts.map +1 -1
- package/dist/odspTokenManager.js +18 -11
- package/dist/odspTokenManager.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.d.ts.map +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/dist/snapshotNormalizer.d.ts +1 -1
- package/dist/snapshotNormalizer.d.ts.map +1 -1
- package/dist/snapshotNormalizer.js +24 -12
- package/dist/snapshotNormalizer.js.map +1 -1
- package/lib/debug.d.ts.map +1 -1
- package/lib/debug.js +2 -0
- package/lib/debug.js.map +1 -1
- package/lib/{fluidToolRC.d.ts → fluidToolRc.d.ts} +7 -9
- package/lib/fluidToolRc.d.ts.map +1 -0
- package/lib/{fluidToolRC.js → fluidToolRc.js} +12 -7
- package/lib/fluidToolRc.js.map +1 -0
- package/lib/httpHelpers.d.ts +2 -2
- package/lib/httpHelpers.d.ts.map +1 -1
- package/lib/httpHelpers.js +15 -3
- package/lib/httpHelpers.js.map +1 -1
- package/lib/index.d.ts +6 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/lib/odspTokenManager.d.ts +2 -2
- package/lib/odspTokenManager.d.ts.map +1 -1
- package/lib/odspTokenManager.js +15 -8
- package/lib/odspTokenManager.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.d.ts.map +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/lib/snapshotNormalizer.d.ts +1 -1
- package/lib/snapshotNormalizer.d.ts.map +1 -1
- package/lib/snapshotNormalizer.js +24 -12
- package/lib/snapshotNormalizer.js.map +1 -1
- package/package.json +11 -10
- package/src/debug.ts +2 -0
- package/src/{fluidToolRC.ts → fluidToolRc.ts} +20 -14
- package/src/httpHelpers.ts +27 -5
- package/src/index.ts +5 -8
- package/src/odspTokenManager.ts +41 -23
- package/src/packageVersion.ts +1 -1
- package/src/snapshotNormalizer.ts +40 -19
- package/dist/fluidToolRC.d.ts.map +0 -1
- package/dist/fluidToolRC.js.map +0 -1
- package/lib/fluidToolRC.d.ts.map +0 -1
- package/lib/fluidToolRC.js.map +0 -1
|
@@ -7,7 +7,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
7
|
exports.getNormalizedSnapshot = exports.gcBlobPrefix = void 0;
|
|
8
8
|
const internal_1 = require("@fluidframework/driver-definitions/internal");
|
|
9
9
|
const internal_2 = require("@fluidframework/driver-utils/internal");
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* The name of the metadata blob added to the root of the container runtime.
|
|
12
|
+
*/
|
|
11
13
|
const metadataBlobName = ".metadata";
|
|
12
14
|
/**
|
|
13
15
|
* The prefix that all GC blob names start with.
|
|
@@ -15,6 +17,11 @@ const metadataBlobName = ".metadata";
|
|
|
15
17
|
* @internal
|
|
16
18
|
*/
|
|
17
19
|
exports.gcBlobPrefix = "__gc";
|
|
20
|
+
const sortStringified = (elem1, elem2) => {
|
|
21
|
+
const serializedElem1 = JSON.stringify(elem1);
|
|
22
|
+
const serializedElem2 = JSON.stringify(elem2);
|
|
23
|
+
return serializedElem1.localeCompare(serializedElem2);
|
|
24
|
+
};
|
|
18
25
|
/**
|
|
19
26
|
* Function that deep sorts an array. It handles cases where array elements are objects or arrays.
|
|
20
27
|
* @returns the sorted array.
|
|
@@ -35,18 +42,14 @@ function getDeepSortedArray(array) {
|
|
|
35
42
|
}
|
|
36
43
|
// Now that all the arrays and objects in this array's elements have been sorted, sort it by comparing each
|
|
37
44
|
// element's stringified version.
|
|
38
|
-
|
|
39
|
-
const serializedElem1 = JSON.stringify(elem1);
|
|
40
|
-
const serializedElem2 = JSON.stringify(elem2);
|
|
41
|
-
return serializedElem1.localeCompare(serializedElem2);
|
|
42
|
-
};
|
|
43
|
-
return sortedArray.sort(sortFn);
|
|
45
|
+
return sortedArray.sort(sortStringified);
|
|
44
46
|
}
|
|
45
47
|
/**
|
|
46
48
|
* Function that deep sorts an object. It handles cases where object properties are arrays or objects.
|
|
47
49
|
* @returns the sorted object.
|
|
48
50
|
*/
|
|
49
51
|
function getDeepSortedObject(obj) {
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
50
53
|
const sortedObj = {};
|
|
51
54
|
// Sort the object keys first. Then sort arrays and objects, if any, in the object.
|
|
52
55
|
const keys = Object.keys(obj).sort();
|
|
@@ -72,10 +75,14 @@ function getDeepSortedObject(obj) {
|
|
|
72
75
|
function getNormalizedBlobContent(blobContent, blobName) {
|
|
73
76
|
let content = blobContent;
|
|
74
77
|
if (blobName.startsWith(exports.gcBlobPrefix)) {
|
|
78
|
+
// The following code parses JSON and makes some assumptions about the type of data within. There does not appear to
|
|
79
|
+
// be a better type than `any` to use here, so the lint rules are disabled.
|
|
80
|
+
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */
|
|
75
81
|
// GC blobs may contain `unreferencedTimestampMs` for node that became unreferenced. This is the timestamp
|
|
76
82
|
// of the last op processed or current timestamp and can differ between clients depending on when GC was run.
|
|
77
83
|
// So, remove it for the purposes of comparing snapshots.
|
|
78
84
|
const gcState = JSON.parse(content);
|
|
85
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
79
86
|
for (const [, data] of Object.entries(gcState.gcNodes)) {
|
|
80
87
|
delete data.unreferencedTimestampMs;
|
|
81
88
|
}
|
|
@@ -116,7 +123,10 @@ function getNormalizedBlobContent(blobContent, blobName) {
|
|
|
116
123
|
}
|
|
117
124
|
content = JSON.stringify(contentObj);
|
|
118
125
|
}
|
|
119
|
-
catch {
|
|
126
|
+
catch {
|
|
127
|
+
// Do nothing
|
|
128
|
+
}
|
|
129
|
+
/* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */
|
|
120
130
|
return content;
|
|
121
131
|
}
|
|
122
132
|
/**
|
|
@@ -162,6 +172,7 @@ function normalizeMatrix(value) {
|
|
|
162
172
|
if (!header?.value.contents.includes("removedClientId")) {
|
|
163
173
|
return value;
|
|
164
174
|
}
|
|
175
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */
|
|
165
176
|
const contents = JSON.parse(header?.value.contents);
|
|
166
177
|
for (const segment of contents.segments) {
|
|
167
178
|
if ("removedClientId" in segment) {
|
|
@@ -172,6 +183,7 @@ function normalizeMatrix(value) {
|
|
|
172
183
|
}
|
|
173
184
|
}
|
|
174
185
|
header.value.contents = JSON.stringify(contents);
|
|
186
|
+
/* eslint-enable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */
|
|
175
187
|
return value;
|
|
176
188
|
}
|
|
177
189
|
function normalizeEntry(entry, config) {
|
|
@@ -179,9 +191,7 @@ function normalizeEntry(entry, config) {
|
|
|
179
191
|
case internal_1.TreeEntry.Blob: {
|
|
180
192
|
let contents = entry.value.contents;
|
|
181
193
|
// If this blob has to be normalized or it's a GC blob, parse and sort the blob contents first.
|
|
182
|
-
if (
|
|
183
|
-
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- ?? is not logically equivalent when .includes returns false.
|
|
184
|
-
config?.blobsToNormalize?.includes(entry.path) ||
|
|
194
|
+
if ((config?.blobsToNormalize?.includes(entry.path) ?? false) ||
|
|
185
195
|
entry.path.startsWith(exports.gcBlobPrefix)) {
|
|
186
196
|
contents = getNormalizedBlobContent(contents, entry.path);
|
|
187
197
|
}
|
|
@@ -192,6 +202,7 @@ function normalizeEntry(entry, config) {
|
|
|
192
202
|
for (const maybeAttributes of entry.value.entries) {
|
|
193
203
|
if (maybeAttributes.type === internal_1.TreeEntry.Blob &&
|
|
194
204
|
maybeAttributes.path === ".attributes") {
|
|
205
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
195
206
|
const parsed = JSON.parse(maybeAttributes.value.contents);
|
|
196
207
|
if (parsed.type === "https://graph.microsoft.com/types/sharedmatrix") {
|
|
197
208
|
return new internal_2.TreeTreeEntry(entry.path, normalizeMatrix(getNormalizedSnapshot(entry.value, config)));
|
|
@@ -209,8 +220,9 @@ function normalizeEntry(entry, config) {
|
|
|
209
220
|
case internal_1.TreeEntry.Attachment: {
|
|
210
221
|
return new internal_2.AttachmentTreeEntry(entry.path, entry.value.id);
|
|
211
222
|
}
|
|
212
|
-
default:
|
|
223
|
+
default: {
|
|
213
224
|
throw new Error("Unknown entry type");
|
|
225
|
+
}
|
|
214
226
|
}
|
|
215
227
|
}
|
|
216
228
|
//# sourceMappingURL=snapshotNormalizer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snapshotNormalizer.js","sourceRoot":"","sources":["../src/snapshotNormalizer.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 { ITree, ITreeEntry, TreeEntry } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tAttachmentTreeEntry,\n\tBlobTreeEntry,\n\tTreeTreeEntry,\n} from \"@fluidframework/driver-utils/internal\";\n\n/** The name of the metadata blob added to the root of the container runtime. */\nconst metadataBlobName = \".metadata\";\n/**\n * The prefix that all GC blob names start with.\n *\n * @internal\n */\nexport const gcBlobPrefix = \"__gc\";\n\n/**\n * @internal\n */\nexport interface ISnapshotNormalizerConfig {\n\t// The paths of blobs whose contents should be normalized.\n\tblobsToNormalize?: string[];\n\t/**\n\t * channel types who's content (non-attribute) blobs will be excluded.\n\t * this is used to exclude the content of channels who's content cannot be compared\n\t * as the content is non-deterministic between snapshot at the same sequence number.\n\t */\n\texcludedChannelContentTypes?: string[];\n}\n\n/**\n * Function that deep sorts an array. It handles cases where array elements are objects or arrays.\n * @returns the sorted array.\n */\nfunction getDeepSortedArray(array: any[]): any[] {\n\tconst sortedArray: any[] = [];\n\t// Sort arrays and objects, if any, in the array.\n\tfor (const element of array) {\n\t\tif (Array.isArray(element)) {\n\t\t\tsortedArray.push(getDeepSortedArray(element));\n\t\t} else if (element instanceof Object) {\n\t\t\tsortedArray.push(getDeepSortedObject(element));\n\t\t} else {\n\t\t\tsortedArray.push(element);\n\t\t}\n\t}\n\n\t// Now that all the arrays and objects in this array's elements have been sorted, sort it by comparing each\n\t// element's stringified version.\n\tconst sortFn = (elem1: any, elem2: any) => {\n\t\tconst serializedElem1 = JSON.stringify(elem1);\n\t\tconst serializedElem2 = JSON.stringify(elem2);\n\t\treturn serializedElem1.localeCompare(serializedElem2);\n\t};\n\n\treturn sortedArray.sort(sortFn);\n}\n\n/**\n * Function that deep sorts an object. It handles cases where object properties are arrays or objects.\n * @returns the sorted object.\n */\nfunction getDeepSortedObject(obj: any): any {\n\tconst sortedObj: any = {};\n\t// Sort the object keys first. Then sort arrays and objects, if any, in the object.\n\tconst keys = Object.keys(obj).sort();\n\tfor (const key of keys) {\n\t\tconst value = obj[key];\n\t\tif (Array.isArray(value)) {\n\t\t\tsortedObj[key] = getDeepSortedArray(value);\n\t\t} else if (value instanceof Object) {\n\t\t\tsortedObj[key] = getDeepSortedObject(value);\n\t\t} else {\n\t\t\tsortedObj[key] = value;\n\t\t}\n\t}\n\n\treturn sortedObj;\n}\n\n/**\n * Function that normalizes a blob's content. If the content is an object or an array, deep sorts them.\n * Special handling for certain runtime blobs, such as the \"gc\" blob.\n * @returns the normalized blob content.\n */\nfunction getNormalizedBlobContent(blobContent: string, blobName: string): string {\n\tlet content = blobContent;\n\tif (blobName.startsWith(gcBlobPrefix)) {\n\t\t// GC blobs may contain `unreferencedTimestampMs` for node that became unreferenced. This is the timestamp\n\t\t// of the last op processed or current timestamp and can differ between clients depending on when GC was run.\n\t\t// So, remove it for the purposes of comparing snapshots.\n\t\tconst gcState = JSON.parse(content);\n\t\tfor (const [, data] of Object.entries(gcState.gcNodes)) {\n\t\t\tdelete (data as any).unreferencedTimestampMs;\n\t\t}\n\t\tcontent = JSON.stringify(gcState);\n\t}\n\n\t/**\n\t * The metadata blob has \"summaryNumber\" or \"summaryCount\" that tells which summary this is for a container. It can\n\t * be different in summaries of two clients even if they are generated at the same sequence#. For instance, at seq#\n\t * 1000, if one client has summarized 10 times and other has summarizer 15 times, summaryNumber will be different\n\t * for them. So, update \"summaryNumber\" to 0 for purposes of comparing snapshots.\n\t */\n\tif (blobName === metadataBlobName) {\n\t\tconst metadata = JSON.parse(content);\n\t\tif (metadata.summaryNumber !== undefined) {\n\t\t\tmetadata.summaryNumber = 0;\n\t\t}\n\t\tif (metadata.summaryCount !== undefined) {\n\t\t\tmetadata.summaryCount = 0;\n\t\t}\n\t\t// \"telemetryDocumentId\" is not a deterministic property (random guid), so we need to set it to something consistent\n\t\tif (metadata.telemetryDocumentId !== undefined) {\n\t\t\tmetadata.telemetryDocumentId = \"x\";\n\t\t}\n\t\t// default was not written before, now it's written in.\n\t\tif (metadata.documentSchema !== undefined) {\n\t\t\tmetadata.documentSchema = undefined;\n\t\t}\n\t\tcontent = JSON.stringify(metadata);\n\t}\n\n\t// Deep sort the content if it's parseable.\n\ttry {\n\t\tlet contentObj = JSON.parse(content);\n\t\tif (Array.isArray(contentObj)) {\n\t\t\tcontentObj = getDeepSortedArray(contentObj);\n\t\t} else if (contentObj instanceof Object) {\n\t\t\tcontentObj = getDeepSortedObject(contentObj);\n\t\t}\n\t\tcontent = JSON.stringify(contentObj);\n\t} catch {}\n\treturn content;\n}\n\n/**\n * Helper function that normalizes the given snapshot tree. It sorts objects and arrays in the snapshot. It also\n * normalizes certain blob contents for which the order of content does not matter. For example, garbage collection\n * blobs contains objects / arrays whose element order do not matter.\n * @param snapshot - The snapshot tree to normalize.\n * @param config - Configs to use when normalizing snapshot. For example, it can contain paths of blobs whose contents\n * should be normalized as well.\n * @returns a copy of the normalized snapshot tree.\n * @internal\n */\nexport function getNormalizedSnapshot(\n\tsnapshot: ITree,\n\tconfig?: ISnapshotNormalizerConfig,\n): ITree {\n\t// Merge blobs to normalize in the config with runtime blobs to normalize. The contents of these blobs will be\n\t// parsed and deep sorted.\n\tconst normalizedEntries: ITreeEntry[] = [];\n\n\t// The metadata blob in the root of the summary tree needs to be normalized.\n\tconst blobsToNormalize = [metadataBlobName, ...(config?.blobsToNormalize ?? [])];\n\tfor (const entry of snapshot.entries) {\n\t\tnormalizedEntries.push(normalizeEntry(entry, { ...config, blobsToNormalize }));\n\t}\n\n\t// Sort the tree entries based on their path.\n\tnormalizedEntries.sort((a, b) => a.path.localeCompare(b.path));\n\n\treturn {\n\t\tentries: normalizedEntries,\n\t\tid: snapshot.id,\n\t};\n}\n\nfunction normalizeMatrix(value: ITree): ITree {\n\tconst rows = value.entries.find((e) => e.path === \"rows\");\n\n\tif (!rows || !(\"entries\" in rows.value)) {\n\t\treturn value;\n\t}\n\n\tconst segments = rows.value.entries.find((e) => e.path === \"segments\");\n\n\tif (!segments || !(\"entries\" in segments.value)) {\n\t\treturn value;\n\t}\n\n\tconst header = segments.value.entries.find((e) => e.path === \"header\");\n\n\tif (!header || !(\"contents\" in header.value)) {\n\t\treturn value;\n\t}\n\n\tif (!header?.value.contents.includes(\"removedClientId\")) {\n\t\treturn value;\n\t}\n\n\tconst contents = JSON.parse(header?.value.contents);\n\n\tfor (const segment of contents.segments) {\n\t\tif (\"removedClientId\" in segment) {\n\t\t\tsegment.removedClientId = undefined;\n\t\t}\n\n\t\tif (\"removedClientIds\" in segment) {\n\t\t\tsegment.removedClientIds = undefined;\n\t\t}\n\t}\n\n\theader.value.contents = JSON.stringify(contents);\n\n\treturn value;\n}\n\nfunction normalizeEntry(\n\tentry: ITreeEntry,\n\tconfig: ISnapshotNormalizerConfig | undefined,\n): ITreeEntry {\n\tswitch (entry.type) {\n\t\tcase TreeEntry.Blob: {\n\t\t\tlet contents = entry.value.contents;\n\t\t\t// If this blob has to be normalized or it's a GC blob, parse and sort the blob contents first.\n\t\t\tif (\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- ?? is not logically equivalent when .includes returns false.\n\t\t\t\tconfig?.blobsToNormalize?.includes(entry.path) ||\n\t\t\t\tentry.path.startsWith(gcBlobPrefix)\n\t\t\t) {\n\t\t\t\tcontents = getNormalizedBlobContent(contents, entry.path);\n\t\t\t}\n\t\t\treturn new BlobTreeEntry(entry.path, contents);\n\t\t}\n\t\tcase TreeEntry.Tree: {\n\t\t\tif (config?.excludedChannelContentTypes !== undefined) {\n\t\t\t\tfor (const maybeAttributes of entry.value.entries) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tmaybeAttributes.type === TreeEntry.Blob &&\n\t\t\t\t\t\tmaybeAttributes.path === \".attributes\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst parsed: { type?: string } = JSON.parse(maybeAttributes.value.contents);\n\t\t\t\t\t\tif (parsed.type === \"https://graph.microsoft.com/types/sharedmatrix\") {\n\t\t\t\t\t\t\treturn new TreeTreeEntry(\n\t\t\t\t\t\t\t\tentry.path,\n\t\t\t\t\t\t\t\tnormalizeMatrix(getNormalizedSnapshot(entry.value, config)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tparsed.type !== undefined &&\n\t\t\t\t\t\t\tconfig.excludedChannelContentTypes.includes(parsed.type)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t// remove everything to match the unknown channel\n\t\t\t\t\t\t\treturn new TreeTreeEntry(entry.path, { entries: [maybeAttributes] });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn new TreeTreeEntry(entry.path, getNormalizedSnapshot(entry.value, config));\n\t\t}\n\t\tcase TreeEntry.Attachment: {\n\t\t\treturn new AttachmentTreeEntry(entry.path, entry.value.id);\n\t\t}\n\n\t\tdefault:\n\t\t\tthrow new Error(\"Unknown entry type\");\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"snapshotNormalizer.js","sourceRoot":"","sources":["../src/snapshotNormalizer.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 type { ITree, ITreeEntry } from \"@fluidframework/driver-definitions/internal\";\nimport { TreeEntry } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tAttachmentTreeEntry,\n\tBlobTreeEntry,\n\tTreeTreeEntry,\n} from \"@fluidframework/driver-utils/internal\";\n\n/**\n * The name of the metadata blob added to the root of the container runtime.\n */\nconst metadataBlobName = \".metadata\";\n\n/**\n * The prefix that all GC blob names start with.\n *\n * @internal\n */\nexport const gcBlobPrefix = \"__gc\";\n\n/**\n * @internal\n */\nexport interface ISnapshotNormalizerConfig {\n\t// The paths of blobs whose contents should be normalized.\n\tblobsToNormalize?: string[];\n\t/**\n\t * channel types who's content (non-attribute) blobs will be excluded.\n\t * this is used to exclude the content of channels who's content cannot be compared\n\t * as the content is non-deterministic between snapshot at the same sequence number.\n\t */\n\texcludedChannelContentTypes?: string[];\n}\n\nconst sortStringified = (elem1: unknown, elem2: unknown): number => {\n\tconst serializedElem1 = JSON.stringify(elem1);\n\tconst serializedElem2 = JSON.stringify(elem2);\n\treturn serializedElem1.localeCompare(serializedElem2);\n};\n\n/**\n * Function that deep sorts an array. It handles cases where array elements are objects or arrays.\n * @returns the sorted array.\n */\nfunction getDeepSortedArray(array: unknown[]): unknown[] {\n\tconst sortedArray: unknown[] = [];\n\t// Sort arrays and objects, if any, in the array.\n\tfor (const element of array) {\n\t\tif (Array.isArray(element)) {\n\t\t\tsortedArray.push(getDeepSortedArray(element));\n\t\t} else if (element instanceof Object) {\n\t\t\tsortedArray.push(getDeepSortedObject(element));\n\t\t} else {\n\t\t\tsortedArray.push(element);\n\t\t}\n\t}\n\n\t// Now that all the arrays and objects in this array's elements have been sorted, sort it by comparing each\n\t// element's stringified version.\n\treturn sortedArray.sort(sortStringified);\n}\n\n/**\n * Function that deep sorts an object. It handles cases where object properties are arrays or objects.\n * @returns the sorted object.\n */\nfunction getDeepSortedObject<T extends object>(obj: T): T {\n\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\tconst sortedObj: T = {} as T;\n\t// Sort the object keys first. Then sort arrays and objects, if any, in the object.\n\tconst keys = Object.keys(obj).sort();\n\tfor (const key of keys) {\n\t\tconst value: unknown = obj[key];\n\t\tif (Array.isArray(value)) {\n\t\t\tsortedObj[key] = getDeepSortedArray(value);\n\t\t} else if (value instanceof Object) {\n\t\t\tsortedObj[key] = getDeepSortedObject(value);\n\t\t} else {\n\t\t\tsortedObj[key] = value;\n\t\t}\n\t}\n\n\treturn sortedObj;\n}\n\n/**\n * Function that normalizes a blob's content. If the content is an object or an array, deep sorts them.\n * Special handling for certain runtime blobs, such as the \"gc\" blob.\n * @returns the normalized blob content.\n */\nfunction getNormalizedBlobContent(blobContent: string, blobName: string): string {\n\tlet content = blobContent;\n\tif (blobName.startsWith(gcBlobPrefix)) {\n\t\t// The following code parses JSON and makes some assumptions about the type of data within. There does not appear to\n\t\t// be a better type than `any` to use here, so the lint rules are disabled.\n\n\t\t/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */\n\n\t\t// GC blobs may contain `unreferencedTimestampMs` for node that became unreferenced. This is the timestamp\n\t\t// of the last op processed or current timestamp and can differ between clients depending on when GC was run.\n\t\t// So, remove it for the purposes of comparing snapshots.\n\t\tconst gcState: any = JSON.parse(content);\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n\t\tfor (const [, data] of Object.entries(gcState.gcNodes)) {\n\t\t\tdelete (data as any).unreferencedTimestampMs;\n\t\t}\n\t\tcontent = JSON.stringify(gcState);\n\t}\n\n\t/**\n\t * The metadata blob has \"summaryNumber\" or \"summaryCount\" that tells which summary this is for a container. It can\n\t * be different in summaries of two clients even if they are generated at the same sequence#. For instance, at seq#\n\t * 1000, if one client has summarized 10 times and other has summarizer 15 times, summaryNumber will be different\n\t * for them. So, update \"summaryNumber\" to 0 for purposes of comparing snapshots.\n\t */\n\tif (blobName === metadataBlobName) {\n\t\tconst metadata = JSON.parse(content);\n\t\tif (metadata.summaryNumber !== undefined) {\n\t\t\tmetadata.summaryNumber = 0;\n\t\t}\n\t\tif (metadata.summaryCount !== undefined) {\n\t\t\tmetadata.summaryCount = 0;\n\t\t}\n\t\t// \"telemetryDocumentId\" is not a deterministic property (random guid), so we need to set it to something consistent\n\t\tif (metadata.telemetryDocumentId !== undefined) {\n\t\t\tmetadata.telemetryDocumentId = \"x\";\n\t\t}\n\t\t// default was not written before, now it's written in.\n\t\tif (metadata.documentSchema !== undefined) {\n\t\t\tmetadata.documentSchema = undefined;\n\t\t}\n\t\tcontent = JSON.stringify(metadata);\n\t}\n\n\t// Deep sort the content if it's parseable.\n\ttry {\n\t\tlet contentObj = JSON.parse(content);\n\t\tif (Array.isArray(contentObj)) {\n\t\t\tcontentObj = getDeepSortedArray(contentObj);\n\t\t} else if (contentObj instanceof Object) {\n\t\t\tcontentObj = getDeepSortedObject(contentObj);\n\t\t}\n\t\tcontent = JSON.stringify(contentObj);\n\t} catch {\n\t\t// Do nothing\n\t}\n\n\t/* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */\n\n\treturn content;\n}\n\n/**\n * Helper function that normalizes the given snapshot tree. It sorts objects and arrays in the snapshot. It also\n * normalizes certain blob contents for which the order of content does not matter. For example, garbage collection\n * blobs contains objects / arrays whose element order do not matter.\n * @param snapshot - The snapshot tree to normalize.\n * @param config - Configs to use when normalizing snapshot. For example, it can contain paths of blobs whose contents\n * should be normalized as well.\n * @returns a copy of the normalized snapshot tree.\n * @internal\n */\nexport function getNormalizedSnapshot(\n\tsnapshot: ITree,\n\tconfig?: ISnapshotNormalizerConfig,\n): ITree {\n\t// Merge blobs to normalize in the config with runtime blobs to normalize. The contents of these blobs will be\n\t// parsed and deep sorted.\n\tconst normalizedEntries: ITreeEntry[] = [];\n\n\t// The metadata blob in the root of the summary tree needs to be normalized.\n\tconst blobsToNormalize = [metadataBlobName, ...(config?.blobsToNormalize ?? [])];\n\tfor (const entry of snapshot.entries) {\n\t\tnormalizedEntries.push(normalizeEntry(entry, { ...config, blobsToNormalize }));\n\t}\n\n\t// Sort the tree entries based on their path.\n\tnormalizedEntries.sort((a, b) => a.path.localeCompare(b.path));\n\n\treturn {\n\t\tentries: normalizedEntries,\n\t\tid: snapshot.id,\n\t};\n}\n\nfunction normalizeMatrix(value: ITree): ITree {\n\tconst rows = value.entries.find((e) => e.path === \"rows\");\n\n\tif (!rows || !(\"entries\" in rows.value)) {\n\t\treturn value;\n\t}\n\n\tconst segments = rows.value.entries.find((e) => e.path === \"segments\");\n\n\tif (!segments || !(\"entries\" in segments.value)) {\n\t\treturn value;\n\t}\n\n\tconst header = segments.value.entries.find((e) => e.path === \"header\");\n\n\tif (!header || !(\"contents\" in header.value)) {\n\t\treturn value;\n\t}\n\n\tif (!header?.value.contents.includes(\"removedClientId\")) {\n\t\treturn value;\n\t}\n\n\t/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */\n\n\tconst contents = JSON.parse(header?.value.contents);\n\n\tfor (const segment of contents.segments) {\n\t\tif (\"removedClientId\" in segment) {\n\t\t\tsegment.removedClientId = undefined;\n\t\t}\n\n\t\tif (\"removedClientIds\" in segment) {\n\t\t\tsegment.removedClientIds = undefined;\n\t\t}\n\t}\n\n\theader.value.contents = JSON.stringify(contents);\n\n\t/* eslint-enable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */\n\n\treturn value;\n}\n\nfunction normalizeEntry(\n\tentry: ITreeEntry,\n\tconfig: ISnapshotNormalizerConfig | undefined,\n): ITreeEntry {\n\tswitch (entry.type) {\n\t\tcase TreeEntry.Blob: {\n\t\t\tlet contents = entry.value.contents;\n\t\t\t// If this blob has to be normalized or it's a GC blob, parse and sort the blob contents first.\n\t\t\tif (\n\t\t\t\t(config?.blobsToNormalize?.includes(entry.path) ?? false) ||\n\t\t\t\tentry.path.startsWith(gcBlobPrefix)\n\t\t\t) {\n\t\t\t\tcontents = getNormalizedBlobContent(contents, entry.path);\n\t\t\t}\n\t\t\treturn new BlobTreeEntry(entry.path, contents);\n\t\t}\n\t\tcase TreeEntry.Tree: {\n\t\t\tif (config?.excludedChannelContentTypes !== undefined) {\n\t\t\t\tfor (const maybeAttributes of entry.value.entries) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tmaybeAttributes.type === TreeEntry.Blob &&\n\t\t\t\t\t\tmaybeAttributes.path === \".attributes\"\n\t\t\t\t\t) {\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\t\t\tconst parsed: { type?: string } = JSON.parse(maybeAttributes.value.contents);\n\t\t\t\t\t\tif (parsed.type === \"https://graph.microsoft.com/types/sharedmatrix\") {\n\t\t\t\t\t\t\treturn new TreeTreeEntry(\n\t\t\t\t\t\t\t\tentry.path,\n\t\t\t\t\t\t\t\tnormalizeMatrix(getNormalizedSnapshot(entry.value, config)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tparsed.type !== undefined &&\n\t\t\t\t\t\t\tconfig.excludedChannelContentTypes.includes(parsed.type)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t// remove everything to match the unknown channel\n\t\t\t\t\t\t\treturn new TreeTreeEntry(entry.path, { entries: [maybeAttributes] });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn new TreeTreeEntry(entry.path, getNormalizedSnapshot(entry.value, config));\n\t\t}\n\t\tcase TreeEntry.Attachment: {\n\t\t\treturn new AttachmentTreeEntry(entry.path, entry.value.id);\n\t\t}\n\n\t\tdefault: {\n\t\t\tthrow new Error(\"Unknown entry type\");\n\t\t}\n\t}\n}\n"]}
|
package/lib/debug.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,aAAa,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,aAAa,MAAM,OAAO,CAAC;AAMlC,eAAO,MAAM,KAAK,wBAAoC,CAAC"}
|
package/lib/debug.js
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import registerDebug from "debug";
|
|
6
6
|
import { pkgName, pkgVersion } from "./packageVersion.js";
|
|
7
|
+
// TODO: Add documentation
|
|
8
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
7
9
|
export const debug = registerDebug("fluid:tool-utils");
|
|
8
10
|
debug(`Package: ${pkgName} - Version: ${pkgVersion}`);
|
|
9
11
|
//# sourceMappingURL=debug.js.map
|
package/lib/debug.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,aAAa,MAAM,OAAO,CAAC;AAElC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE1D,MAAM,CAAC,MAAM,KAAK,GAAG,aAAa,CAAC,kBAAkB,CAAC,CAAC;AACvD,KAAK,CAAC,YAAY,OAAO,eAAe,UAAU,EAAE,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport registerDebug from \"debug\";\n\nimport { pkgName, pkgVersion } from \"./packageVersion.js\";\n\nexport const debug = registerDebug(\"fluid:tool-utils\");\ndebug(`Package: ${pkgName} - Version: ${pkgVersion}`);\n"]}
|
|
1
|
+
{"version":3,"file":"debug.js","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,aAAa,MAAM,OAAO,CAAC;AAElC,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE1D,0BAA0B;AAC1B,+CAA+C;AAC/C,MAAM,CAAC,MAAM,KAAK,GAAG,aAAa,CAAC,kBAAkB,CAAC,CAAC;AACvD,KAAK,CAAC,YAAY,OAAO,eAAe,UAAU,EAAE,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport registerDebug from \"debug\";\n\nimport { pkgName, pkgVersion } from \"./packageVersion.js\";\n\n// TODO: Add documentation\n// eslint-disable-next-line jsdoc/require-jsdoc\nexport const debug = registerDebug(\"fluid:tool-utils\");\ndebug(`Package: ${pkgName} - Version: ${pkgVersion}`);\n"]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import { IOdspTokens } from "@fluidframework/odsp-doclib-utils/internal";
|
|
5
|
+
import type { IOdspTokens } from "@fluidframework/odsp-doclib-utils/internal";
|
|
6
6
|
/**
|
|
7
7
|
* @internal
|
|
8
8
|
*/
|
|
@@ -17,12 +17,10 @@ export interface IAsyncCache<TKey, TValue> {
|
|
|
17
17
|
export interface IResources {
|
|
18
18
|
tokens?: {
|
|
19
19
|
version?: number;
|
|
20
|
-
data: {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
25
|
-
};
|
|
20
|
+
data: Record<string, {
|
|
21
|
+
storage?: IOdspTokens;
|
|
22
|
+
push?: IOdspTokens;
|
|
23
|
+
}>;
|
|
26
24
|
};
|
|
27
25
|
}
|
|
28
26
|
/**
|
|
@@ -36,5 +34,5 @@ export declare function saveRC(rc: IResources): Promise<void>;
|
|
|
36
34
|
/**
|
|
37
35
|
* @internal
|
|
38
36
|
*/
|
|
39
|
-
export declare function lockRC(): Promise<
|
|
40
|
-
//# sourceMappingURL=
|
|
37
|
+
export declare function lockRC(): Promise<() => Promise<void>>;
|
|
38
|
+
//# sourceMappingURL=fluidToolRc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fluidToolRc.d.ts","sourceRoot":"","sources":["../src/fluidToolRc.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4CAA4C,CAAC;AAG9E;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,IAAI,EAAE,MAAM;IACxC,GAAG,CAAC,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC5C,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAChD;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,MAAM,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CACX,MAAM,EACN;YACC,OAAO,CAAC,EAAE,WAAW,CAAC;YACtB,IAAI,CAAC,EAAE,WAAW,CAAC;SACnB,CACD,CAAC;KACF,CAAC;CACF;AAMD;;GAEG;AACH,wBAAsB,MAAM,IAAI,OAAO,CAAC,UAAU,CAAC,CAclD;AAID;;GAEG;AACH,wBAAsB,MAAM,CAAC,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAI1D;AAID;;GAEG;AACH,wBAAsB,MAAM,IAAI,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAQ3D"}
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import fs from "fs";
|
|
6
|
-
import os from "os";
|
|
7
|
-
import path from "path";
|
|
8
|
-
import util from "util";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import os from "node:os";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import util from "node:util";
|
|
9
9
|
import { lock } from "proper-lockfile";
|
|
10
10
|
const getRCFileName = () => path.join(os.homedir(), ".fluidtoolrc");
|
|
11
|
+
// TODO: Add documentation
|
|
12
|
+
// eslint-disable-next-line jsdoc/require-description
|
|
11
13
|
/**
|
|
12
14
|
* @internal
|
|
13
15
|
*/
|
|
@@ -21,12 +23,14 @@ export async function loadRC() {
|
|
|
21
23
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
22
24
|
return JSON.parse(buf.toString("utf8"));
|
|
23
25
|
}
|
|
24
|
-
catch
|
|
26
|
+
catch {
|
|
25
27
|
// Nothing
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
30
|
return {};
|
|
29
31
|
}
|
|
32
|
+
// TODO: Add documentation
|
|
33
|
+
// eslint-disable-next-line jsdoc/require-description
|
|
30
34
|
/**
|
|
31
35
|
* @internal
|
|
32
36
|
*/
|
|
@@ -35,11 +39,12 @@ export async function saveRC(rc) {
|
|
|
35
39
|
const content = JSON.stringify(rc, undefined, 2);
|
|
36
40
|
return writeFile(getRCFileName(), Buffer.from(content, "utf8"));
|
|
37
41
|
}
|
|
42
|
+
// TODO: Add documentation
|
|
43
|
+
// eslint-disable-next-line jsdoc/require-description
|
|
38
44
|
/**
|
|
39
45
|
* @internal
|
|
40
46
|
*/
|
|
41
47
|
export async function lockRC() {
|
|
42
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
43
48
|
return lock(getRCFileName(), {
|
|
44
49
|
retries: {
|
|
45
50
|
forever: true,
|
|
@@ -48,4 +53,4 @@ export async function lockRC() {
|
|
|
48
53
|
realpath: false,
|
|
49
54
|
});
|
|
50
55
|
}
|
|
51
|
-
//# sourceMappingURL=
|
|
56
|
+
//# sourceMappingURL=fluidToolRc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fluidToolRc.js","sourceRoot":"","sources":["../src/fluidToolRc.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AA2BvC,MAAM,aAAa,GAAG,GAAW,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AAE5E,0BAA0B;AAC1B,qDAAqD;AACrD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM;IAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;IACjC,IAAI,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI,CAAC;YACJ,+DAA+D;YAC/D,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACR,UAAU;QACX,CAAC;IACF,CAAC;IACD,OAAO,EAAE,CAAC;AACX,CAAC;AAED,0BAA0B;AAC1B,qDAAqD;AACrD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,EAAc;IAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IACjD,OAAO,SAAS,CAAC,aAAa,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,0BAA0B;AAC1B,qDAAqD;AACrD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM;IAC3B,OAAO,IAAI,CAAC,aAAa,EAAE,EAAE;QAC5B,OAAO,EAAE;YACR,OAAO,EAAE,IAAI;SACb;QACD,KAAK,EAAE,KAAK;QACZ,QAAQ,EAAE,KAAK;KACf,CAAC,CAAC;AACJ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport util from \"node:util\";\n\nimport type { IOdspTokens } from \"@fluidframework/odsp-doclib-utils/internal\";\nimport { lock } from \"proper-lockfile\";\n\n/**\n * @internal\n */\nexport interface IAsyncCache<TKey, TValue> {\n\tget(key: TKey): Promise<TValue | undefined>;\n\tsave(key: TKey, value: TValue): Promise<void>;\n\tlock<T>(callback: () => Promise<T>): Promise<T>;\n}\n\n/**\n * @internal\n */\nexport interface IResources {\n\ttokens?: {\n\t\tversion?: number;\n\t\tdata: Record<\n\t\t\tstring,\n\t\t\t{\n\t\t\t\tstorage?: IOdspTokens;\n\t\t\t\tpush?: IOdspTokens;\n\t\t\t}\n\t\t>;\n\t};\n}\n\nconst getRCFileName = (): string => path.join(os.homedir(), \".fluidtoolrc\");\n\n// TODO: Add documentation\n// eslint-disable-next-line jsdoc/require-description\n/**\n * @internal\n */\nexport async function loadRC(): Promise<IResources> {\n\tconst readFile = util.promisify(fs.readFile);\n\tconst exists = util.promisify(fs.exists);\n\tconst fileName = getRCFileName();\n\tif (await exists(fileName)) {\n\t\tconst buf = await readFile(fileName);\n\t\ttry {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-return\n\t\t\treturn JSON.parse(buf.toString(\"utf8\"));\n\t\t} catch {\n\t\t\t// Nothing\n\t\t}\n\t}\n\treturn {};\n}\n\n// TODO: Add documentation\n// eslint-disable-next-line jsdoc/require-description\n/**\n * @internal\n */\nexport async function saveRC(rc: IResources): Promise<void> {\n\tconst writeFile = util.promisify(fs.writeFile);\n\tconst content = JSON.stringify(rc, undefined, 2);\n\treturn writeFile(getRCFileName(), Buffer.from(content, \"utf8\"));\n}\n\n// TODO: Add documentation\n// eslint-disable-next-line jsdoc/require-description\n/**\n * @internal\n */\nexport async function lockRC(): Promise<() => Promise<void>> {\n\treturn lock(getRCFileName(), {\n\t\tretries: {\n\t\t\tforever: true,\n\t\t},\n\t\tstale: 60000,\n\t\trealpath: false,\n\t});\n}\n"]}
|
package/lib/httpHelpers.d.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
/// <reference types="node" resolution-mode="require"/>
|
|
6
6
|
/// <reference types="node" resolution-mode="require"/>
|
|
7
|
-
import http from "http";
|
|
8
|
-
import { Socket } from "net";
|
|
7
|
+
import http from "node:http";
|
|
8
|
+
import type { Socket } from "node:net";
|
|
9
9
|
export interface ITrackedHttpServer {
|
|
10
10
|
readonly server: http.Server;
|
|
11
11
|
readonly sockets: Set<Socket>;
|
package/lib/httpHelpers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpHelpers.d.ts","sourceRoot":"","sources":["../src/httpHelpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;;;AAEH,OAAO,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"httpHelpers.d.ts","sourceRoot":"","sources":["../src/httpHelpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;;;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAIvC,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,UAAU,IAAI,IAAI,CAAC;CACnB;AAID,wBAAgB,mBAAmB,CAClC,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,IAAI,CAAC,eAAe,GACnC,kBAAkB,CAsBpB;AAID,MAAM,MAAM,mBAAmB,CAAC,CAAC,IAAI,CACpC,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,KACpB,OAAO,CAAC,CAAC,CAAC,CAAC;AAIhB,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,OAAO,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAI9D,eAAO,MAAM,qBAAqB,YAC3B,MAAM,WACH,oBAAoB,CAAC,CAAC,KAC7B,mBAAmB,CAAC,CAsBpB,CAAC;AAIJ,eAAO,MAAM,WAAW,aAAoB,KAAK,cAAc,KAAG,QAAQ,IAAI,CAO3E,CAAC"}
|
package/lib/httpHelpers.js
CHANGED
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import http from "http";
|
|
5
|
+
import http from "node:http";
|
|
6
|
+
// TODO: Add documentation
|
|
7
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
6
8
|
export function createTrackedServer(port, requestListener) {
|
|
9
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
7
10
|
const server = http.createServer(requestListener).listen(port);
|
|
11
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
8
12
|
const sockets = new Set();
|
|
9
13
|
server.on("connection", (socket) => {
|
|
10
14
|
sockets.add(socket);
|
|
@@ -15,15 +19,21 @@ export function createTrackedServer(port, requestListener) {
|
|
|
15
19
|
sockets,
|
|
16
20
|
fullyClose() {
|
|
17
21
|
server.close();
|
|
18
|
-
|
|
22
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
23
|
+
for (const socket of sockets) {
|
|
24
|
+
socket.destroy();
|
|
25
|
+
}
|
|
19
26
|
},
|
|
20
27
|
};
|
|
21
28
|
}
|
|
29
|
+
// TODO: Add documentation
|
|
30
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
22
31
|
export const serverListenAndHandle = async (port, handler) =>
|
|
23
32
|
// eslint-disable-next-line promise/param-names
|
|
24
33
|
new Promise((outerResolve, outerReject) => {
|
|
25
|
-
// eslint-disable-next-line promise/param-names
|
|
34
|
+
// eslint-disable-next-line promise/param-names, jsdoc/require-jsdoc
|
|
26
35
|
const innerP = new Promise((innerResolve, innerReject) => {
|
|
36
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
27
37
|
const httpServer = createTrackedServer(port, (req, res) => {
|
|
28
38
|
// ignore favicon
|
|
29
39
|
if (req.url === "/favicon.ico") {
|
|
@@ -38,6 +48,8 @@ new Promise((outerResolve, outerReject) => {
|
|
|
38
48
|
outerResolve(async () => innerP);
|
|
39
49
|
});
|
|
40
50
|
});
|
|
51
|
+
// TODO: Add documentation
|
|
52
|
+
// eslint-disable-next-line jsdoc/require-jsdoc
|
|
41
53
|
export const endResponse = async (response) => new Promise((resolve, reject) => {
|
|
42
54
|
try {
|
|
43
55
|
response.end(resolve);
|
package/lib/httpHelpers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpHelpers.js","sourceRoot":"","sources":["../src/httpHelpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"httpHelpers.js","sourceRoot":"","sources":["../src/httpHelpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAW7B,0BAA0B;AAC1B,+CAA+C;AAC/C,MAAM,UAAU,mBAAmB,CAClC,IAAY,EACZ,eAAqC;IAErC,+CAA+C;IAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/D,+CAA+C;IAC/C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAElC,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,EAAE;QAClC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpB,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,OAAO;QACN,MAAM;QACN,OAAO;QACP,UAAU;YACT,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,+CAA+C;YAC/C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC9B,MAAM,CAAC,OAAO,EAAE,CAAC;YAClB,CAAC;QACF,CAAC;KACD,CAAC;AACH,CAAC;AAaD,0BAA0B;AAC1B,+CAA+C;AAC/C,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EACzC,IAAY,EACZ,OAA+B,EACP,EAAE;AAC1B,+CAA+C;AAC/C,IAAI,OAAO,CAAC,CAAC,YAAY,EAAE,WAAW,EAAE,EAAE;IACzC,oEAAoE;IACpE,MAAM,MAAM,GAAG,IAAI,OAAO,CAAI,CAAC,YAAY,EAAE,WAAW,EAAE,EAAE;QAC3D,+CAA+C;QAC/C,MAAM,UAAU,GAAG,mBAAmB,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YACzD,iBAAiB;YACjB,IAAI,GAAG,CAAC,GAAG,KAAK,cAAc,EAAE,CAAC;gBAChC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC,CAAC;gBACvD,GAAG,CAAC,GAAG,EAAE,CAAC;gBACV,OAAO;YACR,CAAC;YACD,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC;iBACf,OAAO,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC;iBACtC,IAAI,CACJ,CAAC,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,EAChC,CAAC,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,CAC7B,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,YAAY,CAAC,KAAK,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEJ,0BAA0B;AAC1B,+CAA+C;AAC/C,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,QAA6B,EAAiB,EAAE,CACjF,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IAC/B,IAAI,CAAC;QACJ,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,CAAC,KAAK,CAAC,CAAC;IACf,CAAC;AACF,CAAC,CAAC,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport http from \"node:http\";\nimport type { Socket } from \"node:net\";\n\n// TODO: Add documentation\n// eslint-disable-next-line jsdoc/require-jsdoc\nexport interface ITrackedHttpServer {\n\treadonly server: http.Server;\n\treadonly sockets: Set<Socket>;\n\tfullyClose(): void;\n}\n\n// TODO: Add documentation\n// eslint-disable-next-line jsdoc/require-jsdoc\nexport function createTrackedServer(\n\tport: number,\n\trequestListener: http.RequestListener,\n): ITrackedHttpServer {\n\t// eslint-disable-next-line jsdoc/require-jsdoc\n\tconst server = http.createServer(requestListener).listen(port);\n\t// eslint-disable-next-line jsdoc/require-jsdoc\n\tconst sockets = new Set<Socket>();\n\n\tserver.on(\"connection\", (socket) => {\n\t\tsockets.add(socket);\n\t\tsocket.on(\"close\", () => sockets.delete(socket));\n\t});\n\n\treturn {\n\t\tserver,\n\t\tsockets,\n\t\tfullyClose(): void {\n\t\t\tserver.close();\n\t\t\t// eslint-disable-next-line jsdoc/require-jsdoc\n\t\t\tfor (const socket of sockets) {\n\t\t\t\tsocket.destroy();\n\t\t\t}\n\t\t},\n\t};\n}\n\n// TODO: Add documentation\n// eslint-disable-next-line jsdoc/require-jsdoc\nexport type OnceListenerHandler<T> = (\n\treq: http.IncomingMessage,\n\tres: http.ServerResponse,\n) => Promise<T>;\n\n// TODO: Add documentation\n// eslint-disable-next-line jsdoc/require-jsdoc\nexport type OnceListenerResult<T> = Promise<() => Promise<T>>;\n\n// TODO: Add documentation\n// eslint-disable-next-line jsdoc/require-jsdoc\nexport const serverListenAndHandle = async <T>(\n\tport: number,\n\thandler: OnceListenerHandler<T>,\n): OnceListenerResult<T> =>\n\t// eslint-disable-next-line promise/param-names\n\tnew Promise((outerResolve, outerReject) => {\n\t\t// eslint-disable-next-line promise/param-names, jsdoc/require-jsdoc\n\t\tconst innerP = new Promise<T>((innerResolve, innerReject) => {\n\t\t\t// eslint-disable-next-line jsdoc/require-jsdoc\n\t\t\tconst httpServer = createTrackedServer(port, (req, res) => {\n\t\t\t\t// ignore favicon\n\t\t\t\tif (req.url === \"/favicon.ico\") {\n\t\t\t\t\tres.writeHead(200, { \"Content-Type\": \"image/x-icon\" });\n\t\t\t\t\tres.end();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\thandler(req, res)\n\t\t\t\t\t.finally(() => httpServer.fullyClose())\n\t\t\t\t\t.then(\n\t\t\t\t\t\t(result) => innerResolve(result),\n\t\t\t\t\t\t(error) => innerReject(error),\n\t\t\t\t\t);\n\t\t\t});\n\t\t\touterResolve(async () => innerP);\n\t\t});\n\t});\n\n// TODO: Add documentation\n// eslint-disable-next-line jsdoc/require-jsdoc\nexport const endResponse = async (response: http.ServerResponse): Promise<void> =>\n\tnew Promise((resolve, reject) => {\n\t\ttry {\n\t\t\tresponse.end(resolve);\n\t\t} catch (error) {\n\t\t\treject(error);\n\t\t}\n\t});\n"]}
|
package/lib/index.d.ts
CHANGED
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
export { IAsyncCache, IResources
|
|
6
|
-
export {
|
|
7
|
-
export {
|
|
5
|
+
export type { IAsyncCache, IResources } from "./fluidToolRc.js";
|
|
6
|
+
export { loadRC, lockRC, saveRC } from "./fluidToolRc.js";
|
|
7
|
+
export type { IOdspTokenManagerCacheKey, OdspTokenConfig } from "./odspTokenManager.js";
|
|
8
|
+
export { getMicrosoftConfiguration, OdspTokenManager, odspTokensCache, } from "./odspTokenManager.js";
|
|
9
|
+
export type { ISnapshotNormalizerConfig } from "./snapshotNormalizer.js";
|
|
10
|
+
export { gcBlobPrefix, getNormalizedSnapshot } from "./snapshotNormalizer.js";
|
|
8
11
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1D,YAAY,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxF,OAAO,EACN,yBAAyB,EACzB,gBAAgB,EAChB,eAAe,GACf,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
export { loadRC, lockRC, saveRC } from "./
|
|
5
|
+
export { loadRC, lockRC, saveRC } from "./fluidToolRc.js";
|
|
6
6
|
export { getMicrosoftConfiguration, OdspTokenManager, odspTokensCache, } from "./odspTokenManager.js";
|
|
7
|
-
export { gcBlobPrefix, getNormalizedSnapshot
|
|
7
|
+
export { gcBlobPrefix, getNormalizedSnapshot } from "./snapshotNormalizer.js";
|
|
8
8
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,EACN,yBAAyB,EACzB,gBAAgB,EAChB,eAAe,GACf,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport type { IAsyncCache, IResources } from \"./fluidToolRc.js\";\nexport { loadRC, lockRC, saveRC } from \"./fluidToolRc.js\";\nexport type { IOdspTokenManagerCacheKey, OdspTokenConfig } from \"./odspTokenManager.js\";\nexport {\n\tgetMicrosoftConfiguration,\n\tOdspTokenManager,\n\todspTokensCache,\n} from \"./odspTokenManager.js\";\nexport type { ISnapshotNormalizerConfig } from \"./snapshotNormalizer.js\";\nexport { gcBlobPrefix, getNormalizedSnapshot } from \"./snapshotNormalizer.js\";\n"]}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
import { IPublicClientConfig, IOdspTokens } from "@fluidframework/odsp-doclib-utils/internal";
|
|
6
|
-
import { IAsyncCache } from "./
|
|
5
|
+
import type { IPublicClientConfig, IOdspTokens } from "@fluidframework/odsp-doclib-utils/internal";
|
|
6
|
+
import type { IAsyncCache } from "./fluidToolRc.js";
|
|
7
7
|
/**
|
|
8
8
|
* @internal
|
|
9
9
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspTokenManager.d.ts","sourceRoot":"","sources":["../src/odspTokenManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"odspTokenManager.d.ts","sourceRoot":"","sources":["../src/odspTokenManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EACX,mBAAmB,EACnB,WAAW,EAEX,MAAM,4CAA4C,CAAC;AAYpD,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,kBAAkB,CAAC;AAUhE;;GAEG;AACH,eAAO,MAAM,yBAAyB,QAAO,mBAQ3C,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,eAAe,GACxB;IACA,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAChB,GACD;IACA,IAAI,EAAE,cAAc,CAAC;IACrB,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,mBAAmB,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9D,CAAC;AAEL;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC9B;AAiBD;;GAEG;AACH,qBAAa,gBAAgB;IAK3B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAJ7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkC;IAC/D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkC;IAC5D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAe;gBAExB,UAAU,CAAC,iEAAqD;IAGrE,iBAAiB,CAC7B,GAAG,EAAE,yBAAyB,EAC9B,KAAK,EAAE,WAAW,GAChB,OAAO,CAAC,IAAI,CAAC;YAMF,4BAA4B;IAU7B,aAAa,CACzB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,mBAAmB,EACjC,WAAW,EAAE,eAAe,EAC5B,YAAY,UAAQ,EACpB,WAAW,UAAQ,GACjB,OAAO,CAAC,WAAW,CAAC;IAKV,aAAa,CACzB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,mBAAmB,EACjC,WAAW,EAAE,eAAe,EAC5B,YAAY,UAAQ,EACpB,WAAW,UAAQ,GACjB,OAAO,CAAC,WAAW,CAAC;YAKT,iBAAiB;IAiB/B,OAAO,CAAC,MAAM,CAAC,WAAW;YAYZ,SAAS;YA0CT,aAAa;YAkEb,yBAAyB;YAezB,4BAA4B;YAuC5B,yBAAyB;IASvC,OAAO,CAAC,wBAAwB;CAWhC;AAaD;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,yBAAyB,EAAE,WAAW,CA6B/E,CAAC"}
|
package/lib/odspTokenManager.js
CHANGED
|
@@ -7,16 +7,19 @@ import { fetchTokens, getLoginPageUrl, getOdspScope, pushScope, refreshTokens, }
|
|
|
7
7
|
import { Mutex } from "async-mutex";
|
|
8
8
|
import { jwtDecode } from "jwt-decode";
|
|
9
9
|
import { debug } from "./debug.js";
|
|
10
|
-
import { loadRC, lockRC, saveRC } from "./
|
|
10
|
+
import { loadRC, lockRC, saveRC } from "./fluidToolRc.js";
|
|
11
11
|
import { endResponse, serverListenAndHandle } from "./httpHelpers.js";
|
|
12
12
|
const odspAuthRedirectPort = 7000;
|
|
13
13
|
const odspAuthRedirectOrigin = `http://localhost:${odspAuthRedirectPort}`;
|
|
14
14
|
const odspAuthRedirectUri = new URL("/auth/callback", odspAuthRedirectOrigin).href;
|
|
15
|
+
// TODO: Add documentation
|
|
16
|
+
// eslint-disable-next-line jsdoc/require-description
|
|
15
17
|
/**
|
|
16
18
|
* @internal
|
|
17
19
|
*/
|
|
18
20
|
export const getMicrosoftConfiguration = () => ({
|
|
19
21
|
get clientId() {
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
20
23
|
if (!process.env.login__microsoft__clientId) {
|
|
21
24
|
throw new Error("Client ID environment variable not set: login__microsoft__clientId.");
|
|
22
25
|
}
|
|
@@ -30,7 +33,7 @@ const isValidToken = (token) => {
|
|
|
30
33
|
}
|
|
31
34
|
const decodedToken = jwtDecode(token);
|
|
32
35
|
// Give it a 60s buffer
|
|
33
|
-
return decodedToken.exp - 60 >=
|
|
36
|
+
return decodedToken.exp - 60 >= Date.now() / 1000;
|
|
34
37
|
};
|
|
35
38
|
const cacheKeyToString = (key) => {
|
|
36
39
|
return `${key.userOrServer}${key.isPush ? "[Push]" : ""}`;
|
|
@@ -141,14 +144,17 @@ export class OdspTokenManager {
|
|
|
141
144
|
return tokens;
|
|
142
145
|
}
|
|
143
146
|
switch (tokenConfig.type) {
|
|
144
|
-
case "password":
|
|
147
|
+
case "password": {
|
|
145
148
|
tokens = await this.acquireTokensWithPassword(server, scope, clientConfig, tokenConfig.username, tokenConfig.password);
|
|
146
149
|
break;
|
|
147
|
-
|
|
150
|
+
}
|
|
151
|
+
case "browserLogin": {
|
|
148
152
|
tokens = await this.acquireTokensViaBrowserLogin(getLoginPageUrl(server, clientConfig, scope, odspAuthRedirectUri), server, clientConfig, scope, tokenConfig.navigator, tokenConfig.redirectUriCallback);
|
|
149
153
|
break;
|
|
150
|
-
|
|
154
|
+
}
|
|
155
|
+
default: {
|
|
151
156
|
unreachableCase(tokenConfig);
|
|
157
|
+
}
|
|
152
158
|
}
|
|
153
159
|
await this.updateTokensCacheWithoutLock(cacheKey, tokens);
|
|
154
160
|
return tokens;
|
|
@@ -195,12 +201,12 @@ export class OdspTokenManager {
|
|
|
195
201
|
}
|
|
196
202
|
extractAuthorizationCode(relativeUrl) {
|
|
197
203
|
if (relativeUrl === undefined) {
|
|
198
|
-
throw Error("Failed to get authorization");
|
|
204
|
+
throw new Error("Failed to get authorization");
|
|
199
205
|
}
|
|
200
206
|
const parsedUrl = new URL(relativeUrl, odspAuthRedirectOrigin);
|
|
201
207
|
const code = parsedUrl.searchParams.get("code");
|
|
202
|
-
if (
|
|
203
|
-
throw Error("Failed to get authorization");
|
|
208
|
+
if (code === null || code === undefined) {
|
|
209
|
+
throw new Error("Failed to get authorization");
|
|
204
210
|
}
|
|
205
211
|
return code;
|
|
206
212
|
}
|
|
@@ -210,6 +216,7 @@ async function loadAndPatchRC() {
|
|
|
210
216
|
if (rc.tokens && rc.tokens.version === undefined) {
|
|
211
217
|
// Clean up older versions
|
|
212
218
|
delete rc.tokens;
|
|
219
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
|
|
213
220
|
delete rc.pushTokens;
|
|
214
221
|
}
|
|
215
222
|
return rc;
|