From 272a4291f4175c59ce17e664bd99cce699bce207 Mon Sep 17 00:00:00 2001 From: Tony Xiao Date: Mon, 10 Jun 2019 05:11:51 -0700 Subject: [PATCH 1/5] Rename package to react-native-plaid-linkkit --- react-native/README.md | 12 ++++++------ react-native/demo/App.js | 2 +- .../linkdemo_reactnative.xcodeproj/project.pbxproj | 8 ++++---- react-native/demo/package.json | 2 +- react-native/demo/yarn.lock | 2 +- react-native/linkkit/package.json | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/react-native/README.md b/react-native/README.md index de1f601..d29ce16 100644 --- a/react-native/README.md +++ b/react-native/README.md @@ -4,7 +4,7 @@ Currently only iOS is supported. :warning: Note that this is the React Native bridge for Link officially supported by Plaid, but is very different -from the module with the same name available on [npmjs](https://www.npmjs.com/package/react-native-plaid-link); +from the module with a similar name available on [npmjs](https://www.npmjs.com/package/react-native-plaid-link); we strongly recommend favoring this React Native bridge. ## Prerequisites @@ -17,16 +17,16 @@ To complete the steps in this example the following software is needed: ## Using React Native for Plaid Link * Clone the [Plaid Link](https://github.com/plaid/link) repository -* Add this `react-native-plaid-link` component to your react-native project and install the necessary dependencies: +* Add this `react-native-plaid-linkkit` component to your react-native project and install the necessary dependencies: ```sh % cd $PATH_TO_YOUR_REACT_NATIVE_PROJECT % yarn add file:$PATH_TO_YOUR_CLONE_OF_THIS_REPO/react-native/linkkit % yarn install - % react-native link react-native-plaid-link + % react-native link react-native-plaid-linkkit ``` * Integrate the native Plaid Link for iOS SDK (LinkKit.framework) into the iOS part of your react-native project, see the [documentation](https://plaid.com/docs/link/ios/) for details. * In your `App.js` import Plaid Link using: - `import PlaidLink from 'react-native-plaid-link';` + `import PlaidLink from 'react-native-plaid-linkkit';` * Create a `linkHandler` object (we recommend doing so in `componentDidMount()`) and replace any of the placeholder `<#VARIABLE#>`s in the example below according to your setup (for details see the [Plaid Link documentation](https://plaid.com/docs/quickstart/#client-side-link-configuration)): ```js this.linkHandler = PlaidLink.create({ @@ -45,10 +45,10 @@ To complete the steps in this example the following software is needed: ## About the linkdemo_reactnative Xcode project -ℹ️ In order build and run the `linkdemo_reactnative` iOS demo application the `react-native-plaid-link` component must be registered and linked to the Xcode project as mentioned above, e.g.: +ℹ️ In order build and run the `linkdemo_reactnative` iOS demo application the `react-native-plaid-linkkit` component must be registered and linked to the Xcode project as mentioned above, e.g.: ```sh % cd link/react-native/demo % yarn add file:../linkkit % yarn install - % react-native link react-native-plaid-link + % react-native link react-native-plaid-linkkit ``` diff --git a/react-native/demo/App.js b/react-native/demo/App.js index 9c7ca71..f367f06 100644 --- a/react-native/demo/App.js +++ b/react-native/demo/App.js @@ -15,7 +15,7 @@ import { TouchableOpacity, View } from 'react-native'; -import PlaidLink from 'react-native-plaid-link'; +import PlaidLink from 'react-native-plaid-linkkit'; const title = Platform.select({ ios: 'Plaid Link\nSDK Example', diff --git a/react-native/demo/ios/linkdemo_reactnative.xcodeproj/project.pbxproj b/react-native/demo/ios/linkdemo_reactnative.xcodeproj/project.pbxproj index 88f3ea2..b9d8a59 100644 --- a/react-native/demo/ios/linkdemo_reactnative.xcodeproj/project.pbxproj +++ b/react-native/demo/ios/linkdemo_reactnative.xcodeproj/project.pbxproj @@ -1093,7 +1093,7 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-plaid-link/ios/**", + "$(SRCROOT)/../node_modules/react-native-plaid-linkkit/ios/**", ); INFOPLIST_FILE = linkdemo_reactnativeTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -1119,7 +1119,7 @@ DEVELOPMENT_TEAM = Z2P2MSMY87; HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-plaid-link/ios/**", + "$(SRCROOT)/../node_modules/react-native-plaid-linkkit/ios/**", ); INFOPLIST_FILE = linkdemo_reactnativeTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -1150,7 +1150,7 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-plaid-link/ios/**", + "$(SRCROOT)/../node_modules/react-native-plaid-linkkit/ios/**", ); INFOPLIST_FILE = linkdemo_reactnative/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1178,7 +1178,7 @@ ); HEADER_SEARCH_PATHS = ( "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-plaid-link/ios/**", + "$(SRCROOT)/../node_modules/react-native-plaid-linkkit/ios/**", ); INFOPLIST_FILE = linkdemo_reactnative/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; diff --git a/react-native/demo/package.json b/react-native/demo/package.json index eeffefd..141ff0d 100644 --- a/react-native/demo/package.json +++ b/react-native/demo/package.json @@ -10,7 +10,7 @@ "invariant": "^2.2.4", "react": "16.4.1", "react-native": "0.56.0", - "react-native-plaid-link": "file:../linkkit" + "react-native-plaid-linkkit": "file:../linkkit" }, "devDependencies": { "babel-jest": "22.4.4", diff --git a/react-native/demo/yarn.lock b/react-native/demo/yarn.lock index 3ae70cd..7c64716 100644 --- a/react-native/demo/yarn.lock +++ b/react-native/demo/yarn.lock @@ -4416,7 +4416,7 @@ react-native-git-upgrade@^0.2.7: shelljs "^0.7.5" yeoman-environment "1.5.3" -"react-native-plaid-link@file:../linkkit": +"react-native-plaid-linkkit@file:../linkkit": version "0.1.0" dependencies: react-native-cli "^2.0.1" diff --git a/react-native/linkkit/package.json b/react-native/linkkit/package.json index b1e1284..2c9792e 100644 --- a/react-native/linkkit/package.json +++ b/react-native/linkkit/package.json @@ -1,5 +1,5 @@ { - "name": "react-native-plaid-link", + "name": "react-native-plaid-linkkit", "version": "0.1.0", "description": "A React Native bridge to the Plaid Link for iOS SDK", "main": "index.js", From 753d8547e60110ad9cfe193fde60e2abddd69267 Mon Sep 17 00:00:00 2001 From: Tony Xiao Date: Mon, 10 Jun 2019 05:14:42 -0700 Subject: [PATCH 2/5] Add Plaid dep to ios/RNLinkkit.podspec --- react-native/linkkit/ios/RNLinkkit.podspec | 1 + 1 file changed, 1 insertion(+) diff --git a/react-native/linkkit/ios/RNLinkkit.podspec b/react-native/linkkit/ios/RNLinkkit.podspec index e32e0c3..6bef0a2 100644 --- a/react-native/linkkit/ios/RNLinkkit.podspec +++ b/react-native/linkkit/ios/RNLinkkit.podspec @@ -17,6 +17,7 @@ Pod::Spec.new do |s| s.dependency "React" + s.dependency "Plaid" #s.dependency "others" end From e0baba7e1a8eb2c3f7eb7ff99d28403b7c8c683b Mon Sep 17 00:00:00 2001 From: Tony Xiao Date: Mon, 10 Jun 2019 06:10:07 -0700 Subject: [PATCH 3/5] Getting react-native-plaid-link podspec to work --- react-native/linkkit/package.json | 2 +- ...Linkkit.podspec => react-native-plaid-linkkit.podspec} | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) rename react-native/linkkit/{ios/RNLinkkit.podspec => react-native-plaid-linkkit.podspec} (71%) diff --git a/react-native/linkkit/package.json b/react-native/linkkit/package.json index 2c9792e..1c2451f 100644 --- a/react-native/linkkit/package.json +++ b/react-native/linkkit/package.json @@ -22,7 +22,7 @@ "peerDependencies": { "react-native": "^0.41.2" }, - "dependencies": { + "devDependencies": { "react-native-cli": "^2.0.1", "react-native-git-upgrade": "^0.2.7" } diff --git a/react-native/linkkit/ios/RNLinkkit.podspec b/react-native/linkkit/react-native-plaid-linkkit.podspec similarity index 71% rename from react-native/linkkit/ios/RNLinkkit.podspec rename to react-native/linkkit/react-native-plaid-linkkit.podspec index 6bef0a2..f2189e7 100644 --- a/react-native/linkkit/ios/RNLinkkit.podspec +++ b/react-native/linkkit/react-native-plaid-linkkit.podspec @@ -1,18 +1,18 @@ Pod::Spec.new do |s| - s.name = "RNLinkkit" - s.version = "1.0.0" + s.name = "react-native-plaid-linkkit" + s.version = "0.1.0" s.summary = "RNLinkkit" s.description = <<-DESC RNLinkkit DESC - s.homepage = "" + s.homepage = "https://github.com/alkafinance/plaid-link/tree/master/react-native" s.license = "MIT" # s.license = { :type => "MIT", :file => "FILE_LICENSE" } s.author = { "author" => "author@domain.cn" } s.platform = :ios, "7.0" s.source = { :git => "https://github.com/author/RNLinkkit.git", :tag => "master" } - s.source_files = "RNLinkkit/**/*.{h,m}" + s.source_files = "ios/RNLinkkit.{h,m}" s.requires_arc = true From 1335a45495fc52b1caa62f099a18c3949297aded Mon Sep 17 00:00:00 2001 From: Tony Xiao Date: Mon, 10 Jun 2019 06:13:38 -0700 Subject: [PATCH 4/5] Adding initial type definitions --- react-native/linkkit/index.d.ts | 101 ++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 react-native/linkkit/index.d.ts diff --git a/react-native/linkkit/index.d.ts b/react-native/linkkit/index.d.ts new file mode 100644 index 0000000..5a83528 --- /dev/null +++ b/react-native/linkkit/index.d.ts @@ -0,0 +1,101 @@ +export type PlaidMessage = + | { + action: 'plaid_link-undefined::event' + eventName: 'EXIT' + metadata: { link_session_id: string } + } + | { + action: 'plaid_link-undefined::event' + eventName: 'TRANSITION_VIEW' + metadata: { link_session_id: string } + } + | { + action: 'plaid_link-undefined::event' + eventName: 'OPEN' + metadata: { link_session_id: string } + } + | { + action: 'plaid_link-undefined::connected' + metadata: { public_token: string; link_session_id: string } + } + | { + action: 'plaid_link-undefined::event' + eventName: 'SEARCH_INSTITUTION' + metadata: { institution_search_query: string; link_session_id: string } + } + | { + action: 'plaid_link-undefined::event' + eventName: 'SELECT_INSTITUTION' + metadata: { + institution_id: string + institution_name: string + link_session_id: string + } + } + | { + action: 'plaid_link-undefined::event' + eventName: 'SUBMIT_CREDENTIALS' + metadata: { + institution_id: string + institution_name: string + link_session_id: string + } + } + | { + action: 'plaid_link-undefined::event' + eventName: 'ERROR' + metadata: { + error_code: string // 'INVALID_CREDENTIALS' + error_message: string // 'the provided credentials were not correct' + error_type: string // 'ITEM_ERROR' + link_session_id: string + } + } + +/** + * - `key` (string) - the Plaid public_key (required) + * - `env` (string) - the Plaid environment (required) + * - `product` (array of strings) - a list of Plaid products (required) + * - `clientName` (string) - the name to display on info panes (recommended) + * - `webhook` (string) - webhook to receive transaction and error updates + * - `selectAccount` (boolean) - enables the select account flow when set to true + * + * - `userLegalName` (string) - the legal name of the end-user, necessary for microdeposit support + * - `userEmailAddress` (string) - the email address of the end-user, necessary for microdeposit support + * - `countryCodes` (array of strings) - a list of ISO 3166-1 alpha-2 country codes, used to select institutions available in the given countries + * - `language` (string) - Plaid-supported language to localize Link. English ('en') will be used by default. For details consult https://plaid.com/docs/#parameter-reference. + * - `publicToken` (string) - the public_token to invoke update mode (see https://plaid.com/docs/quickstart/#use-link-to-resolve-error) + * - `institution` (string) - institution identifier for which to invoke the custom initializer flow + * + * The are deprecated configuration options for the legacy API + * - `longtailAuth` (boolean) - enable longtail auth institutions + * - `apiVersion` (string) - the Plaid API version to use + * + * - `onSuccess` (function) - takes two parameters: the created public_token and the associated metadata. + * - `onExit` (function) - takes two parameters: error and the associated metadata. + * - `onEvent` (function) - takes two parameters: the event name and the associated metadata. + */ +export interface PlaidConfiguration { + key: string + env: 'sandbox' | 'development' | 'production' + product: string[] + clientName?: string + webhook?: string + selectAccount?: boolean + + publicToken?: string + institution?: string + + onSuccess: (publicToken: string, meta: any) => void + onExit: (error: any, meta: any) => void + onEvent?: (data: PlaidMessage, meta: any) => void +} + +declare const PlaidLink: { + /** Technically returns `this` but donno how to type that for now... */ + create: (config: PlaidConfiguration) => void + open: () => void + version: string +} + +export default PlaidLink From d763616328b9c27972802902a7eff01911ad175f Mon Sep 17 00:00:00 2001 From: Tony Xiao Date: Mon, 10 Jun 2019 06:43:07 -0700 Subject: [PATCH 5/5] Update typings to be more accurate --- .gitignore | 2 + react-native/linkkit/index.d.ts | 223 ++++++++++++++++++++------------ 2 files changed, 142 insertions(+), 83 deletions(-) diff --git a/.gitignore b/.gitignore index c0eaeeb..ea620a9 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ xcuserdata ## requirejs ## /examples/requirejs/public/vendor/* + +*.log diff --git a/react-native/linkkit/index.d.ts b/react-native/linkkit/index.d.ts index 5a83528..30dea37 100644 --- a/react-native/linkkit/index.d.ts +++ b/react-native/linkkit/index.d.ts @@ -1,80 +1,52 @@ -export type PlaidMessage = - | { - action: 'plaid_link-undefined::event' - eventName: 'EXIT' - metadata: { link_session_id: string } - } - | { - action: 'plaid_link-undefined::event' - eventName: 'TRANSITION_VIEW' - metadata: { link_session_id: string } - } - | { - action: 'plaid_link-undefined::event' - eventName: 'OPEN' - metadata: { link_session_id: string } - } - | { - action: 'plaid_link-undefined::connected' - metadata: { public_token: string; link_session_id: string } - } - | { - action: 'plaid_link-undefined::event' - eventName: 'SEARCH_INSTITUTION' - metadata: { institution_search_query: string; link_session_id: string } - } - | { - action: 'plaid_link-undefined::event' - eventName: 'SELECT_INSTITUTION' - metadata: { - institution_id: string - institution_name: string - link_session_id: string - } - } - | { - action: 'plaid_link-undefined::event' - eventName: 'SUBMIT_CREDENTIALS' - metadata: { - institution_id: string - institution_name: string - link_session_id: string - } - } - | { - action: 'plaid_link-undefined::event' - eventName: 'ERROR' - metadata: { - error_code: string // 'INVALID_CREDENTIALS' - error_message: string // 'the provided credentials were not correct' - error_type: string // 'ITEM_ERROR' - link_session_id: string - } - } - -/** - * - `key` (string) - the Plaid public_key (required) - * - `env` (string) - the Plaid environment (required) - * - `product` (array of strings) - a list of Plaid products (required) - * - `clientName` (string) - the name to display on info panes (recommended) - * - `webhook` (string) - webhook to receive transaction and error updates - * - `selectAccount` (boolean) - enables the select account flow when set to true - * - * - `userLegalName` (string) - the legal name of the end-user, necessary for microdeposit support - * - `userEmailAddress` (string) - the email address of the end-user, necessary for microdeposit support - * - `countryCodes` (array of strings) - a list of ISO 3166-1 alpha-2 country codes, used to select institutions available in the given countries - * - `language` (string) - Plaid-supported language to localize Link. English ('en') will be used by default. For details consult https://plaid.com/docs/#parameter-reference. - * - `publicToken` (string) - the public_token to invoke update mode (see https://plaid.com/docs/quickstart/#use-link-to-resolve-error) - * - `institution` (string) - institution identifier for which to invoke the custom initializer flow - * - * The are deprecated configuration options for the legacy API - * - `longtailAuth` (boolean) - enable longtail auth institutions - * - `apiVersion` (string) - the Plaid API version to use - * - * - `onSuccess` (function) - takes two parameters: the created public_token and the associated metadata. - * - `onExit` (function) - takes two parameters: error and the associated metadata. - * - `onEvent` (function) - takes two parameters: the event name and the associated metadata. - */ +type EventName = + | 'OPEN' + | 'EXIT' + | 'TRANSITION_VIEW' + | 'SEARCH_INSTITUTION' + | 'SELECT_INSTITUTION' + // | 'SUBMIT_CREDENTIALS' // Happens in webview, does this happen in Plaid Link? + | 'ERROR' + | 'HANDOFF' + +export interface EventMeta { + link_session_id: string + request_id?: string + + status?: string + exit_status?: string + + timestamp?: Date + view_name?: string + + mfa_type?: string + + institution?: Institution + institution_search_query?: string + institution_name?: string + institution_id?: string + + account_id?: null + account?: Account + accounts?: Account[] + + error_type?: string + error_code?: string + error_message?: string +} + +export interface Account { + id?: string + type?: string + mask?: string + name?: string + subtype?: string +} + +export interface Institution { + name: string + institution_id: string +} + export interface PlaidConfiguration { key: string env: 'sandbox' | 'development' | 'production' @@ -83,19 +55,104 @@ export interface PlaidConfiguration { webhook?: string selectAccount?: boolean + userLegalName?: string + userEmailAddress?: string + countryCodes?: string[] + language?: string publicToken?: string institution?: string - onSuccess: (publicToken: string, meta: any) => void - onExit: (error: any, meta: any) => void - onEvent?: (data: PlaidMessage, meta: any) => void + onSuccess: (publicToken: string, meta: EventMeta) => void + onExit: (error: any, meta: EventMeta) => void + onEvent?: (eventName: EventName, meta: EventMeta) => void } -declare const PlaidLink: { - /** Technically returns `this` but donno how to type that for now... */ - create: (config: PlaidConfiguration) => void +interface PlaidLink { + /** + * Create Plaid Link. + * + * The `configuration` object must contain one or more of: + * + * - `key` (string) - the Plaid public_key (required) + * - `env` (string) - the Plaid environment (required) + * - `product` (array of strings) - a list of Plaid products (required) + * - `clientName` (string) - the name to display on info panes (recommended) + * - `webhook` (string) - webhook to receive transaction and error updates + * - `selectAccount` (boolean) - enables the select account flow when set to true + * + * - `userLegalName` (string) - the legal name of the end-user, necessary for microdeposit support + * - `userEmailAddress` (string) - the email address of the end-user, necessary for microdeposit support + * - `countryCodes` (array of strings) - a list of ISO 3166-1 alpha-2 country codes, used to select institutions available in the given countries + * - `language` (string) - Plaid-supported language to localize Link. English ('en') will be used by default. For details consult https://plaid.com/docs/#parameter-reference. + * - `publicToken` (string) - the public_token to invoke update mode (see https://plaid.com/docs/quickstart/#use-link-to-resolve-error) + * - `institution` (string) - institution identifier for which to invoke the custom initializer flow + * + * The are deprecated configuration options for the legacy API + * - `longtailAuth` (boolean) - enable longtail auth institutions + * - `apiVersion` (string) - the Plaid API version to use + * + * - `onSuccess` (function) - takes two parameters: the created public_token and the associated metadata. + * - `onExit` (function) - takes two parameters: error and the associated metadata. + * - `onEvent` (function) - takes two parameters: the event name and the associated metadata. + */ + create: (config: PlaidConfiguration) => this + + /** + * Open Plaid Link. + * + * Calling `open()` will present the Plaid Link user interface implemented by the native `PLKPlaidLinkViewController` + */ open: () => void version: string } +declare const PlaidLink: PlaidLink + export default PlaidLink + +/** TODO: Better mapping of eventName to metadata */ +// export type PlaidEvent = +// | { +// eventName: 'EXIT' +// metadata: { link_session_id: string } +// } +// | { +// eventName: 'TRANSITION_VIEW' +// metadata: { link_session_id: string } +// } +// | { +// eventName: 'OPEN' +// metadata: { link_session_id: string } +// } +// | { +// metadata: { public_token: string; link_session_id: string } +// } +// | { +// eventName: 'SEARCH_INSTITUTION' +// metadata: { institution_search_query: string; link_session_id: string } +// } +// | { +// eventName: 'SELECT_INSTITUTION' +// metadata: { +// institution_id: string +// institution_name: string +// link_session_id: string +// } +// } +// | { +// eventName: 'SUBMIT_CREDENTIALS' +// metadata: { +// institution_id: string +// institution_name: string +// link_session_id: string +// } +// } +// | { +// eventName: 'ERROR' +// metadata: { +// error_code: string // 'INVALID_CREDENTIALS' +// error_message: string // 'the provided credentials were not correct' +// error_type: string // 'ITEM_ERROR' +// link_session_id: string +// } +// }