@fluidframework/tool-utils 2.0.0-dev-rc.2.0.0.246488 → 2.0.0-dev-rc.3.0.0.250606

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.
@@ -1 +1 @@
1
- {"version":3,"file":"fluidToolRC.d.ts","sourceRoot":"","sources":["../src/fluidToolRC.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAAE,WAAW,EAAE,MAAM,4CAA4C,CAAC;AAEzE;;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"}
1
+ {"version":3,"file":"fluidToolRC.d.ts","sourceRoot":"","sources":["../src/fluidToolRC.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,WAAW,EAAE,MAAM,4CAA4C,CAAC;AAGzE;;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"}
@@ -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;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/internal\";\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"]}
1
+ {"version":3,"file":"fluidToolRC.js","sourceRoot":"","sources":["../src/fluidToolRC.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;AAEH,4CAAoB;AACpB,4CAAoB;AACpB,gDAAwB;AACxB,gDAAwB;AAExB,qDAAuC;AA0BvC,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 { IOdspTokens } from \"@fluidframework/odsp-doclib-utils/internal\";\nimport { lock } from \"proper-lockfile\";\n\n/**\n * @internal\n */\nexport interface IAsyncCache<TKey, TValue> {\n\tget(key: TKey): Promise<TValue | undefined>;\n\tsave(key: TKey, value: TValue): Promise<void>;\n\tlock<T>(callback: () => Promise<T>): Promise<T>;\n}\n\n/**\n * @internal\n */\nexport interface IResources {\n\ttokens?: {\n\t\tversion?: number;\n\t\tdata: {\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"]}
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { IOdspTokens, IClientConfig } from "@fluidframework/odsp-doclib-utils/internal";
5
+ import { IClientConfig, IOdspTokens } from "@fluidframework/odsp-doclib-utils/internal";
6
6
  import { IAsyncCache } from "./fluidToolRC.js";
