From 4ce72c3afd98013b19d769587d75fa03c8c5fbbd Mon Sep 17 00:00:00 2001 From: Israel Arcos Date: Tue, 16 Jan 2024 20:03:59 -0800 Subject: [PATCH] chore: address feedback --- package.json | 2 +- .../cognito/utils/refreshAuthTokens.ts | 6 +- .../utils/deDupeAsyncRequests.test.ts | 56 +++++++++---------- packages/core/src/libraryUtils.ts | 2 +- ...syncRequests.ts => deDupeAsyncFunction.ts} | 36 ++++++------ packages/core/src/utils/index.ts | 2 +- yarn.lock | 12 ++-- 7 files changed, 56 insertions(+), 60 deletions(-) rename packages/core/src/utils/{deDupeAsyncRequests.ts => deDupeAsyncFunction.ts} (60%) diff --git a/package.json b/package.json index 76d689618cd..5488455c90f 100644 --- a/package.json +++ b/package.json @@ -114,7 +114,7 @@ "tslint-config-airbnb": "^5.8.0", "typedoc": "^0.17.0", "typescript": "^4.3.5", - "typescript-coverage-report": "^0.8.0", + "typescript-coverage-report": "^0.6.4", "uuid-validate": "^0.0.3", "webpack": "^5.75.0", "webpack-bundle-analyzer": "^4.7.0", diff --git a/packages/auth/src/providers/cognito/utils/refreshAuthTokens.ts b/packages/auth/src/providers/cognito/utils/refreshAuthTokens.ts index feb1629495e..2021b5a4c5b 100644 --- a/packages/auth/src/providers/cognito/utils/refreshAuthTokens.ts +++ b/packages/auth/src/providers/cognito/utils/refreshAuthTokens.ts @@ -6,7 +6,7 @@ import { AuthConfig } from '@aws-amplify/core'; import { assertTokenProviderConfig, decodeJWT, - deDupeAsyncRequests, + deDupeAsyncFunction, } from '@aws-amplify/core/internals/utils'; import { initiateAuth } from '../utils/clients/CognitoIdentityProvider'; import { getRegion } from '../utils/clients/CognitoIdentityProvider/utils'; @@ -14,7 +14,7 @@ import { assertAuthTokensWithRefreshToken } from '../utils/types'; import { AuthError } from '../../../errors/AuthError'; import { getUserContextData } from './userContextData'; -const refreshAuthTokensCallback: TokenRefresher = async ({ +const refreshAuthTokensFunction: TokenRefresher = async ({ tokens, authConfig, username, @@ -74,4 +74,4 @@ const refreshAuthTokensCallback: TokenRefresher = async ({ }; }; -export const refreshAuthTokens = deDupeAsyncRequests(refreshAuthTokensCallback); +export const refreshAuthTokens = deDupeAsyncFunction(refreshAuthTokensFunction); diff --git a/packages/core/__tests__/utils/deDupeAsyncRequests.test.ts b/packages/core/__tests__/utils/deDupeAsyncRequests.test.ts index cea33fba7f3..a017a439736 100644 --- a/packages/core/__tests__/utils/deDupeAsyncRequests.test.ts +++ b/packages/core/__tests__/utils/deDupeAsyncRequests.test.ts @@ -1,50 +1,50 @@ -import { deDupeAsyncRequests } from '../../src/utils/deDupeAsyncRequests'; +import { deDupeAsyncFunction } from '../../src/utils/deDupeAsyncFunction'; -describe('test debounce callback', () => { +describe('dedupeAsyncFunction()', () => { const numberOfConcurrentCalls = 10; - const mockServiceCallback = jest.fn(); + const mockServiceFunction = jest.fn(); + const mockReturnValue = { id: 1 }; beforeEach(() => { - mockServiceCallback.mockImplementation(async () => {}); + mockServiceFunction.mockImplementation(async () => mockReturnValue); }); afterEach(() => { - mockServiceCallback.mockClear(); + mockServiceFunction.mockClear(); }); - it('should allow to invoke the callback when there is no concurrent calls', async () => { - const debouncedCallback = deDupeAsyncRequests(mockServiceCallback); + it('should invoke the mockServiceFunction', async () => { + const deDupedFunction = deDupeAsyncFunction(mockServiceFunction); - debouncedCallback(); - expect(mockServiceCallback).toHaveBeenCalledTimes(1); + deDupedFunction(); + expect(mockServiceFunction).toHaveBeenCalledTimes(1); }); - it('should invoke the callback one time during concurrent sync calls', () => { - const debouncedCallback = deDupeAsyncRequests(mockServiceCallback); + it('should invoke the mockServiceFunction one time during concurrent sync calls', () => { + const deDupedFunction = deDupeAsyncFunction(mockServiceFunction); for (let i = 0; i < numberOfConcurrentCalls; i++) { - debouncedCallback(); + deDupedFunction(); } - expect(mockServiceCallback).toHaveBeenCalledTimes(1); + expect(mockServiceFunction).toHaveBeenCalledTimes(1); }); - it('should allow to invoke the callback again after the promise has being resolved', async () => { - const debouncedCallback = deDupeAsyncRequests(mockServiceCallback); + it('should return a value once the mockServiceFunction is resolved', async () => { + const deDupedFunction = deDupeAsyncFunction(mockServiceFunction); + expect(await deDupedFunction()).toEqual(mockReturnValue); + expect(mockServiceFunction).toHaveBeenCalledTimes(1); + }); + + it('should allow to invoke the mockServiceFunction again after the promise has being resolved', async () => { + const deDupedFunction = deDupeAsyncFunction(mockServiceFunction); for (let i = 0; i < numberOfConcurrentCalls; i++) { - debouncedCallback(); + expect(deDupedFunction()).toBeInstanceOf(Promise); } - await debouncedCallback(); + // resolves the promise + expect(await deDupedFunction()).toEqual(mockReturnValue); - debouncedCallback(); - expect(mockServiceCallback).toHaveBeenCalledTimes(2); - }); + // should allow to call the mockServiceFunction again + deDupedFunction(); - it('should return a value once the callback is resolved', async () => { - const mockReturnValue = { id: 1 }; - - mockServiceCallback.mockImplementation(async () => mockReturnValue); - const debouncedCallback = deDupeAsyncRequests(mockServiceCallback); - const result = await debouncedCallback(); - expect(result).toEqual(mockReturnValue); - expect(mockServiceCallback).toHaveBeenCalledTimes(1); + expect(mockServiceFunction).toHaveBeenCalledTimes(2); }); }); diff --git a/packages/core/src/libraryUtils.ts b/packages/core/src/libraryUtils.ts index e5126256ec4..6d8a552ed3c 100644 --- a/packages/core/src/libraryUtils.ts +++ b/packages/core/src/libraryUtils.ts @@ -17,7 +17,7 @@ export { retry, urlSafeDecode, urlSafeEncode, - deDupeAsyncRequests, + deDupeAsyncFunction, } from './utils'; export { parseAWSExports } from './parseAWSExports'; export { LegacyConfig } from './singleton/types'; diff --git a/packages/core/src/utils/deDupeAsyncRequests.ts b/packages/core/src/utils/deDupeAsyncFunction.ts similarity index 60% rename from packages/core/src/utils/deDupeAsyncRequests.ts rename to packages/core/src/utils/deDupeAsyncFunction.ts index e1e49f23a7a..2a1f9a0cb9b 100644 --- a/packages/core/src/utils/deDupeAsyncRequests.ts +++ b/packages/core/src/utils/deDupeAsyncFunction.ts @@ -1,7 +1,7 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -// this will make the tsc-complience-test to pass +// this will make the tsc-compliance-test to pass type Awaited = T extends null | undefined ? T // special case for `null | undefined` when not in `--strictNullChecks` mode : T extends object & { then(onfulfilled: infer F, ...args: infer _): any } // `await` only unwraps object types with a callable `then`. Non-object types are not unwrapped @@ -10,33 +10,29 @@ type Awaited = T extends null | undefined : never // the argument to `then` was not callable : T; // /** - * returns inflight promise if there hasn't been resolved yet + * returns in-flight promise if there is one * - * @param callback - callback to be deDup. + * @param callback - callback to be deduped. * @returns - the return type of the callback */ -export const deDupeAsyncRequests = ( - callback: (...args: A) => Promise +export const deDupeAsyncFunction = ( + fun: (...args: A) => Promise ) => { let inflightPromise: Promise> | undefined; return async (...args: A): Promise> => { if (inflightPromise) return inflightPromise; - if (!inflightPromise) { - inflightPromise = new Promise(async (resolve, reject) => { - try { - const result = await callback(...args); - resolve(result); - } catch (error) { - reject(error); - } - }); - } + inflightPromise = new Promise(async (resolve, reject) => { + try { + const result = await fun(...args); + resolve(result); + } catch (error) { + reject(error); + } finally { + inflightPromise = undefined; + } + }); - try { - return await inflightPromise; - } finally { - inflightPromise = undefined; - } + return await inflightPromise; }; }; diff --git a/packages/core/src/utils/index.ts b/packages/core/src/utils/index.ts index e5dd20848e5..9b713d2066e 100644 --- a/packages/core/src/utils/index.ts +++ b/packages/core/src/utils/index.ts @@ -15,4 +15,4 @@ export { export { urlSafeDecode } from './urlSafeDecode'; export { urlSafeEncode } from './urlSafeEncode'; export { deepFreeze } from './deepFreeze'; -export { deDupeAsyncRequests } from './deDupeAsyncRequests'; +export { deDupeAsyncFunction } from './deDupeAsyncFunction'; diff --git a/yarn.lock b/yarn.lock index fa7a0f389da..6adfd585ce1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -13821,7 +13821,7 @@ tuf-js@^1.1.7: debug "^4.3.4" make-fetch-happen "^11.1.1" -type-coverage-core@^2.23.0: +type-coverage-core@^2.17.2: version "2.27.1" resolved "https://registry.yarnpkg.com/type-coverage-core/-/type-coverage-core-2.27.1.tgz#f552cdabfcbe71408a4cd3886a2c9e4e50cbdbc7" integrity sha512-W+PMYbhUsq+UWkrb7UkmyO7zF3zt4qZuQukyDM6eaiCIkMJclcVmR3O02clDk4FKpKPbzHictOmoIu3fYp+53g== @@ -13905,10 +13905,10 @@ typedoc@^0.17.0: shelljs "^0.8.4" typedoc-default-themes "^0.10.2" -typescript-coverage-report@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/typescript-coverage-report/-/typescript-coverage-report-0.8.0.tgz#d189f7074c1c91ea5c4014c2c7b507037975ff91" - integrity sha512-qYUrPt2CISyXTzwwyD7g6lciovvb2qQGMZKC7zHf2TiLg8QJ6cybYKX1/TETB/BzxaSU7+2FVjiIq3q1TG8A0w== +typescript-coverage-report@^0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/typescript-coverage-report/-/typescript-coverage-report-0.6.4.tgz#3a7a7724c0f27de50d2a0708c7b7b7088bed2055" + integrity sha512-G+0OFYxwN5oRbORlU1nKYtO00G567lcl4+nbg3MU3Y9ayFnh677dMHmAL4JGP/4Cb1IBN5h/DUQDr/z9X+9lag== dependencies: chalk "^4.0.0" cli-table3 "^0.6.1" @@ -13918,7 +13918,7 @@ typescript-coverage-report@^0.8.0: react-dom "^16.13.1" rimraf "^3.0.2" semantic-ui-react "^0.88.2" - type-coverage-core "^2.23.0" + type-coverage-core "^2.17.2" typescript@4.2.x: version "4.2.4"