@fluidframework/tool-utils 2.0.2 → 2.1.0-276326

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/.eslintrc.cjs +2 -15
  2. package/api-report/tool-utils.alpha.api.md +0 -4
  3. package/api-report/tool-utils.beta.api.md +0 -4
  4. package/api-report/tool-utils.public.api.md +0 -4
  5. package/dist/debug.d.ts.map +1 -1
  6. package/dist/debug.js +2 -0
  7. package/dist/debug.js.map +1 -1
  8. package/dist/{fluidToolRC.d.ts → fluidToolRc.d.ts} +7 -9
  9. package/dist/fluidToolRc.d.ts.map +1 -0
  10. package/dist/{fluidToolRC.js → fluidToolRc.js} +16 -11
  11. package/dist/fluidToolRc.js.map +1 -0
  12. package/dist/httpHelpers.d.ts +2 -2
  13. package/dist/httpHelpers.d.ts.map +1 -1
  14. package/dist/httpHelpers.js +16 -4
  15. package/dist/httpHelpers.js.map +1 -1
  16. package/dist/index.d.ts +6 -3
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +4 -4
  19. package/dist/index.js.map +1 -1
  20. package/dist/odspTokenManager.d.ts +2 -2
  21. package/dist/odspTokenManager.d.ts.map +1 -1
  22. package/dist/odspTokenManager.js +18 -11
  23. package/dist/odspTokenManager.js.map +1 -1
  24. package/dist/packageVersion.d.ts +1 -1
  25. package/dist/packageVersion.d.ts.map +1 -1
  26. package/dist/packageVersion.js +1 -1
  27. package/dist/packageVersion.js.map +1 -1
  28. package/dist/snapshotNormalizer.d.ts +1 -1
  29. package/dist/snapshotNormalizer.d.ts.map +1 -1
  30. package/dist/snapshotNormalizer.js +24 -12
  31. package/dist/snapshotNormalizer.js.map +1 -1
  32. package/lib/debug.d.ts.map +1 -1
  33. package/lib/debug.js +2 -0
  34. package/lib/debug.js.map +1 -1
  35. package/lib/{fluidToolRC.d.ts → fluidToolRc.d.ts} +7 -9
  36. package/lib/fluidToolRc.d.ts.map +1 -0
  37. package/lib/{fluidToolRC.js → fluidToolRc.js} +12 -7
  38. package/lib/fluidToolRc.js.map +1 -0
  39. package/lib/httpHelpers.d.ts +2 -2
  40. package/lib/httpHelpers.d.ts.map +1 -1
  41. package/lib/httpHelpers.js +15 -3
  42. package/lib/httpHelpers.js.map +1 -1
  43. package/lib/index.d.ts +6 -3
  44. package/lib/index.d.ts.map +1 -1
  45. package/lib/index.js +2 -2
  46. package/lib/index.js.map +1 -1
  47. package/lib/odspTokenManager.d.ts +2 -2
  48. package/lib/odspTokenManager.d.ts.map +1 -1
  49. package/lib/odspTokenManager.js +15 -8
  50. package/lib/odspTokenManager.js.map +1 -1
  51. package/lib/packageVersion.d.ts +1 -1
  52. package/lib/packageVersion.d.ts.map +1 -1
  53. package/lib/packageVersion.js +1 -1
  54. package/lib/packageVersion.js.map +1 -1
  55. package/lib/snapshotNormalizer.d.ts +1 -1
  56. package/lib/snapshotNormalizer.d.ts.map +1 -1
  57. package/lib/snapshotNormalizer.js +24 -12
  58. package/lib/snapshotNormalizer.js.map +1 -1
  59. package/package.json +11 -10
  60. package/src/debug.ts +2 -0
  61. package/src/{fluidToolRC.ts → fluidToolRc.ts} +20 -14
  62. package/src/httpHelpers.ts +27 -5
  63. package/src/index.ts +5 -8
  64. package/src/odspTokenManager.ts +41 -23
  65. package/src/packageVersion.ts +1 -1
  66. package/src/snapshotNormalizer.ts +40 -19
  67. package/dist/fluidToolRC.d.ts.map +0 -1
  68. package/dist/fluidToolRC.js.map +0 -1
  69. package/lib/fluidToolRC.d.ts.map +0 -1
  70. package/lib/fluidToolRC.js.map +0 -1
