@fluidframework/tool-utils 2.0.0-internal.3.0.2 → 2.0.0-internal.3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +19 -23
- package/.mocharc.js +2 -2
- package/api-extractor.json +2 -2
- package/dist/fluidToolRC.d.ts.map +1 -1
- package/dist/fluidToolRC.js.map +1 -1
- package/dist/httpHelpers.d.ts.map +1 -1
- package/dist/httpHelpers.js +6 -2
- package/dist/httpHelpers.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/odspTokenManager.d.ts.map +1 -1
- package/dist/odspTokenManager.js +5 -2
- 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.map +1 -1
- package/dist/snapshotNormalizer.js +13 -10
- package/dist/snapshotNormalizer.js.map +1 -1
- package/lib/fluidToolRC.d.ts.map +1 -1
- package/lib/fluidToolRC.js.map +1 -1
- package/lib/httpHelpers.d.ts.map +1 -1
- package/lib/httpHelpers.js +6 -2
- package/lib/httpHelpers.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/odspTokenManager.d.ts.map +1 -1
- package/lib/odspTokenManager.js +5 -2
- 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.map +1 -1
- package/lib/snapshotNormalizer.js +14 -11
- package/lib/snapshotNormalizer.js.map +1 -1
- package/package.json +40 -39
- package/prettier.config.cjs +1 -1
- package/src/fluidToolRC.ts +36 -36
- package/src/httpHelpers.ts +58 -44
- package/src/index.ts +5 -1
- package/src/odspTokenManager.ts +301 -309
- package/src/packageVersion.ts +1 -1
- package/src/snapshotNormalizer.ts +178 -171
- package/tsconfig.esnext.json +6 -6
- package/tsconfig.json +10 -16
package/.eslintrc.js
CHANGED
|
@@ -4,26 +4,22 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
module.exports = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
],
|
|
28
|
-
}
|
|
29
|
-
}
|
|
7
|
+
extends: [require.resolve("@fluidframework/eslint-config-fluid/minimal"), "prettier"],
|
|
8
|
+
parserOptions: {
|
|
9
|
+
project: ["./tsconfig.json", "./src/test/tsconfig.json"],
|
|
10
|
+
},
|
|
11
|
+
rules: {
|
|
12
|
+
"@typescript-eslint/strict-boolean-expressions": "off",
|
|
13
|
+
"import/no-nodejs-modules": "off",
|
|
14
|
+
"unicorn/filename-case": [
|
|
15
|
+
"error",
|
|
16
|
+
{
|
|
17
|
+
cases: {
|
|
18
|
+
camelCase: true,
|
|
19
|
+
pascalCase: true,
|
|
20
|
+
},
|
|
21
|
+
ignore: [/.*fluidToolRC\.ts$/],
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
};
|
package/.mocharc.js
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
"use strict";
|
|
7
7
|
|
|
8
|
-
const getFluidTestMochaConfig = require(
|
|
8
|
+
const getFluidTestMochaConfig = require("@fluidframework/mocha-test-setup/mocharc-common");
|
|
9
9
|
|
|
10
10
|
const packageDir = __dirname;
|
|
11
11
|
const config = getFluidTestMochaConfig(packageDir);
|
package/api-extractor.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
|
3
|
+
"extends": "@fluidframework/build-common/api-extractor-common-report.json"
|
|
4
4
|
}
|
|
@@ -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;
|
|
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"}
|
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;AAqBvC,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AAE7D,KAAK,UAAU,MAAM;
|
|
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;AAqBvC,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,cAAI,CAAC,IAAI,CAAC,YAAE,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AAE7D,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;AAEM,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;AAEM,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\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\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\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\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\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"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpHelpers.d.ts","sourceRoot":"","sources":["../src/httpHelpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAE7B,MAAM,WAAW,kBAAkB;
|
|
1
|
+
{"version":3,"file":"httpHelpers.d.ts","sourceRoot":"","sources":["../src/httpHelpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAE7B,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;AACD,wBAAgB,mBAAmB,CAClC,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,IAAI,CAAC,eAAe,GACnC,kBAAkB,CAiBpB;AACD,oBAAY,mBAAmB,CAAC,CAAC,IAAI,CACpC,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,KACpB,OAAO,CAAC,CAAC,CAAC,CAAC;AAChB,oBAAY,kBAAkB,CAAC,CAAC,IAAI,OAAO,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,eAAO,MAAM,qBAAqB,YAC3B,MAAM,2DAuBV,CAAC;AAEJ,eAAO,MAAM,WAAW,aAAoB,KAAK,cAAc,KAAG,QAAQ,IAAI,CAO3E,CAAC"}
|
package/dist/httpHelpers.js
CHANGED
|
@@ -17,7 +17,9 @@ function createTrackedServer(port, requestListener) {
|
|
|
17
17
|
socket.on("close", () => sockets.delete(socket));
|
|
18
18
|
});
|
|
19
19
|
return {
|
|
20
|
-
server,
|
|
20
|
+
server,
|
|
21
|
+
sockets,
|
|
22
|
+
fullyClose() {
|
|
21
23
|
server.close();
|
|
22
24
|
sockets.forEach((socket) => socket.destroy());
|
|
23
25
|
},
|
|
@@ -36,7 +38,9 @@ new Promise((outerResolve, outerReject) => {
|
|
|
36
38
|
res.end();
|
|
37
39
|
return;
|
|
38
40
|
}
|
|
39
|
-
handler(req, res)
|
|
41
|
+
handler(req, res)
|
|
42
|
+
.finally(() => httpServer.fullyClose())
|
|
43
|
+
.then((result) => innerResolve(result), (error) => innerReject(error));
|
|
40
44
|
});
|
|
41
45
|
outerResolve(async () => innerP);
|
|
42
46
|
});
|
package/dist/httpHelpers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpHelpers.js","sourceRoot":"","sources":["../src/httpHelpers.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;AAEH,gDAAwB;AAQxB,SAAgB,mBAAmB,
|
|
1
|
+
{"version":3,"file":"httpHelpers.js","sourceRoot":"","sources":["../src/httpHelpers.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;AAEH,gDAAwB;AAQxB,SAAgB,mBAAmB,CAClC,IAAY,EACZ,eAAqC;IAErC,MAAM,MAAM,GAAG,cAAI,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/D,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,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/C,CAAC;KACD,CAAC;AACH,CAAC;AApBD,kDAoBC;AAMM,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,+CAA+C;IAC/C,MAAM,MAAM,GAAG,IAAI,OAAO,CAAI,CAAC,YAAY,EAAE,WAAW,EAAE,EAAE;QAC3D,MAAM,UAAU,GAAG,mBAAmB,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YACzD,iBAAiB;YACjB,IAAI,GAAG,CAAC,GAAG,KAAK,cAAc,EAAE;gBAC/B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC,CAAC;gBACvD,GAAG,CAAC,GAAG,EAAE,CAAC;gBACV,OAAO;aACP;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;AAxBS,QAAA,qBAAqB,yBAwB9B;AAEG,MAAM,WAAW,GAAG,KAAK,EAAE,QAA6B,EAAiB,EAAE,CACjF,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IAC/B,IAAI;QACH,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;KACtB;IAAC,OAAO,KAAK,EAAE;QACf,MAAM,CAAC,KAAK,CAAC,CAAC;KACd;AACF,CAAC,CAAC,CAAC;AAPS,QAAA,WAAW,eAOpB","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport http from \"http\";\nimport { Socket } from \"net\";\n\nexport interface ITrackedHttpServer {\n\treadonly server: http.Server;\n\treadonly sockets: Set<Socket>;\n\tfullyClose(): void;\n}\nexport function createTrackedServer(\n\tport: number,\n\trequestListener: http.RequestListener,\n): ITrackedHttpServer {\n\tconst server = http.createServer(requestListener).listen(port);\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() {\n\t\t\tserver.close();\n\t\t\tsockets.forEach((socket) => socket.destroy());\n\t\t},\n\t};\n}\nexport type OnceListenerHandler<T> = (\n\treq: http.IncomingMessage,\n\tres: http.ServerResponse,\n) => Promise<T>;\nexport type OnceListenerResult<T> = Promise<() => Promise<T>>;\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\n\t\tconst innerP = new Promise<T>((innerResolve, innerReject) => {\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\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/dist/index.d.ts
CHANGED
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { IAsyncCache, IResources, loadRC, lockRC, saveRC } from "./fluidToolRC";
|
|
6
6
|
export { getMicrosoftConfiguration, IOdspTokenManagerCacheKey, OdspTokenConfig, OdspTokenManager, odspTokensCache, } from "./odspTokenManager";
|
|
7
|
-
export { gcBlobPrefix, getNormalizedSnapshot, ISnapshotNormalizerConfig } from "./snapshotNormalizer";
|
|
7
|
+
export { gcBlobPrefix, getNormalizedSnapshot, ISnapshotNormalizerConfig, } from "./snapshotNormalizer";
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EACN,yBAAyB,EACzB,yBAAyB,EACzB,eAAe,EACf,gBAAgB,EAChB,eAAe,GACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EACN,yBAAyB,EACzB,yBAAyB,EACzB,eAAe,EACf,gBAAgB,EAChB,eAAe,GACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACN,YAAY,EACZ,qBAAqB,EACrB,yBAAyB,GACzB,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,6CAAgF;AAA9C,qGAAA,MAAM,OAAA;AAAE,qGAAA,MAAM,OAAA;AAAE,qGAAA,MAAM,OAAA;AACxD,uDAM4B;AAL3B,6HAAA,yBAAyB,OAAA;AAGzB,oHAAA,gBAAgB,OAAA;AAChB,mHAAA,eAAe,OAAA;AAEhB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,6CAAgF;AAA9C,qGAAA,MAAM,OAAA;AAAE,qGAAA,MAAM,OAAA;AAAE,qGAAA,MAAM,OAAA;AACxD,uDAM4B;AAL3B,6HAAA,yBAAyB,OAAA;AAGzB,oHAAA,gBAAgB,OAAA;AAChB,mHAAA,eAAe,OAAA;AAEhB,2DAI8B;AAH7B,kHAAA,YAAY,OAAA;AACZ,2HAAA,qBAAqB,OAAA","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport { IAsyncCache, IResources, loadRC, lockRC, saveRC } from \"./fluidToolRC\";\nexport {\n\tgetMicrosoftConfiguration,\n\tIOdspTokenManagerCacheKey,\n\tOdspTokenConfig,\n\tOdspTokenManager,\n\todspTokensCache,\n} from \"./odspTokenManager\";\nexport {\n\tgcBlobPrefix,\n\tgetNormalizedSnapshot,\n\tISnapshotNormalizerConfig,\n} from \"./snapshotNormalizer\";\n"]}
|
|
@@ -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,EACN,WAAW,EACX,aAAa,EAOb,MAAM,mCAAmC,CAAC;AAI3C,OAAO,EAAE,WAAW,EAA0B,MAAM,eAAe,CAAC;AAOpE,eAAO,MAAM,yBAAyB,QAAO,aAe3C,CAAC;AAEH,oBAAY,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"}
|
package/dist/odspTokenManager.js
CHANGED
|
@@ -40,7 +40,7 @@ const isValidToken = (token) => {
|
|
|
40
40
|
}
|
|
41
41
|
const decodedToken = (0, jwt_decode_1.default)(token);
|
|
42
42
|
// Give it a 60s buffer
|
|
43
|
-
return
|
|
43
|
+
return decodedToken.exp - 60 >= new Date().getTime() / 1000;
|
|
44
44
|
};
|
|
45
45
|
const cacheKeyToString = (key) => {
|
|
46
46
|
return `${key.userOrServer}${key.isPush ? "[Push]" : ""}`;
|
|
@@ -87,7 +87,10 @@ class OdspTokenManager {
|
|
|
87
87
|
}
|
|
88
88
|
static getCacheKey(isPush, tokenConfig, server) {
|
|
89
89
|
// If we are using password, we should cache the token per user instead of per server
|
|
90
|
-
return {
|
|
90
|
+
return {
|
|
91
|
+
isPush,
|
|
92
|
+
userOrServer: tokenConfig.type === "password" ? tokenConfig.username : server,
|
|
93
|
+
};
|
|
91
94
|
}
|
|
92
95
|
async getTokens(isPush, server, clientConfig, tokenConfig, forceRefresh, forceReauth) {
|
|
93
96
|
const invokeGetTokensCore = async () => {
|
|
@@ -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/common-utils\";\nimport {\n IOdspTokens,\n IClientConfig,\n fetchTokens,\n refreshTokens,\n getOdspScope,\n pushScope,\n getLoginPageUrl,\n TokenRequestCredentials,\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 get clientId() {\n if (!process.env.login__microsoft__clientId) {\n throw new Error(\"Client ID environment variable not set: login__microsoft__clientId.\");\n }\n return process.env.login__microsoft__clientId;\n },\n get clientSecret() {\n if (!process.env.login__microsoft__secret) {\n throw new Error(\"Client Secret environment variable not set: login__microsoft__secret.\");\n }\n return process.env.login__microsoft__secret;\n },\n});\n\nexport type OdspTokenConfig = {\n type: \"password\";\n username: string;\n password: string;\n} | {\n type: \"browserLogin\";\n navigator: (url: string) => void;\n redirectUriCallback?: (tokens: IOdspTokens) => Promise<string>;\n};\n\nexport interface IOdspTokenManagerCacheKey {\n readonly isPush: boolean;\n readonly userOrServer: string;\n}\n\nconst isValidToken = (token: string) => {\n // Return false for undefined or empty tokens.\n if (!token || token.length === 0) {\n return false;\n }\n\n const decodedToken = jwtDecode<any>(token);\n // Give it a 60s buffer\n return (decodedToken.exp - 60 >= (new Date().getTime() / 1000));\n};\n\nconst cacheKeyToString = (key: IOdspTokenManagerCacheKey) => {\n return `${key.userOrServer}${key.isPush ? \"[Push]\" : \"\"}`;\n};\n\nexport class OdspTokenManager {\n private readonly storageCache = new Map<string, IOdspTokens>();\n private readonly pushCache = new Map<string, IOdspTokens>();\n private readonly cacheMutex = new Mutex();\n constructor(\n private readonly tokenCache?: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens>,\n ) { }\n\n public async updateTokensCache(key: IOdspTokenManagerCacheKey, value: IOdspTokens) {\n await this.cacheMutex.runExclusive(async () => {\n await this.updateTokensCacheWithoutLock(key, value);\n });\n }\n\n private async updateTokensCacheWithoutLock(key: IOdspTokenManagerCacheKey, value: IOdspTokens) {\n debug(`${cacheKeyToString(key)}: Saving tokens`);\n const memoryCache = key.isPush ? this.pushCache : this.storageCache;\n memoryCache.set(key.userOrServer, value);\n await this.tokenCache?.save(key, value);\n }\n\n public async getOdspTokens(\n server: string,\n clientConfig: IClientConfig,\n tokenConfig: OdspTokenConfig,\n forceRefresh = false,\n forceReauth = false,\n ): Promise<IOdspTokens> {\n return this.getTokens(\n false,\n server,\n clientConfig,\n tokenConfig,\n forceRefresh,\n forceReauth,\n );\n }\n\n public async getPushTokens(\n server: string,\n clientConfig: IClientConfig,\n tokenConfig: OdspTokenConfig,\n forceRefresh = false,\n forceReauth = false,\n ): Promise<IOdspTokens> {\n return this.getTokens(\n true,\n server,\n clientConfig,\n tokenConfig,\n forceRefresh,\n forceReauth,\n );\n }\n\n private async getTokenFromCache(\n cacheKey: IOdspTokenManagerCacheKey,\n ) {\n const memoryCache = cacheKey.isPush ? this.pushCache : this.storageCache;\n const memoryToken = memoryCache.get(cacheKey.userOrServer);\n if (memoryToken) {\n debug(`${cacheKeyToString(cacheKey)}: Token found in memory `);\n return memoryToken;\n }\n const fileToken = await this.tokenCache?.get(cacheKey);\n if (fileToken) {\n debug(`${cacheKeyToString(cacheKey)}: Token found in file`);\n memoryCache.set(cacheKey.userOrServer, fileToken);\n return fileToken;\n }\n }\n\n private static getCacheKey(\n isPush: boolean,\n tokenConfig: OdspTokenConfig,\n server: string,\n ): IOdspTokenManagerCacheKey {\n // If we are using password, we should cache the token per user instead of per server\n return { isPush, userOrServer: tokenConfig.type === \"password\" ? tokenConfig.username : server };\n }\n\n private async getTokens(\n isPush: boolean,\n server: string,\n clientConfig: IClientConfig,\n tokenConfig: OdspTokenConfig,\n forceRefresh: boolean,\n forceReauth: boolean,\n ): Promise<IOdspTokens> {\n const invokeGetTokensCore = async () => {\n // Don't solely rely on tokenCache lock, ensure serialized execution of\n // cache update to avoid multiple fetch.\n return this.cacheMutex.runExclusive(async () => {\n return this.getTokensCore(\n isPush,\n server,\n clientConfig,\n tokenConfig,\n forceRefresh,\n forceReauth);\n });\n };\n if (!forceReauth && !forceRefresh) {\n // check and return if it exists without lock\n const cacheKey = OdspTokenManager.getCacheKey(isPush, tokenConfig, server);\n const tokensFromCache = await this.getTokenFromCache(cacheKey);\n if (tokensFromCache) {\n if (isValidToken(tokensFromCache.accessToken)) {\n debug(`${cacheKeyToString(cacheKey)}: Token reused from cache `);\n await this.onTokenRetrievalFromCache(tokenConfig, tokensFromCache);\n return tokensFromCache;\n }\n debug(`${cacheKeyToString(cacheKey)}: Token expired from cache `);\n }\n }\n if (this.tokenCache) {\n // check with lock, used to prevent concurrent auth attempts\n return this.tokenCache.lock(invokeGetTokensCore);\n }\n return invokeGetTokensCore();\n }\n\n private async getTokensCore(\n isPush: boolean,\n server: string,\n clientConfig: IClientConfig,\n tokenConfig: OdspTokenConfig,\n forceRefresh,\n forceReauth,\n ): Promise<IOdspTokens> {\n const scope = isPush ? pushScope : getOdspScope(server);\n const cacheKey = OdspTokenManager.getCacheKey(isPush, tokenConfig, server);\n let tokens: IOdspTokens | undefined;\n if (!forceReauth) {\n // check the cache again under the lock (if it is there)\n const tokensFromCache = await this.getTokenFromCache(cacheKey);\n if (tokensFromCache) {\n if (forceRefresh || !isValidToken(tokensFromCache.accessToken)) {\n try {\n // This updates the tokens in tokensFromCache\n tokens = await refreshTokens(server, scope, clientConfig, tokensFromCache);\n await this.updateTokensCacheWithoutLock(cacheKey, tokens);\n } catch (error) {\n debug(`${cacheKeyToString(cacheKey)}: Error in refreshing token. ${error}`);\n }\n } else {\n tokens = tokensFromCache;\n debug(`${cacheKeyToString(cacheKey)}: Token reused from locked cache `);\n }\n }\n }\n\n if (tokens) {\n await this.onTokenRetrievalFromCache(tokenConfig, tokens);\n return tokens;\n }\n\n switch (tokenConfig.type) {\n case \"password\":\n tokens = await this.acquireTokensWithPassword(\n server,\n scope,\n clientConfig,\n tokenConfig.username,\n tokenConfig.password,\n );\n break;\n case \"browserLogin\":\n tokens = await this.acquireTokensViaBrowserLogin(\n getLoginPageUrl(server, clientConfig, scope, odspAuthRedirectUri),\n server,\n clientConfig,\n scope,\n tokenConfig.navigator,\n tokenConfig.redirectUriCallback,\n );\n break;\n default:\n unreachableCase(tokenConfig);\n }\n\n await this.updateTokensCacheWithoutLock(cacheKey, tokens);\n return tokens;\n }\n\n private async acquireTokensWithPassword(\n server: string,\n scope: string,\n clientConfig: IClientConfig,\n username: string,\n password: string,\n ): Promise<IOdspTokens> {\n const credentials: TokenRequestCredentials = {\n grant_type: \"password\",\n username,\n password,\n };\n return fetchTokens(server, scope, clientConfig, credentials);\n }\n\n private async acquireTokensViaBrowserLogin(\n loginPageUrl: string,\n server: string,\n clientConfig: IClientConfig,\n scope: string,\n navigator: (url: string) => void,\n redirectUriCallback?: (tokens: IOdspTokens) => Promise<string>,\n ): Promise<IOdspTokens> {\n // Start up a local auth redirect handler service to receive the tokens after login\n const tokenGetter = await serverListenAndHandle(odspAuthRedirectPort, async (req, res) => {\n // extract code from request URL and fetch the tokens\n const credentials: TokenRequestCredentials = {\n grant_type: \"authorization_code\",\n code: this.extractAuthorizationCode(req.url),\n redirect_uri: odspAuthRedirectUri,\n };\n const tokens = await fetchTokens(server, scope, clientConfig, credentials);\n\n // redirect now that the browser is done with auth\n if (redirectUriCallback) {\n res.writeHead(301, { Location: await redirectUriCallback(tokens) });\n await endResponse(res);\n } else {\n res.write(\"Please close the window\");\n await endResponse(res);\n }\n\n return tokens;\n });\n\n // Now that our local redirect handler is up, navigate the browser to the login page\n navigator(loginPageUrl);\n\n // Receive and extract the tokens\n const odspTokens = await tokenGetter();\n\n return odspTokens;\n }\n\n private async onTokenRetrievalFromCache(config: OdspTokenConfig, tokens: IOdspTokens) {\n if (config.type === \"browserLogin\" && config.redirectUriCallback) {\n config.navigator(await config.redirectUriCallback(tokens));\n }\n }\n\n private extractAuthorizationCode(relativeUrl: string | undefined): string {\n if (relativeUrl === undefined) {\n throw Error(\"Failed to get authorization\");\n }\n const parsedUrl = new URL(relativeUrl, odspAuthRedirectOrigin);\n const code = parsedUrl.searchParams.get(\"code\");\n if (!code) {\n throw Error(\"Failed to get authorization\");\n }\n return code;\n }\n}\n\nasync function loadAndPatchRC() {\n const rc = await loadRC();\n if (rc.tokens && rc.tokens.version === undefined) {\n // Clean up older versions\n delete (rc as any).tokens;\n delete (rc as any).pushTokens;\n }\n return rc;\n}\n\nexport const odspTokensCache: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens> = {\n async get(key: IOdspTokenManagerCacheKey): Promise<IOdspTokens | undefined> {\n const rc = await loadAndPatchRC();\n return rc.tokens?.data[key.userOrServer]?.[key.isPush ? \"push\" : \"storage\"];\n },\n async save(key: IOdspTokenManagerCacheKey, tokens: IOdspTokens): Promise<void> {\n const rc = await loadAndPatchRC();\n if (!rc.tokens) {\n rc.tokens = {\n version: 1,\n data: {},\n };\n }\n let prevTokens = rc.tokens.data[key.userOrServer];\n if (!prevTokens) {\n prevTokens = {};\n rc.tokens.data[key.userOrServer] = prevTokens;\n }\n prevTokens[key.isPush ? \"push\" : \"storage\"] = tokens;\n return saveRC(rc);\n },\n async lock<T>(callback: () => Promise<T>): Promise<T> {\n const release = await lockRC();\n try {\n return await callback();\n } finally {\n await release();\n }\n },\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/common-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"]}
|
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.3.0
|
|
8
|
+
export declare const pkgVersion = "2.0.0-internal.3.2.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.3.0
|
|
11
|
+
exports.pkgVersion = "2.0.0-internal.3.2.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.3.0
|
|
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.3.2.0\";\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snapshotNormalizer.d.ts","sourceRoot":"","sources":["../src/snapshotNormalizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,
|
|
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,oDAAoD;AACpD,eAAO,MAAM,YAAY,SAAS,CAAC;AAEnC,MAAM,WAAW,yBAAyB;IAEzC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B;;;;OAIG;IACH,2BAA2B,CAAC,EAAE,MAAM,EAAE,CAAC;CACvC;AAoGD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,yBAAyB,GAAG,KAAK,CAkBhG"}
|
|
@@ -78,11 +78,11 @@ function getNormalizedBlobContent(blobContent, blobName) {
|
|
|
78
78
|
content = JSON.stringify(gcState);
|
|
79
79
|
}
|
|
80
80
|
/**
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
* The metadata blob has "summaryNumber" or "summaryCount" that tells which summary this is for a container. It can
|
|
82
|
+
* be different in summaries of two clients even if they are generated at the same sequence#. For instance, at seq#
|
|
83
|
+
* 1000, if one client has summarized 10 times and other has summarizer 15 times, summaryNumber will be different
|
|
84
|
+
* for them. So, update "summaryNumber" to 0 for purposes of comparing snapshots.
|
|
85
|
+
*/
|
|
86
86
|
if (blobName === metadataBlobName) {
|
|
87
87
|
const metadata = JSON.parse(content);
|
|
88
88
|
if (metadata.summaryNumber !== undefined) {
|
|
@@ -122,7 +122,7 @@ function getNormalizedSnapshot(snapshot, config) {
|
|
|
122
122
|
// parsed and deep sorted.
|
|
123
123
|
const normalizedEntries = [];
|
|
124
124
|
// The metadata blob in the root of the summary tree needs to be normalized.
|
|
125
|
-
const blobsToNormalize = [metadataBlobName, ...(_a = config === null || config === void 0 ? void 0 : config.blobsToNormalize) !== null && _a !== void 0 ? _a : []];
|
|
125
|
+
const blobsToNormalize = [metadataBlobName, ...((_a = config === null || config === void 0 ? void 0 : config.blobsToNormalize) !== null && _a !== void 0 ? _a : [])];
|
|
126
126
|
for (const entry of snapshot.entries) {
|
|
127
127
|
normalizedEntries.push(normalizeEntry(entry, Object.assign(Object.assign({}, config), { blobsToNormalize })));
|
|
128
128
|
}
|
|
@@ -168,7 +168,8 @@ function normalizeEntry(entry, config) {
|
|
|
168
168
|
case protocol_definitions_1.TreeEntry.Blob: {
|
|
169
169
|
let contents = entry.value.contents;
|
|
170
170
|
// If this blob has to be normalized or it's a GC blob, parse and sort the blob contents first.
|
|
171
|
-
if (((_a = config === null || config === void 0 ? void 0 : config.blobsToNormalize) === null || _a === void 0 ? void 0 : _a.includes(entry.path)) ||
|
|
171
|
+
if (((_a = config === null || config === void 0 ? void 0 : config.blobsToNormalize) === null || _a === void 0 ? void 0 : _a.includes(entry.path)) ||
|
|
172
|
+
entry.path.startsWith(exports.gcBlobPrefix)) {
|
|
172
173
|
contents = getNormalizedBlobContent(contents, entry.path);
|
|
173
174
|
}
|
|
174
175
|
return new protocol_base_1.BlobTreeEntry(entry.path, contents);
|
|
@@ -176,12 +177,14 @@ function normalizeEntry(entry, config) {
|
|
|
176
177
|
case protocol_definitions_1.TreeEntry.Tree: {
|
|
177
178
|
if ((config === null || config === void 0 ? void 0 : config.excludedChannelContentTypes) !== undefined) {
|
|
178
179
|
for (const maybeAttributes of entry.value.entries) {
|
|
179
|
-
if (maybeAttributes.type === protocol_definitions_1.TreeEntry.Blob &&
|
|
180
|
+
if (maybeAttributes.type === protocol_definitions_1.TreeEntry.Blob &&
|
|
181
|
+
maybeAttributes.path === ".attributes") {
|
|
180
182
|
const parsed = JSON.parse(maybeAttributes.value.contents);
|
|
181
183
|
if (parsed.type === "https://graph.microsoft.com/types/sharedmatrix") {
|
|
182
184
|
return new protocol_base_1.TreeTreeEntry(entry.path, normalizeMatrix(getNormalizedSnapshot(entry.value, config)));
|
|
183
185
|
}
|
|
184
|
-
if (parsed.type !== undefined &&
|
|
186
|
+
if (parsed.type !== undefined &&
|
|
187
|
+
config.excludedChannelContentTypes.includes(parsed.type)) {
|
|
185
188
|
// remove everything to match the unknown channel
|
|
186
189
|
return new protocol_base_1.TreeTreeEntry(entry.path, { entries: [maybeAttributes] });
|
|
187
190
|
}
|
|
@@ -191,7 +194,7 @@ function normalizeEntry(entry, config) {
|
|
|
191
194
|
return new protocol_base_1.TreeTreeEntry(entry.path, getNormalizedSnapshot(entry.value, config));
|
|
192
195
|
}
|
|
193
196
|
case protocol_definitions_1.TreeEntry.Attachment: {
|
|
194
|
-
return new protocol_base_1.AttachmentTreeEntry(entry.path,
|
|
197
|
+
return new protocol_base_1.AttachmentTreeEntry(entry.path, entry.value.id);
|
|
195
198
|
}
|
|
196
199
|
default:
|
|
197
200
|
throw new Error("Unknown entry type");
|
|
@@ -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/protocol-base\";\nimport {\n ITree,\n TreeEntry,\n ITreeEntry,\n} 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 // The paths of blobs whose contents should be normalized.\n blobsToNormalize?: string[];\n /**\n * channel types who's content (non-attribute) blobs will be excluded.\n * this is used to exclude the content of channels who's content cannot be compared\n * as the content is non-deterministic between snapshot at the same sequence number.\n */\n excludedChannelContentTypes?: 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 const sortedArray: any[] = [];\n // Sort arrays and objects, if any, in the array.\n for (const element of array) {\n if (Array.isArray(element)) {\n sortedArray.push(getDeepSortedArray(element));\n } else if (element instanceof Object) {\n sortedArray.push(getDeepSortedObject(element));\n } else {\n sortedArray.push(element);\n }\n }\n\n // Now that all the arrays and objects in this array's elements have been sorted, sort it by comparing each\n // element's stringified version.\n const sortFn = (elem1: any, elem2: any) => {\n const serializedElem1 = JSON.stringify(elem1);\n const serializedElem2 = JSON.stringify(elem2);\n return serializedElem1.localeCompare(serializedElem2);\n };\n\n return 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 const sortedObj: any = {};\n // Sort the object keys first. Then sort arrays and objects, if any, in the object.\n const keys = Object.keys(obj).sort();\n for (const key of keys) {\n const value = obj[key];\n if (Array.isArray(value)) {\n sortedObj[key] = getDeepSortedArray(value);\n } else if (value instanceof Object) {\n sortedObj[key] = getDeepSortedObject(value);\n } else {\n sortedObj[key] = value;\n }\n }\n\n return 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 let content = blobContent;\n if (blobName.startsWith(gcBlobPrefix)) {\n // GC blobs may contain `unreferencedTimestampMs` for node that became unreferenced. This is the timestamp\n // of the last op processed or current timestamp and can differ between clients depending on when GC was run.\n // So, remove it for the purposes of comparing snapshots.\n const gcState = JSON.parse(content);\n for (const [, data] of Object.entries(gcState.gcNodes)) {\n delete (data as any).unreferencedTimestampMs;\n }\n content = JSON.stringify(gcState);\n }\n\n /**\n * The metadata blob has \"summaryNumber\" or \"summaryCount\" that tells which summary this is for a container. It can\n * be different in summaries of two clients even if they are generated at the same sequence#. For instance, at seq#\n * 1000, if one client has summarized 10 times and other has summarizer 15 times, summaryNumber will be different\n * for them. So, update \"summaryNumber\" to 0 for purposes of comparing snapshots.\n */\n if (blobName === metadataBlobName) {\n const metadata = JSON.parse(content);\n if (metadata.summaryNumber !== undefined) {\n metadata.summaryNumber = 0;\n }\n if (metadata.summaryCount !== undefined) {\n metadata.summaryCount = 0;\n }\n content = JSON.stringify(metadata);\n }\n\n // Deep sort the content if it's parseable.\n try {\n let contentObj = JSON.parse(content);\n if (Array.isArray(contentObj)) {\n contentObj = getDeepSortedArray(contentObj);\n } else if (contentObj instanceof Object) {\n contentObj = getDeepSortedObject(contentObj);\n }\n content = JSON.stringify(contentObj);\n } catch {}\n return 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 // Merge blobs to normalize in the config with runtime blobs to normalize. The contents of these blobs will be\n // parsed and deep sorted.\n const normalizedEntries: ITreeEntry[] = [];\n\n // The metadata blob in the root of the summary tree needs to be normalized.\n const blobsToNormalize = [metadataBlobName, ...config?.blobsToNormalize ?? []];\n for (const entry of snapshot.entries) {\n normalizedEntries.push(normalizeEntry(entry, { ...config, blobsToNormalize }));\n }\n\n // Sort the tree entries based on their path.\n normalizedEntries.sort((a, b) => a.path.localeCompare(b.path));\n\n return {\n entries: normalizedEntries,\n id: snapshot.id,\n };\n}\n\nfunction normalizeMatrix(value: ITree): ITree {\n const rows = value.entries.find((e) => e.path === \"rows\");\n\n if (!rows || !(\"entries\" in rows.value)) {\n return value;\n }\n\n const segments = rows.value.entries.find((e) => e.path === \"segments\");\n\n if (!segments || !(\"entries\" in segments.value)) {\n return value;\n }\n\n const header = segments.value.entries.find((e) => e.path === \"header\");\n\n if (!header || !(\"contents\" in header.value)) {\n return value;\n }\n\n if (!header?.value.contents.includes(\"removedClientId\")) {\n return value;\n }\n\n const contents = JSON.parse(header?.value.contents);\n\n for (const segment of contents.segments) {\n if (\"removedClientId\" in segment) {\n segment.removedClientId = undefined;\n }\n\n if (\"removedClientIds\" in segment) {\n segment.removedClientIds = undefined;\n }\n }\n\n header.value.contents = JSON.stringify(contents);\n\n return value;\n}\n\nfunction normalizeEntry(\n entry: ITreeEntry,\n config: ISnapshotNormalizerConfig | undefined,\n): ITreeEntry {\n switch (entry.type) {\n case TreeEntry.Blob: {\n let contents = entry.value.contents;\n // If this blob has to be normalized or it's a GC blob, parse and sort the blob contents first.\n if (config?.blobsToNormalize?.includes(entry.path) || entry.path.startsWith(gcBlobPrefix)) {\n contents = getNormalizedBlobContent(contents, entry.path);\n }\n return new BlobTreeEntry(entry.path, contents);\n }\n case TreeEntry.Tree: {\n if (config?.excludedChannelContentTypes !== undefined) {\n for (const maybeAttributes of entry.value.entries) {\n if (maybeAttributes.type === TreeEntry.Blob && maybeAttributes.path === \".attributes\") {\n const parsed: { type?: string; } = JSON.parse(maybeAttributes.value.contents);\n if (parsed.type === \"https://graph.microsoft.com/types/sharedmatrix\") {\n return new TreeTreeEntry(\n entry.path,\n normalizeMatrix(getNormalizedSnapshot(entry.value, config)),\n );\n }\n if (parsed.type !== undefined && config.excludedChannelContentTypes.includes(parsed.type)) {\n // remove everything to match the unknown channel\n return new TreeTreeEntry(entry.path, { entries: [maybeAttributes] });\n }\n }\n }\n }\n\n return new TreeTreeEntry(entry.path, getNormalizedSnapshot(entry.value, config));\n }\n case TreeEntry.Attachment: {\n return new AttachmentTreeEntry(entry.path, (entry.value).id);\n }\n\n default:\n throw new Error(\"Unknown entry type\");\n }\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/protocol-base\";\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\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\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"]}
|
package/lib/fluidToolRC.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/lib/fluidToolRC.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fluidToolRC.js","sourceRoot":"","sources":["../src/fluidToolRC.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAqBvC,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AAEpE,MAAM,CAAC,KAAK,UAAU,MAAM;
|
|
1
|
+
{"version":3,"file":"fluidToolRC.js","sourceRoot":"","sources":["../src/fluidToolRC.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAqBvC,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AAEpE,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;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;AAED,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,MAAM,CAAC,KAAK,UAAU,MAAM;IAC3B,+DAA+D;IAC/D,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 \"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\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\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\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\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\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"]}
|
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,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAE7B,MAAM,WAAW,kBAAkB;
|
|
1
|
+
{"version":3,"file":"httpHelpers.d.ts","sourceRoot":"","sources":["../src/httpHelpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAE7B,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;AACD,wBAAgB,mBAAmB,CAClC,IAAI,EAAE,MAAM,EACZ,eAAe,EAAE,IAAI,CAAC,eAAe,GACnC,kBAAkB,CAiBpB;AACD,oBAAY,mBAAmB,CAAC,CAAC,IAAI,CACpC,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,KACpB,OAAO,CAAC,CAAC,CAAC,CAAC;AAChB,oBAAY,kBAAkB,CAAC,CAAC,IAAI,OAAO,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,eAAO,MAAM,qBAAqB,YAC3B,MAAM,2DAuBV,CAAC;AAEJ,eAAO,MAAM,WAAW,aAAoB,KAAK,cAAc,KAAG,QAAQ,IAAI,CAO3E,CAAC"}
|
package/lib/httpHelpers.js
CHANGED
|
@@ -11,7 +11,9 @@ export function createTrackedServer(port, requestListener) {
|
|
|
11
11
|
socket.on("close", () => sockets.delete(socket));
|
|
12
12
|
});
|
|
13
13
|
return {
|
|
14
|
-
server,
|
|
14
|
+
server,
|
|
15
|
+
sockets,
|
|
16
|
+
fullyClose() {
|
|
15
17
|
server.close();
|
|
16
18
|
sockets.forEach((socket) => socket.destroy());
|
|
17
19
|
},
|
|
@@ -29,7 +31,9 @@ new Promise((outerResolve, outerReject) => {
|
|
|
29
31
|
res.end();
|
|
30
32
|
return;
|
|
31
33
|
}
|
|
32
|
-
handler(req, res)
|
|
34
|
+
handler(req, res)
|
|
35
|
+
.finally(() => httpServer.fullyClose())
|
|
36
|
+
.then((result) => innerResolve(result), (error) => innerReject(error));
|
|
33
37
|
});
|
|
34
38
|
outerResolve(async () => innerP);
|
|
35
39
|
});
|
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,MAAM,CAAC;AAQxB,MAAM,UAAU,mBAAmB,
|
|
1
|
+
{"version":3,"file":"httpHelpers.js","sourceRoot":"","sources":["../src/httpHelpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AAQxB,MAAM,UAAU,mBAAmB,CAClC,IAAY,EACZ,eAAqC;IAErC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/D,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,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/C,CAAC;KACD,CAAC;AACH,CAAC;AAMD,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,+CAA+C;IAC/C,MAAM,MAAM,GAAG,IAAI,OAAO,CAAI,CAAC,YAAY,EAAE,WAAW,EAAE,EAAE;QAC3D,MAAM,UAAU,GAAG,mBAAmB,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YACzD,iBAAiB;YACjB,IAAI,GAAG,CAAC,GAAG,KAAK,cAAc,EAAE;gBAC/B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC,CAAC;gBACvD,GAAG,CAAC,GAAG,EAAE,CAAC;gBACV,OAAO;aACP;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,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,QAA6B,EAAiB,EAAE,CACjF,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;IAC/B,IAAI;QACH,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;KACtB;IAAC,OAAO,KAAK,EAAE;QACf,MAAM,CAAC,KAAK,CAAC,CAAC;KACd;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 \"http\";\nimport { Socket } from \"net\";\n\nexport interface ITrackedHttpServer {\n\treadonly server: http.Server;\n\treadonly sockets: Set<Socket>;\n\tfullyClose(): void;\n}\nexport function createTrackedServer(\n\tport: number,\n\trequestListener: http.RequestListener,\n): ITrackedHttpServer {\n\tconst server = http.createServer(requestListener).listen(port);\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() {\n\t\t\tserver.close();\n\t\t\tsockets.forEach((socket) => socket.destroy());\n\t\t},\n\t};\n}\nexport type OnceListenerHandler<T> = (\n\treq: http.IncomingMessage,\n\tres: http.ServerResponse,\n) => Promise<T>;\nexport type OnceListenerResult<T> = Promise<() => Promise<T>>;\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\n\t\tconst innerP = new Promise<T>((innerResolve, innerReject) => {\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\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
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { IAsyncCache, IResources, loadRC, lockRC, saveRC } from "./fluidToolRC";
|
|
6
6
|
export { getMicrosoftConfiguration, IOdspTokenManagerCacheKey, OdspTokenConfig, OdspTokenManager, odspTokensCache, } from "./odspTokenManager";
|
|
7
|
-
export { gcBlobPrefix, getNormalizedSnapshot, ISnapshotNormalizerConfig } from "./snapshotNormalizer";
|
|
7
|
+
export { gcBlobPrefix, getNormalizedSnapshot, ISnapshotNormalizerConfig, } from "./snapshotNormalizer";
|
|
8
8
|
//# 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,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EACN,yBAAyB,EACzB,yBAAyB,EACzB,eAAe,EACf,gBAAgB,EAChB,eAAe,GACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EACN,yBAAyB,EACzB,yBAAyB,EACzB,eAAe,EACf,gBAAgB,EAChB,eAAe,GACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACN,YAAY,EACZ,qBAAqB,EACrB,yBAAyB,GACzB,MAAM,sBAAsB,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export { loadRC, lockRC, saveRC } from "./fluidToolRC";
|
|
6
6
|
export { getMicrosoftConfiguration, OdspTokenManager, odspTokensCache, } from "./odspTokenManager";
|
|
7
|
-
export { gcBlobPrefix, getNormalizedSnapshot } from "./snapshotNormalizer";
|
|
7
|
+
export { gcBlobPrefix, getNormalizedSnapshot, } from "./snapshotNormalizer";
|
|
8
8
|
//# sourceMappingURL=index.js.map
|