From c280817e03a5e6ff95b32667d799eac717d4cbb4 Mon Sep 17 00:00:00 2001 From: Chris Fang Date: Mon, 29 Apr 2024 14:34:14 -0700 Subject: [PATCH 01/15] fix: Await network call on identifyUser APIs --- .../providers/pinpoint/apis/identifyUser.test.ts | 11 ++++++++++- .../src/providers/pinpoint/apis/identifyUser.ts | 2 +- .../providers/pinpoint/apis/identifyUser.test.ts | 11 ++++++++++- .../pinpoint/apis/identifyUser.native.test.ts | 11 ++++++++++- .../providers/pinpoint/apis/identifyUser.ts | 2 +- .../providers/pinpoint/apis/identifyUser.native.ts | 2 +- 6 files changed, 33 insertions(+), 6 deletions(-) diff --git a/packages/analytics/__tests__/providers/pinpoint/apis/identifyUser.test.ts b/packages/analytics/__tests__/providers/pinpoint/apis/identifyUser.test.ts index a64208f7c23..3da2a528193 100644 --- a/packages/analytics/__tests__/providers/pinpoint/apis/identifyUser.test.ts +++ b/packages/analytics/__tests__/providers/pinpoint/apis/identifyUser.test.ts @@ -38,7 +38,7 @@ describe('Analytics Pinpoint Provider API: identifyUser', () => { }); beforeEach(() => { - mockUpdateEndpoint.mockClear(); + mockUpdateEndpoint.mockReset(); }); it('passes through parameter along with Analytics boilerplate to core Pinpoint identifyUser API', async () => { @@ -82,4 +82,13 @@ describe('Analytics Pinpoint Provider API: identifyUser', () => { userAttributes, }); }); + + it('rejects if underlying promise rejects', async () => { + mockUpdateEndpoint.mockRejectedValue(new Error()); + const input: IdentifyUserInput = { + userId: 'user-id', + userProfile: {}, + }; + await expect(identifyUser(input)).rejects.toBeDefined(); + }); }); diff --git a/packages/analytics/src/providers/pinpoint/apis/identifyUser.ts b/packages/analytics/src/providers/pinpoint/apis/identifyUser.ts index 516c90c6c19..85daa975233 100644 --- a/packages/analytics/src/providers/pinpoint/apis/identifyUser.ts +++ b/packages/analytics/src/providers/pinpoint/apis/identifyUser.ts @@ -65,7 +65,7 @@ export const identifyUser = async ({ const { credentials, identityId } = await resolveCredentials(); const { appId, region } = resolveConfig(); const { userAttributes } = options ?? {}; - updateEndpoint({ + await updateEndpoint({ appId, category: 'Analytics', credentials, diff --git a/packages/notifications/__tests__/inAppMessaging/providers/pinpoint/apis/identifyUser.test.ts b/packages/notifications/__tests__/inAppMessaging/providers/pinpoint/apis/identifyUser.test.ts index 20e3e895f02..4384d008bc4 100644 --- a/packages/notifications/__tests__/inAppMessaging/providers/pinpoint/apis/identifyUser.test.ts +++ b/packages/notifications/__tests__/inAppMessaging/providers/pinpoint/apis/identifyUser.test.ts @@ -44,7 +44,7 @@ describe('InAppMessaging Pinpoint Provider API: identifyUser', () => { }); beforeEach(() => { - mockUpdateEndpoint.mockClear(); + mockUpdateEndpoint.mockReset(); }); it('passes through parameters to core Pinpoint updateEndpoint API', async () => { @@ -93,4 +93,13 @@ describe('InAppMessaging Pinpoint Provider API: identifyUser', () => { userAttributes, }); }); + + it('rejects if underlying promise rejects', async () => { + mockUpdateEndpoint.mockRejectedValue(new Error()); + const input: IdentifyUserInput = { + userId: 'user-id', + userProfile: {}, + }; + await expect(identifyUser(input)).rejects.toBeDefined(); + }); }); diff --git a/packages/notifications/__tests__/pushNotifications/providers/pinpoint/apis/identifyUser.native.test.ts b/packages/notifications/__tests__/pushNotifications/providers/pinpoint/apis/identifyUser.native.test.ts index 8ff028d026e..d759f418ed6 100644 --- a/packages/notifications/__tests__/pushNotifications/providers/pinpoint/apis/identifyUser.native.test.ts +++ b/packages/notifications/__tests__/pushNotifications/providers/pinpoint/apis/identifyUser.native.test.ts @@ -46,8 +46,8 @@ describe('identifyUser (native)', () => { }); afterEach(() => { - mockUpdateEndpoint.mockClear(); mockAssertIsInitialized.mockReset(); + mockUpdateEndpoint.mockReset(); }); it('must be initialized', async () => { @@ -102,4 +102,13 @@ describe('identifyUser (native)', () => { userAttributes, }); }); + + it('rejects if underlying promise rejects', async () => { + mockUpdateEndpoint.mockRejectedValue(new Error()); + const input: IdentifyUserInput = { + userId: 'user-id', + userProfile: {}, + }; + await expect(identifyUser(input)).rejects.toBeDefined(); + }); }); diff --git a/packages/notifications/src/inAppMessaging/providers/pinpoint/apis/identifyUser.ts b/packages/notifications/src/inAppMessaging/providers/pinpoint/apis/identifyUser.ts index a147fdec7c2..215727f3035 100644 --- a/packages/notifications/src/inAppMessaging/providers/pinpoint/apis/identifyUser.ts +++ b/packages/notifications/src/inAppMessaging/providers/pinpoint/apis/identifyUser.ts @@ -73,7 +73,7 @@ export const identifyUser = async (input: IdentifyUserInput): Promise => { const { credentials, identityId } = await resolveCredentials(); const { appId, region } = resolveConfig(); const { address, optOut, userAttributes } = options ?? {}; - updateEndpoint({ + await updateEndpoint({ address, channelType: CHANNEL_TYPE, optOut, diff --git a/packages/notifications/src/pushNotifications/providers/pinpoint/apis/identifyUser.native.ts b/packages/notifications/src/pushNotifications/providers/pinpoint/apis/identifyUser.native.ts index 880d3dc8a43..ee0581d6368 100644 --- a/packages/notifications/src/pushNotifications/providers/pinpoint/apis/identifyUser.native.ts +++ b/packages/notifications/src/pushNotifications/providers/pinpoint/apis/identifyUser.native.ts @@ -21,7 +21,7 @@ export const identifyUser: IdentifyUser = async ({ const { credentials, identityId } = await resolveCredentials(); const { appId, region } = resolveConfig(); const { address, optOut, userAttributes } = options ?? {}; - updateEndpoint({ + await updateEndpoint({ address, channelType: getChannelType(), optOut, From 36b5d1ef6c6151edfe26213a03eb4a1051058ca4 Mon Sep 17 00:00:00 2001 From: Ashwin Kumar Date: Tue, 30 Apr 2024 09:28:04 -0700 Subject: [PATCH 02/15] feat(react-native): add getDeviceName util (#13015) * feat(react-native): add getDeviceName util * code cleanup --------- Co-authored-by: Ashwin Kumar Co-authored-by: Venkata Ramyasri Kota <34170013+kvramyasri7@users.noreply.github.com> --- .../amplify/rtncore/AmplifyRTNCoreModule.kt | 36 +++++++---- packages/react-native/ios/AmplifyRTNCore.mm | 3 + .../react-native/ios/AmplifyRTNCore.swift | 62 ++++++++++++------- .../react-native/src/apis/getDeviceName.ts | 8 +++ packages/react-native/src/apis/index.ts | 1 + packages/react-native/src/index.ts | 7 ++- packages/react-native/src/types.ts | 2 + 7 files changed, 84 insertions(+), 35 deletions(-) create mode 100644 packages/react-native/src/apis/getDeviceName.ts diff --git a/packages/react-native/android/src/main/kotlin/com/amazonaws/amplify/rtncore/AmplifyRTNCoreModule.kt b/packages/react-native/android/src/main/kotlin/com/amazonaws/amplify/rtncore/AmplifyRTNCoreModule.kt index 3e0f201e8b0..b28fd968048 100644 --- a/packages/react-native/android/src/main/kotlin/com/amazonaws/amplify/rtncore/AmplifyRTNCoreModule.kt +++ b/packages/react-native/android/src/main/kotlin/com/amazonaws/amplify/rtncore/AmplifyRTNCoreModule.kt @@ -1,29 +1,43 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + package com.amazonaws.amplify.rtncore +import android.os.Build +import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod -import com.facebook.react.bridge.Promise import com.facebook.react.bridge.ReadableMap class AmplifyRTNCoreModule(reactContext: ReactApplicationContext) : - ReactContextBaseJavaModule(reactContext) { - - override fun getName(): String { - return NAME - } + ReactContextBaseJavaModule(reactContext) { + override fun getName(): String { + return NAME + } @ReactMethod - fun computeModPow(payload: ReadableMap, promise: Promise) { + fun computeModPow( + payload: ReadableMap, + promise: Promise, + ) { BigInteger.computeModPow(payload, promise) } @ReactMethod - fun computeS(payload: ReadableMap, promise: Promise) { + fun computeS( + payload: ReadableMap, + promise: Promise, + ) { BigInteger.computeS(payload, promise) } - companion object { - const val NAME = "AmplifyRTNCore" - } + @ReactMethod + fun getDeviceName(promise: Promise) { + promise.resolve(Build.MODEL) + } + + companion object { + const val NAME = "AmplifyRTNCore" + } } diff --git a/packages/react-native/ios/AmplifyRTNCore.mm b/packages/react-native/ios/AmplifyRTNCore.mm index 6c3237d74ed..b7318222196 100644 --- a/packages/react-native/ios/AmplifyRTNCore.mm +++ b/packages/react-native/ios/AmplifyRTNCore.mm @@ -13,6 +13,9 @@ @interface RCT_EXTERN_MODULE(AmplifyRTNCore, NSObject) withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(getDeviceName:(RCTPromiseResolveBlock)resolve + withResolver:(RCTPromiseRejectBlock)reject) + + (BOOL)requiresMainQueueSetup { return NO; diff --git a/packages/react-native/ios/AmplifyRTNCore.swift b/packages/react-native/ios/AmplifyRTNCore.swift index 7cc7843fafe..db1ae2bc716 100644 --- a/packages/react-native/ios/AmplifyRTNCore.swift +++ b/packages/react-native/ios/AmplifyRTNCore.swift @@ -1,29 +1,45 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +#if canImport(UIKit) + import UIKit +#else + import Foundation +#endif + @objc(AmplifyRTNCore) class AmplifyRTNCore: NSObject { - - @objc(multiply:withB:withResolver:withRejecter:) - func multiply(a: Float, b: Float, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void { - resolve(a*b) - } - - @objc(computeModPow:withResolver:withRejecter:) - func computeModPow( - payload: [String: String], - resolve: RCTPromiseResolveBlock, - reject: RCTPromiseRejectBlock - ) -> Void { - BigInteger.computeModPow(payload, resolve: resolve, reject: reject) - } - - @objc(computeS:withResolver:withRejecter:) - func computeS( - _ payload: [String: String], - resolve: RCTPromiseResolveBlock, - reject: RCTPromiseRejectBlock - ) -> Void { - BigInteger.computeS(payload, resolve: resolve, reject: reject) - } + @objc(multiply:withB:withResolver:withRejecter:) + func multiply(a: Float, b: Float, resolve: RCTPromiseResolveBlock, reject _: RCTPromiseRejectBlock) { + resolve(a * b) + } + + @objc(computeModPow:withResolver:withRejecter:) + func computeModPow( + payload: [String: String], + resolve: RCTPromiseResolveBlock, + reject: RCTPromiseRejectBlock + ) { + BigInteger.computeModPow(payload, resolve: resolve, reject: reject) + } + + @objc(computeS:withResolver:withRejecter:) + func computeS( + _ payload: [String: String], + resolve: RCTPromiseResolveBlock, + reject: RCTPromiseRejectBlock + ) { + BigInteger.computeS(payload, resolve: resolve, reject: reject) + } + + @objc(getDeviceName:withResolver:) + func getDeviceName(resolve: @escaping RCTPromiseResolveBlock, reject _: @escaping RCTPromiseRejectBlock) { + var deviceName: String + #if canImport(UIKit) + deviceName = UIDevice.current.name + #else + deviceName = ProcessInfo.processInfo.hostName + #endif + resolve(deviceName) + } } diff --git a/packages/react-native/src/apis/getDeviceName.ts b/packages/react-native/src/apis/getDeviceName.ts new file mode 100644 index 00000000000..246d6a0bc62 --- /dev/null +++ b/packages/react-native/src/apis/getDeviceName.ts @@ -0,0 +1,8 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { nativeModule } from '../nativeModule'; +import { RTNCore } from '../types'; + +export const getDeviceName: RTNCore['getDeviceName'] = () => + nativeModule.getDeviceName(); diff --git a/packages/react-native/src/apis/index.ts b/packages/react-native/src/apis/index.ts index 63b1caa9bc7..ed2bc4f9678 100644 --- a/packages/react-native/src/apis/index.ts +++ b/packages/react-native/src/apis/index.ts @@ -4,3 +4,4 @@ export { computeModPow } from './computeModPow'; export { computeS } from './computeS'; export { getOperatingSystem } from './getOperatingSystem'; +export { getDeviceName } from './getDeviceName'; diff --git a/packages/react-native/src/index.ts b/packages/react-native/src/index.ts index 8141aa8855b..357e43e0f2b 100644 --- a/packages/react-native/src/index.ts +++ b/packages/react-native/src/index.ts @@ -1,7 +1,12 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -export { computeModPow, computeS, getOperatingSystem } from './apis'; +export { + computeModPow, + computeS, + getOperatingSystem, + getDeviceName, +} from './apis'; export { loadAmplifyPushNotification, loadAmplifyWebBrowser, diff --git a/packages/react-native/src/types.ts b/packages/react-native/src/types.ts index 2d61d088b32..07b868bc9c3 100644 --- a/packages/react-native/src/types.ts +++ b/packages/react-native/src/types.ts @@ -16,4 +16,6 @@ export interface RTNCore { b: string; u: string; }): Promise; + + getDeviceName(): Promise; } From b2bf80a7d74cae0d62cba7a1c7d79a01b117aa70 Mon Sep 17 00:00:00 2001 From: Israel Arcos Date: Mon, 29 Apr 2024 12:54:40 -0500 Subject: [PATCH 03/15] feat(auth): enable gen2 e2e tests --- .github/integ-config/integ-all.yml | 66 ++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/.github/integ-config/integ-all.yml b/.github/integ-config/integ-all.yml index 262b59a4b44..a81a9cea17b 100644 --- a/.github/integ-config/integ-all.yml +++ b/.github/integ-config/integ-all.yml @@ -512,6 +512,72 @@ tests: spec: sign-in-with-oauth browser: [chrome] + # AUTH GEN2 + - test_name: integ_react_javascript_authentication + desc: 'React Authentication' + framework: react + category: auth + sample_name: [javascript-auth] + spec: functional-auth + browser: *minimal_browser_list + backend: gen2 + - test_name: integ_react_auth_1_guest_to_authenticated_user + desc: 'Guest to Authenticated User' + framework: react + category: auth + sample_name: [guest-to-auth-user] + spec: guest-to-auth-user + browser: *minimal_browser_list + backend: gen2 + - test_name: integ_react_typescript_authentication + desc: 'React Typescript Authentication' + framework: react + category: auth + sample_name: [typescript-auth] + spec: functional-auth + browser: *minimal_browser_list + backend: gen2 + - test_name: integ_react_auth_2_sign_in_after_sign_up + desc: 'Sign In after Sign Up' + framework: react + category: auth + sample_name: [auto-signin-after-signup] + spec: auto-signin-after-signup + browser: *minimal_browser_list + backend: gen2 + - test_name: integ_react_device_tracking + desc: 'cognito-device-tracking' + framework: react + category: auth + sample_name: [device-tracking] + spec: device-tracking + browser: *minimal_browser_list + backend: gen2 + - test_name: integ_react_delete_user + desc: 'delete-user' + framework: react + category: auth + sample_name: [delete-user] + spec: delete-user + browser: *minimal_browser_list + backend: gen2 + - test_name: integ_next_auth_authenticator_and_ssr_page + desc: 'Authenticator and SSR page' + framework: next + category: auth + sample_name: [auth-ssr] + spec: auth-ssr + browser: [chrome] + backend: gen2 + - test_name: integ_next_auth_authenticator_and_rsc_page + desc: 'Authenticator and RSC page' + framework: next + category: auth + sample_name: [auth-rsc] + spec: auth-rsc + browser: [chrome] + backend: gen2 + # DISABLED Angular/Vue tests: # TODO: delete tests or add custom ui logic to support them. From 38e20c8371536373c879df09cbe92d7229439e91 Mon Sep 17 00:00:00 2001 From: Israel Arcos Date: Tue, 30 Apr 2024 14:52:56 -0500 Subject: [PATCH 04/15] chore: enable oauth test --- .github/integ-config/integ-all.yml | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/.github/integ-config/integ-all.yml b/.github/integ-config/integ-all.yml index a81a9cea17b..4b6c1b7408f 100644 --- a/.github/integ-config/integ-all.yml +++ b/.github/integ-config/integ-all.yml @@ -513,7 +513,7 @@ tests: browser: [chrome] # AUTH GEN2 - - test_name: integ_react_javascript_authentication + - test_name: integ_react_javascript_authentication_gen2 desc: 'React Authentication' framework: react category: auth @@ -521,7 +521,7 @@ tests: spec: functional-auth browser: *minimal_browser_list backend: gen2 - - test_name: integ_react_auth_1_guest_to_authenticated_user + - test_name: integ_react_auth_1_guest_to_authenticated_user_gen2 desc: 'Guest to Authenticated User' framework: react category: auth @@ -529,7 +529,7 @@ tests: spec: guest-to-auth-user browser: *minimal_browser_list backend: gen2 - - test_name: integ_react_typescript_authentication + - test_name: integ_react_typescript_authentication_gen2 desc: 'React Typescript Authentication' framework: react category: auth @@ -537,7 +537,7 @@ tests: spec: functional-auth browser: *minimal_browser_list backend: gen2 - - test_name: integ_react_auth_2_sign_in_after_sign_up + - test_name: integ_react_auth_2_sign_in_after_sign_up_gen2 desc: 'Sign In after Sign Up' framework: react category: auth @@ -545,7 +545,7 @@ tests: spec: auto-signin-after-signup browser: *minimal_browser_list backend: gen2 - - test_name: integ_react_device_tracking + - test_name: integ_react_device_tracking_gen2 desc: 'cognito-device-tracking' framework: react category: auth @@ -553,7 +553,7 @@ tests: spec: device-tracking browser: *minimal_browser_list backend: gen2 - - test_name: integ_react_delete_user + - test_name: integ_react_delete_user_gen2 desc: 'delete-user' framework: react category: auth @@ -561,7 +561,7 @@ tests: spec: delete-user browser: *minimal_browser_list backend: gen2 - - test_name: integ_next_auth_authenticator_and_ssr_page + - test_name: integ_next_auth_authenticator_and_ssr_page_gen2 desc: 'Authenticator and SSR page' framework: next category: auth @@ -569,7 +569,7 @@ tests: spec: auth-ssr browser: [chrome] backend: gen2 - - test_name: integ_next_auth_authenticator_and_rsc_page + - test_name: integ_next_auth_authenticator_and_rsc_page_gen2 desc: 'Authenticator and RSC page' framework: next category: auth @@ -577,6 +577,15 @@ tests: spec: auth-rsc browser: [chrome] backend: gen2 + - test_name: integ_next_sign_in_with_oauth_gen2 + desc: 'Sign-in with the OAuth flow' + framework: next + category: auth + sample_name: [sign-in-with-oauth] + spec: sign-in-with-oauth + browser: [chrome] + backend: gen2 + # DISABLED Angular/Vue tests: # TODO: delete tests or add custom ui logic to support them. From a75ae7b2d648ea45ad1fa9332ee95a00ba0d1d3b Mon Sep 17 00:00:00 2001 From: Chris Fang Date: Tue, 30 Apr 2024 11:47:24 -0700 Subject: [PATCH 05/15] fix: Prevent creating multiple endpoint ids --- .../pinpoint/apis/updateEndpoint.test.ts | 45 ++++++++++++++++--- .../pinpoint/utils/createEndpointId.test.ts | 45 +++++++++++++++++++ .../providers/pinpoint/apis/updateEndpoint.ts | 24 +++++++--- .../pinpoint/utils/createEndpointId.ts | 39 ++++++++++++++++ .../src/providers/pinpoint/utils/index.ts | 1 + 5 files changed, 142 insertions(+), 12 deletions(-) create mode 100644 packages/core/__tests__/providers/pinpoint/utils/createEndpointId.test.ts create mode 100644 packages/core/src/providers/pinpoint/utils/createEndpointId.ts diff --git a/packages/core/__tests__/providers/pinpoint/apis/updateEndpoint.test.ts b/packages/core/__tests__/providers/pinpoint/apis/updateEndpoint.test.ts index 6ad4e718955..261344cfede 100644 --- a/packages/core/__tests__/providers/pinpoint/apis/updateEndpoint.test.ts +++ b/packages/core/__tests__/providers/pinpoint/apis/updateEndpoint.test.ts @@ -1,13 +1,16 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 -import { v4 } from 'uuid'; - import { getClientInfo } from '../../../../src/utils/getClientInfo'; import { updateEndpoint as clientUpdateEndpoint } from '../../../../src/awsClients/pinpoint'; import { cacheEndpointId } from '../../../../src/providers/pinpoint/utils/cacheEndpointId'; +import { + clearCreatedEndpointId, + createEndpointId, +} from '../../../../src/providers/pinpoint/utils/createEndpointId'; import { getEndpointId } from '../../../../src/providers/pinpoint/utils/getEndpointId'; import { updateEndpoint } from '../../../../src/providers/pinpoint/apis'; +import { amplifyUuid } from '../../../../src/utils/amplifyUuid'; import { appId, category, @@ -22,10 +25,11 @@ import { import { getExpectedInput } from './testUtils/getExpectedInput'; -jest.mock('uuid'); jest.mock('../../../../src/awsClients/pinpoint'); jest.mock('../../../../src/providers/pinpoint/utils/cacheEndpointId'); +jest.mock('../../../../src/providers/pinpoint/utils/createEndpointId'); jest.mock('../../../../src/providers/pinpoint/utils/getEndpointId'); +jest.mock('../../../../src/utils/amplifyUuid'); jest.mock('../../../../src/utils/getClientInfo'); describe('Pinpoint Provider API: updateEndpoint', () => { @@ -41,14 +45,17 @@ describe('Pinpoint Provider API: updateEndpoint', () => { timezone: 'user-timezone', }; // assert mocks + const mockAmplifyUuid = amplifyUuid as jest.Mock; const mockCacheEndpointId = cacheEndpointId as jest.Mock; + const mockClearCreatedEndpointId = clearCreatedEndpointId as jest.Mock; + const mockCreateEndpointId = createEndpointId as jest.Mock; const mockClientUpdateEndpoint = clientUpdateEndpoint as jest.Mock; const mockGetClientInfo = getClientInfo as jest.Mock; const mockGetEndpointId = getEndpointId as jest.Mock; - const mockUuid = v4 as jest.Mock; beforeAll(() => { - mockUuid.mockReturnValue(uuid); + mockAmplifyUuid.mockReturnValue(uuid); + mockCreateEndpointId.mockReturnValue(createdEndpointId); mockGetClientInfo.mockReturnValue(clientDemographic); }); @@ -58,7 +65,9 @@ describe('Pinpoint Provider API: updateEndpoint', () => { afterEach(() => { mockCacheEndpointId.mockClear(); - mockClientUpdateEndpoint.mockClear(); + mockClearCreatedEndpointId.mockClear(); + mockCreateEndpointId.mockClear(); + mockClientUpdateEndpoint.mockReset(); mockGetEndpointId.mockReset(); }); @@ -148,7 +157,6 @@ describe('Pinpoint Provider API: updateEndpoint', () => { it('creates an endpoint if one is not already cached', async () => { mockGetEndpointId.mockReturnValue(undefined); - mockUuid.mockReturnValueOnce(createdEndpointId); await updateEndpoint({ appId, category, credentials, region }); expect(mockClientUpdateEndpoint).toHaveBeenCalledWith( { credentials, region }, @@ -159,10 +167,33 @@ describe('Pinpoint Provider API: updateEndpoint', () => { category, createdEndpointId, ); + expect(mockClearCreatedEndpointId).toHaveBeenCalledWith(appId, category); + }); + + it('does not create an endpoint if previously cached', async () => { + await updateEndpoint({ appId, category, credentials, region }); + expect(mockCreateEndpointId).not.toHaveBeenCalled(); }); it('does not cache endpoint if previously cached', async () => { await updateEndpoint({ appId, category, credentials, region }); expect(mockCacheEndpointId).not.toHaveBeenCalled(); + expect(mockClearCreatedEndpointId).not.toHaveBeenCalled(); + }); + + it('throws on update failure', async () => { + mockClientUpdateEndpoint.mockRejectedValue(new Error()); + await expect( + updateEndpoint({ appId, category, credentials, region }), + ).rejects.toThrow(); + }); + + it('clears a created endpoint on update failure', async () => { + mockGetEndpointId.mockReturnValue(undefined); + mockClientUpdateEndpoint.mockRejectedValue(new Error()); + await expect( + updateEndpoint({ appId, category, credentials, region }), + ).rejects.toThrow(); + expect(mockClearCreatedEndpointId).toHaveBeenCalledWith(appId, category); }); }); diff --git a/packages/core/__tests__/providers/pinpoint/utils/createEndpointId.test.ts b/packages/core/__tests__/providers/pinpoint/utils/createEndpointId.test.ts new file mode 100644 index 00000000000..daa96737e23 --- /dev/null +++ b/packages/core/__tests__/providers/pinpoint/utils/createEndpointId.test.ts @@ -0,0 +1,45 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { + clearCreatedEndpointId, + createEndpointId, +} from '../../../../src/providers/pinpoint/utils/createEndpointId'; +import { amplifyUuid } from '../../../../src/utils/amplifyUuid'; +import { appId, category, uuid } from '../testUtils/data'; + +jest.mock('../../../../src/utils/amplifyUuid'); + +describe('Pinpoint Provider Util: createEndpointId', () => { + // assert mocks + const mockAmplifyUuid = amplifyUuid as jest.Mock; + + it('returns a new endpoint id for a category', () => { + mockAmplifyUuid.mockReturnValue(uuid); + + expect(createEndpointId(appId, category)).toBe(uuid); + }); + + it('returns the same endpoint id for a category', () => { + const newUuid = `new-${uuid}`; + mockAmplifyUuid.mockReturnValue(newUuid); + + expect(createEndpointId(appId, category)).toBe(uuid); + }); + + it('returns a new endpoint id for a different category', () => { + const newUuid = `new-${uuid}`; + const newCategory = 'PushNotification'; + mockAmplifyUuid.mockReturnValue(newUuid); + + expect(createEndpointId(appId, newCategory)).toBe(newUuid); + }); + + it('clears a created endpoint id for a category', () => { + const newUuid = `new-${uuid}`; + mockAmplifyUuid.mockReturnValue(newUuid); + clearCreatedEndpointId(appId, category); + + expect(createEndpointId(appId, category)).toBe(newUuid); + }); +}); diff --git a/packages/core/src/providers/pinpoint/apis/updateEndpoint.ts b/packages/core/src/providers/pinpoint/apis/updateEndpoint.ts index 1e49383a83d..88a9370e9f8 100644 --- a/packages/core/src/providers/pinpoint/apis/updateEndpoint.ts +++ b/packages/core/src/providers/pinpoint/apis/updateEndpoint.ts @@ -9,6 +9,10 @@ import { } from '../../../awsClients/pinpoint'; import { PinpointUpdateEndpointInput } from '../types'; import { cacheEndpointId } from '../utils/cacheEndpointId'; +import { + clearCreatedEndpointId, + createEndpointId, +} from '../utils/createEndpointId'; import { getEndpointId } from '../utils/getEndpointId'; /** @@ -30,7 +34,9 @@ export const updateEndpoint = async ({ }: PinpointUpdateEndpointInput): Promise => { const endpointId = await getEndpointId(appId, category); // only generate a new endpoint id if one was not found in cache - const createdEndpointId = !endpointId ? amplifyUuid() : undefined; + const createdEndpointId = !endpointId + ? createEndpointId(appId, category) + : undefined; const { customProperties, demographic, @@ -91,9 +97,17 @@ export const updateEndpoint = async ({ }, }, }; - await clientUpdateEndpoint({ credentials, region, userAgentValue }, input); - // if we had to create an endpoint id, we need to now cache it - if (createdEndpointId) { - return cacheEndpointId(appId, category, createdEndpointId); + try { + await clientUpdateEndpoint({ credentials, region, userAgentValue }, input); + // if we had to create an endpoint id, we need to now cache it + if (createdEndpointId) { + await cacheEndpointId(appId, category, createdEndpointId); + } + } finally { + // at this point, we completely reset the behavior so even if the update was unsuccessful + // we can just start over with a newly created endpoint id + if (createdEndpointId) { + clearCreatedEndpointId(appId, category); + } } }; diff --git a/packages/core/src/providers/pinpoint/utils/createEndpointId.ts b/packages/core/src/providers/pinpoint/utils/createEndpointId.ts new file mode 100644 index 00000000000..b2544cf4326 --- /dev/null +++ b/packages/core/src/providers/pinpoint/utils/createEndpointId.ts @@ -0,0 +1,39 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { amplifyUuid } from '../../../utils/amplifyUuid'; +import { SupportedCategory } from '../types'; + +import { getCacheKey } from './getCacheKey'; + +const createdEndpointIds: Record = {}; + +/** + * Creates an endpoint id and guarantees multiple creations for a category returns the same uuid. + * + * @internal + */ +export const createEndpointId = ( + appId: string, + category: SupportedCategory, +): string => { + const cacheKey = getCacheKey(appId, category); + if (!createdEndpointIds[cacheKey]) { + createdEndpointIds[cacheKey] = amplifyUuid(); + } + + return createdEndpointIds[cacheKey]; +}; + +/** + * Clears a created endpoint id for a category. + * + * @internal + */ +export const clearCreatedEndpointId = ( + appId: string, + category: SupportedCategory, +): void => { + const cacheKey = getCacheKey(appId, category); + delete createdEndpointIds[cacheKey]; +}; diff --git a/packages/core/src/providers/pinpoint/utils/index.ts b/packages/core/src/providers/pinpoint/utils/index.ts index ad19b92e89c..ed49553bf12 100644 --- a/packages/core/src/providers/pinpoint/utils/index.ts +++ b/packages/core/src/providers/pinpoint/utils/index.ts @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 export { cacheEndpointId } from './cacheEndpointId'; +export { createEndpointId } from './createEndpointId'; export { getCacheKey } from './getCacheKey'; export { getEndpointId } from './getEndpointId'; export { resolveEndpointId } from './resolveEndpointId'; From fd859f98792db9e6a12fffb14e16a6db95968a59 Mon Sep 17 00:00:00 2001 From: Chris Fang Date: Tue, 30 Apr 2024 13:37:31 -0700 Subject: [PATCH 06/15] Bump bundle size limit --- packages/aws-amplify/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/aws-amplify/package.json b/packages/aws-amplify/package.json index a3f3364484c..7e2f6090c8a 100644 --- a/packages/aws-amplify/package.json +++ b/packages/aws-amplify/package.json @@ -317,7 +317,7 @@ "name": "[Analytics] identifyUser (Pinpoint)", "path": "./dist/esm/analytics/index.mjs", "import": "{ identifyUser }", - "limit": "15.52 kB" + "limit": "15.53 kB" }, { "name": "[Analytics] enable", From 2f3d65dde1cf98cb84f35cd7952f9553a002a931 Mon Sep 17 00:00:00 2001 From: Chris Fang Date: Tue, 30 Apr 2024 14:54:08 -0700 Subject: [PATCH 07/15] Update unit test to be more meaningful/robust --- .../providers/pinpoint/utils/createEndpointId.test.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/core/__tests__/providers/pinpoint/utils/createEndpointId.test.ts b/packages/core/__tests__/providers/pinpoint/utils/createEndpointId.test.ts index daa96737e23..462eee902a5 100644 --- a/packages/core/__tests__/providers/pinpoint/utils/createEndpointId.test.ts +++ b/packages/core/__tests__/providers/pinpoint/utils/createEndpointId.test.ts @@ -14,10 +14,15 @@ describe('Pinpoint Provider Util: createEndpointId', () => { // assert mocks const mockAmplifyUuid = amplifyUuid as jest.Mock; + afterEach(() => { + mockAmplifyUuid.mockReset(); + }); + it('returns a new endpoint id for a category', () => { mockAmplifyUuid.mockReturnValue(uuid); expect(createEndpointId(appId, category)).toBe(uuid); + expect(mockAmplifyUuid).toHaveBeenCalled(); }); it('returns the same endpoint id for a category', () => { @@ -25,6 +30,7 @@ describe('Pinpoint Provider Util: createEndpointId', () => { mockAmplifyUuid.mockReturnValue(newUuid); expect(createEndpointId(appId, category)).toBe(uuid); + expect(mockAmplifyUuid).not.toHaveBeenCalled(); }); it('returns a new endpoint id for a different category', () => { @@ -33,6 +39,7 @@ describe('Pinpoint Provider Util: createEndpointId', () => { mockAmplifyUuid.mockReturnValue(newUuid); expect(createEndpointId(appId, newCategory)).toBe(newUuid); + expect(mockAmplifyUuid).toHaveBeenCalled(); }); it('clears a created endpoint id for a category', () => { From e2cdd3843c910572ef952164fd630ca15a7ce92b Mon Sep 17 00:00:00 2001 From: Chris Fang Date: Tue, 30 Apr 2024 15:18:26 -0700 Subject: [PATCH 08/15] Update unit test description --- .../pinpoint/utils/createEndpointId.test.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/core/__tests__/providers/pinpoint/utils/createEndpointId.test.ts b/packages/core/__tests__/providers/pinpoint/utils/createEndpointId.test.ts index 462eee902a5..841707ded77 100644 --- a/packages/core/__tests__/providers/pinpoint/utils/createEndpointId.test.ts +++ b/packages/core/__tests__/providers/pinpoint/utils/createEndpointId.test.ts @@ -42,11 +42,13 @@ describe('Pinpoint Provider Util: createEndpointId', () => { expect(mockAmplifyUuid).toHaveBeenCalled(); }); - it('clears a created endpoint id for a category', () => { - const newUuid = `new-${uuid}`; - mockAmplifyUuid.mockReturnValue(newUuid); - clearCreatedEndpointId(appId, category); - - expect(createEndpointId(appId, category)).toBe(newUuid); + describe('clearCreatedEndpointId()', () => { + it('can create a new endpoint id for a category after clearing', () => { + const newUuid = `new-${uuid}`; + mockAmplifyUuid.mockReturnValue(newUuid); + clearCreatedEndpointId(appId, category); + + expect(createEndpointId(appId, category)).toBe(newUuid); + }); }); }); From d218d816f1a211e3915a7d8a98acbb762fabbad5 Mon Sep 17 00:00:00 2001 From: Jon Wire Date: Wed, 1 May 2024 09:24:55 -0500 Subject: [PATCH 09/15] chore: add deprecation notice to DataStore exported Schemaa type (#13321) add deprecation notice to DataStore exported Schemaa type --- packages/datastore/src/types.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/datastore/src/types.ts b/packages/datastore/src/types.ts index 37d98d1c2a5..e443726cdd7 100644 --- a/packages/datastore/src/types.ts +++ b/packages/datastore/src/types.ts @@ -22,10 +22,18 @@ import { GraphQLAuthMode } from '@aws-amplify/core/internals/utils'; export type Scalar = T extends Array ? InnerType : T; //#region Schema types -export type Schema = UserSchema & { +/** + * @deprecated If you intended to use the Schema for `generateClient`, then you've imported the wrong Schema type. + * Use `import { type Schema } from '../amplify/data/resource' instead. If you intended to import the type for DataStore + * Schemas, then import "DataStoreSchema" instead. + */ +export type Schema = DataStoreSchema; + +export type DataStoreSchema = UserSchema & { version: string; codegenVersion: string; }; + export type UserSchema = { models: SchemaModels; nonModels?: SchemaNonModels; From e8e879623888a9ada2dc2ad3f1b2775048e2e05d Mon Sep 17 00:00:00 2001 From: Jim Blanchard Date: Wed, 1 May 2024 11:39:24 -0500 Subject: [PATCH 10/15] chore: Bump `@aws-amplify/core` peer dependency across the library (#13308) --- packages/analytics/package.json | 2 +- packages/api-rest/package.json | 2 +- packages/auth/package.json | 2 +- packages/datastore-storage-adapter/package.json | 2 +- packages/datastore/package.json | 2 +- packages/geo/package.json | 2 +- packages/notifications/package.json | 2 +- packages/predictions/package.json | 2 +- packages/pubsub/package.json | 2 +- packages/storage/package.json | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/analytics/package.json b/packages/analytics/package.json index 6640f85c121..50da64d17bd 100644 --- a/packages/analytics/package.json +++ b/packages/analytics/package.json @@ -100,7 +100,7 @@ "tslib": "^2.5.0" }, "peerDependencies": { - "@aws-amplify/core": "^6.0.0" + "@aws-amplify/core": "^6.1.0" }, "devDependencies": { "@aws-amplify/core": "6.1.0", diff --git a/packages/api-rest/package.json b/packages/api-rest/package.json index 1885a341168..64a3abe7fde 100644 --- a/packages/api-rest/package.json +++ b/packages/api-rest/package.json @@ -84,7 +84,7 @@ "tslib": "^2.5.0" }, "peerDependencies": { - "@aws-amplify/core": "^6.0.0" + "@aws-amplify/core": "^6.1.0" }, "devDependencies": { "@aws-amplify/core": "6.1.0", diff --git a/packages/auth/package.json b/packages/auth/package.json index 2631594aace..3e66125d20a 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -94,7 +94,7 @@ "tslib": "^2.5.0" }, "peerDependencies": { - "@aws-amplify/core": "^6.0.0" + "@aws-amplify/core": "^6.1.0" }, "devDependencies": { "@aws-amplify/core": "6.1.0", diff --git a/packages/datastore-storage-adapter/package.json b/packages/datastore-storage-adapter/package.json index d382c1288bd..6dae0abcee7 100644 --- a/packages/datastore-storage-adapter/package.json +++ b/packages/datastore-storage-adapter/package.json @@ -32,7 +32,7 @@ }, "homepage": "https://aws-amplify.github.io/", "peerDependencies": { - "@aws-amplify/core": "^6.0.0" + "@aws-amplify/core": "^6.1.0" }, "devDependencies": { "@aws-amplify/core": "6.1.0", diff --git a/packages/datastore/package.json b/packages/datastore/package.json index 210d7279fe2..31bfd2cbe38 100644 --- a/packages/datastore/package.json +++ b/packages/datastore/package.json @@ -51,7 +51,7 @@ "ulid": "^2.3.0" }, "peerDependencies": { - "@aws-amplify/core": "^6.0.0" + "@aws-amplify/core": "^6.1.0" }, "devDependencies": { "@aws-amplify/core": "6.1.0", diff --git a/packages/geo/package.json b/packages/geo/package.json index dd9170af620..96029d70793 100644 --- a/packages/geo/package.json +++ b/packages/geo/package.json @@ -73,7 +73,7 @@ "tslib": "^2.5.0" }, "peerDependencies": { - "@aws-amplify/core": "^6.0.0" + "@aws-amplify/core": "^6.1.0" }, "devDependencies": { "@aws-amplify/core": "6.1.0", diff --git a/packages/notifications/package.json b/packages/notifications/package.json index 446c272751e..79edf890aa6 100644 --- a/packages/notifications/package.json +++ b/packages/notifications/package.json @@ -95,7 +95,7 @@ "tslib": "^2.5.0" }, "peerDependencies": { - "@aws-amplify/core": "^6.0.0" + "@aws-amplify/core": "^6.1.0" }, "devDependencies": { "@aws-amplify/core": "6.1.0", diff --git a/packages/predictions/package.json b/packages/predictions/package.json index 94fe33542ab..f3c64a235e0 100644 --- a/packages/predictions/package.json +++ b/packages/predictions/package.json @@ -56,7 +56,7 @@ "uuid": "^9.0.0" }, "peerDependencies": { - "@aws-amplify/core": "^6.0.0" + "@aws-amplify/core": "^6.1.0" }, "devDependencies": { "@aws-amplify/core": "6.1.0", diff --git a/packages/pubsub/package.json b/packages/pubsub/package.json index 96dc2cd5aae..17e5cab8a35 100644 --- a/packages/pubsub/package.json +++ b/packages/pubsub/package.json @@ -81,7 +81,7 @@ "url": "0.11.0" }, "peerDependencies": { - "@aws-amplify/core": "^6.0.0" + "@aws-amplify/core": "^6.1.0" }, "devDependencies": { "@aws-amplify/core": "6.1.0", diff --git a/packages/storage/package.json b/packages/storage/package.json index 8b136f7fdcc..a9121fce3dd 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -98,7 +98,7 @@ "./package.json": "./package.json" }, "peerDependencies": { - "@aws-amplify/core": "^6.0.0" + "@aws-amplify/core": "^6.1.0" }, "devDependencies": { "@aws-amplify/core": "6.1.0", From 420e2c57a17f0e423386b3c58ad554ad0b5d0e6e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 May 2024 09:58:30 -0500 Subject: [PATCH 11/15] chore(deps): bump ejs from 3.1.9 to 3.1.10 (#13325) Bumps [ejs](https://github.com/mde/ejs) from 3.1.9 to 3.1.10. - [Release notes](https://github.com/mde/ejs/releases) - [Commits](https://github.com/mde/ejs/compare/v3.1.9...v3.1.10) --- updated-dependencies: - dependency-name: ejs dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index 83c82754b5f..3ba05bc1428 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7234,9 +7234,9 @@ ee-first@1.1.1: integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== ejs@^3.1.7: - version "3.1.9" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.9.tgz#03c9e8777fe12686a9effcef22303ca3d8eeb361" - integrity sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ== + version "3.1.10" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b" + integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA== dependencies: jake "^10.8.5" @@ -14207,7 +14207,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -14275,7 +14284,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -14289,6 +14298,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -15481,7 +15497,7 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -15508,6 +15524,15 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 78a21b8b3623fff5beee893853e7c9a619d4cd06 Mon Sep 17 00:00:00 2001 From: ManojNB Date: Thu, 2 May 2024 10:24:20 -0700 Subject: [PATCH 12/15] feat(gh-actions): gen2 e2e rest api (#13293) * feat: gen2 e2e rest api * chore: update gen2 test name * chore: reverted branch name --------- Co-authored-by: israx <70438514+israx@users.noreply.github.com> --- .github/integ-config/integ-all.yml | 10 ++++++++++ .github/workflows/callable-e2e-test.yml | 7 +++++++ .github/workflows/callable-e2e-tests.yml | 1 + 3 files changed, 18 insertions(+) diff --git a/.github/integ-config/integ-all.yml b/.github/integ-config/integ-all.yml index 262b59a4b44..5602c4da5e5 100644 --- a/.github/integ-config/integ-all.yml +++ b/.github/integ-config/integ-all.yml @@ -440,6 +440,16 @@ tests: spec: restful browser: *minimal_browser_list + # API Gen2 + - test_name: integ_react_rest_api_gen2 + desc: 'GEN2 Vite + React REST API' + framework: vite + category: api + sample_name: [rest] + spec: restful + backend: gen2 + browser: *minimal_browser_list + # AUTH - test_name: integ_react_javascript_authentication desc: 'React Authentication' diff --git a/.github/workflows/callable-e2e-test.yml b/.github/workflows/callable-e2e-test.yml index 2628eac2704..67b35106458 100644 --- a/.github/workflows/callable-e2e-test.yml +++ b/.github/workflows/callable-e2e-test.yml @@ -22,6 +22,9 @@ on: browser: required: true type: string + backend: + required: true + type: string amplifyjs_dir: required: true type: boolean @@ -73,6 +76,7 @@ jobs: E2E_SAMPLE_NAME: ${{ matrix.sample_name }} E2E_SPEC: ${{ inputs.spec }} E2E_BROWSER: ${{ matrix.browser }} + E2E_BACKEND: ${{ inputs.backend }} E2E_AMPLIFY_JS_DIR: ${{ inputs.amplifyjs_dir == true && env.AMPLIFY_DIR || ''}} E2E_RETRY_COUNT: ${{ inputs.retry_count }} E2E_TEST_NAME: ${{ inputs.test_name }} @@ -85,6 +89,7 @@ jobs: $E2E_SPEC \ $E2E_BROWSER \ dev \ + $E2E_BACKEND \ $E2E_AMPLIFY_JS_DIR" \ -n $E2E_RETRY_COUNT @@ -97,6 +102,7 @@ jobs: E2E_SAMPLE_NAME: ${{ matrix.sample_name }} E2E_SPEC: ${{ inputs.spec }} E2E_BROWSER: ${{ matrix.browser }} + E2E_BACKEND: ${{ inputs.backend }} E2E_AMPLIFY_JS_DIR: ${{ inputs.amplifyjs_dir == true && env.AMPLIFY_DIR || ''}} E2E_RETRY_COUNT: ${{ inputs.retry_count }} E2E_TEST_NAME: ${{ inputs.test_name }} @@ -109,6 +115,7 @@ jobs: $E2E_SPEC \ $E2E_BROWSER \ prod \ + $E2E_BACKEND \ $E2E_AMPLIFY_JS_DIR" \ -n $E2E_RETRY_COUNT - name: Upload artifact diff --git a/.github/workflows/callable-e2e-tests.yml b/.github/workflows/callable-e2e-tests.yml index 93459f49a9e..2bfc5161ec3 100644 --- a/.github/workflows/callable-e2e-tests.yml +++ b/.github/workflows/callable-e2e-tests.yml @@ -40,6 +40,7 @@ jobs: amplifyjs_dir: ${{ matrix.integ-config.amplifyjs_dir || false }} sample_name: ${{ toJSON(matrix.integ-config.sample_name) || '[""]' }} browser: ${{ toJSON(matrix.integ-config.browser) || '[""]' }} + backend: ${{ matrix.integ-config.backend }} timeout_minutes: ${{ matrix.integ-config.timeout_minutes || 35 }} retry_count: ${{ matrix.integ-config.retry_count || 3 }} From 5f3418678a06ac43ed8bf700649703c1cf280eeb Mon Sep 17 00:00:00 2001 From: Ashwin Kumar Date: Thu, 2 May 2024 13:01:40 -0700 Subject: [PATCH 13/15] feat(auth): add a default deviceName when remembering device (#13022) * feat(auth): add a default deviceName when remembering device * increase bundle size --------- Co-authored-by: Ashwin Kumar --- .../providers/cognito/fetchDevices.test.ts | 8 ++- .../providers/cognito/apis/fetchDevices.ts | 3 ++ .../providers/cognito/utils/signInHelpers.ts | 2 + packages/aws-amplify/package.json | 4 +- packages/core/src/libraryUtils.ts | 1 + .../utils/deviceName/getDeviceName.native.ts | 15 ++++++ .../src/utils/deviceName/getDeviceName.ts | 52 +++++++++++++++++++ packages/core/src/utils/deviceName/index.ts | 4 ++ packages/core/src/utils/deviceName/types.ts | 44 ++++++++++++++++ 9 files changed, 129 insertions(+), 4 deletions(-) create mode 100644 packages/core/src/utils/deviceName/getDeviceName.native.ts create mode 100644 packages/core/src/utils/deviceName/getDeviceName.ts create mode 100644 packages/core/src/utils/deviceName/index.ts create mode 100644 packages/core/src/utils/deviceName/types.ts diff --git a/packages/auth/__tests__/providers/cognito/fetchDevices.test.ts b/packages/auth/__tests__/providers/cognito/fetchDevices.test.ts index a3f6fb40384..c7b09e53d8a 100644 --- a/packages/auth/__tests__/providers/cognito/fetchDevices.test.ts +++ b/packages/auth/__tests__/providers/cognito/fetchDevices.test.ts @@ -26,7 +26,10 @@ describe('fetchDevices', () => { const dateEpoch = 1.696296885807e9; const date = new Date(dateEpoch * 1000); const clientResponseDevice = { - DeviceAttributes: [{ Name: 'attributeName', Value: 'attributeValue' }], + DeviceAttributes: [ + { Name: 'attributeName', Value: 'attributeValue' }, + { Name: 'device_name', Value: 'deviceNameValue' }, + ], DeviceCreateDate: dateEpoch, DeviceKey: 'DeviceKey', DeviceLastAuthenticatedDate: dateEpoch, @@ -34,9 +37,10 @@ describe('fetchDevices', () => { }; const apiOutputDevice = { id: 'DeviceKey', - name: undefined, + name: 'deviceNameValue', attributes: { attributeName: 'attributeValue', + device_name: 'deviceNameValue', }, createDate: date, lastModifiedDate: date, diff --git a/packages/auth/src/providers/cognito/apis/fetchDevices.ts b/packages/auth/src/providers/cognito/apis/fetchDevices.ts index 2ac3bddde30..29be20e7a78 100644 --- a/packages/auth/src/providers/cognito/apis/fetchDevices.ts +++ b/packages/auth/src/providers/cognito/apis/fetchDevices.ts @@ -59,9 +59,11 @@ const parseDevicesResponse = async ( DeviceLastModifiedDate, DeviceLastAuthenticatedDate, }) => { + let deviceName: string | undefined; const attributes = DeviceAttributes.reduce( (attrs: any, { Name, Value }) => { if (Name && Value) { + if (Name === 'device_name') deviceName = Value; attrs[Name] = Value; } @@ -72,6 +74,7 @@ const parseDevicesResponse = async ( return { id, + name: deviceName, attributes, createDate: DeviceCreateDate ? new Date(DeviceCreateDate * 1000) diff --git a/packages/auth/src/providers/cognito/utils/signInHelpers.ts b/packages/auth/src/providers/cognito/utils/signInHelpers.ts index ce1336ce611..13edcd84e62 100644 --- a/packages/auth/src/providers/cognito/utils/signInHelpers.ts +++ b/packages/auth/src/providers/cognito/utils/signInHelpers.ts @@ -7,6 +7,7 @@ import { AuthAction, assertTokenProviderConfig, base64Encoder, + getDeviceName, } from '@aws-amplify/core/internals/utils'; import { ClientMetadata, ConfirmSignInOptions } from '../types'; @@ -1072,6 +1073,7 @@ export async function getNewDeviceMetatada( { region: getRegion(userPoolId) }, { AccessToken: accessToken, + DeviceName: await getDeviceName(), DeviceKey: newDeviceMetadata?.DeviceKey, DeviceSecretVerifierConfig: deviceSecretVerifierConfig, }, diff --git a/packages/aws-amplify/package.json b/packages/aws-amplify/package.json index 7e2f6090c8a..a3254ed2252 100644 --- a/packages/aws-amplify/package.json +++ b/packages/aws-amplify/package.json @@ -383,7 +383,7 @@ "name": "[Auth] confirmSignIn (Cognito)", "path": "./dist/esm/auth/index.mjs", "import": "{ confirmSignIn }", - "limit": "28.10 kB" + "limit": "28.26 kB" }, { "name": "[Auth] updateMFAPreference (Cognito)", @@ -449,7 +449,7 @@ "name": "[Auth] Basic Auth Flow (Cognito)", "path": "./dist/esm/auth/index.mjs", "import": "{ signIn, signOut, fetchAuthSession, confirmSignIn }", - "limit": "29.90 kB" + "limit": "30.06 kB" }, { "name": "[Auth] OAuth Auth Flow (Cognito)", diff --git a/packages/core/src/libraryUtils.ts b/packages/core/src/libraryUtils.ts index 1eadf9d5c5a..717bfc7805a 100644 --- a/packages/core/src/libraryUtils.ts +++ b/packages/core/src/libraryUtils.ts @@ -29,6 +29,7 @@ export { amplifyUuid } from './utils/amplifyUuid'; export { AmplifyUrl, AmplifyUrlSearchParams } from './utils/amplifyUrl'; export { parseAmplifyConfig } from './utils/parseAmplifyConfig'; export { getClientInfo } from './utils'; +export { getDeviceName } from './utils/deviceName'; // Auth utilities export { diff --git a/packages/core/src/utils/deviceName/getDeviceName.native.ts b/packages/core/src/utils/deviceName/getDeviceName.native.ts new file mode 100644 index 00000000000..e8257aaa807 --- /dev/null +++ b/packages/core/src/utils/deviceName/getDeviceName.native.ts @@ -0,0 +1,15 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { getDeviceName as getDeviceNameNative } from '@aws-amplify/react-native'; + +/** + * Retrieves the device name using name in ios and model in android, + * + * @returns {Promise} A promise that resolves with a string representing the device name. + * + * Example Output: + * ios: 'iPhone' / 'user's iPhone' + * android: 'sdk_gphone64_arm64' + */ +export const getDeviceName = async (): Promise => getDeviceNameNative(); diff --git a/packages/core/src/utils/deviceName/getDeviceName.ts b/packages/core/src/utils/deviceName/getDeviceName.ts new file mode 100644 index 00000000000..3916ba7b36e --- /dev/null +++ b/packages/core/src/utils/deviceName/getDeviceName.ts @@ -0,0 +1,52 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import { NavigatorUA } from './types'; +/** + * Retrieves the device name using the User-Agent Client Hints API if available, + * falling back to the traditional userAgent string if not. + * + * @returns {Promise} A promise that resolves with a string representing the device name. + * + * Example Output: + * navigator.userAgentData: + * 'macOS 14.2.1 arm macOS Not A(Brand/99.0.0.0;Google Chrome/121.0.6167.160;Chromium/121.0.6167.160' + * navigator.userAgent: + * 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/115.0' + */ +export const getDeviceName = async (): Promise => { + const { userAgentData } = navigator as NavigatorUA; + + if (!userAgentData) return navigator.userAgent; + + const { + platform = '', + platformVersion = '', + model = '', + architecture = '', + fullVersionList = [], + } = await userAgentData.getHighEntropyValues([ + 'platform', + 'platformVersion', + 'architecture', + 'model', + 'fullVersionList', + ]); + + const versionList = fullVersionList + .map((v: { brand: string; version: string }) => `${v.brand}/${v.version}`) + .join(';'); + + const deviceName = [ + platform, + platformVersion, + architecture, + model, + platform, + versionList, + ] + .filter(value => value) + .join(' '); + + return deviceName; +}; diff --git a/packages/core/src/utils/deviceName/index.ts b/packages/core/src/utils/deviceName/index.ts new file mode 100644 index 00000000000..13b50ee98bd --- /dev/null +++ b/packages/core/src/utils/deviceName/index.ts @@ -0,0 +1,4 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +export { getDeviceName } from './getDeviceName'; diff --git a/packages/core/src/utils/deviceName/types.ts b/packages/core/src/utils/deviceName/types.ts new file mode 100644 index 00000000000..06980d1bf67 --- /dev/null +++ b/packages/core/src/utils/deviceName/types.ts @@ -0,0 +1,44 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// WICG Spec: https://wicg.github.io/ua-client-hints + +// https://wicg.github.io/ua-client-hints/#navigatorua +export interface NavigatorUA { + readonly userAgentData?: NavigatorUAData; +} + +// https://wicg.github.io/ua-client-hints/#dictdef-navigatoruabrandversion +interface NavigatorUABrandVersion { + readonly brand: string; + readonly version: string; +} + +// https://wicg.github.io/ua-client-hints/#dictdef-uadatavalues +interface UADataValues { + readonly brands?: NavigatorUABrandVersion[]; + readonly mobile?: boolean; + readonly platform?: string; + readonly architecture?: string; + readonly bitness?: string; + readonly formFactor?: string[]; + readonly model?: string; + readonly platformVersion?: string; + /** @deprecated in favour of fullVersionList */ + readonly uaFullVersion?: string; + readonly fullVersionList?: NavigatorUABrandVersion[]; + readonly wow64?: boolean; +} + +// https://wicg.github.io/ua-client-hints/#dictdef-ualowentropyjson +interface UALowEntropyJSON { + readonly brands: NavigatorUABrandVersion[]; + readonly mobile: boolean; + readonly platform: string; +} + +// https://wicg.github.io/ua-client-hints/#navigatoruadata +interface NavigatorUAData extends UALowEntropyJSON { + getHighEntropyValues(hints: string[]): Promise; + toJSON(): UALowEntropyJSON; +} From f65cae2c0e288bec0d43fd1826dd224b4aa30a69 Mon Sep 17 00:00:00 2001 From: Jim Blanchard Date: Thu, 2 May 2024 15:47:20 -0500 Subject: [PATCH 14/15] fix(core): Always set login methods when parsing Gen2 config files (#13315) --- packages/aws-amplify/package.json | 2 +- packages/core/__mocks__/configMocks/README.md | 2 + .../configMocks/amplify_outputs.json | 78 ++++++++++++ .../configMocks/amplifyconfiguration.json | 69 ++++++++++ packages/core/__tests__/amplify_outputs.json | 72 ----------- .../__tests__/parseAmplifyOutputs.test.ts | 118 ++++++++++++------ .../parseAmplifyConfigCompatibility.test.ts | 12 ++ packages/core/src/parseAmplifyOutputs.ts | 14 +-- 8 files changed, 247 insertions(+), 120 deletions(-) create mode 100644 packages/core/__mocks__/configMocks/README.md create mode 100644 packages/core/__mocks__/configMocks/amplify_outputs.json create mode 100644 packages/core/__mocks__/configMocks/amplifyconfiguration.json delete mode 100644 packages/core/__tests__/amplify_outputs.json create mode 100644 packages/core/__tests__/utils/parseAmplifyConfigCompatibility.test.ts diff --git a/packages/aws-amplify/package.json b/packages/aws-amplify/package.json index a3254ed2252..6bcb6ddc582 100644 --- a/packages/aws-amplify/package.json +++ b/packages/aws-amplify/package.json @@ -293,7 +293,7 @@ "name": "[Analytics] record (Pinpoint)", "path": "./dist/esm/analytics/index.mjs", "import": "{ record }", - "limit": "17.02 kB" + "limit": "17.05 kB" }, { "name": "[Analytics] record (Kinesis)", diff --git a/packages/core/__mocks__/configMocks/README.md b/packages/core/__mocks__/configMocks/README.md new file mode 100644 index 00000000000..14e8c18908c --- /dev/null +++ b/packages/core/__mocks__/configMocks/README.md @@ -0,0 +1,2 @@ +This directory contains equivalent Gen1 & Gen2 configurations which are used to validate interoperability between +different config versions/schemas. Make sure that any updates applied to one are applied to the other. diff --git a/packages/core/__mocks__/configMocks/amplify_outputs.json b/packages/core/__mocks__/configMocks/amplify_outputs.json new file mode 100644 index 00000000000..432a6247e91 --- /dev/null +++ b/packages/core/__mocks__/configMocks/amplify_outputs.json @@ -0,0 +1,78 @@ +{ + "$schema": "adipisicing cillum", + "version": "1", + "auth": { + "aws_region": "us-west-2", + "user_pool_id": "mock-cup-id", + "user_pool_client_id": "mock-cup-client-id", + "identity_pool_id": "mock-idp-id", + "oauth": { + "identity_providers": ["FACEBOOK", "SIGN_IN_WITH_APPLE", "GOOGLE"], + "domain": "mock-oauth-domain", + "scopes": ["phone"], + "redirect_sign_in_uri": ["mock-sign-in-uri"], + "redirect_sign_out_uri": ["mock-sign-out-uri"], + "response_type": "token" + }, + "standard_required_attributes": [ + "address", + "locale", + "email" + ], + "username_attributes": ["phone_number", "email"], + "user_verification_types": ["email"], + "unauthenticated_identities_enabled": true, + "mfa_configuration": "OPTIONAL", + "mfa_methods": ["TOTP", "SMS"], + "password_policy": { + "require_lowercase": true, + "require_numbers": true, + "require_uppercase": true, + "require_symbols": true, + "min_length": 6 + } + }, + "data": { + "aws_region": "us-west-2", + "url": "mock-data-url", + "api_key": "mock-data-api-key", + "default_authorization_type": "API_KEY", + "authorization_types": [] + }, + "geo": { + "aws_region": "us-west-2", + "search_indices": { + "items": [ + "mock-geo-search-item", + "mock-geo-search-item-alt" + ], + "default": "mock-geo-search-item" + }, + "geofence_collections": { + "items": [ + "mock-geo-fence-item", + "mock-geo-fence-item-alt" + ], + "default": "mock-geo-fence-item" + } + }, + "custom": { + "custom-prop": -51806024, + "custom-prop-alt": 87599986 + }, + "notifications": { + "aws_region": "us-west-2", + "amazon_pinpoint_app_id": "mock-pinpoint-app-id", + "channels": ["IN_APP_MESSAGING", "APNS"] + }, + "analytics": { + "amazon_pinpoint": { + "app_id": "mock-pinpoint-app-id", + "aws_region": "us-west-2" + } + }, + "storage": { + "bucket_name": "mock-storage-bucket", + "aws_region": "us-west-2" + } +} diff --git a/packages/core/__mocks__/configMocks/amplifyconfiguration.json b/packages/core/__mocks__/configMocks/amplifyconfiguration.json new file mode 100644 index 00000000000..452ab0c64f0 --- /dev/null +++ b/packages/core/__mocks__/configMocks/amplifyconfiguration.json @@ -0,0 +1,69 @@ +{ + "aws_project_region": "us-west-2", + "aws_cognito_identity_pool_id": "mock-idp-id", + "aws_cognito_username_attributes": ["PHONE_NUMBER", "EMAIL"], + "aws_cognito_signup_attributes": ["EMAIL", "ADDRESS", "LOCALE"], + "aws_cognito_mfa_configuration": "OPTIONAL", + "aws_cognito_mfa_types": ["TOTP", "SMS"], + "aws_cognito_password_protection_settings": { + "passwordPolicyMinLength": 6, + "passwordPolicyCharacters": [ + "REQUIRES_SYMBOLS", + "REQUIRES_UPPERCASE", + "REQUIRES_LOWERCASE", + "REQUIRES_NUMBERS" + ] + }, + "oauth": { + "domain": "mock-oauth-domain", + "scope": ["phone"], + "redirectSignIn": "mock-sign-in-uri", + "redirectSignOut": "mock-sign-out-uri", + "responseType": "token" + }, + "aws_cognito_verification_mechanisms": ["EMAIL"], + "aws_cognito_social_providers": ["FACEBOOK", "APPLE", "GOOGLE"], + "aws_mobile_analytics_app_id": "mock-pinpoint-app-id", + "aws_mobile_analytics_app_region": "us-west-2", + "aws_user_files_s3_bucket": "mock-storage-bucket", + "aws_user_files_s3_bucket_region": "us-west-2", + "aws_user_pools_id": "mock-cup-id", + "aws_user_pools_web_client_id": "mock-cup-client-id", + "geo": { + "amazon_location_service": { + "search_indices": { + "items": [ + "mock-geo-search-item", + "mock-geo-search-item-alt" + ], + "default": "mock-geo-search-item" + }, + "geofenceCollections": { + "items": [ + "mock-geo-fence-item", + "mock-geo-fence-item-alt" + ], + "default": "mock-geo-fence-item" + }, + "region": "us-west-2" + } + }, + "aws_appsync_graphqlEndpoint": "mock-data-url", + "aws_appsync_apiKey": "mock-data-api-key", + "aws_appsync_region": "us-west-2", + "aws_appsync_authenticationType": "API_KEY", + "Notifications": { + "InAppMessaging": { + "AWSPinpoint": { + "appId": "mock-pinpoint-app-id", + "region": "us-west-2" + } + }, + "Push": { + "AWSPinpoint": { + "appId": "mock-pinpoint-app-id", + "region": "us-west-2" + } + } + } +} \ No newline at end of file diff --git a/packages/core/__tests__/amplify_outputs.json b/packages/core/__tests__/amplify_outputs.json deleted file mode 100644 index 3ab7633d1a7..00000000000 --- a/packages/core/__tests__/amplify_outputs.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "$schema": "adipisicing cillum", - "version": "1", - "auth": { - "aws_region": "non proident exercitation anim fugiat", - "user_pool_id": "sit velit dolor magna est", - "user_pool_client_id": "voluptate", - "identity_pool_id": "Lorem", - "oauth": { - "identity_providers": ["FACEBOOK", "SIGN_IN_WITH_APPLE", "GOOGLE"], - "domain": "proident dolore do mollit ad", - "scopes": ["incididunt proident"], - "redirect_sign_in_uri": ["Duis", "ipsum velit in dolore"], - "redirect_sign_out_uri": [ - "Excepteur pariatur cillum officia", - "incididunt in Ut Excepteur commodo" - ], - "response_type": "token" - }, - "standard_required_attributes": [ - "address", - "locale", - "family_name", - "sub", - "email" - ], - "username_attributes": ["phone_number", "email"], - "user_verification_types": ["email", "email"], - "unauthenticated_identities_enabled": true, - "mfa_configuration": "OPTIONAL", - "mfa_methods": ["TOTP", "TOTP", "SMS", "TOTP", "TOTP"] - }, - "data": { - "aws_region": "regasd", - "url": "dolore dolor do cillum nulla", - "api_key": "non", - "default_authorization_type": "API_KEY", - "authorization_types": [] - }, - "geo": { - "aws_region": "tempor", - "search_indices": { - "items": [ - "commodo Lorem", - "reprehenderit consequat", - "amet", - "aliquip deserunt", - "ea dolor in proident" - ], - "default": "exercitation fugiat ut dolor sed" - }, - "geofence_collections": { - "items": [ - "fugiat ea irure dolor", - "Ut", - "culpa ut enim exercitation", - "labore", - "ex pariatur est ullamco" - ], - "default": "ullamco incididunt aliquip" - } - }, - "custom": { - "occaecat_4_": -51806024, - "dolorc": 87599986 - }, - "notifications": { - "aws_region": "labore nisi ad", - "amazon_pinpoint_app_id": "in dolor veniam reprehenderit", - "channels": ["EMAIL"] - } -} diff --git a/packages/core/__tests__/parseAmplifyOutputs.test.ts b/packages/core/__tests__/parseAmplifyOutputs.test.ts index 53496954be5..7d15f7b1f52 100644 --- a/packages/core/__tests__/parseAmplifyOutputs.test.ts +++ b/packages/core/__tests__/parseAmplifyOutputs.test.ts @@ -1,7 +1,6 @@ /* eslint-disable camelcase */ import { AmplifyOutputs, parseAmplifyOutputs } from '../src/libraryUtils'; - -import mockAmplifyOutputs from './amplify_outputs.json'; +import mockAmplifyOutputs from '../__mocks__/configMocks/amplify_outputs.json'; describe('parseAmplifyOutputs tests', () => { describe('auth tests', () => { @@ -11,37 +10,42 @@ describe('parseAmplifyOutputs tests', () => { expect(result).toEqual({ API: { GraphQL: { - apiKey: 'non', + apiKey: 'mock-data-api-key', defaultAuthMode: 'apiKey', - endpoint: 'dolore dolor do cillum nulla', + endpoint: 'mock-data-url', modelIntrospection: undefined, - region: 'regasd', + region: 'us-west-2', }, }, Auth: { Cognito: { allowGuestAccess: true, - identityPoolId: 'Lorem', + identityPoolId: 'mock-idp-id', loginWith: { email: true, oauth: { - domain: 'proident dolore do mollit ad', + domain: 'mock-oauth-domain', providers: ['Facebook', 'Apple', 'Google'], - redirectSignIn: ['Duis', 'ipsum velit in dolore'], - redirectSignOut: [ - 'Excepteur pariatur cillum officia', - 'incididunt in Ut Excepteur commodo', - ], + redirectSignIn: ['mock-sign-in-uri'], + redirectSignOut: ['mock-sign-out-uri'], responseType: 'token', - scopes: ['incididunt proident'], + scopes: ['phone'], }, phone: true, + username: false, }, mfa: { smsEnabled: true, status: 'optional', totpEnabled: true, }, + passwordFormat: { + minLength: 6, + requireLowercase: true, + requireNumbers: true, + requireSpecialCharacters: true, + requireUppercase: true, + }, userAttributes: { address: { required: true, @@ -49,43 +53,51 @@ describe('parseAmplifyOutputs tests', () => { email: { required: true, }, - family_name: { - required: true, - }, locale: { required: true, }, - sub: { - required: true, - }, }, - userPoolClientId: 'voluptate', - userPoolId: 'sit velit dolor magna est', + userPoolClientId: 'mock-cup-client-id', + userPoolId: 'mock-cup-id', }, }, Geo: { LocationService: { geofenceCollections: { - default: 'ullamco incididunt aliquip', - items: [ - 'fugiat ea irure dolor', - 'Ut', - 'culpa ut enim exercitation', - 'labore', - 'ex pariatur est ullamco', - ], + default: 'mock-geo-fence-item', + items: ['mock-geo-fence-item', 'mock-geo-fence-item-alt'], }, maps: undefined, - region: 'tempor', + region: 'us-west-2', searchIndices: { - default: 'exercitation fugiat ut dolor sed', - items: [ - 'commodo Lorem', - 'reprehenderit consequat', - 'amet', - 'aliquip deserunt', - 'ea dolor in proident', - ], + default: 'mock-geo-search-item', + items: ['mock-geo-search-item', 'mock-geo-search-item-alt'], + }, + }, + }, + Storage: { + S3: { + bucket: 'mock-storage-bucket', + region: 'us-west-2', + }, + }, + Analytics: { + Pinpoint: { + appId: 'mock-pinpoint-app-id', + region: 'us-west-2', + }, + }, + Notifications: { + InAppMessaging: { + Pinpoint: { + appId: 'mock-pinpoint-app-id', + region: 'us-west-2', + }, + }, + PushNotification: { + Pinpoint: { + appId: 'mock-pinpoint-app-id', + region: 'us-west-2', }, }, }, @@ -151,6 +163,8 @@ describe('parseAmplifyOutputs tests', () => { userPoolId: 'us-east-1:', loginWith: { email: true, + phone: false, + username: false, oauth: { domain: 'https://cognito.com...', providers: ['Google'], @@ -166,6 +180,34 @@ describe('parseAmplifyOutputs tests', () => { }); }); + it('should correctly set loginWith options', () => { + const testAmplifyOutputs = JSON.parse(JSON.stringify(mockAmplifyOutputs)); + + // Phone only + testAmplifyOutputs.auth.username_attributes = ['phone_number']; + let result = parseAmplifyOutputs(testAmplifyOutputs); + + expect(result.Auth?.Cognito.loginWith?.email).toBe(false); + expect(result.Auth?.Cognito.loginWith?.phone).toBe(true); + expect(result.Auth?.Cognito.loginWith?.username).toBe(false); + + // Email only + testAmplifyOutputs.auth.username_attributes = ['email']; + result = parseAmplifyOutputs(testAmplifyOutputs); + + expect(result.Auth?.Cognito.loginWith?.email).toBe(true); + expect(result.Auth?.Cognito.loginWith?.phone).toBe(false); + expect(result.Auth?.Cognito.loginWith?.username).toBe(false); + + // Email & phone + testAmplifyOutputs.auth.username_attributes = ['email', 'phone_number']; + result = parseAmplifyOutputs(testAmplifyOutputs); + + expect(result.Auth?.Cognito.loginWith?.email).toBe(true); + expect(result.Auth?.Cognito.loginWith?.phone).toBe(true); + expect(result.Auth?.Cognito.loginWith?.username).toBe(false); + }); + describe('storage tests', () => { it('should parse storage happy path', () => { const amplifyOutputs: AmplifyOutputs = { diff --git a/packages/core/__tests__/utils/parseAmplifyConfigCompatibility.test.ts b/packages/core/__tests__/utils/parseAmplifyConfigCompatibility.test.ts new file mode 100644 index 00000000000..0642eb339ae --- /dev/null +++ b/packages/core/__tests__/utils/parseAmplifyConfigCompatibility.test.ts @@ -0,0 +1,12 @@ +import { parseAmplifyConfig } from '../../src/libraryUtils'; +import mockAmplifyOutputs from '../../__mocks__/configMocks/amplify_outputs.json'; +import mockAmplifyConfiguration from '../../__mocks__/configMocks/amplifyconfiguration.json'; + +describe('parseAmplifyConfig backwards compatibility', () => { + it('returns identical ResourcesConfig for equivalent CLI & Gen2 configuration files', () => { + const cliConfig = parseAmplifyConfig(mockAmplifyConfiguration); + const gen2Config = parseAmplifyConfig(mockAmplifyOutputs); + + expect(gen2Config).toEqual(cliConfig); + }); +}); diff --git a/packages/core/src/parseAmplifyOutputs.ts b/packages/core/src/parseAmplifyOutputs.ts index 930f36df2de..fcabd1aac06 100644 --- a/packages/core/src/parseAmplifyOutputs.ts +++ b/packages/core/src/parseAmplifyOutputs.ts @@ -135,17 +135,13 @@ function parseAuth( }; } - if (username_attributes?.includes('email')) { + if (username_attributes) { authConfig.Cognito.loginWith = { ...authConfig.Cognito.loginWith, - email: true, - }; - } - - if (username_attributes?.includes('phone_number')) { - authConfig.Cognito.loginWith = { - ...authConfig.Cognito.loginWith, - phone: true, + email: username_attributes.includes('email'), + phone: username_attributes.includes('phone_number'), + // Signing in with a username is not currently supported in Gen2, this should always evaluate to false + username: username_attributes.includes('username'), }; } From c794c14d34a8feabc1b085171f69bce49a67423b Mon Sep 17 00:00:00 2001 From: Hui Zhao <10602282+HuiSF@users.noreply.github.com> Date: Thu, 2 May 2024 14:44:54 -0700 Subject: [PATCH 15/15] chore(repo): add --forceExit to rollup command (#13331) --- packages/adapter-nextjs/package.json | 2 +- packages/analytics/package.json | 2 +- packages/api-graphql/package.json | 2 +- packages/api-rest/package.json | 2 +- packages/api/package.json | 2 +- packages/auth/package.json | 2 +- packages/aws-amplify/package.json | 2 +- packages/core/package.json | 2 +- packages/datastore-storage-adapter/package.json | 2 +- packages/datastore/package.json | 2 +- packages/geo/package.json | 2 +- packages/interactions/package.json | 2 +- packages/notifications/package.json | 2 +- packages/predictions/package.json | 2 +- packages/pubsub/package.json | 4 ++-- packages/react-native/package.json | 2 +- packages/rtn-push-notification/package.json | 2 +- packages/rtn-web-browser/package.json | 2 +- packages/storage/package.json | 2 +- 19 files changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/adapter-nextjs/package.json b/packages/adapter-nextjs/package.json index e29ef63616a..df06139955a 100644 --- a/packages/adapter-nextjs/package.json +++ b/packages/adapter-nextjs/package.json @@ -60,7 +60,7 @@ "scripts": { "build": "npm run clean && npm run build:esm-cjs", "build-with-test": "npm test && npm run build", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "clean": "npm run clean:size && rimraf dist", "clean:size": "rimraf dual-publish-tmp tmp*", diff --git a/packages/analytics/package.json b/packages/analytics/package.json index 50da64d17bd..9b882e632e7 100644 --- a/packages/analytics/package.json +++ b/packages/analytics/package.json @@ -14,7 +14,7 @@ "test": "npm run lint && jest -w 1 --coverage --logHeapUsage", "build-with-test": "npm run clean && npm run test && npm run build", "build:umd": "webpack && webpack --config ./webpack.config.dev.js", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "build": "npm run clean && npm run build:esm-cjs && npm run build:umd", "clean": "npm run clean:size && rimraf dist lib lib-esm", diff --git a/packages/api-graphql/package.json b/packages/api-graphql/package.json index 55ad528801e..2daf9136d8a 100644 --- a/packages/api-graphql/package.json +++ b/packages/api-graphql/package.json @@ -18,7 +18,7 @@ "test:watch": "tslint 'src/**/*.ts' && jest -w 1 --watch", "build-with-test": "npm test && npm build", "build:umd": "webpack && webpack --config ./webpack.config.dev.js", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "build": "npm run clean && npm run build:esm-cjs && npm run build:umd", "clean": "npm run clean:size && rimraf dist lib lib-esm", diff --git a/packages/api-rest/package.json b/packages/api-rest/package.json index 64a3abe7fde..4f3fd81c839 100644 --- a/packages/api-rest/package.json +++ b/packages/api-rest/package.json @@ -15,7 +15,7 @@ "test:watch": "tslint 'src/**/*.ts' && jest -w 1 --watch", "build-with-test": "npm test && npm build", "build:umd": "webpack && webpack --config ./webpack.config.dev.js", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "build": "npm run clean && npm run build:esm-cjs && npm run build:umd", "clean": "npm run clean:size && rimraf dist lib lib-esm", diff --git a/packages/api/package.json b/packages/api/package.json index 98bff622393..4eea4911bb9 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -17,7 +17,7 @@ "test": "npm run lint && jest -w 1 --coverage --logHeapUsage", "build-with-test": "npm test && npm run build", "build:umd": "webpack && webpack --config ./webpack.config.dev.js", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "build": "npm run clean && npm run build:esm-cjs && npm run build:umd", "clean": "npm run clean:size && rimraf dist lib lib-esm", diff --git a/packages/auth/package.json b/packages/auth/package.json index 3e66125d20a..494fce7fe53 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -19,7 +19,7 @@ "test": "yarn lint --fix && jest -w 1 --coverage --logHeapUsage", "build-with-test": "npm test && npm run build", "build:umd": "webpack && webpack --config ./webpack.config.dev.js", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "build": "npm run clean && npm run build:esm-cjs && npm run build:umd", "clean": "npm run clean:size && rimraf lib-esm lib dist", diff --git a/packages/aws-amplify/package.json b/packages/aws-amplify/package.json index 6bcb6ddc582..20fa124d423 100644 --- a/packages/aws-amplify/package.json +++ b/packages/aws-amplify/package.json @@ -239,7 +239,7 @@ "test:size": "size-limit", "build-with-test": "npm run clean && npm test && tsc && webpack -p", "build:umd": "webpack && webpack --config ./webpack.config.dev.js", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "build": "npm run clean && npm run build:esm-cjs && npm run build:umd", "clean": "rimraf lib-esm lib dist", diff --git a/packages/core/package.json b/packages/core/package.json index 759d8aa3b7d..1e3245bdf98 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -20,7 +20,7 @@ "test:size": "size-limit", "build-with-test": "npm test && npm run build", "build:umd": "webpack && webpack --config ./webpack.config.dev.js", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "build": "npm run clean && npm run generate-version && npm run build:esm-cjs && npm run build:umd", "generate-version": "genversion src/Platform/version.ts --es6 --semi --source ../aws-amplify", diff --git a/packages/datastore-storage-adapter/package.json b/packages/datastore-storage-adapter/package.json index 6dae0abcee7..31f290b0d0f 100644 --- a/packages/datastore-storage-adapter/package.json +++ b/packages/datastore-storage-adapter/package.json @@ -13,7 +13,7 @@ "test": "npm run lint && jest -w 1 --coverage --logHeapUsage", "build-with-test": "npm test && npm run build", "build:umd": "webpack && webpack --config ./webpack.config.dev.js", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "build": "npm run clean && npm run build:esm-cjs && npm run build:umd", "clean": "rimraf dist lib lib-esm", diff --git a/packages/datastore/package.json b/packages/datastore/package.json index 31bfd2cbe38..041843344c6 100644 --- a/packages/datastore/package.json +++ b/packages/datastore/package.json @@ -18,7 +18,7 @@ "test:size": "size-limit", "build-with-test": "npm test && npm run build", "build:umd": "webpack && webpack --config ./webpack.config.dev.js", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "build": "npm run clean && npm run build:esm-cjs && npm run build:umd", "clean": "npm run clean:size && rimraf dist lib lib-esm", diff --git a/packages/geo/package.json b/packages/geo/package.json index 96029d70793..c0b8f40b2ae 100644 --- a/packages/geo/package.json +++ b/packages/geo/package.json @@ -18,7 +18,7 @@ "test:size": "size-limit", "build-with-test": "npm test && npm run build", "build:umd": "webpack && webpack --config ./webpack.config.dev.js", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "build": "npm run clean && npm run build:esm-cjs && npm run build:umd", "clean": "npm run clean:size && rimraf dist lib lib-esm", diff --git a/packages/interactions/package.json b/packages/interactions/package.json index 90c53bd156f..8f9e26d7e04 100644 --- a/packages/interactions/package.json +++ b/packages/interactions/package.json @@ -15,7 +15,7 @@ "test:size": "size-limit", "build-with-test": "npm run clean && npm run build", "build:umd": "webpack && webpack --config ./webpack.config.dev.js", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "build": "npm run clean && npm run build:esm-cjs && npm run build:umd", "clean": "npm run clean:size && rimraf dist lib lib-esm", diff --git a/packages/notifications/package.json b/packages/notifications/package.json index 79edf890aa6..e2b908b30ee 100644 --- a/packages/notifications/package.json +++ b/packages/notifications/package.json @@ -15,7 +15,7 @@ "test:watch": "tslint 'src/**/*.ts' && jest -w 1 --watch", "build-with-test": "npm run clean && npm run build", "build:umd": "webpack && webpack --config ./webpack.config.dev.js", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "build": "npm run clean && npm run build:esm-cjs && npm run build:umd", "clean": "npm run clean:size && rimraf dist lib lib-esm", diff --git a/packages/predictions/package.json b/packages/predictions/package.json index f3c64a235e0..bdeaa6202e4 100644 --- a/packages/predictions/package.json +++ b/packages/predictions/package.json @@ -15,7 +15,7 @@ "test:size": "size-limit", "build-with-test": "npm run clean && npm run build", "build:umd": "webpack && webpack --config ./webpack.config.dev.js", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "build": "npm run clean && npm run build:esm-cjs && npm run build:umd", "clean": "npm run clean:size && rimraf dist lib lib-esm", diff --git a/packages/pubsub/package.json b/packages/pubsub/package.json index 17e5cab8a35..fde263ffe38 100644 --- a/packages/pubsub/package.json +++ b/packages/pubsub/package.json @@ -15,8 +15,8 @@ "test:size": "size-limit", "build-with-test": "npm run clean && npm run build", "build:umd": "webpack && webpack --config ./webpack.config.dev.js", - "build:esm-cjs": "rollup -c rollup.config.mjs && cp -R src/vendor dist/cjs/vendor && cp -R src/vendor dist/esm/vendor", - "build:watch": "mkdirp dist/esm/vendor && mkdirp dist/cjs/vendor && cp -R src/vendor dist/cjs/vendor && cp -R src/vendor dist/esm/vendor && rollup -c rollup.config.mjs --watch", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs && cp -R src/vendor dist/cjs/vendor && cp -R src/vendor dist/esm/vendor", + "build:watch": "mkdirp dist/esm/vendor && mkdirp dist/cjs/vendor && cp -R src/vendor dist/cjs/vendor && cp -R src/vendor dist/esm/vendor && rollup --forceExit -c rollup.config.mjs --watch", "build": "npm run clean && npm run build:esm-cjs && npm run build:umd", "clean": "npm run clean:size && rimraf dist lib lib-esm", "clean:size": "rimraf dual-publish-tmp tmp*", diff --git a/packages/react-native/package.json b/packages/react-native/package.json index 3aebd6de1cf..b639c576f95 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -14,7 +14,7 @@ "test": "tslint 'src/**/*.ts'", "test:android": "./android/gradlew test -p ./android", "build-with-test": "npm run clean && npm test && tsc", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "build": "npm run clean && npm run build:esm-cjs", "clean": "rimraf lib-esm lib dist", diff --git a/packages/rtn-push-notification/package.json b/packages/rtn-push-notification/package.json index ac0f26025e1..712cce11806 100644 --- a/packages/rtn-push-notification/package.json +++ b/packages/rtn-push-notification/package.json @@ -14,7 +14,7 @@ "test": "npm run lint && jest -w 1 --coverage --logHeapUsage", "test:android": "./android/gradlew test -p ./android", "build-with-test": "npm run clean && npm test && tsc", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "build": "npm run clean && npm run build:esm-cjs", "clean": "rimraf lib-esm lib dist", diff --git a/packages/rtn-web-browser/package.json b/packages/rtn-web-browser/package.json index f4813648aae..d19fdec72f1 100644 --- a/packages/rtn-web-browser/package.json +++ b/packages/rtn-web-browser/package.json @@ -14,7 +14,7 @@ "test": "tslint 'src/**/*.ts'", "test:android": "./android/gradlew test -p ./android", "build-with-test": "npm run clean && npm test && tsc", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "build": "npm run clean && npm run build:esm-cjs", "clean": "rimraf dist lib lib-esm", diff --git a/packages/storage/package.json b/packages/storage/package.json index a9121fce3dd..e4df9764636 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -25,7 +25,7 @@ "test": "npm run lint && jest -w 1 --coverage --logHeapUsage", "build-with-test": "npm test && npm run build", "build:umd": "webpack && webpack --config ./webpack.config.dev.js", - "build:esm-cjs": "rollup -c rollup.config.mjs", + "build:esm-cjs": "rollup --forceExit -c rollup.config.mjs", "build:watch": "npm run build:esm-cjs -- --watch", "build": "npm run clean && npm run build:esm-cjs && npm run build:umd", "clean": "npm run clean:size && rimraf lib-esm lib dist",