@fluidframework/tool-utils 2.0.0-internal.7.2.2 → 2.0.0-internal.7.4.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/CHANGELOG.md +8 -0
- package/README.md +1 -2
- package/api-extractor-lint.json +13 -0
- package/api-extractor.json +3 -3
- package/api-report/tool-utils.api.md +13 -13
- package/dist/fluidToolRC.d.ts +15 -0
- package/dist/fluidToolRC.d.ts.map +1 -1
- package/dist/fluidToolRC.js +9 -0
- package/dist/fluidToolRC.js.map +1 -1
- package/dist/odspTokenManager.d.ts +15 -0
- package/dist/odspTokenManager.d.ts.map +1 -1
- package/dist/odspTokenManager.js +11 -5
- package/dist/odspTokenManager.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/snapshotNormalizer.d.ts +9 -1
- package/dist/snapshotNormalizer.d.ts.map +1 -1
- package/dist/snapshotNormalizer.js +6 -1
- package/dist/snapshotNormalizer.js.map +1 -1
- package/dist/tool-utils-alpha.d.ts +35 -0
- package/dist/tool-utils-beta.d.ts +35 -0
- package/dist/tool-utils-public.d.ts +35 -0
- package/dist/tool-utils-untrimmed.d.ts +130 -0
- package/dist/tsdoc-metadata.json +1 -1
- package/lib/fluidToolRC.d.ts +15 -0
- package/lib/fluidToolRC.d.ts.map +1 -1
- package/lib/fluidToolRC.js +9 -0
- package/lib/fluidToolRC.js.map +1 -1
- package/lib/odspTokenManager.d.ts +15 -0
- package/lib/odspTokenManager.d.ts.map +1 -1
- package/lib/odspTokenManager.js +10 -1
- package/lib/odspTokenManager.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/snapshotNormalizer.d.ts +9 -1
- package/lib/snapshotNormalizer.d.ts.map +1 -1
- package/lib/snapshotNormalizer.js +6 -1
- package/lib/snapshotNormalizer.js.map +1 -1
- package/lib/tool-utils-alpha.d.ts +35 -0
- package/lib/tool-utils-beta.d.ts +35 -0
- package/lib/tool-utils-public.d.ts +35 -0
- package/lib/tool-utils-untrimmed.d.ts +130 -0
- package/package.json +37 -19
- package/src/fluidToolRC.ts +15 -0
- package/src/odspTokenManager.ts +16 -1
- package/src/packageVersion.ts +1 -1
- package/src/snapshotNormalizer.ts +9 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -63,8 +63,7 @@ Thank you!
|
|
|
63
63
|
|
|
64
64
|
This project may contain Microsoft trademarks or logos for Microsoft projects, products, or services.
|
|
65
65
|
|
|
66
|
-
Use of these trademarks or logos must follow Microsoft's [Trademark & Brand
|
|
67
|
-
Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
|
|
66
|
+
Use of these trademarks or logos must follow Microsoft's [Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
|
|
68
67
|
|
|
69
68
|
Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
|
|
70
69
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
|
3
|
+
"extends": "../../../common/build/build-common/api-extractor-lint.json",
|
|
4
|
+
"messages": {
|
|
5
|
+
"extractorMessageReporting": {
|
|
6
|
+
// TODO: remove once base config has this enabled as an error
|
|
7
|
+
"ae-incompatible-release-tags": {
|
|
8
|
+
"logLevel": "error",
|
|
9
|
+
"addToApiReportFile": false
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
package/api-extractor.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
|
3
|
-
"extends": "
|
|
3
|
+
"extends": "../../../common/build/build-common/api-extractor-base.json",
|
|
4
4
|
"messages": {
|
|
5
5
|
"extractorMessageReporting": {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
// TODO: Add missing documentation and remove this rule override
|
|
7
|
+
"ae-undocumented": {
|
|
8
8
|
"logLevel": "none"
|
|
9
9
|
}
|
|
10
10
|
}
|
|
@@ -8,16 +8,16 @@ import { IClientConfig } from '@fluidframework/odsp-doclib-utils';
|
|
|
8
8
|
import { IOdspTokens } from '@fluidframework/odsp-doclib-utils';
|
|
9
9
|
import { ITree } from '@fluidframework/protocol-definitions';
|
|
10
10
|
|
|
11
|
-
// @
|
|
11
|
+
// @internal
|
|
12
12
|
export const gcBlobPrefix = "__gc";
|
|
13
13
|
|
|
14
|
-
// @
|
|
14
|
+
// @internal (undocumented)
|
|
15
15
|
export const getMicrosoftConfiguration: () => IClientConfig;
|
|
16
16
|
|
|
17
|
-
// @
|
|
17
|
+
// @internal
|
|
18
18
|
export function getNormalizedSnapshot(snapshot: ITree, config?: ISnapshotNormalizerConfig): ITree;
|
|
19
19
|
|
|
20
|
-
// @
|
|
20
|
+
// @internal (undocumented)
|
|
21
21
|
export interface IAsyncCache<TKey, TValue> {
|
|
22
22
|
// (undocumented)
|
|
23
23
|
get(key: TKey): Promise<TValue | undefined>;
|
|
@@ -27,7 +27,7 @@ export interface IAsyncCache<TKey, TValue> {
|
|
|
27
27
|
save(key: TKey, value: TValue): Promise<void>;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
// @
|
|
30
|
+
// @internal (undocumented)
|
|
31
31
|
export interface IOdspTokenManagerCacheKey {
|
|
32
32
|
// (undocumented)
|
|
33
33
|
readonly isPush: boolean;
|
|
@@ -35,7 +35,7 @@ export interface IOdspTokenManagerCacheKey {
|
|
|
35
35
|
readonly userOrServer: string;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
// @
|
|
38
|
+
// @internal (undocumented)
|
|
39
39
|
export interface IResources {
|
|
40
40
|
// (undocumented)
|
|
41
41
|
tokens?: {
|
|
@@ -49,20 +49,20 @@ export interface IResources {
|
|
|
49
49
|
};
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
// @
|
|
52
|
+
// @internal (undocumented)
|
|
53
53
|
export interface ISnapshotNormalizerConfig {
|
|
54
54
|
// (undocumented)
|
|
55
55
|
blobsToNormalize?: string[];
|
|
56
56
|
excludedChannelContentTypes?: string[];
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
// @
|
|
59
|
+
// @internal (undocumented)
|
|
60
60
|
export function loadRC(): Promise<IResources>;
|
|
61
61
|
|
|
62
|
-
// @
|
|
62
|
+
// @internal (undocumented)
|
|
63
63
|
export function lockRC(): Promise<any>;
|
|
64
64
|
|
|
65
|
-
// @
|
|
65
|
+
// @internal (undocumented)
|
|
66
66
|
export type OdspTokenConfig = {
|
|
67
67
|
type: "password";
|
|
68
68
|
username: string;
|
|
@@ -73,7 +73,7 @@ export type OdspTokenConfig = {
|
|
|
73
73
|
redirectUriCallback?: (tokens: IOdspTokens) => Promise<string>;
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
-
// @
|
|
76
|
+
// @internal (undocumented)
|
|
77
77
|
export class OdspTokenManager {
|
|
78
78
|
constructor(tokenCache?: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens> | undefined);
|
|
79
79
|
// (undocumented)
|
|
@@ -84,10 +84,10 @@ export class OdspTokenManager {
|
|
|
84
84
|
updateTokensCache(key: IOdspTokenManagerCacheKey, value: IOdspTokens): Promise<void>;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
// @
|
|
87
|
+
// @internal (undocumented)
|
|
88
88
|
export const odspTokensCache: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens>;
|
|
89
89
|
|
|
90
|
-
// @
|
|
90
|
+
// @internal (undocumented)
|
|
91
91
|
export function saveRC(rc: IResources): Promise<void>;
|
|
92
92
|
|
|
93
93
|
// (No @packageDocumentation comment for this package)
|
package/dist/fluidToolRC.d.ts
CHANGED
|
@@ -3,11 +3,17 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import { IOdspTokens } from "@fluidframework/odsp-doclib-utils";
|
|
6
|
+
/**
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
6
9
|
export interface IAsyncCache<TKey, TValue> {
|
|
7
10
|
get(key: TKey): Promise<TValue | undefined>;
|
|
8
11
|
save(key: TKey, value: TValue): Promise<void>;
|
|
9
12
|
lock<T>(callback: () => Promise<T>): Promise<T>;
|
|
10
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
11
17
|
export interface IResources {
|
|
12
18
|
tokens?: {
|
|
13
19
|
version?: number;
|
|
@@ -19,7 +25,16 @@ export interface IResources {
|
|
|
19
25
|
};
|
|
20
26
|
};
|
|
21
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* @internal
|
|
30
|
+
*/
|
|
22
31
|
export declare function loadRC(): Promise<IResources>;
|
|
32
|
+
/**
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
23
35
|
export declare function saveRC(rc: IResources): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* @internal
|
|
38
|
+
*/
|
|
24
39
|
export declare function lockRC(): Promise<any>;
|
|
25
40
|
//# sourceMappingURL=fluidToolRC.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fluidToolRC.d.ts","sourceRoot":"","sources":["../src/fluidToolRC.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAEhE,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,MAAM,WAAW,UAAU;IAC1B,MAAM,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE;YACL,CAAC,GAAG,EAAE,MAAM,GAAG;gBACd,OAAO,CAAC,EAAE,WAAW,CAAC;gBACtB,IAAI,CAAC,EAAE,WAAW,CAAC;aACnB,CAAC;SACF,CAAC;KACF,CAAC;CACF;AAID,wBAAsB,MAAM,IAAI,OAAO,CAAC,UAAU,CAAC,CAclD;AAED,wBAAsB,MAAM,CAAC,EAAE,EAAE,UAAU,iBAI1C;AAED,wBAAsB,MAAM,iBAS3B"}
|
|
1
|
+
{"version":3,"file":"fluidToolRC.d.ts","sourceRoot":"","sources":["../src/fluidToolRC.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAEhE;;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;YACL,CAAC,GAAG,EAAE,MAAM,GAAG;gBACd,OAAO,CAAC,EAAE,WAAW,CAAC;gBACtB,IAAI,CAAC,EAAE,WAAW,CAAC;aACnB,CAAC;SACF,CAAC;KACF,CAAC;CACF;AAID;;GAEG;AACH,wBAAsB,MAAM,IAAI,OAAO,CAAC,UAAU,CAAC,CAclD;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,EAAE,EAAE,UAAU,iBAI1C;AAED;;GAEG;AACH,wBAAsB,MAAM,iBAS3B"}
|
package/dist/fluidToolRC.js
CHANGED
|
@@ -14,6 +14,9 @@ const path_1 = __importDefault(require("path"));
|
|
|
14
14
|
const util_1 = __importDefault(require("util"));
|
|
15
15
|
const proper_lockfile_1 = require("proper-lockfile");
|
|
16
16
|
const getRCFileName = () => path_1.default.join(os_1.default.homedir(), ".fluidtoolrc");
|
|
17
|
+
/**
|
|
18
|
+
* @internal
|
|
19
|
+
*/
|
|
17
20
|
async function loadRC() {
|
|
18
21
|
const readFile = util_1.default.promisify(fs_1.default.readFile);
|
|
19
22
|
const exists = util_1.default.promisify(fs_1.default.exists);
|
|
@@ -31,12 +34,18 @@ async function loadRC() {
|
|
|
31
34
|
return {};
|
|
32
35
|
}
|
|
33
36
|
exports.loadRC = loadRC;
|
|
37
|
+
/**
|
|
38
|
+
* @internal
|
|
39
|
+
*/
|
|
34
40
|
async function saveRC(rc) {
|
|
35
41
|
const writeFile = util_1.default.promisify(fs_1.default.writeFile);
|
|
36
42
|
const content = JSON.stringify(rc, undefined, 2);
|
|
37
43
|
return writeFile(getRCFileName(), Buffer.from(content, "utf8"));
|
|
38
44
|
}
|
|
39
45
|
exports.saveRC = saveRC;
|
|
46
|
+
/**
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
40
49
|
async function lockRC() {
|
|
41
50
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
42
51
|
return (0, proper_lockfile_1.lock)(getRCFileName(), {
|
package/dist/fluidToolRC.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fluidToolRC.js","sourceRoot":"","sources":["../src/fluidToolRC.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;AAEH,4CAAoB;AACpB,4CAAoB;AACpB,gDAAwB;AACxB,gDAAwB;AACxB,qDAAuC;
|
|
1
|
+
{"version":3,"file":"fluidToolRC.js","sourceRoot":"","sources":["../src/fluidToolRC.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;AAEH,4CAAoB;AACpB,4CAAoB;AACpB,gDAAwB;AACxB,gDAAwB;AACxB,qDAAuC;AA2BvC,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AAEpE;;GAEG;AACI,KAAK,UAAU,MAAM;IAC3B,MAAM,QAAQ,GAAG,cAAI,CAAC,SAAS,CAAC,YAAE,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,cAAI,CAAC,SAAS,CAAC,YAAE,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;IACjC,IAAI,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE;QAC3B,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACrC,IAAI;YACH,+DAA+D;YAC/D,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;SACxC;QAAC,OAAO,CAAC,EAAE;YACX,UAAU;SACV;KACD;IACD,OAAO,EAAE,CAAC;AACX,CAAC;AAdD,wBAcC;AAED;;GAEG;AACI,KAAK,UAAU,MAAM,CAAC,EAAc;IAC1C,MAAM,SAAS,GAAG,cAAI,CAAC,SAAS,CAAC,YAAE,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;AAJD,wBAIC;AAED;;GAEG;AACI,KAAK,UAAU,MAAM;IAC3B,+DAA+D;IAC/D,OAAO,IAAA,sBAAI,EAAC,aAAa,EAAE,EAAE;QAC5B,OAAO,EAAE;YACR,OAAO,EAAE,IAAI;SACb;QACD,KAAK,EAAE,KAAK;QACZ,QAAQ,EAAE,KAAK;KACf,CAAC,CAAC;AACJ,CAAC;AATD,wBASC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport fs from \"fs\";\nimport os from \"os\";\nimport path from \"path\";\nimport util from \"util\";\nimport { lock } from \"proper-lockfile\";\nimport { IOdspTokens } from \"@fluidframework/odsp-doclib-utils\";\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: {\n\t\t\t[key: string]: {\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 = () => path.join(os.homedir(), \".fluidtoolrc\");\n\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 (e) {\n\t\t\t// Nothing\n\t\t}\n\t}\n\treturn {};\n}\n\n/**\n * @internal\n */\nexport async function saveRC(rc: IResources) {\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/**\n * @internal\n */\nexport async function lockRC() {\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-return\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"]}
|
|
@@ -4,7 +4,13 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { IOdspTokens, IClientConfig } from "@fluidframework/odsp-doclib-utils";
|
|
6
6
|
import { IAsyncCache } from "./fluidToolRC";
|
|
7
|
+
/**
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
7
10
|
export declare const getMicrosoftConfiguration: () => IClientConfig;
|
|
11
|
+
/**
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
8
14
|
export type OdspTokenConfig = {
|
|
9
15
|
type: "password";
|
|
10
16
|
username: string;
|
|
@@ -14,10 +20,16 @@ export type OdspTokenConfig = {
|
|
|
14
20
|
navigator: (url: string) => void;
|
|
15
21
|
redirectUriCallback?: (tokens: IOdspTokens) => Promise<string>;
|
|
16
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* @internal
|
|
25
|
+
*/
|
|
17
26
|
export interface IOdspTokenManagerCacheKey {
|
|
18
27
|
readonly isPush: boolean;
|
|
19
28
|
readonly userOrServer: string;
|
|
20
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* @internal
|
|
32
|
+
*/
|
|
21
33
|
export declare class OdspTokenManager {
|
|
22
34
|
private readonly tokenCache?;
|
|
23
35
|
private readonly storageCache;
|
|
@@ -37,5 +49,8 @@ export declare class OdspTokenManager {
|
|
|
37
49
|
private onTokenRetrievalFromCache;
|
|
38
50
|
private extractAuthorizationCode;
|
|
39
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* @internal
|
|
54
|
+
*/
|
|
40
55
|
export declare const odspTokensCache: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens>;
|
|
41
56
|
//# sourceMappingURL=odspTokenManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspTokenManager.d.ts","sourceRoot":"","sources":["../src/odspTokenManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACN,WAAW,EACX,aAAa,EAOb,MAAM,mCAAmC,CAAC;AAI3C,OAAO,EAAE,WAAW,EAA0B,MAAM,eAAe,CAAC;AAOpE,eAAO,MAAM,yBAAyB,QAAO,aAe3C,CAAC;AAEH,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,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC9B;AAiBD,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,CAAC,GAAG,EAAE,yBAAyB,EAAE,KAAK,EAAE,WAAW;YAMnE,4BAA4B;IAO7B,aAAa,CACzB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,aAAa,EAC3B,WAAW,EAAE,eAAe,EAC5B,YAAY,UAAQ,EACpB,WAAW,UAAQ,GACjB,OAAO,CAAC,WAAW,CAAC;IAIV,aAAa,CACzB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,aAAa,EAC3B,WAAW,EAAE,eAAe,EAC5B,YAAY,UAAQ,EACpB,WAAW,UAAQ,GACjB,OAAO,CAAC,WAAW,CAAC;YAIT,iBAAiB;IAe/B,OAAO,CAAC,MAAM,CAAC,WAAW;YAYZ,SAAS;YA0CT,aAAa;YA+Db,yBAAyB;YAezB,4BAA4B;YAuC5B,yBAAyB;IAMvC,OAAO,CAAC,wBAAwB;CAWhC;AAYD,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,yBAAyB,EAAE,WAAW,CA6B/E,CAAC"}
|
|
1
|
+
{"version":3,"file":"odspTokenManager.d.ts","sourceRoot":"","sources":["../src/odspTokenManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACN,WAAW,EACX,aAAa,EAOb,MAAM,mCAAmC,CAAC;AAI3C,OAAO,EAAE,WAAW,EAA0B,MAAM,eAAe,CAAC;AAOpE;;GAEG;AACH,eAAO,MAAM,yBAAyB,QAAO,aAe3C,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,CAAC,GAAG,EAAE,yBAAyB,EAAE,KAAK,EAAE,WAAW;YAMnE,4BAA4B;IAO7B,aAAa,CACzB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,aAAa,EAC3B,WAAW,EAAE,eAAe,EAC5B,YAAY,UAAQ,EACpB,WAAW,UAAQ,GACjB,OAAO,CAAC,WAAW,CAAC;IAIV,aAAa,CACzB,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,aAAa,EAC3B,WAAW,EAAE,eAAe,EAC5B,YAAY,UAAQ,EACpB,WAAW,UAAQ,GACjB,OAAO,CAAC,WAAW,CAAC;YAIT,iBAAiB;IAe/B,OAAO,CAAC,MAAM,CAAC,WAAW;YAYZ,SAAS;YA0CT,aAAa;YA+Db,yBAAyB;YAezB,4BAA4B;YAuC5B,yBAAyB;IAMvC,OAAO,CAAC,wBAAwB;CAWhC;AAYD;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,yBAAyB,EAAE,WAAW,CA6B/E,CAAC"}
|
package/dist/odspTokenManager.js
CHANGED
|
@@ -3,14 +3,11 @@
|
|
|
3
3
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
4
|
* Licensed under the MIT License.
|
|
5
5
|
*/
|
|
6
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
-
};
|
|
9
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
7
|
exports.odspTokensCache = exports.OdspTokenManager = exports.getMicrosoftConfiguration = void 0;
|
|
11
8
|
const core_utils_1 = require("@fluidframework/core-utils");
|
|
12
9
|
const odsp_doclib_utils_1 = require("@fluidframework/odsp-doclib-utils");
|
|
13
|
-
const jwt_decode_1 =
|
|
10
|
+
const jwt_decode_1 = require("jwt-decode");
|
|
14
11
|
const async_mutex_1 = require("async-mutex");
|
|
15
12
|
const debug_1 = require("./debug");
|
|
16
13
|
const fluidToolRC_1 = require("./fluidToolRC");
|
|
@@ -18,6 +15,9 @@ const httpHelpers_1 = require("./httpHelpers");
|
|
|
18
15
|
const odspAuthRedirectPort = 7000;
|
|
19
16
|
const odspAuthRedirectOrigin = `http://localhost:${odspAuthRedirectPort}`;
|
|
20
17
|
const odspAuthRedirectUri = new URL("/auth/callback", odspAuthRedirectOrigin).href;
|
|
18
|
+
/**
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
21
|
const getMicrosoftConfiguration = () => ({
|
|
22
22
|
get clientId() {
|
|
23
23
|
if (!process.env.login__microsoft__clientId) {
|
|
@@ -38,13 +38,16 @@ const isValidToken = (token) => {
|
|
|
38
38
|
if (!token || token.length === 0) {
|
|
39
39
|
return false;
|
|
40
40
|
}
|
|
41
|
-
const decodedToken = (0, jwt_decode_1.
|
|
41
|
+
const decodedToken = (0, jwt_decode_1.jwtDecode)(token);
|
|
42
42
|
// Give it a 60s buffer
|
|
43
43
|
return decodedToken.exp - 60 >= new Date().getTime() / 1000;
|
|
44
44
|
};
|
|
45
45
|
const cacheKeyToString = (key) => {
|
|
46
46
|
return `${key.userOrServer}${key.isPush ? "[Push]" : ""}`;
|
|
47
47
|
};
|
|
48
|
+
/**
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
48
51
|
class OdspTokenManager {
|
|
49
52
|
constructor(tokenCache) {
|
|
50
53
|
this.tokenCache = tokenCache;
|
|
@@ -220,6 +223,9 @@ async function loadAndPatchRC() {
|
|
|
220
223
|
}
|
|
221
224
|
return rc;
|
|
222
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* @internal
|
|
228
|
+
*/
|
|
223
229
|
exports.odspTokensCache = {
|
|
224
230
|
async get(key) {
|
|
225
231
|
const rc = await loadAndPatchRC();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"odspTokenManager.js","sourceRoot":"","sources":["../src/odspTokenManager.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 { unreachableCase } from \"@fluidframework/core-utils\";\nimport {\n\tIOdspTokens,\n\tIClientConfig,\n\tfetchTokens,\n\trefreshTokens,\n\tgetOdspScope,\n\tpushScope,\n\tgetLoginPageUrl,\n\tTokenRequestCredentials,\n} from \"@fluidframework/odsp-doclib-utils\";\nimport jwtDecode from \"jwt-decode\";\nimport { Mutex } from \"async-mutex\";\nimport { debug } from \"./debug\";\nimport { IAsyncCache, loadRC, saveRC, lockRC } from \"./fluidToolRC\";\nimport { serverListenAndHandle, endResponse } from \"./httpHelpers\";\n\nconst odspAuthRedirectPort = 7000;\nconst odspAuthRedirectOrigin = `http://localhost:${odspAuthRedirectPort}`;\nconst odspAuthRedirectUri = new URL(\"/auth/callback\", odspAuthRedirectOrigin).href;\n\nexport const getMicrosoftConfiguration = (): IClientConfig => ({\n\tget clientId() {\n\t\tif (!process.env.login__microsoft__clientId) {\n\t\t\tthrow new Error(\"Client ID environment variable not set: login__microsoft__clientId.\");\n\t\t}\n\t\treturn process.env.login__microsoft__clientId;\n\t},\n\tget clientSecret() {\n\t\tif (!process.env.login__microsoft__secret) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Client Secret environment variable not set: login__microsoft__secret.\",\n\t\t\t);\n\t\t}\n\t\treturn process.env.login__microsoft__secret;\n\t},\n});\n\nexport type OdspTokenConfig =\n\t| {\n\t\t\ttype: \"password\";\n\t\t\tusername: string;\n\t\t\tpassword: string;\n\t }\n\t| {\n\t\t\ttype: \"browserLogin\";\n\t\t\tnavigator: (url: string) => void;\n\t\t\tredirectUriCallback?: (tokens: IOdspTokens) => Promise<string>;\n\t };\n\nexport interface IOdspTokenManagerCacheKey {\n\treadonly isPush: boolean;\n\treadonly userOrServer: string;\n}\n\nconst isValidToken = (token: string) => {\n\t// Return false for undefined or empty tokens.\n\tif (!token || token.length === 0) {\n\t\treturn false;\n\t}\n\n\tconst decodedToken = jwtDecode<any>(token);\n\t// Give it a 60s buffer\n\treturn decodedToken.exp - 60 >= new Date().getTime() / 1000;\n};\n\nconst cacheKeyToString = (key: IOdspTokenManagerCacheKey) => {\n\treturn `${key.userOrServer}${key.isPush ? \"[Push]\" : \"\"}`;\n};\n\nexport class OdspTokenManager {\n\tprivate readonly storageCache = new Map<string, IOdspTokens>();\n\tprivate readonly pushCache = new Map<string, IOdspTokens>();\n\tprivate readonly cacheMutex = new Mutex();\n\tconstructor(\n\t\tprivate readonly tokenCache?: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens>,\n\t) {}\n\n\tpublic async updateTokensCache(key: IOdspTokenManagerCacheKey, value: IOdspTokens) {\n\t\tawait this.cacheMutex.runExclusive(async () => {\n\t\t\tawait this.updateTokensCacheWithoutLock(key, value);\n\t\t});\n\t}\n\n\tprivate async updateTokensCacheWithoutLock(key: IOdspTokenManagerCacheKey, value: IOdspTokens) {\n\t\tdebug(`${cacheKeyToString(key)}: Saving tokens`);\n\t\tconst memoryCache = key.isPush ? this.pushCache : this.storageCache;\n\t\tmemoryCache.set(key.userOrServer, value);\n\t\tawait this.tokenCache?.save(key, value);\n\t}\n\n\tpublic async getOdspTokens(\n\t\tserver: string,\n\t\tclientConfig: IClientConfig,\n\t\ttokenConfig: OdspTokenConfig,\n\t\tforceRefresh = false,\n\t\tforceReauth = false,\n\t): Promise<IOdspTokens> {\n\t\treturn this.getTokens(false, server, clientConfig, tokenConfig, forceRefresh, forceReauth);\n\t}\n\n\tpublic async getPushTokens(\n\t\tserver: string,\n\t\tclientConfig: IClientConfig,\n\t\ttokenConfig: OdspTokenConfig,\n\t\tforceRefresh = false,\n\t\tforceReauth = false,\n\t): Promise<IOdspTokens> {\n\t\treturn this.getTokens(true, server, clientConfig, tokenConfig, forceRefresh, forceReauth);\n\t}\n\n\tprivate async getTokenFromCache(cacheKey: IOdspTokenManagerCacheKey) {\n\t\tconst memoryCache = cacheKey.isPush ? this.pushCache : this.storageCache;\n\t\tconst memoryToken = memoryCache.get(cacheKey.userOrServer);\n\t\tif (memoryToken) {\n\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token found in memory `);\n\t\t\treturn memoryToken;\n\t\t}\n\t\tconst fileToken = await this.tokenCache?.get(cacheKey);\n\t\tif (fileToken) {\n\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token found in file`);\n\t\t\tmemoryCache.set(cacheKey.userOrServer, fileToken);\n\t\t\treturn fileToken;\n\t\t}\n\t}\n\n\tprivate static getCacheKey(\n\t\tisPush: boolean,\n\t\ttokenConfig: OdspTokenConfig,\n\t\tserver: string,\n\t): IOdspTokenManagerCacheKey {\n\t\t// If we are using password, we should cache the token per user instead of per server\n\t\treturn {\n\t\t\tisPush,\n\t\t\tuserOrServer: tokenConfig.type === \"password\" ? tokenConfig.username : server,\n\t\t};\n\t}\n\n\tprivate async getTokens(\n\t\tisPush: boolean,\n\t\tserver: string,\n\t\tclientConfig: IClientConfig,\n\t\ttokenConfig: OdspTokenConfig,\n\t\tforceRefresh: boolean,\n\t\tforceReauth: boolean,\n\t): Promise<IOdspTokens> {\n\t\tconst invokeGetTokensCore = async () => {\n\t\t\t// Don't solely rely on tokenCache lock, ensure serialized execution of\n\t\t\t// cache update to avoid multiple fetch.\n\t\t\treturn this.cacheMutex.runExclusive(async () => {\n\t\t\t\treturn this.getTokensCore(\n\t\t\t\t\tisPush,\n\t\t\t\t\tserver,\n\t\t\t\t\tclientConfig,\n\t\t\t\t\ttokenConfig,\n\t\t\t\t\tforceRefresh,\n\t\t\t\t\tforceReauth,\n\t\t\t\t);\n\t\t\t});\n\t\t};\n\t\tif (!forceReauth && !forceRefresh) {\n\t\t\t// check and return if it exists without lock\n\t\t\tconst cacheKey = OdspTokenManager.getCacheKey(isPush, tokenConfig, server);\n\t\t\tconst tokensFromCache = await this.getTokenFromCache(cacheKey);\n\t\t\tif (tokensFromCache) {\n\t\t\t\tif (isValidToken(tokensFromCache.accessToken)) {\n\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token reused from cache `);\n\t\t\t\t\tawait this.onTokenRetrievalFromCache(tokenConfig, tokensFromCache);\n\t\t\t\t\treturn tokensFromCache;\n\t\t\t\t}\n\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token expired from cache `);\n\t\t\t}\n\t\t}\n\t\tif (this.tokenCache) {\n\t\t\t// check with lock, used to prevent concurrent auth attempts\n\t\t\treturn this.tokenCache.lock(invokeGetTokensCore);\n\t\t}\n\t\treturn invokeGetTokensCore();\n\t}\n\n\tprivate async getTokensCore(\n\t\tisPush: boolean,\n\t\tserver: string,\n\t\tclientConfig: IClientConfig,\n\t\ttokenConfig: OdspTokenConfig,\n\t\tforceRefresh,\n\t\tforceReauth,\n\t): Promise<IOdspTokens> {\n\t\tconst scope = isPush ? pushScope : getOdspScope(server);\n\t\tconst cacheKey = OdspTokenManager.getCacheKey(isPush, tokenConfig, server);\n\t\tlet tokens: IOdspTokens | undefined;\n\t\tif (!forceReauth) {\n\t\t\t// check the cache again under the lock (if it is there)\n\t\t\tconst tokensFromCache = await this.getTokenFromCache(cacheKey);\n\t\t\tif (tokensFromCache) {\n\t\t\t\tif (forceRefresh || !isValidToken(tokensFromCache.accessToken)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// This updates the tokens in tokensFromCache\n\t\t\t\t\t\ttokens = await refreshTokens(server, scope, clientConfig, tokensFromCache);\n\t\t\t\t\t\tawait this.updateTokensCacheWithoutLock(cacheKey, tokens);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Error in refreshing token. ${error}`);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttokens = tokensFromCache;\n\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token reused from locked cache `);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (tokens) {\n\t\t\tawait this.onTokenRetrievalFromCache(tokenConfig, tokens);\n\t\t\treturn tokens;\n\t\t}\n\n\t\tswitch (tokenConfig.type) {\n\t\t\tcase \"password\":\n\t\t\t\ttokens = await this.acquireTokensWithPassword(\n\t\t\t\t\tserver,\n\t\t\t\t\tscope,\n\t\t\t\t\tclientConfig,\n\t\t\t\t\ttokenConfig.username,\n\t\t\t\t\ttokenConfig.password,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"browserLogin\":\n\t\t\t\ttokens = await this.acquireTokensViaBrowserLogin(\n\t\t\t\t\tgetLoginPageUrl(server, clientConfig, scope, odspAuthRedirectUri),\n\t\t\t\t\tserver,\n\t\t\t\t\tclientConfig,\n\t\t\t\t\tscope,\n\t\t\t\t\ttokenConfig.navigator,\n\t\t\t\t\ttokenConfig.redirectUriCallback,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tunreachableCase(tokenConfig);\n\t\t}\n\n\t\tawait this.updateTokensCacheWithoutLock(cacheKey, tokens);\n\t\treturn tokens;\n\t}\n\n\tprivate async acquireTokensWithPassword(\n\t\tserver: string,\n\t\tscope: string,\n\t\tclientConfig: IClientConfig,\n\t\tusername: string,\n\t\tpassword: string,\n\t): Promise<IOdspTokens> {\n\t\tconst credentials: TokenRequestCredentials = {\n\t\t\tgrant_type: \"password\",\n\t\t\tusername,\n\t\t\tpassword,\n\t\t};\n\t\treturn fetchTokens(server, scope, clientConfig, credentials);\n\t}\n\n\tprivate async acquireTokensViaBrowserLogin(\n\t\tloginPageUrl: string,\n\t\tserver: string,\n\t\tclientConfig: IClientConfig,\n\t\tscope: string,\n\t\tnavigator: (url: string) => void,\n\t\tredirectUriCallback?: (tokens: IOdspTokens) => Promise<string>,\n\t): Promise<IOdspTokens> {\n\t\t// Start up a local auth redirect handler service to receive the tokens after login\n\t\tconst tokenGetter = await serverListenAndHandle(odspAuthRedirectPort, async (req, res) => {\n\t\t\t// extract code from request URL and fetch the tokens\n\t\t\tconst credentials: TokenRequestCredentials = {\n\t\t\t\tgrant_type: \"authorization_code\",\n\t\t\t\tcode: this.extractAuthorizationCode(req.url),\n\t\t\t\tredirect_uri: odspAuthRedirectUri,\n\t\t\t};\n\t\t\tconst tokens = await fetchTokens(server, scope, clientConfig, credentials);\n\n\t\t\t// redirect now that the browser is done with auth\n\t\t\tif (redirectUriCallback) {\n\t\t\t\tres.writeHead(301, { Location: await redirectUriCallback(tokens) });\n\t\t\t\tawait endResponse(res);\n\t\t\t} else {\n\t\t\t\tres.write(\"Please close the window\");\n\t\t\t\tawait endResponse(res);\n\t\t\t}\n\n\t\t\treturn tokens;\n\t\t});\n\n\t\t// Now that our local redirect handler is up, navigate the browser to the login page\n\t\tnavigator(loginPageUrl);\n\n\t\t// Receive and extract the tokens\n\t\tconst odspTokens = await tokenGetter();\n\n\t\treturn odspTokens;\n\t}\n\n\tprivate async onTokenRetrievalFromCache(config: OdspTokenConfig, tokens: IOdspTokens) {\n\t\tif (config.type === \"browserLogin\" && config.redirectUriCallback) {\n\t\t\tconfig.navigator(await config.redirectUriCallback(tokens));\n\t\t}\n\t}\n\n\tprivate extractAuthorizationCode(relativeUrl: string | undefined): string {\n\t\tif (relativeUrl === undefined) {\n\t\t\tthrow Error(\"Failed to get authorization\");\n\t\t}\n\t\tconst parsedUrl = new URL(relativeUrl, odspAuthRedirectOrigin);\n\t\tconst code = parsedUrl.searchParams.get(\"code\");\n\t\tif (!code) {\n\t\t\tthrow Error(\"Failed to get authorization\");\n\t\t}\n\t\treturn code;\n\t}\n}\n\nasync function loadAndPatchRC() {\n\tconst rc = await loadRC();\n\tif (rc.tokens && rc.tokens.version === undefined) {\n\t\t// Clean up older versions\n\t\tdelete (rc as any).tokens;\n\t\tdelete (rc as any).pushTokens;\n\t}\n\treturn rc;\n}\n\nexport const odspTokensCache: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens> = {\n\tasync get(key: IOdspTokenManagerCacheKey): Promise<IOdspTokens | undefined> {\n\t\tconst rc = await loadAndPatchRC();\n\t\treturn rc.tokens?.data[key.userOrServer]?.[key.isPush ? \"push\" : \"storage\"];\n\t},\n\tasync save(key: IOdspTokenManagerCacheKey, tokens: IOdspTokens): Promise<void> {\n\t\tconst rc = await loadAndPatchRC();\n\t\tif (!rc.tokens) {\n\t\t\trc.tokens = {\n\t\t\t\tversion: 1,\n\t\t\t\tdata: {},\n\t\t\t};\n\t\t}\n\t\tlet prevTokens = rc.tokens.data[key.userOrServer];\n\t\tif (!prevTokens) {\n\t\t\tprevTokens = {};\n\t\t\trc.tokens.data[key.userOrServer] = prevTokens;\n\t\t}\n\t\tprevTokens[key.isPush ? \"push\" : \"storage\"] = tokens;\n\t\treturn saveRC(rc);\n\t},\n\tasync lock<T>(callback: () => Promise<T>): Promise<T> {\n\t\tconst release = await lockRC();\n\t\ttry {\n\t\t\treturn await callback();\n\t\t} finally {\n\t\t\tawait release();\n\t\t}\n\t},\n};\n"]}
|
|
1
|
+
{"version":3,"file":"odspTokenManager.js","sourceRoot":"","sources":["../src/odspTokenManager.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 { unreachableCase } from \"@fluidframework/core-utils\";\nimport {\n\tIOdspTokens,\n\tIClientConfig,\n\tfetchTokens,\n\trefreshTokens,\n\tgetOdspScope,\n\tpushScope,\n\tgetLoginPageUrl,\n\tTokenRequestCredentials,\n} from \"@fluidframework/odsp-doclib-utils\";\nimport { jwtDecode } from \"jwt-decode\";\nimport { Mutex } from \"async-mutex\";\nimport { debug } from \"./debug\";\nimport { IAsyncCache, loadRC, saveRC, lockRC } from \"./fluidToolRC\";\nimport { serverListenAndHandle, endResponse } from \"./httpHelpers\";\n\nconst odspAuthRedirectPort = 7000;\nconst odspAuthRedirectOrigin = `http://localhost:${odspAuthRedirectPort}`;\nconst odspAuthRedirectUri = new URL(\"/auth/callback\", odspAuthRedirectOrigin).href;\n\n/**\n * @internal\n */\nexport const getMicrosoftConfiguration = (): IClientConfig => ({\n\tget clientId() {\n\t\tif (!process.env.login__microsoft__clientId) {\n\t\t\tthrow new Error(\"Client ID environment variable not set: login__microsoft__clientId.\");\n\t\t}\n\t\treturn process.env.login__microsoft__clientId;\n\t},\n\tget clientSecret() {\n\t\tif (!process.env.login__microsoft__secret) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Client Secret environment variable not set: login__microsoft__secret.\",\n\t\t\t);\n\t\t}\n\t\treturn process.env.login__microsoft__secret;\n\t},\n});\n\n/**\n * @internal\n */\nexport type OdspTokenConfig =\n\t| {\n\t\t\ttype: \"password\";\n\t\t\tusername: string;\n\t\t\tpassword: string;\n\t }\n\t| {\n\t\t\ttype: \"browserLogin\";\n\t\t\tnavigator: (url: string) => void;\n\t\t\tredirectUriCallback?: (tokens: IOdspTokens) => Promise<string>;\n\t };\n\n/**\n * @internal\n */\nexport interface IOdspTokenManagerCacheKey {\n\treadonly isPush: boolean;\n\treadonly userOrServer: string;\n}\n\nconst isValidToken = (token: string) => {\n\t// Return false for undefined or empty tokens.\n\tif (!token || token.length === 0) {\n\t\treturn false;\n\t}\n\n\tconst decodedToken = jwtDecode<any>(token);\n\t// Give it a 60s buffer\n\treturn decodedToken.exp - 60 >= new Date().getTime() / 1000;\n};\n\nconst cacheKeyToString = (key: IOdspTokenManagerCacheKey) => {\n\treturn `${key.userOrServer}${key.isPush ? \"[Push]\" : \"\"}`;\n};\n\n/**\n * @internal\n */\nexport class OdspTokenManager {\n\tprivate readonly storageCache = new Map<string, IOdspTokens>();\n\tprivate readonly pushCache = new Map<string, IOdspTokens>();\n\tprivate readonly cacheMutex = new Mutex();\n\tconstructor(\n\t\tprivate readonly tokenCache?: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens>,\n\t) {}\n\n\tpublic async updateTokensCache(key: IOdspTokenManagerCacheKey, value: IOdspTokens) {\n\t\tawait this.cacheMutex.runExclusive(async () => {\n\t\t\tawait this.updateTokensCacheWithoutLock(key, value);\n\t\t});\n\t}\n\n\tprivate async updateTokensCacheWithoutLock(key: IOdspTokenManagerCacheKey, value: IOdspTokens) {\n\t\tdebug(`${cacheKeyToString(key)}: Saving tokens`);\n\t\tconst memoryCache = key.isPush ? this.pushCache : this.storageCache;\n\t\tmemoryCache.set(key.userOrServer, value);\n\t\tawait this.tokenCache?.save(key, value);\n\t}\n\n\tpublic async getOdspTokens(\n\t\tserver: string,\n\t\tclientConfig: IClientConfig,\n\t\ttokenConfig: OdspTokenConfig,\n\t\tforceRefresh = false,\n\t\tforceReauth = false,\n\t): Promise<IOdspTokens> {\n\t\treturn this.getTokens(false, server, clientConfig, tokenConfig, forceRefresh, forceReauth);\n\t}\n\n\tpublic async getPushTokens(\n\t\tserver: string,\n\t\tclientConfig: IClientConfig,\n\t\ttokenConfig: OdspTokenConfig,\n\t\tforceRefresh = false,\n\t\tforceReauth = false,\n\t): Promise<IOdspTokens> {\n\t\treturn this.getTokens(true, server, clientConfig, tokenConfig, forceRefresh, forceReauth);\n\t}\n\n\tprivate async getTokenFromCache(cacheKey: IOdspTokenManagerCacheKey) {\n\t\tconst memoryCache = cacheKey.isPush ? this.pushCache : this.storageCache;\n\t\tconst memoryToken = memoryCache.get(cacheKey.userOrServer);\n\t\tif (memoryToken) {\n\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token found in memory `);\n\t\t\treturn memoryToken;\n\t\t}\n\t\tconst fileToken = await this.tokenCache?.get(cacheKey);\n\t\tif (fileToken) {\n\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token found in file`);\n\t\t\tmemoryCache.set(cacheKey.userOrServer, fileToken);\n\t\t\treturn fileToken;\n\t\t}\n\t}\n\n\tprivate static getCacheKey(\n\t\tisPush: boolean,\n\t\ttokenConfig: OdspTokenConfig,\n\t\tserver: string,\n\t): IOdspTokenManagerCacheKey {\n\t\t// If we are using password, we should cache the token per user instead of per server\n\t\treturn {\n\t\t\tisPush,\n\t\t\tuserOrServer: tokenConfig.type === \"password\" ? tokenConfig.username : server,\n\t\t};\n\t}\n\n\tprivate async getTokens(\n\t\tisPush: boolean,\n\t\tserver: string,\n\t\tclientConfig: IClientConfig,\n\t\ttokenConfig: OdspTokenConfig,\n\t\tforceRefresh: boolean,\n\t\tforceReauth: boolean,\n\t): Promise<IOdspTokens> {\n\t\tconst invokeGetTokensCore = async () => {\n\t\t\t// Don't solely rely on tokenCache lock, ensure serialized execution of\n\t\t\t// cache update to avoid multiple fetch.\n\t\t\treturn this.cacheMutex.runExclusive(async () => {\n\t\t\t\treturn this.getTokensCore(\n\t\t\t\t\tisPush,\n\t\t\t\t\tserver,\n\t\t\t\t\tclientConfig,\n\t\t\t\t\ttokenConfig,\n\t\t\t\t\tforceRefresh,\n\t\t\t\t\tforceReauth,\n\t\t\t\t);\n\t\t\t});\n\t\t};\n\t\tif (!forceReauth && !forceRefresh) {\n\t\t\t// check and return if it exists without lock\n\t\t\tconst cacheKey = OdspTokenManager.getCacheKey(isPush, tokenConfig, server);\n\t\t\tconst tokensFromCache = await this.getTokenFromCache(cacheKey);\n\t\t\tif (tokensFromCache) {\n\t\t\t\tif (isValidToken(tokensFromCache.accessToken)) {\n\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token reused from cache `);\n\t\t\t\t\tawait this.onTokenRetrievalFromCache(tokenConfig, tokensFromCache);\n\t\t\t\t\treturn tokensFromCache;\n\t\t\t\t}\n\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token expired from cache `);\n\t\t\t}\n\t\t}\n\t\tif (this.tokenCache) {\n\t\t\t// check with lock, used to prevent concurrent auth attempts\n\t\t\treturn this.tokenCache.lock(invokeGetTokensCore);\n\t\t}\n\t\treturn invokeGetTokensCore();\n\t}\n\n\tprivate async getTokensCore(\n\t\tisPush: boolean,\n\t\tserver: string,\n\t\tclientConfig: IClientConfig,\n\t\ttokenConfig: OdspTokenConfig,\n\t\tforceRefresh,\n\t\tforceReauth,\n\t): Promise<IOdspTokens> {\n\t\tconst scope = isPush ? pushScope : getOdspScope(server);\n\t\tconst cacheKey = OdspTokenManager.getCacheKey(isPush, tokenConfig, server);\n\t\tlet tokens: IOdspTokens | undefined;\n\t\tif (!forceReauth) {\n\t\t\t// check the cache again under the lock (if it is there)\n\t\t\tconst tokensFromCache = await this.getTokenFromCache(cacheKey);\n\t\t\tif (tokensFromCache) {\n\t\t\t\tif (forceRefresh || !isValidToken(tokensFromCache.accessToken)) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// This updates the tokens in tokensFromCache\n\t\t\t\t\t\ttokens = await refreshTokens(server, scope, clientConfig, tokensFromCache);\n\t\t\t\t\t\tawait this.updateTokensCacheWithoutLock(cacheKey, tokens);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Error in refreshing token. ${error}`);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttokens = tokensFromCache;\n\t\t\t\t\tdebug(`${cacheKeyToString(cacheKey)}: Token reused from locked cache `);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (tokens) {\n\t\t\tawait this.onTokenRetrievalFromCache(tokenConfig, tokens);\n\t\t\treturn tokens;\n\t\t}\n\n\t\tswitch (tokenConfig.type) {\n\t\t\tcase \"password\":\n\t\t\t\ttokens = await this.acquireTokensWithPassword(\n\t\t\t\t\tserver,\n\t\t\t\t\tscope,\n\t\t\t\t\tclientConfig,\n\t\t\t\t\ttokenConfig.username,\n\t\t\t\t\ttokenConfig.password,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"browserLogin\":\n\t\t\t\ttokens = await this.acquireTokensViaBrowserLogin(\n\t\t\t\t\tgetLoginPageUrl(server, clientConfig, scope, odspAuthRedirectUri),\n\t\t\t\t\tserver,\n\t\t\t\t\tclientConfig,\n\t\t\t\t\tscope,\n\t\t\t\t\ttokenConfig.navigator,\n\t\t\t\t\ttokenConfig.redirectUriCallback,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tunreachableCase(tokenConfig);\n\t\t}\n\n\t\tawait this.updateTokensCacheWithoutLock(cacheKey, tokens);\n\t\treturn tokens;\n\t}\n\n\tprivate async acquireTokensWithPassword(\n\t\tserver: string,\n\t\tscope: string,\n\t\tclientConfig: IClientConfig,\n\t\tusername: string,\n\t\tpassword: string,\n\t): Promise<IOdspTokens> {\n\t\tconst credentials: TokenRequestCredentials = {\n\t\t\tgrant_type: \"password\",\n\t\t\tusername,\n\t\t\tpassword,\n\t\t};\n\t\treturn fetchTokens(server, scope, clientConfig, credentials);\n\t}\n\n\tprivate async acquireTokensViaBrowserLogin(\n\t\tloginPageUrl: string,\n\t\tserver: string,\n\t\tclientConfig: IClientConfig,\n\t\tscope: string,\n\t\tnavigator: (url: string) => void,\n\t\tredirectUriCallback?: (tokens: IOdspTokens) => Promise<string>,\n\t): Promise<IOdspTokens> {\n\t\t// Start up a local auth redirect handler service to receive the tokens after login\n\t\tconst tokenGetter = await serverListenAndHandle(odspAuthRedirectPort, async (req, res) => {\n\t\t\t// extract code from request URL and fetch the tokens\n\t\t\tconst credentials: TokenRequestCredentials = {\n\t\t\t\tgrant_type: \"authorization_code\",\n\t\t\t\tcode: this.extractAuthorizationCode(req.url),\n\t\t\t\tredirect_uri: odspAuthRedirectUri,\n\t\t\t};\n\t\t\tconst tokens = await fetchTokens(server, scope, clientConfig, credentials);\n\n\t\t\t// redirect now that the browser is done with auth\n\t\t\tif (redirectUriCallback) {\n\t\t\t\tres.writeHead(301, { Location: await redirectUriCallback(tokens) });\n\t\t\t\tawait endResponse(res);\n\t\t\t} else {\n\t\t\t\tres.write(\"Please close the window\");\n\t\t\t\tawait endResponse(res);\n\t\t\t}\n\n\t\t\treturn tokens;\n\t\t});\n\n\t\t// Now that our local redirect handler is up, navigate the browser to the login page\n\t\tnavigator(loginPageUrl);\n\n\t\t// Receive and extract the tokens\n\t\tconst odspTokens = await tokenGetter();\n\n\t\treturn odspTokens;\n\t}\n\n\tprivate async onTokenRetrievalFromCache(config: OdspTokenConfig, tokens: IOdspTokens) {\n\t\tif (config.type === \"browserLogin\" && config.redirectUriCallback) {\n\t\t\tconfig.navigator(await config.redirectUriCallback(tokens));\n\t\t}\n\t}\n\n\tprivate extractAuthorizationCode(relativeUrl: string | undefined): string {\n\t\tif (relativeUrl === undefined) {\n\t\t\tthrow Error(\"Failed to get authorization\");\n\t\t}\n\t\tconst parsedUrl = new URL(relativeUrl, odspAuthRedirectOrigin);\n\t\tconst code = parsedUrl.searchParams.get(\"code\");\n\t\tif (!code) {\n\t\t\tthrow Error(\"Failed to get authorization\");\n\t\t}\n\t\treturn code;\n\t}\n}\n\nasync function loadAndPatchRC() {\n\tconst rc = await loadRC();\n\tif (rc.tokens && rc.tokens.version === undefined) {\n\t\t// Clean up older versions\n\t\tdelete (rc as any).tokens;\n\t\tdelete (rc as any).pushTokens;\n\t}\n\treturn rc;\n}\n\n/**\n * @internal\n */\nexport const odspTokensCache: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens> = {\n\tasync get(key: IOdspTokenManagerCacheKey): Promise<IOdspTokens | undefined> {\n\t\tconst rc = await loadAndPatchRC();\n\t\treturn rc.tokens?.data[key.userOrServer]?.[key.isPush ? \"push\" : \"storage\"];\n\t},\n\tasync save(key: IOdspTokenManagerCacheKey, tokens: IOdspTokens): Promise<void> {\n\t\tconst rc = await loadAndPatchRC();\n\t\tif (!rc.tokens) {\n\t\t\trc.tokens = {\n\t\t\t\tversion: 1,\n\t\t\t\tdata: {},\n\t\t\t};\n\t\t}\n\t\tlet prevTokens = rc.tokens.data[key.userOrServer];\n\t\tif (!prevTokens) {\n\t\t\tprevTokens = {};\n\t\t\trc.tokens.data[key.userOrServer] = prevTokens;\n\t\t}\n\t\tprevTokens[key.isPush ? \"push\" : \"storage\"] = tokens;\n\t\treturn saveRC(rc);\n\t},\n\tasync lock<T>(callback: () => Promise<T>): Promise<T> {\n\t\tconst release = await lockRC();\n\t\ttry {\n\t\t\treturn await callback();\n\t\t} finally {\n\t\t\tawait release();\n\t\t}\n\t},\n};\n"]}
|
package/dist/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluidframework/tool-utils";
|
|
8
|
-
export declare const pkgVersion = "2.0.0-internal.7.
|
|
8
|
+
export declare const pkgVersion = "2.0.0-internal.7.4.0";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/dist/packageVersion.js
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.pkgVersion = exports.pkgName = void 0;
|
|
10
10
|
exports.pkgName = "@fluidframework/tool-utils";
|
|
11
|
-
exports.pkgVersion = "2.0.0-internal.7.
|
|
11
|
+
exports.pkgVersion = "2.0.0-internal.7.4.0";
|
|
12
12
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,4BAA4B,CAAC;AACvC,QAAA,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/tool-utils\";\nexport const pkgVersion = \"2.0.0-internal.7.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,4BAA4B,CAAC;AACvC,QAAA,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/tool-utils\";\nexport const pkgVersion = \"2.0.0-internal.7.4.0\";\n"]}
|
|
@@ -3,8 +3,15 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import { ITree } from "@fluidframework/protocol-definitions";
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* The prefix that all GC blob names start with.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
7
11
|
export declare const gcBlobPrefix = "__gc";
|
|
12
|
+
/**
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
8
15
|
export interface ISnapshotNormalizerConfig {
|
|
9
16
|
blobsToNormalize?: string[];
|
|
10
17
|
/**
|
|
@@ -22,6 +29,7 @@ export interface ISnapshotNormalizerConfig {
|
|
|
22
29
|
* @param config - Configs to use when normalizing snapshot. For example, it can contain paths of blobs whose contents
|
|
23
30
|
* should be normalized as well.
|
|
24
31
|
* @returns a copy of the normalized snapshot tree.
|
|
32
|
+
* @internal
|
|
25
33
|
*/
|
|
26
34
|
export declare function getNormalizedSnapshot(snapshot: ITree, config?: ISnapshotNormalizerConfig): ITree;
|
|
27
35
|
//# sourceMappingURL=snapshotNormalizer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snapshotNormalizer.d.ts","sourceRoot":"","sources":["../src/snapshotNormalizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,KAAK,EAAyB,MAAM,sCAAsC,CAAC;AAIpF
|
|
1
|
+
{"version":3,"file":"snapshotNormalizer.d.ts","sourceRoot":"","sources":["../src/snapshotNormalizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,KAAK,EAAyB,MAAM,sCAAsC,CAAC;AAIpF;;;;GAIG;AACH,eAAO,MAAM,YAAY,SAAS,CAAC;AAEnC;;GAEG;AACH,MAAM,WAAW,yBAAyB;IAEzC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B;;;;OAIG;IACH,2BAA2B,CAAC,EAAE,MAAM,EAAE,CAAC;CACvC;AAwGD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,yBAAyB,GAAG,KAAK,CAkBhG"}
|
|
@@ -9,7 +9,11 @@ const driver_utils_1 = require("@fluidframework/driver-utils");
|
|
|
9
9
|
const protocol_definitions_1 = require("@fluidframework/protocol-definitions");
|
|
10
10
|
/** The name of the metadata blob added to the root of the container runtime. */
|
|
11
11
|
const metadataBlobName = ".metadata";
|
|
12
|
-
/**
|
|
12
|
+
/**
|
|
13
|
+
* The prefix that all GC blob names start with.
|
|
14
|
+
*
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
13
17
|
exports.gcBlobPrefix = "__gc";
|
|
14
18
|
/**
|
|
15
19
|
* Function that deep sorts an array. It handles cases where array elements are objects or arrays.
|
|
@@ -119,6 +123,7 @@ function getNormalizedBlobContent(blobContent, blobName) {
|
|
|
119
123
|
* @param config - Configs to use when normalizing snapshot. For example, it can contain paths of blobs whose contents
|
|
120
124
|
* should be normalized as well.
|
|
121
125
|
* @returns a copy of the normalized snapshot tree.
|
|
126
|
+
* @internal
|
|
122
127
|
*/
|
|
123
128
|
function getNormalizedSnapshot(snapshot, config) {
|
|
124
129
|
// Merge blobs to normalize in the config with runtime blobs to normalize. The contents of these blobs will be
|
|
@@ -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 { AttachmentTreeEntry, BlobTreeEntry, TreeTreeEntry } from \"@fluidframework/driver-utils\";\nimport { ITree, TreeEntry, ITreeEntry } from \"@fluidframework/protocol-definitions\";\n\n/** The name of the metadata blob added to the root of the container runtime. */\nconst metadataBlobName = \".metadata\";\n/** The prefix that all GC blob names start with. */\nexport const gcBlobPrefix = \"__gc\";\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\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 */\nexport function getNormalizedSnapshot(snapshot: ITree, config?: ISnapshotNormalizerConfig): 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(\n\t\t\t\t\t\t\tmaybeAttributes.value.contents,\n\t\t\t\t\t\t);\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 { AttachmentTreeEntry, BlobTreeEntry, TreeTreeEntry } from \"@fluidframework/driver-utils\";\nimport { ITree, TreeEntry, ITreeEntry } from \"@fluidframework/protocol-definitions\";\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\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(snapshot: ITree, config?: ISnapshotNormalizerConfig): 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(\n\t\t\t\t\t\t\tmaybeAttributes.value.contents,\n\t\t\t\t\t\t);\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"]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { IClientConfig } from '@fluidframework/odsp-doclib-utils';
|
|
2
|
+
import { IOdspTokens } from '@fluidframework/odsp-doclib-utils';
|
|
3
|
+
import { ITree } from '@fluidframework/protocol-definitions';
|
|
4
|
+
|
|
5
|
+
/* Excluded from this release type: gcBlobPrefix */
|
|
6
|
+
|
|
7
|
+
/* Excluded from this release type: getMicrosoftConfiguration */
|
|
8
|
+
|
|
9
|
+
/* Excluded from this release type: getNormalizedSnapshot */
|
|
10
|
+
|
|
11
|
+
/* Excluded from this release type: IAsyncCache */
|
|
12
|
+
|
|
13
|
+
/* Excluded from this release type: IClientConfig */
|
|
14
|
+
|
|
15
|
+
/* Excluded from this release type: IOdspTokenManagerCacheKey */
|
|
16
|
+
|
|
17
|
+
/* Excluded from this release type: IOdspTokens */
|
|
18
|
+
|
|
19
|
+
/* Excluded from this release type: IResources */
|
|
20
|
+
|
|
21
|
+
/* Excluded from this release type: ISnapshotNormalizerConfig */
|
|
22
|
+
|
|
23
|
+
/* Excluded from this release type: loadRC */
|
|
24
|
+
|
|
25
|
+
/* Excluded from this release type: lockRC */
|
|
26
|
+
|
|
27
|
+
/* Excluded from this release type: OdspTokenConfig */
|
|
28
|
+
|
|
29
|
+
/* Excluded from this release type: OdspTokenManager */
|
|
30
|
+
|
|
31
|
+
/* Excluded from this release type: odspTokensCache */
|
|
32
|
+
|
|
33
|
+
/* Excluded from this release type: saveRC */
|
|
34
|
+
|
|
35
|
+
export { }
|