7
7
  /**
8
8
  * @internal
@@ -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,4CAA4C,CAAC;AAIpD,OAAO,EAAE,WAAW,EAA0B,MAAM,kBAAkB,CAAC;AAOvE;;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"}
1
+ {"version":3,"file":"odspTokenManager.d.ts","sourceRoot":"","sources":["../src/odspTokenManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACN,aAAa,EACb,WAAW,EAOX,MAAM,4CAA4C,CAAC;AAIpD,OAAO,EAAE,WAAW,EAA0B,MAAM,kBAAkB,CAAC;AAOvE;;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"}
@@ -7,8 +7,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.odspTokensCache = exports.OdspTokenManager = exports.getMicrosoftConfiguration = void 0;
8
8
  const core_utils_1 = require("@fluidframework/core-utils");
9
9
  const internal_1 = require("@fluidframework/odsp-doclib-utils/internal");
10
- const jwt_decode_1 = require("jwt-decode");
11
10
  const async_mutex_1 = require("async-mutex");
11
+ const jwt_decode_1 = require("jwt-decode");
12
12
  const debug_js_1 = require("./debug.js");
13
13
  const fluidToolRC_js_1 = require("./fluidToolRC.js");
14
14
  const httpHelpers_js_1 = require("./httpHelpers.js");
@@ -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/internal\";\nimport { jwtDecode } from \"jwt-decode\";\nimport { Mutex } from \"async-mutex\";\nimport { debug } from \"./debug.js\";\nimport { IAsyncCache, loadRC, saveRC, lockRC } from \"./fluidToolRC.js\";\nimport { serverListenAndHandle, endResponse } from \"./httpHelpers.js\";\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"]}
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\tIClientConfig,\n\tIOdspTokens,\n\tTokenRequestCredentials,\n\tfetchTokens,\n\tgetLoginPageUrl,\n\tgetOdspScope,\n\tpushScope,\n\trefreshTokens,\n} from \"@fluidframework/odsp-doclib-utils/internal\";\nimport { Mutex } from \"async-mutex\";\nimport { jwtDecode } from \"jwt-decode\";\nimport { debug } from \"./debug.js\";\nimport { IAsyncCache, loadRC, lockRC, saveRC } from \"./fluidToolRC.js\";\nimport { endResponse, serverListenAndHandle } from \"./httpHelpers.js\";\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"]}
@@ -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-dev-rc.2.0.0.246488";
8
+ export declare const pkgVersion = "2.0.0-dev-rc.3.0.0.250606";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -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-dev-rc.2.0.0.246488";
11
+ exports.pkgVersion = "2.0.0-dev-rc.3.0.0.250606";
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,2BAA2B,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-dev-rc.2.0.0.246488\";\n"]}
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,2BAA2B,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-dev-rc.3.0.0.250606\";\n"]}
@@ -100,8 +100,8 @@ function getNormalizedBlobContent(blobContent, blobName) {
100
100
  metadata.telemetryDocumentId = "x";
101
101
  }
102
102
  // default was not written before, now it's written in.
103
- if (metadata.idCompressorMode === undefined) {
104
- metadata.idCompressorMode = "off";
103
+ if (metadata.documentSchema !== undefined) {
104
+ metadata.documentSchema = undefined;
105
105
  }
106
106
  content = JSON.stringify(metadata);
107
107
  }
@@ -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/**\n * The prefix that all GC blob names start with.\n *\n * @internal\n */\nexport const gcBlobPrefix = \"__gc\";\n\n/**\n * @internal\n */\nexport interface ISnapshotNormalizerConfig {\n\t// The paths of blobs whose contents should be normalized.\n\tblobsToNormalize?: string[];\n\t/**\n\t * channel types who's content (non-attribute) blobs will be excluded.\n\t * this is used to exclude the content of channels who's content cannot be compared\n\t * as the content is non-deterministic between snapshot at the same sequence number.\n\t */\n\texcludedChannelContentTypes?: string[];\n}\n\n/**\n * Function that deep sorts an array. It handles cases where array elements are objects or arrays.\n * @returns the sorted array.\n */\nfunction getDeepSortedArray(array: any[]): any[] {\n\tconst sortedArray: any[] = [];\n\t// Sort arrays and objects, if any, in the array.\n\tfor (const element of array) {\n\t\tif (Array.isArray(element)) {\n\t\t\tsortedArray.push(getDeepSortedArray(element));\n\t\t} else if (element instanceof Object) {\n\t\t\tsortedArray.push(getDeepSortedObject(element));\n\t\t} else {\n\t\t\tsortedArray.push(element);\n\t\t}\n\t}\n\n\t// Now that all the arrays and objects in this array's elements have been sorted, sort it by comparing each\n\t// element's stringified version.\n\tconst sortFn = (elem1: any, elem2: any) => {\n\t\tconst serializedElem1 = JSON.stringify(elem1);\n\t\tconst serializedElem2 = JSON.stringify(elem2);\n\t\treturn serializedElem1.localeCompare(serializedElem2);\n\t};\n\n\treturn sortedArray.sort(sortFn);\n}\n\n/**\n * Function that deep sorts an object. It handles cases where object properties are arrays or objects.\n * @returns the sorted object.\n */\nfunction getDeepSortedObject(obj: any): any {\n\tconst sortedObj: any = {};\n\t// Sort the object keys first. Then sort arrays and objects, if any, in the object.\n\tconst keys = Object.keys(obj).sort();\n\tfor (const key of keys) {\n\t\tconst value = obj[key];\n\t\tif (Array.isArray(value)) {\n\t\t\tsortedObj[key] = getDeepSortedArray(value);\n\t\t} else if (value instanceof Object) {\n\t\t\tsortedObj[key] = getDeepSortedObject(value);\n\t\t} else {\n\t\t\tsortedObj[key] = value;\n\t\t}\n\t}\n\n\treturn sortedObj;\n}\n\n/**\n * Function that normalizes a blob's content. If the content is an object or an array, deep sorts them.\n * Special handling for certain runtime blobs, such as the \"gc\" blob.\n * @returns the normalized blob content.\n */\nfunction getNormalizedBlobContent(blobContent: string, blobName: string): string {\n\tlet content = blobContent;\n\tif (blobName.startsWith(gcBlobPrefix)) {\n\t\t// GC blobs may contain `unreferencedTimestampMs` for node that became unreferenced. This is the timestamp\n\t\t// of the last op processed or current timestamp and can differ between clients depending on when GC was run.\n\t\t// So, remove it for the purposes of comparing snapshots.\n\t\tconst gcState = JSON.parse(content);\n\t\tfor (const [, data] of Object.entries(gcState.gcNodes)) {\n\t\t\tdelete (data as any).unreferencedTimestampMs;\n\t\t}\n\t\tcontent = JSON.stringify(gcState);\n\t}\n\n\t/**\n\t * The metadata blob has \"summaryNumber\" or \"summaryCount\" that tells which summary this is for a container. It can\n\t * be different in summaries of two clients even if they are generated at the same sequence#. For instance, at seq#\n\t * 1000, if one client has summarized 10 times and other has summarizer 15 times, summaryNumber will be different\n\t * for them. So, update \"summaryNumber\" to 0 for purposes of comparing snapshots.\n\t */\n\tif (blobName === metadataBlobName) {\n\t\tconst metadata = JSON.parse(content);\n\t\tif (metadata.summaryNumber !== undefined) {\n\t\t\tmetadata.summaryNumber = 0;\n\t\t}\n\t\tif (metadata.summaryCount !== undefined) {\n\t\t\tmetadata.summaryCount = 0;\n\t\t}\n\t\t// \"telemetryDocumentId\" is not a deterministic property (random guid), so we need to set it to something consistent\n\t\tif (metadata.telemetryDocumentId !== undefined) {\n\t\t\tmetadata.telemetryDocumentId = \"x\";\n\t\t}\n\t\t// default was not written before, now it's written in.\n\t\tif (metadata.idCompressorMode === undefined) {\n\t\t\tmetadata.idCompressorMode = \"off\";\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"]}
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, ITreeEntry, TreeEntry } 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\t// default was not written before, now it's written in.\n\t\tif (metadata.documentSchema !== undefined) {\n\t\t\tmetadata.documentSchema = undefined;\n\t\t}\n\t\tcontent = JSON.stringify(metadata);\n\t}\n\n\t// Deep sort the content if it's parseable.\n\ttry {\n\t\tlet contentObj = JSON.parse(content);\n\t\tif (Array.isArray(contentObj)) {\n\t\t\tcontentObj = getDeepSortedArray(contentObj);\n\t\t} else if (contentObj instanceof Object) {\n\t\t\tcontentObj = getDeepSortedObject(contentObj);\n\t\t}\n\t\tcontent = JSON.stringify(contentObj);\n\t} catch {}\n\treturn content;\n}\n\n/**\n * Helper function that normalizes the given snapshot tree. It sorts objects and arrays in the snapshot. It also\n * normalizes certain blob contents for which the order of content does not matter. For example, garbage collection\n * blobs contains objects / arrays whose element order do not matter.\n * @param snapshot - The snapshot tree to normalize.\n * @param config - Configs to use when normalizing snapshot. For example, it can contain paths of blobs whose contents\n * should be normalized as well.\n * @returns a copy of the normalized snapshot tree.\n * @internal\n */\nexport function getNormalizedSnapshot(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 +1 @@
1
- {"version":3,"file":"fluidToolRC.d.ts","sourceRoot":"","sources":["../src/fluidToolRC.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,EAAE,WAAW,EAAE,MAAM,4CAA4C,CAAC;AAEzE;;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"}
1
+ {"version":3,"file":"fluidToolRC.d.ts","sourceRoot":"","sources":["../src/fluidToolRC.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,WAAW,EAAE,MAAM,4CAA4C,CAAC;AAGzE;;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"}
@@ -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;AA2BvC,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AAEpE;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM;IAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;IACjC,IAAI,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE;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;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,EAAc;IAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IACjD,OAAO,SAAS,CAAC,aAAa,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;;GAEG;AACH,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/internal\";\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"]}
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;AAExB,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AA0BvC,MAAM,aAAa,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,cAAc,CAAC,CAAC;AAEpE;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM;IAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;IACjC,IAAI,MAAM,MAAM,CAAC,QAAQ,CAAC,EAAE;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;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,EAAc;IAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IACjD,OAAO,SAAS,CAAC,aAAa,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;;GAEG;AACH,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 { IOdspTokens } from \"@fluidframework/odsp-doclib-utils/internal\";\nimport { lock } from \"proper-lockfile\";\n\n/**\n * @internal\n */\nexport interface IAsyncCache<TKey, TValue> {\n\tget(key: TKey): Promise<TValue | undefined>;\n\tsave(key: TKey, value: TValue): Promise<void>;\n\tlock<T>(callback: () => Promise<T>): Promise<T>;\n}\n\n/**\n * @internal\n */\nexport interface IResources {\n\ttokens?: {\n\t\tversion?: number;\n\t\tdata: {\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"]}
@@ -2,7 +2,7 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { IOdspTokens, IClientConfig } from "@fluidframework/odsp-doclib-utils/internal";
5
+ import { IClientConfig, IOdspTokens } from "@fluidframework/odsp-doclib-utils/internal";
6
6
  import { IAsyncCache } from "./fluidToolRC.js";