@@ -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/internal\";\nimport {\n\tIPublicClientConfig,\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\";\n\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 = (): IPublicClientConfig => ({\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});\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(\n\t\tkey: IOdspTokenManagerCacheKey,\n\t\tvalue: IOdspTokens,\n\t) {\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: IPublicClientConfig,\n\t\ttokenConfig: OdspTokenConfig,\n\t\tforceRefresh = false,\n\t\tforceReauth = false,\n\t): Promise<IOdspTokens> {\n\t\tdebug(\"Getting odsp tokens\");\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: IPublicClientConfig,\n\t\ttokenConfig: OdspTokenConfig,\n\t\tforceRefresh = false,\n\t\tforceReauth = false,\n\t): Promise<IOdspTokens> {\n\t\tdebug(\"Getting push tokens\");\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: IPublicClientConfig,\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: IPublicClientConfig,\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: IPublicClientConfig,\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: IPublicClientConfig,\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/internal\";\nimport type {\n\tIPublicClientConfig,\n\tIOdspTokens,\n\tTokenRequestCredentials,\n} from \"@fluidframework/odsp-doclib-utils/internal\";\nimport {\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\";\n\nimport { debug } from \"./debug.js\";\nimport type { IAsyncCache, IResources } from \"./fluidToolRc.js\";\nimport { 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// TODO: Add documentation\n// eslint-disable-next-line jsdoc/require-description\n/**\n * @internal\n */\nexport const getMicrosoftConfiguration = (): IPublicClientConfig => ({\n\tget clientId(): string {\n\t\t// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions\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});\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): boolean => {\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<{ exp: number }>(token);\n\t// Give it a 60s buffer\n\treturn decodedToken.exp - 60 >= Date.now() / 1000;\n};\n\nconst cacheKeyToString = (key: IOdspTokenManagerCacheKey): string => {\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\tpublic constructor(\n\t\tprivate readonly tokenCache?: IAsyncCache<IOdspTokenManagerCacheKey, IOdspTokens>,\n\t) {}\n\n\tpublic async updateTokensCache(\n\t\tkey: IOdspTokenManagerCacheKey,\n\t\tvalue: IOdspTokens,\n\t): Promise<void> {\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(\n\t\tkey: IOdspTokenManagerCacheKey,\n\t\tvalue: IOdspTokens,\n\t): Promise<void> {\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: IPublicClientConfig,\n\t\ttokenConfig: OdspTokenConfig,\n\t\tforceRefresh = false,\n\t\tforceReauth = false,\n\t): Promise<IOdspTokens> {\n\t\tdebug(\"Getting odsp tokens\");\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: IPublicClientConfig,\n\t\ttokenConfig: OdspTokenConfig,\n\t\tforceRefresh = false,\n\t\tforceReauth = false,\n\t): Promise<IOdspTokens> {\n\t\tdebug(\"Getting push tokens\");\n\t\treturn this.getTokens(true, server, clientConfig, tokenConfig, forceRefresh, forceReauth);\n\t}\n\n\tprivate async getTokenFromCache(\n\t\tcacheKey: IOdspTokenManagerCacheKey,\n\t): Promise<IOdspTokens | undefined> {\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: IPublicClientConfig,\n\t\ttokenConfig: OdspTokenConfig,\n\t\tforceRefresh: boolean,\n\t\tforceReauth: boolean,\n\t): Promise<IOdspTokens> {\n\t\tconst invokeGetTokensCore = async (): Promise<IOdspTokens> => {\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: IPublicClientConfig,\n\t\ttokenConfig: OdspTokenConfig,\n\t\tforceRefresh: boolean,\n\t\tforceReauth: boolean,\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\t}\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\t}\n\t\t\tdefault: {\n\t\t\t\tunreachableCase(tokenConfig);\n\t\t\t}\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: IPublicClientConfig,\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: IPublicClientConfig,\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(\n\t\tconfig: OdspTokenConfig,\n\t\ttokens: IOdspTokens,\n\t): Promise<void> {\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 new 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 === null || code === undefined) {\n\t\t\tthrow new Error(\"Failed to get authorization\");\n\t\t}\n\t\treturn code;\n\t}\n}\n\nasync function loadAndPatchRC(): Promise<IResources> {\n\tconst rc = await loadRC();\n\tif (rc.tokens && rc.tokens.version === undefined) {\n\t\t// Clean up older versions\n\t\tdelete rc.tokens;\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any\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.2";
8
+ export declare const pkgVersion = "2.1.0-276326";
9
9
  //# sourceMappingURL=packageVersion.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,+BAA+B,CAAC;AACpD,eAAO,MAAM,UAAU,UAAU,CAAC"}
1
+ {"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,+BAA+B,CAAC;AACpD,eAAO,MAAM,UAAU,iBAAiB,CAAC"}
@@ -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.2";
8
+ export const pkgVersion = "2.1.0-276326";
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,OAAO,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.2\";\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,cAAc,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.1.0-276326\";\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 { ITree } from "@fluidframework/driver-definitions/internal";
5
+ import type { ITree } from "@fluidframework/driver-definitions/internal";
6
6
  /**
7
7
  * The prefix that all GC blob names start with.
8
8
  *
@@ -1 +1 @@
1
- {"version":3,"file":"snapshotNormalizer.d.ts","sourceRoot":"","sources":["../src/snapshotNormalizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAyB,MAAM,6CAA6C,CAAC;AAS3F;;;;GAIG;AACH,eAAO,MAAM,YAAY,SAAS,CAAC;AAEnC;;GAEG;AACH,MAAM,WAAW,yBAAyB;IAEzC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B;;;;OAIG;IACH,2BAA2B,CAAC,EAAE,MAAM,EAAE,CAAC;CACvC;AA4GD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACpC,QAAQ,EAAE,KAAK,EACf,MAAM,CAAC,EAAE,yBAAyB,GAChC,KAAK,CAkBP"}
1
+ {"version":3,"file":"snapshotNormalizer.d.ts","sourceRoot":"","sources":["../src/snapshotNormalizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAc,MAAM,6CAA6C,CAAC;AAarF;;;;GAIG;AACH,eAAO,MAAM,YAAY,SAAS,CAAC;AAEnC;;GAEG;AACH,MAAM,WAAW,yBAAyB;IAEzC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B;;;;OAIG;IACH,2BAA2B,CAAC,EAAE,MAAM,EAAE,CAAC;CACvC;AAwHD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACpC,QAAQ,EAAE,KAAK,EACf,MAAM,CAAC,EAAE,yBAAyB,GAChC,KAAK,CAkBP"}
@@ -4,7 +4,9 @@
4
4
  */
5
5
  import { TreeEntry } from "@fluidframework/driver-definitions/internal";
6
6
  import { AttachmentTreeEntry, BlobTreeEntry, TreeTreeEntry, } from "@fluidframework/driver-utils/internal";
7
- /** The name of the metadata blob added to the root of the container runtime. */
7
+ /**
8
+ * The name of the metadata blob added to the root of the container runtime.
9
+ */
8
10
  const metadataBlobName = ".metadata";
9
11
  /**
10
12
  * The prefix that all GC blob names start with.
@@ -12,6 +14,11 @@ const metadataBlobName = ".metadata";
12
14
  * @internal
13
15
  */
14
16
  export const gcBlobPrefix = "__gc";
17
+ const sortStringified = (elem1, elem2) => {
18
+ const serializedElem1 = JSON.stringify(elem1);
19
+ const serializedElem2 = JSON.stringify(elem2);
20
+ return serializedElem1.localeCompare(serializedElem2);
21
+ };
15
22
  /**
16
23
  * Function that deep sorts an array. It handles cases where array elements are objects or arrays.
17
24
  * @returns the sorted array.
@@ -32,18 +39,14 @@ function getDeepSortedArray(array) {
32
39
  }
33
40
  // Now that all the arrays and objects in this array's elements have been sorted, sort it by comparing each
34
41
  // element's stringified version.
35
- const sortFn = (elem1, elem2) => {
36
- const serializedElem1 = JSON.stringify(elem1);
37
- const serializedElem2 = JSON.stringify(elem2);
38
- return serializedElem1.localeCompare(serializedElem2);
39
- };
40
- return sortedArray.sort(sortFn);
42
+ return sortedArray.sort(sortStringified);
41
43
  }
42
44
  /**
43
45
  * Function that deep sorts an object. It handles cases where object properties are arrays or objects.
44
46
  * @returns the sorted object.
45
47
  */
