From 8c008e338a30992f4e8fc9cd60c7b18d846f75c7 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Fri, 3 Nov 2023 09:23:20 +0100 Subject: [PATCH 1/9] start migrating PlaidLink to TypeScript --- .../{index.native.js => index.native.tsx} | 17 ++++++++-------- .../PlaidLink/{index.js => index.tsx} | 20 ++++++++----------- 2 files changed, 17 insertions(+), 20 deletions(-) rename src/components/PlaidLink/{index.native.js => index.native.tsx} (66%) rename src/components/PlaidLink/{index.js => index.tsx} (70%) diff --git a/src/components/PlaidLink/index.native.js b/src/components/PlaidLink/index.native.tsx similarity index 66% rename from src/components/PlaidLink/index.native.js rename to src/components/PlaidLink/index.native.tsx index 7d995d03926b..e1e9e7756620 100644 --- a/src/components/PlaidLink/index.native.js +++ b/src/components/PlaidLink/index.native.tsx @@ -1,27 +1,28 @@ import {useEffect} from 'react'; -import {dismissLink, openLink, useDeepLinkRedirector, usePlaidEmitter} from 'react-native-plaid-link-sdk'; +import {dismissLink, LinkEvent, openLink, useDeepLinkRedirector, usePlaidEmitter} from 'react-native-plaid-link-sdk'; import Log from '@libs/Log'; import CONST from '@src/CONST'; import {plaidLinkDefaultProps, plaidLinkPropTypes} from './plaidLinkPropTypes'; +import PlaidLinkProps from './types'; -function PlaidLink(props) { +function PlaidLink({token, onSuccess = () => {}, onExit = () => {}, onEvent}: PlaidLinkProps) { useDeepLinkRedirector(); - usePlaidEmitter((event) => { + usePlaidEmitter((event: LinkEvent) => { Log.info('[PlaidLink] Handled Plaid Event: ', false, event); - props.onEvent(event.eventName, event.metadata); + onEvent?.(event.eventName, event.metadata); }); useEffect(() => { - props.onEvent(CONST.BANK_ACCOUNT.PLAID.EVENTS_NAME.OPEN, {}); + onEvent?.(CONST.BANK_ACCOUNT.PLAID.EVENTS_NAME.OPEN, {}); openLink({ tokenConfig: { - token: props.token, + token, }, onSuccess: ({publicToken, metadata}) => { - props.onSuccess({publicToken, metadata}); + onSuccess({publicToken, metadata}); }, onExit: (exitError, metadata) => { Log.info('[PlaidLink] Exit: ', false, {exitError, metadata}); - props.onExit(); + onExit(); }, }); diff --git a/src/components/PlaidLink/index.js b/src/components/PlaidLink/index.tsx similarity index 70% rename from src/components/PlaidLink/index.js rename to src/components/PlaidLink/index.tsx index 790206f34ce7..39b9ffda54b2 100644 --- a/src/components/PlaidLink/index.js +++ b/src/components/PlaidLink/index.tsx @@ -1,35 +1,33 @@ import {useCallback, useEffect, useState} from 'react'; -import {usePlaidLink} from 'react-plaid-link'; +import {PlaidLinkOnSuccessMetadata, usePlaidLink} from 'react-plaid-link'; import Log from '@libs/Log'; -import {plaidLinkDefaultProps, plaidLinkPropTypes} from './plaidLinkPropTypes'; +import PlaidLinkProps from './types'; -function PlaidLink(props) { +function PlaidLink({token, onSuccess = () => {}, onError = () => {}, onExit = () => {}, onEvent, receivedRedirectURI}: PlaidLinkProps) { const [isPlaidLoaded, setIsPlaidLoaded] = useState(false); - const onSuccess = props.onSuccess; - const onError = props.onError; const successCallback = useCallback( - (publicToken, metadata) => { + (publicToken: string, metadata: PlaidLinkOnSuccessMetadata) => { onSuccess({publicToken, metadata}); }, [onSuccess], ); const {open, ready, error} = usePlaidLink({ - token: props.token, + token, onSuccess: successCallback, onExit: (exitError, metadata) => { Log.info('[PlaidLink] Exit: ', false, {exitError, metadata}); - props.onExit(); + onExit(); }, onEvent: (event, metadata) => { Log.info('[PlaidLink] Event: ', false, {event, metadata}); - props.onEvent(event, metadata); + onEvent?.(event, metadata); }, onLoad: () => setIsPlaidLoaded(true), // The redirect URI with an OAuth state ID. Needed to re-initialize the PlaidLink after directing the // user to their respective bank platform - receivedRedirectUri: props.receivedRedirectURI, + receivedRedirectUri: receivedRedirectURI, }); useEffect(() => { @@ -52,7 +50,5 @@ function PlaidLink(props) { return null; } -PlaidLink.propTypes = plaidLinkPropTypes; -PlaidLink.defaultProps = plaidLinkDefaultProps; PlaidLink.displayName = 'PlaidLink'; export default PlaidLink; From 0205ca59215bbbbb36e85fbedff479aab95f3780 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Fri, 3 Nov 2023 09:23:54 +0100 Subject: [PATCH 2/9] migrate PlaidLinks native module to TypeScript, create a file for types --- .../{index.android.js => index.android.ts} | 0 .../{index.ios.js => index.ios.ts} | 0 src/components/PlaidLink/types.ts | 24 +++++++++++++++++++ 3 files changed, 24 insertions(+) rename src/components/PlaidLink/nativeModule/{index.android.js => index.android.ts} (100%) rename src/components/PlaidLink/nativeModule/{index.ios.js => index.ios.ts} (100%) create mode 100644 src/components/PlaidLink/types.ts diff --git a/src/components/PlaidLink/nativeModule/index.android.js b/src/components/PlaidLink/nativeModule/index.android.ts similarity index 100% rename from src/components/PlaidLink/nativeModule/index.android.js rename to src/components/PlaidLink/nativeModule/index.android.ts diff --git a/src/components/PlaidLink/nativeModule/index.ios.js b/src/components/PlaidLink/nativeModule/index.ios.ts similarity index 100% rename from src/components/PlaidLink/nativeModule/index.ios.js rename to src/components/PlaidLink/nativeModule/index.ios.ts diff --git a/src/components/PlaidLink/types.ts b/src/components/PlaidLink/types.ts new file mode 100644 index 000000000000..06b81d06b5c9 --- /dev/null +++ b/src/components/PlaidLink/types.ts @@ -0,0 +1,24 @@ +import {PlaidLinkOnEvent, PlaidLinkOnSuccessMetadata} from 'react-plaid-link'; + +type PlaidLinkProps = { + // Plaid Link SDK public token used to initialize the Plaid SDK + token: string; + + // Callback to execute once the user taps continue after successfully entering their account information + onSuccess?: (args: {publicToken?: string; metadata: PlaidLinkOnSuccessMetadata}) => void; + + // Callback to execute when there is an error event emitted by the Plaid SDK + onError?: (error: ErrorEvent | null) => void; + + // Callback to execute when the user leaves the Plaid widget flow without entering any information + onExit?: () => void; + + // Callback to execute whenever a Plaid event occurs + onEvent?: PlaidLinkOnEvent; + + // The redirect URI with an OAuth state ID. Needed to re-initialize the PlaidLink after directing the + // user to their respective bank platform + receivedRedirectURI?: string; +}; + +export default PlaidLinkProps; From e55fe141ecdce19e1b39becf1e29f7b7a1c98de4 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Mon, 6 Nov 2023 15:59:55 +0100 Subject: [PATCH 3/9] migrate native PlaidLink to TypeScript --- src/components/PlaidLink/index.native.tsx | 12 +++---- .../PlaidLink/plaidLinkPropTypes.js | 31 ------------------- src/components/PlaidLink/types.ts | 7 +++-- 3 files changed, 9 insertions(+), 41 deletions(-) delete mode 100644 src/components/PlaidLink/plaidLinkPropTypes.js diff --git a/src/components/PlaidLink/index.native.tsx b/src/components/PlaidLink/index.native.tsx index e1e9e7756620..874d7c77414c 100644 --- a/src/components/PlaidLink/index.native.tsx +++ b/src/components/PlaidLink/index.native.tsx @@ -2,26 +2,26 @@ import {useEffect} from 'react'; import {dismissLink, LinkEvent, openLink, useDeepLinkRedirector, usePlaidEmitter} from 'react-native-plaid-link-sdk'; import Log from '@libs/Log'; import CONST from '@src/CONST'; -import {plaidLinkDefaultProps, plaidLinkPropTypes} from './plaidLinkPropTypes'; import PlaidLinkProps from './types'; function PlaidLink({token, onSuccess = () => {}, onExit = () => {}, onEvent}: PlaidLinkProps) { useDeepLinkRedirector(); usePlaidEmitter((event: LinkEvent) => { - Log.info('[PlaidLink] Handled Plaid Event: ', false, event); + Log.info('[PlaidLink] Handled Plaid Event: ', false, event.eventName); onEvent?.(event.eventName, event.metadata); }); useEffect(() => { - onEvent?.(CONST.BANK_ACCOUNT.PLAID.EVENTS_NAME.OPEN, {}); + onEvent?.(CONST.BANK_ACCOUNT.PLAID.EVENTS_NAME.OPEN); openLink({ tokenConfig: { token, + noLoadingState: false, }, onSuccess: ({publicToken, metadata}) => { onSuccess({publicToken, metadata}); }, - onExit: (exitError, metadata) => { - Log.info('[PlaidLink] Exit: ', false, {exitError, metadata}); + onExit: ({error, metadata}) => { + Log.info('[PlaidLink] Exit: ', false, {error, metadata}); onExit(); }, }); @@ -36,8 +36,6 @@ function PlaidLink({token, onSuccess = () => {}, onExit = () => {}, onEvent}: Pl return null; } -PlaidLink.propTypes = plaidLinkPropTypes; -PlaidLink.defaultProps = plaidLinkDefaultProps; PlaidLink.displayName = 'PlaidLink'; export default PlaidLink; diff --git a/src/components/PlaidLink/plaidLinkPropTypes.js b/src/components/PlaidLink/plaidLinkPropTypes.js deleted file mode 100644 index 6d647d26f17e..000000000000 --- a/src/components/PlaidLink/plaidLinkPropTypes.js +++ /dev/null @@ -1,31 +0,0 @@ -import PropTypes from 'prop-types'; - -const plaidLinkPropTypes = { - // Plaid Link SDK public token used to initialize the Plaid SDK - token: PropTypes.string.isRequired, - - // Callback to execute once the user taps continue after successfully entering their account information - onSuccess: PropTypes.func, - - // Callback to execute when there is an error event emitted by the Plaid SDK - onError: PropTypes.func, - - // Callback to execute when the user leaves the Plaid widget flow without entering any information - onExit: PropTypes.func, - - // Callback to execute whenever a Plaid event occurs - onEvent: PropTypes.func, - - // The redirect URI with an OAuth state ID. Needed to re-initialize the PlaidLink after directing the - // user to their respective bank platform - receivedRedirectURI: PropTypes.string, -}; - -const plaidLinkDefaultProps = { - onSuccess: () => {}, - onError: () => {}, - onExit: () => {}, - receivedRedirectURI: null, -}; - -export {plaidLinkPropTypes, plaidLinkDefaultProps}; diff --git a/src/components/PlaidLink/types.ts b/src/components/PlaidLink/types.ts index 06b81d06b5c9..4fc44cbf9b9c 100644 --- a/src/components/PlaidLink/types.ts +++ b/src/components/PlaidLink/types.ts @@ -1,11 +1,12 @@ -import {PlaidLinkOnEvent, PlaidLinkOnSuccessMetadata} from 'react-plaid-link'; +import {LinkEventMetadata, LinkSuccessMetadata} from 'react-native-plaid-link-sdk'; +import {PlaidLinkOnEventMetadata, PlaidLinkOnSuccessMetadata, PlaidLinkStableEvent} from 'react-plaid-link'; type PlaidLinkProps = { // Plaid Link SDK public token used to initialize the Plaid SDK token: string; // Callback to execute once the user taps continue after successfully entering their account information - onSuccess?: (args: {publicToken?: string; metadata: PlaidLinkOnSuccessMetadata}) => void; + onSuccess?: (args: {publicToken?: string; metadata: PlaidLinkOnSuccessMetadata | LinkSuccessMetadata}) => void; // Callback to execute when there is an error event emitted by the Plaid SDK onError?: (error: ErrorEvent | null) => void; @@ -14,7 +15,7 @@ type PlaidLinkProps = { onExit?: () => void; // Callback to execute whenever a Plaid event occurs - onEvent?: PlaidLinkOnEvent; + onEvent?: (eventName: PlaidLinkStableEvent | string, metadata?: PlaidLinkOnEventMetadata | LinkEventMetadata) => void; // The redirect URI with an OAuth state ID. Needed to re-initialize the PlaidLink after directing the // user to their respective bank platform From 9e15bc8409ee4d66943e3dfa0638364305170058 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Tue, 7 Nov 2023 12:00:22 +0100 Subject: [PATCH 4/9] make onEvent a required prop to avoid optional chaining --- src/components/PlaidLink/index.native.tsx | 4 ++-- src/components/PlaidLink/index.tsx | 2 +- src/components/PlaidLink/types.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/PlaidLink/index.native.tsx b/src/components/PlaidLink/index.native.tsx index 874d7c77414c..b9accb0c0ad7 100644 --- a/src/components/PlaidLink/index.native.tsx +++ b/src/components/PlaidLink/index.native.tsx @@ -8,10 +8,10 @@ function PlaidLink({token, onSuccess = () => {}, onExit = () => {}, onEvent}: Pl useDeepLinkRedirector(); usePlaidEmitter((event: LinkEvent) => { Log.info('[PlaidLink] Handled Plaid Event: ', false, event.eventName); - onEvent?.(event.eventName, event.metadata); + onEvent(event.eventName, event.metadata); }); useEffect(() => { - onEvent?.(CONST.BANK_ACCOUNT.PLAID.EVENTS_NAME.OPEN); + onEvent(CONST.BANK_ACCOUNT.PLAID.EVENTS_NAME.OPEN); openLink({ tokenConfig: { token, diff --git a/src/components/PlaidLink/index.tsx b/src/components/PlaidLink/index.tsx index 39b9ffda54b2..2109771473aa 100644 --- a/src/components/PlaidLink/index.tsx +++ b/src/components/PlaidLink/index.tsx @@ -21,7 +21,7 @@ function PlaidLink({token, onSuccess = () => {}, onError = () => {}, onExit = () }, onEvent: (event, metadata) => { Log.info('[PlaidLink] Event: ', false, {event, metadata}); - onEvent?.(event, metadata); + onEvent(event, metadata); }, onLoad: () => setIsPlaidLoaded(true), diff --git a/src/components/PlaidLink/types.ts b/src/components/PlaidLink/types.ts index 4fc44cbf9b9c..fe23e09151ca 100644 --- a/src/components/PlaidLink/types.ts +++ b/src/components/PlaidLink/types.ts @@ -15,7 +15,7 @@ type PlaidLinkProps = { onExit?: () => void; // Callback to execute whenever a Plaid event occurs - onEvent?: (eventName: PlaidLinkStableEvent | string, metadata?: PlaidLinkOnEventMetadata | LinkEventMetadata) => void; + onEvent: (eventName: PlaidLinkStableEvent | string, metadata?: PlaidLinkOnEventMetadata | LinkEventMetadata) => void; // The redirect URI with an OAuth state ID. Needed to re-initialize the PlaidLink after directing the // user to their respective bank platform From 42d0373d4def45e84a77b1f99c1fe26c1003cdd4 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Fri, 17 Nov 2023 09:02:10 +0100 Subject: [PATCH 5/9] remove unused nativeModule --- src/components/PlaidLink/nativeModule/index.android.ts | 3 --- src/components/PlaidLink/nativeModule/index.ios.ts | 3 --- 2 files changed, 6 deletions(-) delete mode 100644 src/components/PlaidLink/nativeModule/index.android.ts delete mode 100644 src/components/PlaidLink/nativeModule/index.ios.ts diff --git a/src/components/PlaidLink/nativeModule/index.android.ts b/src/components/PlaidLink/nativeModule/index.android.ts deleted file mode 100644 index d4280feddb8e..000000000000 --- a/src/components/PlaidLink/nativeModule/index.android.ts +++ /dev/null @@ -1,3 +0,0 @@ -import {NativeModules} from 'react-native'; - -export default NativeModules.PlaidAndroid; diff --git a/src/components/PlaidLink/nativeModule/index.ios.ts b/src/components/PlaidLink/nativeModule/index.ios.ts deleted file mode 100644 index 78d4315eac2d..000000000000 --- a/src/components/PlaidLink/nativeModule/index.ios.ts +++ /dev/null @@ -1,3 +0,0 @@ -import {NativeModules} from 'react-native'; - -export default NativeModules.RNLinksdk; From 3d12dc8e5184c4b8a55ed6dc303dfc1bddec5bf1 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Mon, 27 Nov 2023 13:41:14 +0100 Subject: [PATCH 6/9] pass event to Log.info --- src/components/PlaidLink/index.native.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PlaidLink/index.native.tsx b/src/components/PlaidLink/index.native.tsx index b9accb0c0ad7..02d4669bc861 100644 --- a/src/components/PlaidLink/index.native.tsx +++ b/src/components/PlaidLink/index.native.tsx @@ -7,7 +7,7 @@ import PlaidLinkProps from './types'; function PlaidLink({token, onSuccess = () => {}, onExit = () => {}, onEvent}: PlaidLinkProps) { useDeepLinkRedirector(); usePlaidEmitter((event: LinkEvent) => { - Log.info('[PlaidLink] Handled Plaid Event: ', false, event.eventName); + Log.info('[PlaidLink] Handled Plaid Event: ', false, {...event}); onEvent(event.eventName, event.metadata); }); useEffect(() => { From 2eaae670645882712e9f756e4748ac79d76faf8e Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Mon, 27 Nov 2023 13:45:11 +0100 Subject: [PATCH 7/9] allow metadata to be undefined in onEvent --- src/components/AddPlaidBankAccount.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js index 566b6c709423..d5d5f4903888 100644 --- a/src/components/AddPlaidBankAccount.js +++ b/src/components/AddPlaidBankAccount.js @@ -207,7 +207,7 @@ function AddPlaidBankAccount({ // Handle Plaid login errors (will potentially reset plaid token and item depending on the error) if (event === 'ERROR') { Log.hmmm('[PlaidLink] Error: ', metadata); - if (bankAccountID && metadata.error_code) { + if (bankAccountID && metadata && metadata.error_code) { BankAccounts.handlePlaidError(bankAccountID, metadata.error_code, metadata.error_message, metadata.request_id); } } From b41332c91cd8c7e412be1704d87a05f39b9cfd5f Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Mon, 27 Nov 2023 13:49:00 +0100 Subject: [PATCH 8/9] make publicToken required param --- src/components/PlaidLink/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PlaidLink/types.ts b/src/components/PlaidLink/types.ts index fe23e09151ca..dda6d9d869cb 100644 --- a/src/components/PlaidLink/types.ts +++ b/src/components/PlaidLink/types.ts @@ -6,7 +6,7 @@ type PlaidLinkProps = { token: string; // Callback to execute once the user taps continue after successfully entering their account information - onSuccess?: (args: {publicToken?: string; metadata: PlaidLinkOnSuccessMetadata | LinkSuccessMetadata}) => void; + onSuccess?: (args: {publicToken: string; metadata: PlaidLinkOnSuccessMetadata | LinkSuccessMetadata}) => void; // Callback to execute when there is an error event emitted by the Plaid SDK onError?: (error: ErrorEvent | null) => void; From 938887fec81430dbcf84d0311f58410d5d11b7b2 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Mon, 27 Nov 2023 14:11:36 +0100 Subject: [PATCH 9/9] change eventName type to string --- src/components/PlaidLink/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/PlaidLink/types.ts b/src/components/PlaidLink/types.ts index dda6d9d869cb..1034eb935f74 100644 --- a/src/components/PlaidLink/types.ts +++ b/src/components/PlaidLink/types.ts @@ -1,5 +1,5 @@ import {LinkEventMetadata, LinkSuccessMetadata} from 'react-native-plaid-link-sdk'; -import {PlaidLinkOnEventMetadata, PlaidLinkOnSuccessMetadata, PlaidLinkStableEvent} from 'react-plaid-link'; +import {PlaidLinkOnEventMetadata, PlaidLinkOnSuccessMetadata} from 'react-plaid-link'; type PlaidLinkProps = { // Plaid Link SDK public token used to initialize the Plaid SDK @@ -15,7 +15,7 @@ type PlaidLinkProps = { onExit?: () => void; // Callback to execute whenever a Plaid event occurs - onEvent: (eventName: PlaidLinkStableEvent | string, metadata?: PlaidLinkOnEventMetadata | LinkEventMetadata) => void; + onEvent: (eventName: string, metadata?: PlaidLinkOnEventMetadata | LinkEventMetadata) => void; // The redirect URI with an OAuth state ID. Needed to re-initialize the PlaidLink after directing the // user to their respective bank platform