7
7
  /**
8
8
  * @internal
@@ -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,4CAA4C,CAAC;AAIpD,OAAO,EAAE,WAAW,EAA0B,MAAM,kBAAkB,CAAC;AAOvE;;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"}
1
+ {"version":3,"file":"odspTokenManager.d.ts","sourceRoot":"","sources":["../src/odspTokenManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACN,aAAa,EACb,WAAW,EAOX,MAAM,4CAA4C,CAAC;AAIpD,OAAO,EAAE,WAAW,EAA0B,MAAM,kBAAkB,CAAC;AAOvE;;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"}
@@ -3,12 +3,12 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import { unreachableCase } from "@fluidframework/core-utils";
6
- import { fetchTokens, refreshTokens, getOdspScope, pushScope, getLoginPageUrl, } from "@fluidframework/odsp-doclib-utils/internal";
7
- import { jwtDecode } from "jwt-decode";
6
+ import { fetchTokens, getLoginPageUrl, getOdspScope, pushScope, refreshTokens, } from "@fluidframework/odsp-doclib-utils/internal";
8
7
  import { Mutex } from "async-mutex";
8
+ import { jwtDecode } from "jwt-decode";
9
9
  import { debug } from "./debug.js";
10
- import { loadRC, saveRC, lockRC } from "./fluidToolRC.js";
11
- import { serverListenAndHandle, endResponse } from "./httpHelpers.js";
10
+ import { loadRC, lockRC, saveRC } from "./fluidToolRC.js";
11
+ import { endResponse, serverListenAndHandle } from "./httpHelpers.js";
12
12
  const odspAuthRedirectPort = 7000;
13
13
  const odspAuthRedirectOrigin = `http://localhost:${odspAuthRedirectPort}`;
14
14
  const odspAuthRedirectUri = new URL("/auth/callback", odspAuthRedirectOrigin).href;
@@ -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/internal\";\nimport { jwtDecode } from \"jwt-decode\";\nimport { Mutex } from \"async-mutex\";\nimport { debug } from \"./debug.js\";\nimport { IAsyncCache, loadRC, saveRC, lockRC } from \"./fluidToolRC.js\";\nimport { serverListenAndHandle, endResponse } from \"./httpHelpers.js\";\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"]}
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\tIClientConfig,\n\tIOdspTokens,\n\tTokenRequestCredentials,\n\tfetchTokens,\n\tgetLoginPageUrl,\n\tgetOdspScope,\n\tpushScope,\n\trefreshTokens,\n} from \"@fluidframework/odsp-doclib-utils/internal\";\nimport { Mutex } from \"async-mutex\";\nimport { jwtDecode } from \"jwt-decode\";\nimport { debug } from \"./debug.js\";\nimport { IAsyncCache, loadRC, lockRC, saveRC } from \"./fluidToolRC.js\";\nimport { endResponse, serverListenAndHandle } from \"./httpHelpers.js\";\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"]}
@@ -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-dev-rc.2.0.0.246488";
8
+ export declare const pkgVersion = "2.0.0-dev-rc.3.0.0.250606";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -5,5 +5,5 @@
5
5
  * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
6
  */
7
7
  export const pkgName = "@fluidframework/tool-utils";
8
- export const pkgVersion = "2.0.0-dev-rc.2.0.0.246488";
8
+ export const pkgVersion = "2.0.0-dev-rc.3.0.0.250606";
9
9
  //# sourceMappingURL=packageVersion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,4BAA4B,CAAC;AACpD,MAAM,CAAC,MAAM,UAAU,GAAG,2BAA2B,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-dev-rc.2.0.0.246488\";\n"]}
1
+ {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,4BAA4B,CAAC;AACpD,MAAM,CAAC,MAAM,UAAU,GAAG,2BAA2B,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-dev-rc.3.0.0.250606\";\n"]}
@@ -97,8 +97,8 @@ function getNormalizedBlobContent(blobContent, blobName) {
97
97
  metadata.telemetryDocumentId = "x";
98
98
  }
99
99
  // default was not written before, now it's written in.
100
- if (metadata.idCompressorMode === undefined) {
101
- metadata.idCompressorMode = "off";
100
+ if (metadata.documentSchema !== undefined) {
101
+ metadata.documentSchema = undefined;
102
102
  }
103
103
  content = JSON.stringify(metadata);
104
104
  }