46
48
  function getDeepSortedObject(obj) {
49
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
47
50
  const sortedObj = {};
48
51
  // Sort the object keys first. Then sort arrays and objects, if any, in the object.
49
52
  const keys = Object.keys(obj).sort();
@@ -69,10 +72,14 @@ function getDeepSortedObject(obj) {
69
72
  function getNormalizedBlobContent(blobContent, blobName) {
70
73
  let content = blobContent;
71
74
  if (blobName.startsWith(gcBlobPrefix)) {
75
+ // The following code parses JSON and makes some assumptions about the type of data within. There does not appear to
76
+ // be a better type than `any` to use here, so the lint rules are disabled.
77
+ /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */
72
78
  // GC blobs may contain `unreferencedTimestampMs` for node that became unreferenced. This is the timestamp
73
79
  // of the last op processed or current timestamp and can differ between clients depending on when GC was run.
74
80
  // So, remove it for the purposes of comparing snapshots.
75
81
  const gcState = JSON.parse(content);
82
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
76
83
  for (const [, data] of Object.entries(gcState.gcNodes)) {
77
84
  delete data.unreferencedTimestampMs;
78
85
  }
@@ -113,7 +120,10 @@ function getNormalizedBlobContent(blobContent, blobName) {
113
120
  }
114
121
  content = JSON.stringify(contentObj);
115
122
  }
116
- catch { }
123
+ catch {
124
+ // Do nothing
125
+ }
126
+ /* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */
117
127
  return content;
118
128
  }
119
129
  /**
@@ -158,6 +168,7 @@ function normalizeMatrix(value) {
158
168
  if (!header?.value.contents.includes("removedClientId")) {
159
169
  return value;
160
170
  }
171
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */
161
172
  const contents = JSON.parse(header?.value.contents);
162
173
  for (const segment of contents.segments) {
163
174
  if ("removedClientId" in segment) {
@@ -168,6 +179,7 @@ function normalizeMatrix(value) {
168
179
  }
169
180
  }
170
181
  header.value.contents = JSON.stringify(contents);
182
+ /* eslint-enable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */
171
183
  return value;
172
184
  }
173
185
  function normalizeEntry(entry, config) {
@@ -175,9 +187,7 @@ function normalizeEntry(entry, config) {
175
187
  case TreeEntry.Blob: {
176
188
  let contents = entry.value.contents;
177
189
  // If this blob has to be normalized or it's a GC blob, parse and sort the blob contents first.
178
- if (
179
- // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- ?? is not logically equivalent when .includes returns false.
180
- config?.blobsToNormalize?.includes(entry.path) ||
190
+ if ((config?.blobsToNormalize?.includes(entry.path) ?? false) ||
181
191
  entry.path.startsWith(gcBlobPrefix)) {
182
192
  contents = getNormalizedBlobContent(contents, entry.path);
183
193
  }
@@ -188,6 +198,7 @@ function normalizeEntry(entry, config) {
188
198
  for (const maybeAttributes of entry.value.entries) {
189
199
  if (maybeAttributes.type === TreeEntry.Blob &&
190
200
  maybeAttributes.path === ".attributes") {
201
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
191
202
  const parsed = JSON.parse(maybeAttributes.value.contents);
192
203
  if (parsed.type === "https://graph.microsoft.com/types/sharedmatrix") {
193
204
  return new TreeTreeEntry(entry.path, normalizeMatrix(getNormalizedSnapshot(entry.value, config)));
@@ -205,8 +216,9 @@ function normalizeEntry(entry, config) {
205
216
  case TreeEntry.Attachment: {
206
217
  return new AttachmentTreeEntry(entry.path, entry.value.id);
207
218
  }
208
- default:
219
+ default: {
209
220
  throw new Error("Unknown entry type");
221
+ }
210
222
  }
211
223
  }
212
224
  //# sourceMappingURL=snapshotNormalizer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"snapshotNormalizer.js","sourceRoot":"","sources":["../src/snapshotNormalizer.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITree, ITreeEntry, TreeEntry } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tAttachmentTreeEntry,\n\tBlobTreeEntry,\n\tTreeTreeEntry,\n} from \"@fluidframework/driver-utils/internal\";\n\n/** The name of the metadata blob added to the root of the container runtime. */\nconst metadataBlobName = \".metadata\";\n/**\n * The prefix that all GC blob names start with.\n *\n * @internal\n */\nexport const gcBlobPrefix = \"__gc\";\n\n/**\n * @internal\n */\nexport interface ISnapshotNormalizerConfig {\n\t// The paths of blobs whose contents should be normalized.\n\tblobsToNormalize?: string[];\n\t/**\n\t * channel types who's content (non-attribute) blobs will be excluded.\n\t * this is used to exclude the content of channels who's content cannot be compared\n\t * as the content is non-deterministic between snapshot at the same sequence number.\n\t */\n\texcludedChannelContentTypes?: string[];\n}\n\n/**\n * Function that deep sorts an array. It handles cases where array elements are objects or arrays.\n * @returns the sorted array.\n */\nfunction getDeepSortedArray(array: any[]): any[] {\n\tconst sortedArray: any[] = [];\n\t// Sort arrays and objects, if any, in the array.\n\tfor (const element of array) {\n\t\tif (Array.isArray(element)) {\n\t\t\tsortedArray.push(getDeepSortedArray(element));\n\t\t} else if (element instanceof Object) {\n\t\t\tsortedArray.push(getDeepSortedObject(element));\n\t\t} else {\n\t\t\tsortedArray.push(element);\n\t\t}\n\t}\n\n\t// Now that all the arrays and objects in this array's elements have been sorted, sort it by comparing each\n\t// element's stringified version.\n\tconst sortFn = (elem1: any, elem2: any) => {\n\t\tconst serializedElem1 = JSON.stringify(elem1);\n\t\tconst serializedElem2 = JSON.stringify(elem2);\n\t\treturn serializedElem1.localeCompare(serializedElem2);\n\t};\n\n\treturn sortedArray.sort(sortFn);\n}\n\n/**\n * Function that deep sorts an object. It handles cases where object properties are arrays or objects.\n * @returns the sorted object.\n */\nfunction getDeepSortedObject(obj: any): any {\n\tconst sortedObj: any = {};\n\t// Sort the object keys first. Then sort arrays and objects, if any, in the object.\n\tconst keys = Object.keys(obj).sort();\n\tfor (const key of keys) {\n\t\tconst value = obj[key];\n\t\tif (Array.isArray(value)) {\n\t\t\tsortedObj[key] = getDeepSortedArray(value);\n\t\t} else if (value instanceof Object) {\n\t\t\tsortedObj[key] = getDeepSortedObject(value);\n\t\t} else {\n\t\t\tsortedObj[key] = value;\n\t\t}\n\t}\n\n\treturn sortedObj;\n}\n\n/**\n * Function that normalizes a blob's content. If the content is an object or an array, deep sorts them.\n * Special handling for certain runtime blobs, such as the \"gc\" blob.\n * @returns the normalized blob content.\n */\nfunction getNormalizedBlobContent(blobContent: string, blobName: string): string {\n\tlet content = blobContent;\n\tif (blobName.startsWith(gcBlobPrefix)) {\n\t\t// GC blobs may contain `unreferencedTimestampMs` for node that became unreferenced. This is the timestamp\n\t\t// of the last op processed or current timestamp and can differ between clients depending on when GC was run.\n\t\t// So, remove it for the purposes of comparing snapshots.\n\t\tconst gcState = JSON.parse(content);\n\t\tfor (const [, data] of Object.entries(gcState.gcNodes)) {\n\t\t\tdelete (data as any).unreferencedTimestampMs;\n\t\t}\n\t\tcontent = JSON.stringify(gcState);\n\t}\n\n\t/**\n\t * The metadata blob has \"summaryNumber\" or \"summaryCount\" that tells which summary this is for a container. It can\n\t * be different in summaries of two clients even if they are generated at the same sequence#. For instance, at seq#\n\t * 1000, if one client has summarized 10 times and other has summarizer 15 times, summaryNumber will be different\n\t * for them. So, update \"summaryNumber\" to 0 for purposes of comparing snapshots.\n\t */\n\tif (blobName === metadataBlobName) {\n\t\tconst metadata = JSON.parse(content);\n\t\tif (metadata.summaryNumber !== undefined) {\n\t\t\tmetadata.summaryNumber = 0;\n\t\t}\n\t\tif (metadata.summaryCount !== undefined) {\n\t\t\tmetadata.summaryCount = 0;\n\t\t}\n\t\t// \"telemetryDocumentId\" is not a deterministic property (random guid), so we need to set it to something consistent\n\t\tif (metadata.telemetryDocumentId !== undefined) {\n\t\t\tmetadata.telemetryDocumentId = \"x\";\n\t\t}\n\t\t// default was not written before, now it's written in.\n\t\tif (metadata.documentSchema !== undefined) {\n\t\t\tmetadata.documentSchema = undefined;\n\t\t}\n\t\tcontent = JSON.stringify(metadata);\n\t}\n\n\t// Deep sort the content if it's parseable.\n\ttry {\n\t\tlet contentObj = JSON.parse(content);\n\t\tif (Array.isArray(contentObj)) {\n\t\t\tcontentObj = getDeepSortedArray(contentObj);\n\t\t} else if (contentObj instanceof Object) {\n\t\t\tcontentObj = getDeepSortedObject(contentObj);\n\t\t}\n\t\tcontent = JSON.stringify(contentObj);\n\t} catch {}\n\treturn content;\n}\n\n/**\n * Helper function that normalizes the given snapshot tree. It sorts objects and arrays in the snapshot. It also\n * normalizes certain blob contents for which the order of content does not matter. For example, garbage collection\n * blobs contains objects / arrays whose element order do not matter.\n * @param snapshot - The snapshot tree to normalize.\n * @param config - Configs to use when normalizing snapshot. For example, it can contain paths of blobs whose contents\n * should be normalized as well.\n * @returns a copy of the normalized snapshot tree.\n * @internal\n */\nexport function getNormalizedSnapshot(\n\tsnapshot: ITree,\n\tconfig?: ISnapshotNormalizerConfig,\n): ITree {\n\t// Merge blobs to normalize in the config with runtime blobs to normalize. The contents of these blobs will be\n\t// parsed and deep sorted.\n\tconst normalizedEntries: ITreeEntry[] = [];\n\n\t// The metadata blob in the root of the summary tree needs to be normalized.\n\tconst blobsToNormalize = [metadataBlobName, ...(config?.blobsToNormalize ?? [])];\n\tfor (const entry of snapshot.entries) {\n\t\tnormalizedEntries.push(normalizeEntry(entry, { ...config, blobsToNormalize }));\n\t}\n\n\t// Sort the tree entries based on their path.\n\tnormalizedEntries.sort((a, b) => a.path.localeCompare(b.path));\n\n\treturn {\n\t\tentries: normalizedEntries,\n\t\tid: snapshot.id,\n\t};\n}\n\nfunction normalizeMatrix(value: ITree): ITree {\n\tconst rows = value.entries.find((e) => e.path === \"rows\");\n\n\tif (!rows || !(\"entries\" in rows.value)) {\n\t\treturn value;\n\t}\n\n\tconst segments = rows.value.entries.find((e) => e.path === \"segments\");\n\n\tif (!segments || !(\"entries\" in segments.value)) {\n\t\treturn value;\n\t}\n\n\tconst header = segments.value.entries.find((e) => e.path === \"header\");\n\n\tif (!header || !(\"contents\" in header.value)) {\n\t\treturn value;\n\t}\n\n\tif (!header?.value.contents.includes(\"removedClientId\")) {\n\t\treturn value;\n\t}\n\n\tconst contents = JSON.parse(header?.value.contents);\n\n\tfor (const segment of contents.segments) {\n\t\tif (\"removedClientId\" in segment) {\n\t\t\tsegment.removedClientId = undefined;\n\t\t}\n\n\t\tif (\"removedClientIds\" in segment) {\n\t\t\tsegment.removedClientIds = undefined;\n\t\t}\n\t}\n\n\theader.value.contents = JSON.stringify(contents);\n\n\treturn value;\n}\n\nfunction normalizeEntry(\n\tentry: ITreeEntry,\n\tconfig: ISnapshotNormalizerConfig | undefined,\n): ITreeEntry {\n\tswitch (entry.type) {\n\t\tcase TreeEntry.Blob: {\n\t\t\tlet contents = entry.value.contents;\n\t\t\t// If this blob has to be normalized or it's a GC blob, parse and sort the blob contents first.\n\t\t\tif (\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- ?? is not logically equivalent when .includes returns false.\n\t\t\t\tconfig?.blobsToNormalize?.includes(entry.path) ||\n\t\t\t\tentry.path.startsWith(gcBlobPrefix)\n\t\t\t) {\n\t\t\t\tcontents = getNormalizedBlobContent(contents, entry.path);\n\t\t\t}\n\t\t\treturn new BlobTreeEntry(entry.path, contents);\n\t\t}\n\t\tcase TreeEntry.Tree: {\n\t\t\tif (config?.excludedChannelContentTypes !== undefined) {\n\t\t\t\tfor (const maybeAttributes of entry.value.entries) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tmaybeAttributes.type === TreeEntry.Blob &&\n\t\t\t\t\t\tmaybeAttributes.path === \".attributes\"\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst parsed: { type?: string } = JSON.parse(maybeAttributes.value.contents);\n\t\t\t\t\t\tif (parsed.type === \"https://graph.microsoft.com/types/sharedmatrix\") {\n\t\t\t\t\t\t\treturn new TreeTreeEntry(\n\t\t\t\t\t\t\t\tentry.path,\n\t\t\t\t\t\t\t\tnormalizeMatrix(getNormalizedSnapshot(entry.value, config)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tparsed.type !== undefined &&\n\t\t\t\t\t\t\tconfig.excludedChannelContentTypes.includes(parsed.type)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t// remove everything to match the unknown channel\n\t\t\t\t\t\t\treturn new TreeTreeEntry(entry.path, { entries: [maybeAttributes] });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn new TreeTreeEntry(entry.path, getNormalizedSnapshot(entry.value, config));\n\t\t}\n\t\tcase TreeEntry.Attachment: {\n\t\t\treturn new AttachmentTreeEntry(entry.path, entry.value.id);\n\t\t}\n\n\t\tdefault:\n\t\t\tthrow new Error(\"Unknown entry type\");\n\t}\n}\n"]}
1
+ {"version":3,"file":"snapshotNormalizer.js","sourceRoot":"","sources":["../src/snapshotNormalizer.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { ITree, ITreeEntry } from \"@fluidframework/driver-definitions/internal\";\nimport { TreeEntry } from \"@fluidframework/driver-definitions/internal\";\nimport {\n\tAttachmentTreeEntry,\n\tBlobTreeEntry,\n\tTreeTreeEntry,\n} from \"@fluidframework/driver-utils/internal\";\n\n/**\n * The name of the metadata blob added to the root of the container runtime.\n */\nconst metadataBlobName = \".metadata\";\n\n/**\n * The prefix that all GC blob names start with.\n *\n * @internal\n */\nexport const gcBlobPrefix = \"__gc\";\n\n/**\n * @internal\n */\nexport interface ISnapshotNormalizerConfig {\n\t// The paths of blobs whose contents should be normalized.\n\tblobsToNormalize?: string[];\n\t/**\n\t * channel types who's content (non-attribute) blobs will be excluded.\n\t * this is used to exclude the content of channels who's content cannot be compared\n\t * as the content is non-deterministic between snapshot at the same sequence number.\n\t */\n\texcludedChannelContentTypes?: string[];\n}\n\nconst sortStringified = (elem1: unknown, elem2: unknown): number => {\n\tconst serializedElem1 = JSON.stringify(elem1);\n\tconst serializedElem2 = JSON.stringify(elem2);\n\treturn serializedElem1.localeCompare(serializedElem2);\n};\n\n/**\n * Function that deep sorts an array. It handles cases where array elements are objects or arrays.\n * @returns the sorted array.\n */\nfunction getDeepSortedArray(array: unknown[]): unknown[] {\n\tconst sortedArray: unknown[] = [];\n\t// Sort arrays and objects, if any, in the array.\n\tfor (const element of array) {\n\t\tif (Array.isArray(element)) {\n\t\t\tsortedArray.push(getDeepSortedArray(element));\n\t\t} else if (element instanceof Object) {\n\t\t\tsortedArray.push(getDeepSortedObject(element));\n\t\t} else {\n\t\t\tsortedArray.push(element);\n\t\t}\n\t}\n\n\t// Now that all the arrays and objects in this array's elements have been sorted, sort it by comparing each\n\t// element's stringified version.\n\treturn sortedArray.sort(sortStringified);\n}\n\n/**\n * Function that deep sorts an object. It handles cases where object properties are arrays or objects.\n * @returns the sorted object.\n */\nfunction getDeepSortedObject<T extends object>(obj: T): T {\n\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\tconst sortedObj: T = {} as T;\n\t// Sort the object keys first. Then sort arrays and objects, if any, in the object.\n\tconst keys = Object.keys(obj).sort();\n\tfor (const key of keys) {\n\t\tconst value: unknown = obj[key];\n\t\tif (Array.isArray(value)) {\n\t\t\tsortedObj[key] = getDeepSortedArray(value);\n\t\t} else if (value instanceof Object) {\n\t\t\tsortedObj[key] = getDeepSortedObject(value);\n\t\t} else {\n\t\t\tsortedObj[key] = value;\n\t\t}\n\t}\n\n\treturn sortedObj;\n}\n\n/**\n * Function that normalizes a blob's content. If the content is an object or an array, deep sorts them.\n * Special handling for certain runtime blobs, such as the \"gc\" blob.\n * @returns the normalized blob content.\n */\nfunction getNormalizedBlobContent(blobContent: string, blobName: string): string {\n\tlet content = blobContent;\n\tif (blobName.startsWith(gcBlobPrefix)) {\n\t\t// The following code parses JSON and makes some assumptions about the type of data within. There does not appear to\n\t\t// be a better type than `any` to use here, so the lint rules are disabled.\n\n\t\t/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */\n\n\t\t// GC blobs may contain `unreferencedTimestampMs` for node that became unreferenced. This is the timestamp\n\t\t// of the last op processed or current timestamp and can differ between clients depending on when GC was run.\n\t\t// So, remove it for the purposes of comparing snapshots.\n\t\tconst gcState: any = JSON.parse(content);\n\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n\t\tfor (const [, data] of Object.entries(gcState.gcNodes)) {\n\t\t\tdelete (data as any).unreferencedTimestampMs;\n\t\t}\n\t\tcontent = JSON.stringify(gcState);\n\t}\n\n\t/**\n\t * The metadata blob has \"summaryNumber\" or \"summaryCount\" that tells which summary this is for a container. It can\n\t * be different in summaries of two clients even if they are generated at the same sequence#. For instance, at seq#\n\t * 1000, if one client has summarized 10 times and other has summarizer 15 times, summaryNumber will be different\n\t * for them. So, update \"summaryNumber\" to 0 for purposes of comparing snapshots.\n\t */\n\tif (blobName === metadataBlobName) {\n\t\tconst metadata = JSON.parse(content);\n\t\tif (metadata.summaryNumber !== undefined) {\n\t\t\tmetadata.summaryNumber = 0;\n\t\t}\n\t\tif (metadata.summaryCount !== undefined) {\n\t\t\tmetadata.summaryCount = 0;\n\t\t}\n\t\t// \"telemetryDocumentId\" is not a deterministic property (random guid), so we need to set it to something consistent\n\t\tif (metadata.telemetryDocumentId !== undefined) {\n\t\t\tmetadata.telemetryDocumentId = \"x\";\n\t\t}\n\t\t// default was not written before, now it's written in.\n\t\tif (metadata.documentSchema !== undefined) {\n\t\t\tmetadata.documentSchema = undefined;\n\t\t}\n\t\tcontent = JSON.stringify(metadata);\n\t}\n\n\t// Deep sort the content if it's parseable.\n\ttry {\n\t\tlet contentObj = JSON.parse(content);\n\t\tif (Array.isArray(contentObj)) {\n\t\t\tcontentObj = getDeepSortedArray(contentObj);\n\t\t} else if (contentObj instanceof Object) {\n\t\t\tcontentObj = getDeepSortedObject(contentObj);\n\t\t}\n\t\tcontent = JSON.stringify(contentObj);\n\t} catch {\n\t\t// Do nothing\n\t}\n\n\t/* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */\n\n\treturn content;\n}\n\n/**\n * Helper function that normalizes the given snapshot tree. It sorts objects and arrays in the snapshot. It also\n * normalizes certain blob contents for which the order of content does not matter. For example, garbage collection\n * blobs contains objects / arrays whose element order do not matter.\n * @param snapshot - The snapshot tree to normalize.\n * @param config - Configs to use when normalizing snapshot. For example, it can contain paths of blobs whose contents\n * should be normalized as well.\n * @returns a copy of the normalized snapshot tree.\n * @internal\n */\nexport function getNormalizedSnapshot(\n\tsnapshot: ITree,\n\tconfig?: ISnapshotNormalizerConfig,\n): ITree {\n\t// Merge blobs to normalize in the config with runtime blobs to normalize. The contents of these blobs will be\n\t// parsed and deep sorted.\n\tconst normalizedEntries: ITreeEntry[] = [];\n\n\t// The metadata blob in the root of the summary tree needs to be normalized.\n\tconst blobsToNormalize = [metadataBlobName, ...(config?.blobsToNormalize ?? [])];\n\tfor (const entry of snapshot.entries) {\n\t\tnormalizedEntries.push(normalizeEntry(entry, { ...config, blobsToNormalize }));\n\t}\n\n\t// Sort the tree entries based on their path.\n\tnormalizedEntries.sort((a, b) => a.path.localeCompare(b.path));\n\n\treturn {\n\t\tentries: normalizedEntries,\n\t\tid: snapshot.id,\n\t};\n}\n\nfunction normalizeMatrix(value: ITree): ITree {\n\tconst rows = value.entries.find((e) => e.path === \"rows\");\n\n\tif (!rows || !(\"entries\" in rows.value)) {\n\t\treturn value;\n\t}\n\n\tconst segments = rows.value.entries.find((e) => e.path === \"segments\");\n\n\tif (!segments || !(\"entries\" in segments.value)) {\n\t\treturn value;\n\t}\n\n\tconst header = segments.value.entries.find((e) => e.path === \"header\");\n\n\tif (!header || !(\"contents\" in header.value)) {\n\t\treturn value;\n\t}\n\n\tif (!header?.value.contents.includes(\"removedClientId\")) {\n\t\treturn value;\n\t}\n\n\t/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */\n\n\tconst contents = JSON.parse(header?.value.contents);\n\n\tfor (const segment of contents.segments) {\n\t\tif (\"removedClientId\" in segment) {\n\t\t\tsegment.removedClientId = undefined;\n\t\t}\n\n\t\tif (\"removedClientIds\" in segment) {\n\t\t\tsegment.removedClientIds = undefined;\n\t\t}\n\t}\n\n\theader.value.contents = JSON.stringify(contents);\n\n\t/* eslint-enable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access */\n\n\treturn value;\n}\n\nfunction normalizeEntry(\n\tentry: ITreeEntry,\n\tconfig: ISnapshotNormalizerConfig | undefined,\n): ITreeEntry {\n\tswitch (entry.type) {\n\t\tcase TreeEntry.Blob: {\n\t\t\tlet contents = entry.value.contents;\n\t\t\t// If this blob has to be normalized or it's a GC blob, parse and sort the blob contents first.\n\t\t\tif (\n\t\t\t\t(config?.blobsToNormalize?.includes(entry.path) ?? false) ||\n\t\t\t\tentry.path.startsWith(gcBlobPrefix)\n\t\t\t) {\n\t\t\t\tcontents = getNormalizedBlobContent(contents, entry.path);\n\t\t\t}\n\t\t\treturn new BlobTreeEntry(entry.path, contents);\n\t\t}\n\t\tcase TreeEntry.Tree: {\n\t\t\tif (config?.excludedChannelContentTypes !== undefined) {\n\t\t\t\tfor (const maybeAttributes of entry.value.entries) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tmaybeAttributes.type === TreeEntry.Blob &&\n\t\t\t\t\t\tmaybeAttributes.path === \".attributes\"\n\t\t\t\t\t) {\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\t\t\tconst parsed: { type?: string } = JSON.parse(maybeAttributes.value.contents);\n\t\t\t\t\t\tif (parsed.type === \"https://graph.microsoft.com/types/sharedmatrix\") {\n\t\t\t\t\t\t\treturn new TreeTreeEntry(\n\t\t\t\t\t\t\t\tentry.path,\n\t\t\t\t\t\t\t\tnormalizeMatrix(getNormalizedSnapshot(entry.value, config)),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tparsed.type !== undefined &&\n\t\t\t\t\t\t\tconfig.excludedChannelContentTypes.includes(parsed.type)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t// remove everything to match the unknown channel\n\t\t\t\t\t\t\treturn new TreeTreeEntry(entry.path, { entries: [maybeAttributes] });\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn new TreeTreeEntry(entry.path, getNormalizedSnapshot(entry.value, config));\n\t\t}\n\t\tcase TreeEntry.Attachment: {\n\t\t\treturn new AttachmentTreeEntry(entry.path, entry.value.id);\n\t\t}\n\n\t\tdefault: {\n\t\t\tthrow new Error(\"Unknown entry type\");\n\t\t}\n\t}\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/tool-utils",
3
- "version": "2.0.2",
3
+ "version": "2.1.0-276326",
4
4
  "description": "Common utilities for Fluid tools",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -57,10 +57,10 @@
57
57
  "temp-directory": "nyc/.nyc_output"
58
58
  },
59
59
  "dependencies": {
60
- "@fluidframework/core-utils": "~2.0.2",
61
- "@fluidframework/driver-definitions": "~2.0.2",
62
- "@fluidframework/driver-utils": "~2.0.2",
63
- "@fluidframework/odsp-doclib-utils": "~2.0.2",
60
+ "@fluidframework/core-utils": "2.1.0-276326",
61
+ "@fluidframework/driver-definitions": "2.1.0-276326",
62
+ "@fluidframework/driver-utils": "2.1.0-276326",
63
+ "@fluidframework/odsp-doclib-utils": "2.1.0-276326",
64
64
  "async-mutex": "^0.3.1",
65
65
  "debug": "^4.3.4",
66
66
  "jwt-decode": "^4.0.0",
@@ -69,16 +69,17 @@
69
69
  "devDependencies": {
70
70
  "@arethetypeswrong/cli": "^0.15.2",
71
71
  "@biomejs/biome": "^1.7.3",
72
- "@fluid-internal/mocha-test-setup": "~2.0.2",
72
+ "@fluid-internal/mocha-test-setup": "2.1.0-276326",
73
73
  "@fluid-tools/build-cli": "^0.39.0",
74
74
  "@fluidframework/build-common": "^2.0.3",
75
75
  "@fluidframework/build-tools": "^0.39.0",
76
76
  "@fluidframework/eslint-config-fluid": "^5.3.0",
77
- "@fluidframework/tool-utils-previous": "npm:@fluidframework/tool-utils@2.0.0-rc.4.0.0",
77
+ "@fluidframework/tool-utils-previous": "npm:@fluidframework/tool-utils@2.0.0-rc.5.0.0",
78
78
  "@microsoft/api-extractor": "^7.45.1",
79
79
  "@types/debug": "^4.1.5",
80
80
  "@types/mocha": "^9.1.1",
81
81
  "@types/node": "^18.19.0",
82
+ "@types/proper-lockfile": "^4.1.4",
82
83
  "c8": "^8.0.1",
83
84
  "concurrently": "^8.2.1",
84
85
  "copyfiles": "^2.4.1",
@@ -97,8 +98,8 @@
97
98
  },
98
99
  "scripts": {
99
100
  "api": "fluid-build . --task api",
100
- "api-extractor:commonjs": "flub generate entrypoints --outFileAlpha legacy --outDir ./dist",
101
- "api-extractor:esnext": "flub generate entrypoints --outFileAlpha legacy --outDir ./lib --node10TypeCompat",
101
+ "api-extractor:commonjs": "flub generate entrypoints --outDir ./dist",
102
+ "api-extractor:esnext": "flub generate entrypoints --outDir ./lib --node10TypeCompat",
102
103
  "build": "fluid-build . --task build",
103
104
  "build:commonjs": "fluid-build . --task commonjs",
104
105
  "build:compile": "fluid-build . --task compile",
@@ -132,7 +133,7 @@
132
133
  "test:mocha:esm": "mocha --recursive \"lib/test/**/*.spec.*js\" --exit",
133
134
  "test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
134
135
  "tsc": "fluid-tsc commonjs --project ./tsconfig.cjs.json && copyfiles -f ../../../common/build/build-common/src/cjs/package.json ./dist",
135
- "typetests:gen": "flub generate typetests --dir . -v --publicFallback",
136
+ "typetests:gen": "flub generate typetests --dir . -v",
136
137
  "typetests:prepare": "flub typetests --dir . --reset --previous --normalize"
137
138
  }
138
139
  }
package/src/debug.ts CHANGED
@@ -7,5 +7,7 @@ import registerDebug from "debug";
7
7
 
8
8
  import { pkgName, pkgVersion } from "./packageVersion.js";
9
9
 
10
+ // TODO: Add documentation
11
+ // eslint-disable-next-line jsdoc/require-jsdoc
10
12
  export const debug = registerDebug("fluid:tool-utils");
11
13
  debug(`Package: ${pkgName} - Version: ${pkgVersion}`);
@@ -3,12 +3,12 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import fs from "fs";
7
- import os from "os";
8
- import path from "path";
9
- import util from "util";
6
+ import fs from "node:fs";
7
+ import os from "node:os";
8
+ import path from "node:path";
9
+ import util from "node:util";
10
10
 
11
- import { IOdspTokens } from "@fluidframework/odsp-doclib-utils/internal";
11
+ import type { IOdspTokens } from "@fluidframework/odsp-doclib-utils/internal";
12
12
  import { lock } from "proper-lockfile";
13
13
 
14
14
  /**
@@ -26,17 +26,20 @@ export interface IAsyncCache<TKey, TValue> {
26
26
  export interface IResources {
27
27
  tokens?: {
28
28
  version?: number;
29
- data: {
30
- [key: string]: {
29
+ data: Record<
30
+ string,
31
+ {
31
32
  storage?: IOdspTokens;
32
33
  push?: IOdspTokens;
33
- };
34
- };
34
+ }
35
+ >;
35
36
  };
36
37
  }
37
38
 
38
- const getRCFileName = () => path.join(os.homedir(), ".fluidtoolrc");
39
+ const getRCFileName = (): string => path.join(os.homedir(), ".fluidtoolrc");
39
40
 
41
+ // TODO: Add documentation
42
+ // eslint-disable-next-line jsdoc/require-description
40
43
  /**
41
44
  * @internal
42
45
  */
@@ -49,27 +52,30 @@ export async function loadRC(): Promise<IResources> {
49
52
  try {
50
53
  // eslint-disable-next-line @typescript-eslint/no-unsafe-return
51
54
  return JSON.parse(buf.toString("utf8"));
52
- } catch (e) {
55
+ } catch {
53
56
  // Nothing
54
57
  }
55
58
  }
56
59
  return {};
57
60
  }
58
61
 
62
+ // TODO: Add documentation
63
+ // eslint-disable-next-line jsdoc/require-description
59
64
  /**
60
65
  * @internal
61
66
  */
62
- export async function saveRC(rc: IResources) {
67
+ export async function saveRC(rc: IResources): Promise<void> {
63
68
  const writeFile = util.promisify(fs.writeFile);
64
69
  const content = JSON.stringify(rc, undefined, 2);
65
70
  return writeFile(getRCFileName(), Buffer.from(content, "utf8"));
66
71
  }
67
72
 
73
+ // TODO: Add documentation
74
+ // eslint-disable-next-line jsdoc/require-description
68
75
  /**
69
76
  * @internal
70
77
  */
71
- export async function lockRC() {
72
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
78
+ export async function lockRC(): Promise<() => Promise<void>> {
73
79
  return lock(getRCFileName(), {
74
80
  retries: {
75
81
  forever: true,
@@ -3,19 +3,26 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import http from "http";
7
- import { Socket } from "net";
6
+ import http from "node:http";
7
+ import type { Socket } from "node:net";
8
8
 
9
+ // TODO: Add documentation
10
+ // eslint-disable-next-line jsdoc/require-jsdoc
9
11
  export interface ITrackedHttpServer {
10
12
  readonly server: http.Server;
11
13
  readonly sockets: Set<Socket>;
12
14
  fullyClose(): void;
13
15
  }
16
+
17
+ // TODO: Add documentation
18
+ // eslint-disable-next-line jsdoc/require-jsdoc
14
19
  export function createTrackedServer(
15
20
  port: number,
16
21
  requestListener: http.RequestListener,
17
22
  ): ITrackedHttpServer {
23
+ // eslint-disable-next-line jsdoc/require-jsdoc
18
24
  const server = http.createServer(requestListener).listen(port);
25
+ // eslint-disable-next-line jsdoc/require-jsdoc
19
26
  const sockets = new Set<Socket>();
20
27
 
21
28
  server.on("connection", (socket) => {
@@ -26,25 +33,38 @@ export function createTrackedServer(
26
33
  return {
27
34
  server,
28
35
  sockets,
29
- fullyClose() {
36
+ fullyClose(): void {
30
37
  server.close();
31
- sockets.forEach((socket) => socket.destroy());
38
+ // eslint-disable-next-line jsdoc/require-jsdoc
39
+ for (const socket of sockets) {
40
+ socket.destroy();
41
+ }
32
42
  },
33
43
  };
34
44
  }
45
+
46
+ // TODO: Add documentation
47
+ // eslint-disable-next-line jsdoc/require-jsdoc
35
48
  export type OnceListenerHandler<T> = (
36
49
  req: http.IncomingMessage,
37
50
  res: http.ServerResponse,
38
51
  ) => Promise<T>;
52
+
53
+ // TODO: Add documentation
54
+ // eslint-disable-next-line jsdoc/require-jsdoc
39
55
  export type OnceListenerResult<T> = Promise<() => Promise<T>>;
56
+
57
+ // TODO: Add documentation
58
+ // eslint-disable-next-line jsdoc/require-jsdoc
40
59
  export const serverListenAndHandle = async <T>(
41
60
  port: number,
42
61
  handler: OnceListenerHandler<T>,
43
62
  ): OnceListenerResult<T> =>
44
63
  // eslint-disable-next-line promise/param-names
45
64
  new Promise((outerResolve, outerReject) => {
46
- // eslint-disable-next-line promise/param-names
65
+ // eslint-disable-next-line promise/param-names, jsdoc/require-jsdoc
47
66
  const innerP = new Promise<T>((innerResolve, innerReject) => {
67
+ // eslint-disable-next-line jsdoc/require-jsdoc
48
68
  const httpServer = createTrackedServer(port, (req, res) => {
49
69
  // ignore favicon
50
70
  if (req.url === "/favicon.ico") {
@@ -63,6 +83,8 @@ export const serverListenAndHandle = async <T>(
63
83
  });
64
84
  });
65
85
 
86
+ // TODO: Add documentation
87
+ // eslint-disable-next-line jsdoc/require-jsdoc
66
88
  export const endResponse = async (response: http.ServerResponse): Promise<void> =>
67
89
  new Promise((resolve, reject) => {
68
90
  try {
package/src/index.ts CHANGED
@@ -3,16 +3,13 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- export { IAsyncCache, IResources, loadRC, lockRC, saveRC } from "./fluidToolRC.js";
6
+ export type { IAsyncCache, IResources } from "./fluidToolRc.js";
7
+ export { loadRC, lockRC, saveRC } from "./fluidToolRc.js";
8
+ export type { IOdspTokenManagerCacheKey, OdspTokenConfig } from "./odspTokenManager.js";
7
9
  export {
8
10
  getMicrosoftConfiguration,
9
- IOdspTokenManagerCacheKey,
10
- OdspTokenConfig,
11
11
  OdspTokenManager,
12
12
  odspTokensCache,
13
13
  } from "./odspTokenManager.js";
14
- export {
15
- gcBlobPrefix,
16
- getNormalizedSnapshot,
17
- ISnapshotNormalizerConfig,
18
- } from "./snapshotNormalizer.js";
14
+ export type { ISnapshotNormalizerConfig } from "./snapshotNormalizer.js";
15
+ export { gcBlobPrefix, getNormalizedSnapshot } from "./snapshotNormalizer.js";