@@ -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/**\n * The prefix that all GC blob names start with.\n *\n * @internal\n */\nexport const gcBlobPrefix = \"__gc\";\n\n/**\n * @internal\n */\nexport interface ISnapshotNormalizerConfig {\n\t// The paths of blobs whose contents should be normalized.\n\tblobsToNormalize?: string[];\n\t/**\n\t * channel types who's content (non-attribute) blobs will be excluded.\n\t * this is used to exclude the content of channels who's content cannot be compared\n\t * as the content is non-deterministic between snapshot at the same sequence number.\n\t */\n\texcludedChannelContentTypes?: string[];\n}\n\n/**\n * Function that deep sorts an array. It handles cases where array elements are objects or arrays.\n * @returns the sorted array.\n */\nfunction getDeepSortedArray(array: any[]): any[] {\n\tconst sortedArray: any[] = [];\n\t// Sort arrays and objects, if any, in the array.\n\tfor (const element of array) {\n\t\tif (Array.isArray(element)) {\n\t\t\tsortedArray.push(getDeepSortedArray(element));\n\t\t} else if (element instanceof Object) {\n\t\t\tsortedArray.push(getDeepSortedObject(element));\n\t\t} else {\n\t\t\tsortedArray.push(element);\n\t\t}\n\t}\n\n\t// Now that all the arrays and objects in this array's elements have been sorted, sort it by comparing each\n\t// element's stringified version.\n\tconst sortFn = (elem1: any, elem2: any) => {\n\t\tconst serializedElem1 = JSON.stringify(elem1);\n\t\tconst serializedElem2 = JSON.stringify(elem2);\n\t\treturn serializedElem1.localeCompare(serializedElem2);\n\t};\n\n\treturn sortedArray.sort(sortFn);\n}\n\n/**\n * Function that deep sorts an object. It handles cases where object properties are arrays or objects.\n * @returns the sorted object.\n */\nfunction getDeepSortedObject(obj: any): any {\n\tconst sortedObj: any = {};\n\t// Sort the object keys first. Then sort arrays and objects, if any, in the object.\n\tconst keys = Object.keys(obj).sort();\n\tfor (const key of keys) {\n\t\tconst value = obj[key];\n\t\tif (Array.isArray(value)) {\n\t\t\tsortedObj[key] = getDeepSortedArray(value);\n\t\t} else if (value instanceof Object) {\n\t\t\tsortedObj[key] = getDeepSortedObject(value);\n\t\t} else {\n\t\t\tsortedObj[key] = value;\n\t\t}\n\t}\n\n\treturn sortedObj;\n}\n\n/**\n * Function that normalizes a blob's content. If the content is an object or an array, deep sorts them.\n * Special handling for certain runtime blobs, such as the \"gc\" blob.\n * @returns the normalized blob content.\n */\nfunction getNormalizedBlobContent(blobContent: string, blobName: string): string {\n\tlet content = blobContent;\n\tif (blobName.startsWith(gcBlobPrefix)) {\n\t\t// GC blobs may contain `unreferencedTimestampMs` for node that became unreferenced. This is the timestamp\n\t\t// of the last op processed or current timestamp and can differ between clients depending on when GC was run.\n\t\t// So, remove it for the purposes of comparing snapshots.\n\t\tconst gcState = JSON.parse(content);\n\t\tfor (const [, data] of Object.entries(gcState.gcNodes)) {\n\t\t\tdelete (data as any).unreferencedTimestampMs;\n\t\t}\n\t\tcontent = JSON.stringify(gcState);\n\t}\n\n\t/**\n\t * The metadata blob has \"summaryNumber\" or \"summaryCount\" that tells which summary this is for a container. It can\n\t * be different in summaries of two clients even if they are generated at the same sequence#. For instance, at seq#\n\t * 1000, if one client has summarized 10 times and other has summarizer 15 times, summaryNumber will be different\n\t * for them. So, update \"summaryNumber\" to 0 for purposes of comparing snapshots.\n\t */\n\tif (blobName === metadataBlobName) {\n\t\tconst metadata = JSON.parse(content);\n\t\tif (metadata.summaryNumber !== undefined) {\n\t\t\tmetadata.summaryNumber = 0;\n\t\t}\n\t\tif (metadata.summaryCount !== undefined) {\n\t\t\tmetadata.summaryCount = 0;\n\t\t}\n\t\t// \"telemetryDocumentId\" is not a deterministic property (random guid), so we need to set it to something consistent\n\t\tif (metadata.telemetryDocumentId !== undefined) {\n\t\t\tmetadata.telemetryDocumentId = \"x\";\n\t\t}\n\t\t// default was not written before, now it's written in.\n\t\tif (metadata.idCompressorMode === undefined) {\n\t\t\tmetadata.idCompressorMode = \"off\";\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"]}
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, ITreeEntry, TreeEntry } 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\t// default was not written before, now it's written in.\n\t\tif (metadata.documentSchema !== undefined) {\n\t\t\tmetadata.documentSchema = undefined;\n\t\t}\n\t\tcontent = JSON.stringify(metadata);\n\t}\n\n\t// Deep sort the content if it's parseable.\n\ttry {\n\t\tlet contentObj = JSON.parse(content);\n\t\tif (Array.isArray(contentObj)) {\n\t\t\tcontentObj = getDeepSortedArray(contentObj);\n\t\t} else if (contentObj instanceof Object) {\n\t\t\tcontentObj = getDeepSortedObject(contentObj);\n\t\t}\n\t\tcontent = JSON.stringify(contentObj);\n\t} catch {}\n\treturn content;\n}\n\n/**\n * Helper function that normalizes the given snapshot tree. It sorts objects and arrays in the snapshot. It also\n * normalizes certain blob contents for which the order of content does not matter. For example, garbage collection\n * blobs contains objects / arrays whose element order do not matter.\n * @param snapshot - The snapshot tree to normalize.\n * @param config - Configs to use when normalizing snapshot. For example, it can contain paths of blobs whose contents\n * should be normalized as well.\n * @returns a copy of the normalized snapshot tree.\n * @internal\n */\nexport function getNormalizedSnapshot(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 +1 @@
1
- {"version":3,"file":"snapshotNormalizer.spec.js","sourceRoot":"","sources":["../../src/test/snapshotNormalizer.spec.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 { strict as assert } from \"assert\";\nimport { BlobTreeEntry, TreeTreeEntry } from \"@fluidframework/driver-utils\";\nimport { IBlob, ITree } from \"@fluidframework/protocol-definitions\";\nimport {\n\tgcBlobPrefix,\n\tgetNormalizedSnapshot,\n\tISnapshotNormalizerConfig,\n} from \"../snapshotNormalizer.js\";\n\ndescribe(\"Snapshot Normalizer\", () => {\n\tit(\"can normalize tree entries\", () => {\n\t\t// Snapshot tree with entries whose paths are not sorted.\n\t\tconst snapshot: ITree = {\n\t\t\tid: \"root\",\n\t\t\tentries: [\n\t\t\t\tnew TreeTreeEntry(\"entry2\", {\n\t\t\t\t\tid: \"subTree\",\n\t\t\t\t\tentries: [],\n\t\t\t\t}),\n\t\t\t\tnew BlobTreeEntry(\"entry3\", \"blob3\"),\n\t\t\t\tnew BlobTreeEntry(\"entry1\", \"blob1\"),\n\t\t\t],\n\t\t};\n\t\tconst normalizedSnapshot = getNormalizedSnapshot(snapshot);\n\t\tassert.strictEqual(\n\t\t\tnormalizedSnapshot.entries[0].path,\n\t\t\t\"entry1\",\n\t\t\t\"Snapshot tree entries not sorted\",\n\t\t);\n\t\tassert.strictEqual(\n\t\t\tnormalizedSnapshot.entries[1].path,\n\t\t\t\"entry2\",\n\t\t\t\"Snapshot tree entries not sorted\",\n\t\t);\n\t\tassert.strictEqual(\n\t\t\tnormalizedSnapshot.entries[2].path,\n\t\t\t\"entry3\",\n\t\t\t\"Snapshot tree entries not sorted\",\n\t\t);\n\t});\n\n\tit(\"can normalize GC blobs\", () => {\n\t\tconst gcDetails = {\n\t\t\tisRootNode: true,\n\t\t\tgcNodes: {\n\t\t\t\tnode2: [\"node1\", \"/\"],\n\t\t\t\tnode1: [\"node2\", \"/\"],\n\t\t\t},\n\t\t};\n\t\tconst normalizedGCDetails = {\n\t\t\tisRootNode: true,\n\t\t\tgcNodes: {\n\t\t\t\tnode1: [\"/\", \"node2\"],\n\t\t\t\tnode2: [\"/\", \"node1\"],\n\t\t\t},\n\t\t};\n\t\tconst gcBlobName1 = `${gcBlobPrefix}_1`;\n\t\tconst gcBlobName2 = `${gcBlobPrefix}_2`;\n\t\t// Snapshot with couple of GC blobs at different layers.\n\t\tconst snapshot: ITree = {\n\t\t\tid: \"root\",\n\t\t\tentries: [\n\t\t\t\tnew TreeTreeEntry(\"tree\", {\n\t\t\t\t\tid: \"subTree\",\n\t\t\t\t\tentries: [new BlobTreeEntry(gcBlobName1, JSON.stringify(gcDetails))],\n\t\t\t\t}),\n\t\t\t\tnew BlobTreeEntry(gcBlobName2, JSON.stringify(gcDetails)),\n\t\t\t],\n\t\t};\n\n\t\tconst normalizedSnapshot = getNormalizedSnapshot(snapshot);\n\t\tassert.strictEqual(\n\t\t\tnormalizedSnapshot.entries[0].path,\n\t\t\tgcBlobName2,\n\t\t\t\"Snapshot tree entries not sorted\",\n\t\t);\n\t\tconst gcBlob = normalizedSnapshot.entries[0].value as IBlob;\n\t\tassert.deepStrictEqual(\n\t\t\tJSON.parse(gcBlob.contents),\n\t\t\tnormalizedGCDetails,\n\t\t\t\"GC blob not normalized\",\n\t\t);\n\n\t\tconst innerGCBlob = (normalizedSnapshot.entries[1].value as ITree).entries[0]\n\t\t\t.value as IBlob;\n\t\tassert.deepStrictEqual(\n\t\t\tJSON.parse(innerGCBlob.contents),\n\t\t\tnormalizedGCDetails,\n\t\t\t\"Inner blob not normalized\",\n\t\t);\n\t});\n\n\tit(\"can normalize custom blobs with array of objects\", () => {\n\t\t// Blob content which is an array of objects within objects.\n\t\tconst blobContents = [\n\t\t\t{ id: \"2\", content: { key: \"2\", value: \"two\" } },\n\t\t\t{ id: \"1\", content: { key: \"1\", value: \"one\" } },\n\t\t\t{ id: \"3\", content: { key: \"3\", value: \"three\" } },\n\t\t];\n\t\tconst normalizedBlobContents = [\n\t\t\t{ id: \"1\", content: { key: \"1\", value: \"one\" } },\n\t\t\t{ id: \"2\", content: { key: \"2\", value: \"two\" } },\n\t\t\t{ id: \"3\", content: { key: \"3\", value: \"three\" } },\n\t\t];\n\n\t\tconst snapshot: ITree = {\n\t\t\tid: \"root\",\n\t\t\tentries: [\n\t\t\t\t// Create a blob entry with normalized blob contents to make sure it remains normalized.\n\t\t\t\tnew BlobTreeEntry(\"normalized\", JSON.stringify(normalizedBlobContents)),\n\t\t\t\tnew BlobTreeEntry(\"custom\", JSON.stringify(blobContents)),\n\t\t\t],\n\t\t};\n\n\t\t// Config to normalize the above blobs.\n\t\tconst config: ISnapshotNormalizerConfig = { blobsToNormalize: [\"custom\", \"normalized\"] };\n\t\tconst normalizedSnapshot = getNormalizedSnapshot(snapshot, config);\n\n\t\tassert.strictEqual(\n\t\t\tnormalizedSnapshot.entries[0].path,\n\t\t\t\"custom\",\n\t\t\t\"Snapshot tree entries not sorted\",\n\t\t);\n\t\tconst customBlob = normalizedSnapshot.entries[0].value as IBlob;\n\t\tassert.deepStrictEqual(\n\t\t\tJSON.parse(customBlob.contents),\n\t\t\tnormalizedBlobContents,\n\t\t\t\"Custom blob not normalized\",\n\t\t);\n\n\t\tassert.strictEqual(normalizedSnapshot.entries[1].path, \"normalized\");\n\t\tconst normalizedBlob = normalizedSnapshot.entries[0].value as IBlob;\n\t\tassert.deepStrictEqual(\n\t\t\tJSON.parse(normalizedBlob.contents),\n\t\t\tnormalizedBlobContents,\n\t\t\t\"Normalized blob changed\",\n\t\t);\n\t});\n\n\tit(\"can normalize custom blobs with object of arrays\", () => {\n\t\t// Blob content which is an object whose properties are arrays.\n\t\tconst blobContents = {\n\t\t\tarray2: [\"2\", \"1\", \"3\", \"4\"],\n\t\t\tarray1: [\"c\", \"a\", \"d\", \"b\"],\n\t\t};\n\t\tconst normalizedBlobContents = {\n\t\t\tarray1: [\"a\", \"b\", \"c\", \"d\"],\n\t\t\tarray2: [\"1\", \"2\", \"3\", \"4\"],\n\t\t};\n\n\t\tconst snapshot: ITree = {\n\t\t\tid: \"root\",\n\t\t\tentries: [\n\t\t\t\t// Create a blob entry with normalized blob contents to make sure it remains normalized.\n\t\t\t\tnew BlobTreeEntry(\"normalized\", JSON.stringify(normalizedBlobContents)),\n\t\t\t\tnew BlobTreeEntry(\"custom\", JSON.stringify(blobContents)),\n\t\t\t],\n\t\t};\n\n\t\t// Config to normalize the above blobs.\n\t\tconst config: ISnapshotNormalizerConfig = { blobsToNormalize: [\"custom\", \"normalized\"] };\n\t\tconst normalizedSnapshot = getNormalizedSnapshot(snapshot, config);\n\n\t\tassert.strictEqual(\n\t\t\tnormalizedSnapshot.entries[0].path,\n\t\t\t\"custom\",\n\t\t\t\"Snapshot tree entries not sorted\",\n\t\t);\n\t\tconst customBlob = normalizedSnapshot.entries[0].value as IBlob;\n\t\tassert.deepStrictEqual(\n\t\t\tJSON.parse(customBlob.contents),\n\t\t\tnormalizedBlobContents,\n\t\t\t\"Custom blob not normalized\",\n\t\t);\n\n\t\tassert.strictEqual(normalizedSnapshot.entries[1].path, \"normalized\");\n\t\tconst normalizedBlob = normalizedSnapshot.entries[0].value as IBlob;\n\t\tassert.deepStrictEqual(\n\t\t\tJSON.parse(normalizedBlob.contents),\n\t\t\tnormalizedBlobContents,\n\t\t\t\"Normalized blob changed\",\n\t\t);\n\t});\n\n\tit(\"can normalize blob whose contents are not objects\", () => {\n\t\tconst snapshot: ITree = {\n\t\t\tid: \"root\",\n\t\t\tentries: [\n\t\t\t\t// Create blob entry whose content is a string so that it cannot be JSON parsed.\n\t\t\t\tnew BlobTreeEntry(\"custom1\", \"contents\"),\n\t\t\t\t// Create another blob whose content is a JSON stringified string which is already normalized.\n\t\t\t\tnew BlobTreeEntry(\"custom2\", JSON.stringify(\"contents\")),\n\t\t\t],\n\t\t};\n\n\t\t// Config to normalize the above blobs.\n\t\tconst config: ISnapshotNormalizerConfig = { blobsToNormalize: [\"custom1\", \"custom2\"] };\n\t\tconst normalizedSnapshot = getNormalizedSnapshot(snapshot, config);\n\t\tconst customBlob1 = normalizedSnapshot.entries[0].value as IBlob;\n\t\tassert.strictEqual(customBlob1.contents, \"contents\", \"Blob with string not as expected\");\n\n\t\tconst customBlob2 = normalizedSnapshot.entries[1].value as IBlob;\n\t\tassert.strictEqual(\n\t\t\tcustomBlob2.contents,\n\t\t\tJSON.stringify(\"contents\"),\n\t\t\t\"Blob with JSON strigified string not as expected\",\n\t\t);\n\t});\n});\n"]}
1
+ {"version":3,"file":"snapshotNormalizer.spec.js","sourceRoot":"","sources":["../../src/test/snapshotNormalizer.spec.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 { strict as assert } from \"assert\";\nimport { BlobTreeEntry, TreeTreeEntry } from \"@fluidframework/driver-utils\";\nimport { IBlob, ITree } from \"@fluidframework/protocol-definitions\";\nimport {\n\tISnapshotNormalizerConfig,\n\tgcBlobPrefix,\n\tgetNormalizedSnapshot,\n} from \"../snapshotNormalizer.js\";\n\ndescribe(\"Snapshot Normalizer\", () => {\n\tit(\"can normalize tree entries\", () => {\n\t\t// Snapshot tree with entries whose paths are not sorted.\n\t\tconst snapshot: ITree = {\n\t\t\tid: \"root\",\n\t\t\tentries: [\n\t\t\t\tnew TreeTreeEntry(\"entry2\", {\n\t\t\t\t\tid: \"subTree\",\n\t\t\t\t\tentries: [],\n\t\t\t\t}),\n\t\t\t\tnew BlobTreeEntry(\"entry3\", \"blob3\"),\n\t\t\t\tnew BlobTreeEntry(\"entry1\", \"blob1\"),\n\t\t\t],\n\t\t};\n\t\tconst normalizedSnapshot = getNormalizedSnapshot(snapshot);\n\t\tassert.strictEqual(\n\t\t\tnormalizedSnapshot.entries[0].path,\n\t\t\t\"entry1\",\n\t\t\t\"Snapshot tree entries not sorted\",\n\t\t);\n\t\tassert.strictEqual(\n\t\t\tnormalizedSnapshot.entries[1].path,\n\t\t\t\"entry2\",\n\t\t\t\"Snapshot tree entries not sorted\",\n\t\t);\n\t\tassert.strictEqual(\n\t\t\tnormalizedSnapshot.entries[2].path,\n\t\t\t\"entry3\",\n\t\t\t\"Snapshot tree entries not sorted\",\n\t\t);\n\t});\n\n\tit(\"can normalize GC blobs\", () => {\n\t\tconst gcDetails = {\n\t\t\tisRootNode: true,\n\t\t\tgcNodes: {\n\t\t\t\tnode2: [\"node1\", \"/\"],\n\t\t\t\tnode1: [\"node2\", \"/\"],\n\t\t\t},\n\t\t};\n\t\tconst normalizedGCDetails = {\n\t\t\tisRootNode: true,\n\t\t\tgcNodes: {\n\t\t\t\tnode1: [\"/\", \"node2\"],\n\t\t\t\tnode2: [\"/\", \"node1\"],\n\t\t\t},\n\t\t};\n\t\tconst gcBlobName1 = `${gcBlobPrefix}_1`;\n\t\tconst gcBlobName2 = `${gcBlobPrefix}_2`;\n\t\t// Snapshot with couple of GC blobs at different layers.\n\t\tconst snapshot: ITree = {\n\t\t\tid: \"root\",\n\t\t\tentries: [\n\t\t\t\tnew TreeTreeEntry(\"tree\", {\n\t\t\t\t\tid: \"subTree\",\n\t\t\t\t\tentries: [new BlobTreeEntry(gcBlobName1, JSON.stringify(gcDetails))],\n\t\t\t\t}),\n\t\t\t\tnew BlobTreeEntry(gcBlobName2, JSON.stringify(gcDetails)),\n\t\t\t],\n\t\t};\n\n\t\tconst normalizedSnapshot = getNormalizedSnapshot(snapshot);\n\t\tassert.strictEqual(\n\t\t\tnormalizedSnapshot.entries[0].path,\n\t\t\tgcBlobName2,\n\t\t\t\"Snapshot tree entries not sorted\",\n\t\t);\n\t\tconst gcBlob = normalizedSnapshot.entries[0].value as IBlob;\n\t\tassert.deepStrictEqual(\n\t\t\tJSON.parse(gcBlob.contents),\n\t\t\tnormalizedGCDetails,\n\t\t\t\"GC blob not normalized\",\n\t\t);\n\n\t\tconst innerGCBlob = (normalizedSnapshot.entries[1].value as ITree).entries[0]\n\t\t\t.value as IBlob;\n\t\tassert.deepStrictEqual(\n\t\t\tJSON.parse(innerGCBlob.contents),\n\t\t\tnormalizedGCDetails,\n\t\t\t\"Inner blob not normalized\",\n\t\t);\n\t});\n\n\tit(\"can normalize custom blobs with array of objects\", () => {\n\t\t// Blob content which is an array of objects within objects.\n\t\tconst blobContents = [\n\t\t\t{ id: \"2\", content: { key: \"2\", value: \"two\" } },\n\t\t\t{ id: \"1\", content: { key: \"1\", value: \"one\" } },\n\t\t\t{ id: \"3\", content: { key: \"3\", value: \"three\" } },\n\t\t];\n\t\tconst normalizedBlobContents = [\n\t\t\t{ id: \"1\", content: { key: \"1\", value: \"one\" } },\n\t\t\t{ id: \"2\", content: { key: \"2\", value: \"two\" } },\n\t\t\t{ id: \"3\", content: { key: \"3\", value: \"three\" } },\n\t\t];\n\n\t\tconst snapshot: ITree = {\n\t\t\tid: \"root\",\n\t\t\tentries: [\n\t\t\t\t// Create a blob entry with normalized blob contents to make sure it remains normalized.\n\t\t\t\tnew BlobTreeEntry(\"normalized\", JSON.stringify(normalizedBlobContents)),\n\t\t\t\tnew BlobTreeEntry(\"custom\", JSON.stringify(blobContents)),\n\t\t\t],\n\t\t};\n\n\t\t// Config to normalize the above blobs.\n\t\tconst config: ISnapshotNormalizerConfig = { blobsToNormalize: [\"custom\", \"normalized\"] };\n\t\tconst normalizedSnapshot = getNormalizedSnapshot(snapshot, config);\n\n\t\tassert.strictEqual(\n\t\t\tnormalizedSnapshot.entries[0].path,\n\t\t\t\"custom\",\n\t\t\t\"Snapshot tree entries not sorted\",\n\t\t);\n\t\tconst customBlob = normalizedSnapshot.entries[0].value as IBlob;\n\t\tassert.deepStrictEqual(\n\t\t\tJSON.parse(customBlob.contents),\n\t\t\tnormalizedBlobContents,\n\t\t\t\"Custom blob not normalized\",\n\t\t);\n\n\t\tassert.strictEqual(normalizedSnapshot.entries[1].path, \"normalized\");\n\t\tconst normalizedBlob = normalizedSnapshot.entries[0].value as IBlob;\n\t\tassert.deepStrictEqual(\n\t\t\tJSON.parse(normalizedBlob.contents),\n\t\t\tnormalizedBlobContents,\n\t\t\t\"Normalized blob changed\",\n\t\t);\n\t});\n\n\tit(\"can normalize custom blobs with object of arrays\", () => {\n\t\t// Blob content which is an object whose properties are arrays.\n\t\tconst blobContents = {\n\t\t\tarray2: [\"2\", \"1\", \"3\", \"4\"],\n\t\t\tarray1: [\"c\", \"a\", \"d\", \"b\"],\n\t\t};\n\t\tconst normalizedBlobContents = {\n\t\t\tarray1: [\"a\", \"b\", \"c\", \"d\"],\n\t\t\tarray2: [\"1\", \"2\", \"3\", \"4\"],\n\t\t};\n\n\t\tconst snapshot: ITree = {\n\t\t\tid: \"root\",\n\t\t\tentries: [\n\t\t\t\t// Create a blob entry with normalized blob contents to make sure it remains normalized.\n\t\t\t\tnew BlobTreeEntry(\"normalized\", JSON.stringify(normalizedBlobContents)),\n\t\t\t\tnew BlobTreeEntry(\"custom\", JSON.stringify(blobContents)),\n\t\t\t],\n\t\t};\n\n\t\t// Config to normalize the above blobs.\n\t\tconst config: ISnapshotNormalizerConfig = { blobsToNormalize: [\"custom\", \"normalized\"] };\n\t\tconst normalizedSnapshot = getNormalizedSnapshot(snapshot, config);\n\n\t\tassert.strictEqual(\n\t\t\tnormalizedSnapshot.entries[0].path,\n\t\t\t\"custom\",\n\t\t\t\"Snapshot tree entries not sorted\",\n\t\t);\n\t\tconst customBlob = normalizedSnapshot.entries[0].value as IBlob;\n\t\tassert.deepStrictEqual(\n\t\t\tJSON.parse(customBlob.contents),\n\t\t\tnormalizedBlobContents,\n\t\t\t\"Custom blob not normalized\",\n\t\t);\n\n\t\tassert.strictEqual(normalizedSnapshot.entries[1].path, \"normalized\");\n\t\tconst normalizedBlob = normalizedSnapshot.entries[0].value as IBlob;\n\t\tassert.deepStrictEqual(\n\t\t\tJSON.parse(normalizedBlob.contents),\n\t\t\tnormalizedBlobContents,\n\t\t\t\"Normalized blob changed\",\n\t\t);\n\t});\n\n\tit(\"can normalize blob whose contents are not objects\", () => {\n\t\tconst snapshot: ITree = {\n\t\t\tid: \"root\",\n\t\t\tentries: [\n\t\t\t\t// Create blob entry whose content is a string so that it cannot be JSON parsed.\n\t\t\t\tnew BlobTreeEntry(\"custom1\", \"contents\"),\n\t\t\t\t// Create another blob whose content is a JSON stringified string which is already normalized.\n\t\t\t\tnew BlobTreeEntry(\"custom2\", JSON.stringify(\"contents\")),\n\t\t\t],\n\t\t};\n\n\t\t// Config to normalize the above blobs.\n\t\tconst config: ISnapshotNormalizerConfig = { blobsToNormalize: [\"custom1\", \"custom2\"] };\n\t\tconst normalizedSnapshot = getNormalizedSnapshot(snapshot, config);\n\t\tconst customBlob1 = normalizedSnapshot.entries[0].value as IBlob;\n\t\tassert.strictEqual(customBlob1.contents, \"contents\", \"Blob with string not as expected\");\n\n\t\tconst customBlob2 = normalizedSnapshot.entries[1].value as IBlob;\n\t\tassert.strictEqual(\n\t\t\tcustomBlob2.contents,\n\t\t\tJSON.stringify(\"contents\"),\n\t\t\t\"Blob with JSON strigified string not as expected\",\n\t\t);\n\t});\n});\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/tool-utils",
3
- "version": "2.0.0-dev-rc.2.0.0.246488",
3
+ "version": "2.0.0-dev-rc.3.0.0.250606",
4
4
  "description": "Common utilities for Fluid tools",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -67,9 +67,9 @@
67
67
  "temp-directory": "nyc/.nyc_output"
68
68
  },
69
69
  "dependencies": {
70
- "@fluidframework/core-utils": "2.0.0-dev-rc.2.0.0.246488",
71
- "@fluidframework/driver-utils": "2.0.0-dev-rc.2.0.0.246488",
72
- "@fluidframework/odsp-doclib-utils": "2.0.0-dev-rc.2.0.0.246488",
70
+ "@fluidframework/core-utils": "2.0.0-dev-rc.3.0.0.250606",
71
+ "@fluidframework/driver-utils": "2.0.0-dev-rc.3.0.0.250606",
72
+ "@fluidframework/odsp-doclib-utils": "2.0.0-dev-rc.3.0.0.250606",
73
73
  "@fluidframework/protocol-definitions": "^3.2.0",
74
74
  "async-mutex": "^0.3.1",
75
75
  "debug": "^4.3.4",
@@ -78,7 +78,8 @@
78
78
  },
79
79
  "devDependencies": {
80
80
  "@arethetypeswrong/cli": "^0.13.3",
81
- "@fluid-internal/mocha-test-setup": "2.0.0-dev-rc.2.0.0.246488",
81
+ "@biomejs/biome": "^1.6.2",
82
+ "@fluid-internal/mocha-test-setup": "2.0.0-dev-rc.3.0.0.250606",
82
83
  "@fluid-tools/build-cli": "^0.34.0",
83
84
  "@fluidframework/build-common": "^2.0.3",
84
85
  "@fluidframework/build-tools": "^0.34.0",
@@ -129,16 +130,18 @@
129
130
  "build:test:cjs": "fluid-tsc commonjs --project ./src/test/tsconfig.cjs.json",
130
131
  "build:test:esm": "tsc --project ./src/test/tsconfig.json",
131
132
  "check:are-the-types-wrong": "attw --pack . --entrypoints .",
133
+ "check:biome": "biome check .",
134
+ "check:prettier": "prettier --check . --cache --ignore-path ../../../.prettierignore",
132
135
  "check:release-tags": "api-extractor run --local --config ./api-extractor-lint.json",
133
136
  "ci:build:docs": "api-extractor run",
134
137
  "clean": "rimraf --glob dist lib \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp nyc",
135
138
  "eslint": "eslint --format stylish src",
136
139
  "eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
137
- "format": "npm run prettier:fix",
138
- "lint": "npm run prettier && npm run check:release-tags && npm run eslint",
139
- "lint:fix": "npm run prettier:fix && npm run eslint:fix",
140
- "prettier": "prettier --check . --cache --ignore-path ../../../.prettierignore",
141
- "prettier:fix": "prettier --write . --cache --ignore-path ../../../.prettierignore",
140
+ "format": "fluid-build --task format .",
141
+ "format:biome": "biome check --apply .",
142
+ "format:prettier": "prettier --write . --cache --ignore-path ../../../.prettierignore",
143
+ "lint": "fluid-build . --task lint",
144
+ "lint:fix": "fluid-build . --task eslint:fix --task format",
142
145
  "test": "npm run test:mocha",
143
146
  "test:coverage": "c8 npm test",
144
147
  "test:mocha": "npm run test:mocha:esm && echo skipping cjs to avoid overhead - npm run test:mocha:cjs",
@@ -7,8 +7,8 @@ import fs from "fs";
7
7
  import os from "os";
8
8
  import path from "path";
9
9
  import util from "util";
10
- import { lock } from "proper-lockfile";
11
10
  import { IOdspTokens } from "@fluidframework/odsp-doclib-utils/internal";
11
+ import { lock } from "proper-lockfile";
12
12
 
13
13
  /**
14
14
  * @internal
@@ -5,20 +5,20 @@
5
5
 
6
6
  import { unreachableCase } from "@fluidframework/core-utils";
7
7
  import {
8
- IOdspTokens,
9
8
  IClientConfig,
9
+ IOdspTokens,
10
+ TokenRequestCredentials,
10
11
  fetchTokens,
11
- refreshTokens,
12
+ getLoginPageUrl,
12
13
  getOdspScope,
13
14
  pushScope,
14
- getLoginPageUrl,
15
- TokenRequestCredentials,
15
+ refreshTokens,
16
16
  } from "@fluidframework/odsp-doclib-utils/internal";
17
- import { jwtDecode } from "jwt-decode";
18
17
  import { Mutex } from "async-mutex";
18
+ import { jwtDecode } from "jwt-decode";
19
19
  import { debug } from "./debug.js";
20
- import { IAsyncCache, loadRC, saveRC, lockRC } from "./fluidToolRC.js";
21
- import { serverListenAndHandle, endResponse } from "./httpHelpers.js";
20
+ import { IAsyncCache, loadRC, lockRC, saveRC } from "./fluidToolRC.js";
21
+ import { endResponse, serverListenAndHandle } from "./httpHelpers.js";
22
22
 
23
23
  const odspAuthRedirectPort = 7000;
24
24
  const odspAuthRedirectOrigin = `http://localhost:${odspAuthRedirectPort}`;
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/tool-utils";
9
- export const pkgVersion = "2.0.0-dev-rc.2.0.0.246488";
9
+ export const pkgVersion = "2.0.0-dev-rc.3.0.0.250606";
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { AttachmentTreeEntry, BlobTreeEntry, TreeTreeEntry } from "@fluidframework/driver-utils";
7
- import { ITree, TreeEntry, ITreeEntry } from "@fluidframework/protocol-definitions";
7
+ import { ITree, ITreeEntry, TreeEntry } from "@fluidframework/protocol-definitions";
8
8
 
9
9
  /** The name of the metadata blob added to the root of the container runtime. */
10
10
  const metadataBlobName = ".metadata";
@@ -116,8 +116,8 @@ function getNormalizedBlobContent(blobContent: string, blobName: string): string
116
116
  metadata.telemetryDocumentId = "x";
117
117
  }
118
118
  // default was not written before, now it's written in.
119
- if (metadata.idCompressorMode === undefined) {
120
- metadata.idCompressorMode = "off";
119
+ if (metadata.documentSchema !== undefined) {
120
+ metadata.documentSchema = undefined;
121
121
  }
122
122
  content = JSON.stringify(metadata);
123
123
  }