@quiltt/react-native 3.6.4 → 3.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @quiltt/react-native
2
2
 
3
+ ## 3.6.6
4
+
5
+ ### Patch Changes
6
+
7
+ - [#251](https://github.com/quiltt/quiltt-js/pull/251) [`07a3eb1`](https://github.com/quiltt/quiltt-js/commit/07a3eb1b2b719ae1073287079d6a0e61e432cc96) Thanks [@zubairaziz](https://github.com/zubairaziz)! - Update @quiltt/react-native OAuthURL handling
8
+
9
+ - Updated dependencies [[`07a3eb1`](https://github.com/quiltt/quiltt-js/commit/07a3eb1b2b719ae1073287079d6a0e61e432cc96)]:
10
+ - @quiltt/react@3.6.6
11
+ - @quiltt/core@3.6.6
12
+
13
+ ## 3.6.5
14
+
15
+ ### Patch Changes
16
+
17
+ - [#248](https://github.com/quiltt/quiltt-js/pull/248) [`d15297e`](https://github.com/quiltt/quiltt-js/commit/d15297e4dea40c90dab97d1f8e8797b5cfe8395c) Thanks [@sirwolfgang](https://github.com/sirwolfgang)! - Fix issue with loading Plaid's new Link
18
+
19
+ - Updated dependencies [[`d15297e`](https://github.com/quiltt/quiltt-js/commit/d15297e4dea40c90dab97d1f8e8797b5cfe8395c)]:
20
+ - @quiltt/core@3.6.5
21
+ - @quiltt/react@3.6.5
22
+
3
23
  ## 3.6.4
4
24
 
5
25
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -10,126 +10,13 @@ var reactNativeWebview = require('react-native-webview');
10
10
  var reactNative = require('react-native');
11
11
  var util = require('@honeybadger-io/core/build/src/util');
12
12
 
13
- // Generated by genversion.
14
- const version = '3.6.4';
15
-
16
- const AndroidSafeAreaView = ({ testId, children })=>/*#__PURE__*/ jsxRuntime.jsx(reactNative.SafeAreaView, {
17
- testID: testId,
18
- style: styles$1.AndroidSafeArea,
19
- children: children
20
- });
21
- const styles$1 = reactNative.StyleSheet.create({
22
- AndroidSafeArea: {
23
- flex: 1,
24
- backgroundColor: 'white',
25
- paddingTop: reactNative.Platform.OS === 'android' ? reactNative.StatusBar.currentHeight : 0
26
- }
27
- });
28
-
29
- const ErrorScreen = ({ testId, error, cta })=>/*#__PURE__*/ jsxRuntime.jsx(AndroidSafeAreaView, {
30
- testId: testId,
31
- children: /*#__PURE__*/ jsxRuntime.jsxs(reactNative.View, {
32
- style: [
33
- styles.container,
34
- styles.padding
35
- ],
36
- children: [
37
- /*#__PURE__*/ jsxRuntime.jsxs(reactNative.View, {
38
- style: {
39
- flex: 1,
40
- justifyContent: 'center'
41
- },
42
- children: [
43
- /*#__PURE__*/ jsxRuntime.jsx(reactNative.View, {
44
- style: {
45
- flexDirection: 'row',
46
- justifyContent: 'space-between',
47
- alignItems: 'center',
48
- marginVertical: 10
49
- },
50
- children: /*#__PURE__*/ jsxRuntime.jsx(reactNative.Text, {
51
- style: [
52
- styles.title
53
- ],
54
- children: "Cannot connect to the internet."
55
- })
56
- }),
57
- /*#__PURE__*/ jsxRuntime.jsx(reactNative.Text, {
58
- style: [
59
- styles.subtitle
60
- ],
61
- children: error
62
- })
63
- ]
64
- }),
65
- /*#__PURE__*/ jsxRuntime.jsx(reactNative.Pressable, {
66
- style: [
67
- styles.pressable
68
- ],
69
- onPress: cta,
70
- children: /*#__PURE__*/ jsxRuntime.jsx(reactNative.Text, {
71
- style: [
72
- styles.pressableText
73
- ],
74
- children: "Exit"
75
- })
76
- })
77
- ]
78
- })
79
- });
80
- const styles = reactNative.StyleSheet.create({
81
- container: {
82
- flex: 1,
83
- flexDirection: 'column',
84
- justifyContent: 'flex-start',
85
- alignItems: 'stretch',
86
- backgroundColor: '#F3F4F6'
87
- },
88
- title: {
89
- color: '#1F2937',
90
- fontSize: 30,
91
- fontWeight: 'bold'
92
- },
93
- subtitle: {
94
- color: 'rgba(107, 114, 128, 1)'
95
- },
96
- padding: {
97
- paddingHorizontal: 16,
98
- paddingVertical: 24
99
- },
100
- pressable: {
101
- marginTop: 20,
102
- backgroundColor: '#1F2937',
103
- padding: 10,
104
- paddingHorizontal: 25,
105
- borderRadius: 5
106
- },
107
- pressableText: {
108
- color: '#fff',
109
- textAlign: 'center'
110
- }
111
- });
112
-
113
- const LoadingScreen = ({ testId })=>/*#__PURE__*/ jsxRuntime.jsx(AndroidSafeAreaView, {
114
- testId: testId,
115
- children: /*#__PURE__*/ jsxRuntime.jsx(reactNative.View, {
116
- style: {
117
- flex: 1,
118
- justifyContent: 'center',
119
- alignItems: 'center'
120
- },
121
- children: /*#__PURE__*/ jsxRuntime.jsx(reactNative.ActivityIndicator, {
122
- testID: "activity-indicator",
123
- size: "large",
124
- color: "#5928A3"
125
- })
126
- })
127
- });
128
-
129
13
  const ErrorReporterConfig = {
130
14
  honeybadger_api_key: 'undefined'
131
15
  };
132
16
 
17
+ // Generated by genversion.
18
+ const version = '3.6.6';
19
+
133
20
  // Quick hack to send error to Honeybadger to debug why the connector is not routable
134
21
  const notifier = {
135
22
  name: 'Quiltt React Native SDK Reporter',
@@ -214,7 +101,7 @@ const getErrorMessage = (responseStatus, error)=>{
214
101
  return responseStatus ? `The URL is not routable. Response status: ${responseStatus}` : 'An error occurred while checking the connector URL';
215
102
  };
216
103
 
217
- const errorReporter = new ErrorReporter(`${reactNative.Platform.OS} ${reactNative.Platform.Version}`);
104
+ const errorReporter$1 = new ErrorReporter(`${reactNative.Platform.OS} ${reactNative.Platform.Version}`);
218
105
  const PREFLIGHT_RETRY_COUNT = 3;
219
106
  const checkConnectorUrl = async (connectorUrl, retryCount = 0)=>{
220
107
  let responseStatus;
@@ -249,21 +136,149 @@ const checkConnectorUrl = async (connectorUrl, retryCount = 0)=>{
249
136
  connectorUrl,
250
137
  responseStatus
251
138
  };
252
- if (responseStatus !== 404) await errorReporter.send(errorToSend, context);
139
+ if (responseStatus !== 404) await errorReporter$1.send(errorToSend, context);
253
140
  return {
254
141
  checked: true,
255
142
  error: errorMessage
256
143
  };
257
144
  };
258
145
 
259
- const handleOAuthUrl = (oauthUrl)=>{
260
- if (oauthUrl.protocol !== 'https:') {
261
- console.log(`handleOAuthUrl - Skipping non https url - ${oauthUrl.href}`);
262
- return;
146
+ const errorReporter = new ErrorReporter(`${reactNative.Platform.OS} ${reactNative.Platform.Version}`);
147
+ const handleOAuthUrl = async (oauthUrl, context)=>{
148
+ const parsedUrl = new reactNativeUrlPolyfill.URL(oauthUrl.href);
149
+ try {
150
+ // Check if the URL protocol is HTTPS
151
+ if (parsedUrl.protocol !== 'https:') {
152
+ console.warn(`handleOAuthUrl - Skipping non-HTTPS URL - ${parsedUrl.href}`);
153
+ return;
154
+ }
155
+ // Open the URL using Linking module
156
+ await reactNative.Linking.openURL(parsedUrl.href);
157
+ } catch (error) {
158
+ console.error('handleOAuthUrl - Error opening URL:', error);
159
+ // Report error to HoneyBadger
160
+ const errorContext = {
161
+ ...context,
162
+ oauthUrl: parsedUrl.href,
163
+ passedUrl: oauthUrl.toString()
164
+ };
165
+ await errorReporter.send(error, errorContext);
263
166
  }
264
- reactNative.Linking.openURL(oauthUrl.href);
265
167
  };
266
168
 
169
+ const AndroidSafeAreaView = ({ testId, children })=>/*#__PURE__*/ jsxRuntime.jsx(reactNative.SafeAreaView, {
170
+ testID: testId,
171
+ style: styles$1.AndroidSafeArea,
172
+ children: children
173
+ });
174
+ const styles$1 = reactNative.StyleSheet.create({
175
+ AndroidSafeArea: {
176
+ flex: 1,
177
+ backgroundColor: 'white',
178
+ paddingTop: reactNative.Platform.OS === 'android' ? reactNative.StatusBar.currentHeight : 0
179
+ }
180
+ });
181
+
182
+ const ErrorScreen = ({ testId, error, cta })=>/*#__PURE__*/ jsxRuntime.jsx(AndroidSafeAreaView, {
183
+ testId: testId,
184
+ children: /*#__PURE__*/ jsxRuntime.jsxs(reactNative.View, {
185
+ style: [
186
+ styles.container,
187
+ styles.padding
188
+ ],
189
+ children: [
190
+ /*#__PURE__*/ jsxRuntime.jsxs(reactNative.View, {
191
+ style: {
192
+ flex: 1,
193
+ justifyContent: 'center'
194
+ },
195
+ children: [
196
+ /*#__PURE__*/ jsxRuntime.jsx(reactNative.View, {
197
+ style: {
198
+ flexDirection: 'row',
199
+ justifyContent: 'space-between',
200
+ alignItems: 'center',
201
+ marginVertical: 10
202
+ },
203
+ children: /*#__PURE__*/ jsxRuntime.jsx(reactNative.Text, {
204
+ style: [
205
+ styles.title
206
+ ],
207
+ children: "Cannot connect to the internet."
208
+ })
209
+ }),
210
+ /*#__PURE__*/ jsxRuntime.jsx(reactNative.Text, {
211
+ style: [
212
+ styles.subtitle
213
+ ],
214
+ children: error
215
+ })
216
+ ]
217
+ }),
218
+ /*#__PURE__*/ jsxRuntime.jsx(reactNative.Pressable, {
219
+ style: [
220
+ styles.pressable
221
+ ],
222
+ onPress: cta,
223
+ children: /*#__PURE__*/ jsxRuntime.jsx(reactNative.Text, {
224
+ style: [
225
+ styles.pressableText
226
+ ],
227
+ children: "Exit"
228
+ })
229
+ })
230
+ ]
231
+ })
232
+ });
233
+ const styles = reactNative.StyleSheet.create({
234
+ container: {
235
+ flex: 1,
236
+ flexDirection: 'column',
237
+ justifyContent: 'flex-start',
238
+ alignItems: 'stretch',
239
+ backgroundColor: '#F3F4F6'
240
+ },
241
+ title: {
242
+ color: '#1F2937',
243
+ fontSize: 30,
244
+ fontWeight: 'bold'
245
+ },
246
+ subtitle: {
247
+ color: 'rgba(107, 114, 128, 1)'
248
+ },
249
+ padding: {
250
+ paddingHorizontal: 16,
251
+ paddingVertical: 24
252
+ },
253
+ pressable: {
254
+ marginTop: 20,
255
+ backgroundColor: '#1F2937',
256
+ padding: 10,
257
+ paddingHorizontal: 25,
258
+ borderRadius: 5
259
+ },
260
+ pressableText: {
261
+ color: '#fff',
262
+ textAlign: 'center'
263
+ }
264
+ });
265
+
266
+ const LoadingScreen = ({ testId })=>/*#__PURE__*/ jsxRuntime.jsx(AndroidSafeAreaView, {
267
+ testId: testId,
268
+ children: /*#__PURE__*/ jsxRuntime.jsx(reactNative.View, {
269
+ style: {
270
+ flex: 1,
271
+ justifyContent: 'center',
272
+ alignItems: 'center'
273
+ },
274
+ children: /*#__PURE__*/ jsxRuntime.jsx(reactNative.ActivityIndicator, {
275
+ testID: "activity-indicator",
276
+ size: "large",
277
+ color: "#5928A3"
278
+ })
279
+ })
280
+ });
281
+
267
282
  const QuilttConnector = ({ testId, connectorId, connectionId, institution, oauthRedirectUrl, onEvent, onLoad, onExit, onExitSuccess, onExitAbort, onExitError })=>{
268
283
  const webViewRef = react$1.useRef(null);
269
284
  const { session } = react.useQuilttSession();
@@ -326,7 +341,7 @@ const QuilttConnector = ({ testId, connectorId, connectionId, institution, oauth
326
341
  'quiltt.app',
327
342
  'quiltt.dev',
328
343
  'moneydesktop.com',
329
- 'cdn.plaid.com/link/v2/stable/link.html'
344
+ 'cdn.plaid.com'
330
345
  ], []);
331
346
  const isQuilttEvent = react$1.useCallback((url)=>url.protocol === 'quilttconnector:', []);
332
347
  const shouldRender = react$1.useCallback((url)=>{
@@ -339,10 +354,10 @@ const QuilttConnector = ({ testId, connectorId, connectionId, institution, oauth
339
354
  allowedListUrl,
340
355
  isQuilttEvent
341
356
  ]);
342
- const clearLocalStorage = ()=>{
357
+ const clearLocalStorage = react$1.useCallback(()=>{
343
358
  const script = 'localStorage.clear();';
344
359
  webViewRef.current?.injectJavaScript(script);
345
- };
360
+ }, []);
346
361
  const handleQuilttEvent = react$1.useCallback((url)=>{
347
362
  url.searchParams.delete('source');
348
363
  url.searchParams.append('connectorId', connectorId);
@@ -375,7 +390,12 @@ const QuilttConnector = ({ testId, connectorId, connectionId, institution, oauth
375
390
  case 'Authenticate':
376
391
  break;
377
392
  case 'OauthRequested':
378
- handleOAuthUrl(new reactNativeUrlPolyfill.URL(url.searchParams.get('oauthUrl')));
393
+ handleOAuthUrl(new reactNativeUrlPolyfill.URL(url.searchParams.get('oauthUrl')), {
394
+ connectorId,
395
+ connectionId,
396
+ institution,
397
+ oauthRedirectUrl
398
+ });
379
399
  break;
380
400
  default:
381
401
  console.log('unhandled event', url);
@@ -385,11 +405,15 @@ const QuilttConnector = ({ testId, connectorId, connectionId, institution, oauth
385
405
  connectorId,
386
406
  initInjectedJavaScript,
387
407
  onEvent,
408
+ onLoad,
409
+ clearLocalStorage,
388
410
  onExit,
389
411
  onExitAbort,
390
412
  onExitError,
391
413
  onExitSuccess,
392
- onLoad
414
+ connectionId,
415
+ institution,
416
+ oauthRedirectUrl
393
417
  ]);
394
418
  const requestHandler = react$1.useCallback((request)=>{
395
419
  const url = new reactNativeUrlPolyfill.URL(request.url);
@@ -400,11 +424,20 @@ const QuilttConnector = ({ testId, connectorId, connectionId, institution, oauth
400
424
  if (shouldRender(url)) return true;
401
425
  // Plaid set oauth url by doing window.location.href = url
402
426
  // So we use `handleOAuthUrl` as a catch all and assume all url got to this step is Plaid OAuth url
403
- handleOAuthUrl(url);
427
+ handleOAuthUrl(url, {
428
+ connectorId,
429
+ connectionId,
430
+ institution,
431
+ oauthRedirectUrl
432
+ });
404
433
  return false;
405
434
  }, [
435
+ connectionId,
436
+ connectorId,
406
437
  handleQuilttEvent,
438
+ institution,
407
439
  isQuilttEvent,
440
+ oauthRedirectUrl,
408
441
  shouldRender
409
442
  ]);
410
443
  if (!preFlightCheck.checked) return /*#__PURE__*/ jsxRuntime.jsx(LoadingScreen, {
package/dist/index.js CHANGED
@@ -6,129 +6,16 @@ import { jsx, jsxs } from 'react/jsx-runtime';
6
6
  import { useRef, useMemo, useState, useEffect, useCallback } from 'react';
7
7
  import { URL } from 'react-native-url-polyfill';
8
8
  import { WebView } from 'react-native-webview';
9
- import { StyleSheet, Platform, StatusBar, SafeAreaView, View, Text, Pressable, ActivityIndicator, Linking } from 'react-native';
9
+ import { Platform, Linking, StyleSheet, StatusBar, SafeAreaView, View, Text, Pressable, ActivityIndicator } from 'react-native';
10
10
  import { generateStackTrace, makeBacktrace, getCauses } from '@honeybadger-io/core/build/src/util';
11
11
 
12
- // Generated by genversion.
13
- const version = '3.6.4';
14
-
15
- const AndroidSafeAreaView = ({ testId, children })=>/*#__PURE__*/ jsx(SafeAreaView, {
16
- testID: testId,
17
- style: styles$1.AndroidSafeArea,
18
- children: children
19
- });
20
- const styles$1 = StyleSheet.create({
21
- AndroidSafeArea: {
22
- flex: 1,
23
- backgroundColor: 'white',
24
- paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0
25
- }
26
- });
27
-
28
- const ErrorScreen = ({ testId, error, cta })=>/*#__PURE__*/ jsx(AndroidSafeAreaView, {
29
- testId: testId,
30
- children: /*#__PURE__*/ jsxs(View, {
31
- style: [
32
- styles.container,
33
- styles.padding
34
- ],
35
- children: [
36
- /*#__PURE__*/ jsxs(View, {
37
- style: {
38
- flex: 1,
39
- justifyContent: 'center'
40
- },
41
- children: [
42
- /*#__PURE__*/ jsx(View, {
43
- style: {
44
- flexDirection: 'row',
45
- justifyContent: 'space-between',
46
- alignItems: 'center',
47
- marginVertical: 10
48
- },
49
- children: /*#__PURE__*/ jsx(Text, {
50
- style: [
51
- styles.title
52
- ],
53
- children: "Cannot connect to the internet."
54
- })
55
- }),
56
- /*#__PURE__*/ jsx(Text, {
57
- style: [
58
- styles.subtitle
59
- ],
60
- children: error
61
- })
62
- ]
63
- }),
64
- /*#__PURE__*/ jsx(Pressable, {
65
- style: [
66
- styles.pressable
67
- ],
68
- onPress: cta,
69
- children: /*#__PURE__*/ jsx(Text, {
70
- style: [
71
- styles.pressableText
72
- ],
73
- children: "Exit"
74
- })
75
- })
76
- ]
77
- })
78
- });
79
- const styles = StyleSheet.create({
80
- container: {
81
- flex: 1,
82
- flexDirection: 'column',
83
- justifyContent: 'flex-start',
84
- alignItems: 'stretch',
85
- backgroundColor: '#F3F4F6'
86
- },
87
- title: {
88
- color: '#1F2937',
89
- fontSize: 30,
90
- fontWeight: 'bold'
91
- },
92
- subtitle: {
93
- color: 'rgba(107, 114, 128, 1)'
94
- },
95
- padding: {
96
- paddingHorizontal: 16,
97
- paddingVertical: 24
98
- },
99
- pressable: {
100
- marginTop: 20,
101
- backgroundColor: '#1F2937',
102
- padding: 10,
103
- paddingHorizontal: 25,
104
- borderRadius: 5
105
- },
106
- pressableText: {
107
- color: '#fff',
108
- textAlign: 'center'
109
- }
110
- });
111
-
112
- const LoadingScreen = ({ testId })=>/*#__PURE__*/ jsx(AndroidSafeAreaView, {
113
- testId: testId,
114
- children: /*#__PURE__*/ jsx(View, {
115
- style: {
116
- flex: 1,
117
- justifyContent: 'center',
118
- alignItems: 'center'
119
- },
120
- children: /*#__PURE__*/ jsx(ActivityIndicator, {
121
- testID: "activity-indicator",
122
- size: "large",
123
- color: "#5928A3"
124
- })
125
- })
126
- });
127
-
128
12
  const ErrorReporterConfig = {
129
13
  honeybadger_api_key: 'undefined'
130
14
  };
131
15
 
16
+ // Generated by genversion.
17
+ const version = '3.6.6';
18
+
132
19
  // Quick hack to send error to Honeybadger to debug why the connector is not routable
133
20
  const notifier = {
134
21
  name: 'Quiltt React Native SDK Reporter',
@@ -213,7 +100,7 @@ const getErrorMessage = (responseStatus, error)=>{
213
100
  return responseStatus ? `The URL is not routable. Response status: ${responseStatus}` : 'An error occurred while checking the connector URL';
214
101
  };
215
102
 
216
- const errorReporter = new ErrorReporter(`${Platform.OS} ${Platform.Version}`);
103
+ const errorReporter$1 = new ErrorReporter(`${Platform.OS} ${Platform.Version}`);
217
104
  const PREFLIGHT_RETRY_COUNT = 3;
218
105
  const checkConnectorUrl = async (connectorUrl, retryCount = 0)=>{
219
106
  let responseStatus;
@@ -248,21 +135,149 @@ const checkConnectorUrl = async (connectorUrl, retryCount = 0)=>{
248
135
  connectorUrl,
249
136
  responseStatus
250
137
  };
251
- if (responseStatus !== 404) await errorReporter.send(errorToSend, context);
138
+ if (responseStatus !== 404) await errorReporter$1.send(errorToSend, context);
252
139
  return {
253
140
  checked: true,
254
141
  error: errorMessage
255
142
  };
256
143
  };
257
144
 
258
- const handleOAuthUrl = (oauthUrl)=>{
259
- if (oauthUrl.protocol !== 'https:') {
260
- console.log(`handleOAuthUrl - Skipping non https url - ${oauthUrl.href}`);
261
- return;
145
+ const errorReporter = new ErrorReporter(`${Platform.OS} ${Platform.Version}`);
146
+ const handleOAuthUrl = async (oauthUrl, context)=>{
147
+ const parsedUrl = new URL(oauthUrl.href);
148
+ try {
149
+ // Check if the URL protocol is HTTPS
150
+ if (parsedUrl.protocol !== 'https:') {
151
+ console.warn(`handleOAuthUrl - Skipping non-HTTPS URL - ${parsedUrl.href}`);
152
+ return;
153
+ }
154
+ // Open the URL using Linking module
155
+ await Linking.openURL(parsedUrl.href);
156
+ } catch (error) {
157
+ console.error('handleOAuthUrl - Error opening URL:', error);
158
+ // Report error to HoneyBadger
159
+ const errorContext = {
160
+ ...context,
161
+ oauthUrl: parsedUrl.href,
162
+ passedUrl: oauthUrl.toString()
163
+ };
164
+ await errorReporter.send(error, errorContext);
262
165
  }
263
- Linking.openURL(oauthUrl.href);
264
166
  };
265
167
 
168
+ const AndroidSafeAreaView = ({ testId, children })=>/*#__PURE__*/ jsx(SafeAreaView, {
169
+ testID: testId,
170
+ style: styles$1.AndroidSafeArea,
171
+ children: children
172
+ });
173
+ const styles$1 = StyleSheet.create({
174
+ AndroidSafeArea: {
175
+ flex: 1,
176
+ backgroundColor: 'white',
177
+ paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0
178
+ }
179
+ });
180
+
181
+ const ErrorScreen = ({ testId, error, cta })=>/*#__PURE__*/ jsx(AndroidSafeAreaView, {
182
+ testId: testId,
183
+ children: /*#__PURE__*/ jsxs(View, {
184
+ style: [
185
+ styles.container,
186
+ styles.padding
187
+ ],
188
+ children: [
189
+ /*#__PURE__*/ jsxs(View, {
190
+ style: {
191
+ flex: 1,
192
+ justifyContent: 'center'
193
+ },
194
+ children: [
195
+ /*#__PURE__*/ jsx(View, {
196
+ style: {
197
+ flexDirection: 'row',
198
+ justifyContent: 'space-between',
199
+ alignItems: 'center',
200
+ marginVertical: 10
201
+ },
202
+ children: /*#__PURE__*/ jsx(Text, {
203
+ style: [
204
+ styles.title
205
+ ],
206
+ children: "Cannot connect to the internet."
207
+ })
208
+ }),
209
+ /*#__PURE__*/ jsx(Text, {
210
+ style: [
211
+ styles.subtitle
212
+ ],
213
+ children: error
214
+ })
215
+ ]
216
+ }),
217
+ /*#__PURE__*/ jsx(Pressable, {
218
+ style: [
219
+ styles.pressable
220
+ ],
221
+ onPress: cta,
222
+ children: /*#__PURE__*/ jsx(Text, {
223
+ style: [
224
+ styles.pressableText
225
+ ],
226
+ children: "Exit"
227
+ })
228
+ })
229
+ ]
230
+ })
231
+ });
232
+ const styles = StyleSheet.create({
233
+ container: {
234
+ flex: 1,
235
+ flexDirection: 'column',
236
+ justifyContent: 'flex-start',
237
+ alignItems: 'stretch',
238
+ backgroundColor: '#F3F4F6'
239
+ },
240
+ title: {
241
+ color: '#1F2937',
242
+ fontSize: 30,
243
+ fontWeight: 'bold'
244
+ },
245
+ subtitle: {
246
+ color: 'rgba(107, 114, 128, 1)'
247
+ },
248
+ padding: {
249
+ paddingHorizontal: 16,
250
+ paddingVertical: 24
251
+ },
252
+ pressable: {
253
+ marginTop: 20,
254
+ backgroundColor: '#1F2937',
255
+ padding: 10,
256
+ paddingHorizontal: 25,
257
+ borderRadius: 5
258
+ },
259
+ pressableText: {
260
+ color: '#fff',
261
+ textAlign: 'center'
262
+ }
263
+ });
264
+
265
+ const LoadingScreen = ({ testId })=>/*#__PURE__*/ jsx(AndroidSafeAreaView, {
266
+ testId: testId,
267
+ children: /*#__PURE__*/ jsx(View, {
268
+ style: {
269
+ flex: 1,
270
+ justifyContent: 'center',
271
+ alignItems: 'center'
272
+ },
273
+ children: /*#__PURE__*/ jsx(ActivityIndicator, {
274
+ testID: "activity-indicator",
275
+ size: "large",
276
+ color: "#5928A3"
277
+ })
278
+ })
279
+ });
280
+
266
281
  const QuilttConnector = ({ testId, connectorId, connectionId, institution, oauthRedirectUrl, onEvent, onLoad, onExit, onExitSuccess, onExitAbort, onExitError })=>{
267
282
  const webViewRef = useRef(null);
268
283
  const { session } = useQuilttSession();
@@ -325,7 +340,7 @@ const QuilttConnector = ({ testId, connectorId, connectionId, institution, oauth
325
340
  'quiltt.app',
326
341
  'quiltt.dev',
327
342
  'moneydesktop.com',
328
- 'cdn.plaid.com/link/v2/stable/link.html'
343
+ 'cdn.plaid.com'
329
344
  ], []);
330
345
  const isQuilttEvent = useCallback((url)=>url.protocol === 'quilttconnector:', []);
331
346
  const shouldRender = useCallback((url)=>{
@@ -338,10 +353,10 @@ const QuilttConnector = ({ testId, connectorId, connectionId, institution, oauth
338
353
  allowedListUrl,
339
354
  isQuilttEvent
340
355
  ]);
341
- const clearLocalStorage = ()=>{
356
+ const clearLocalStorage = useCallback(()=>{
342
357
  const script = 'localStorage.clear();';
343
358
  webViewRef.current?.injectJavaScript(script);
344
- };
359
+ }, []);
345
360
  const handleQuilttEvent = useCallback((url)=>{
346
361
  url.searchParams.delete('source');
347
362
  url.searchParams.append('connectorId', connectorId);
@@ -374,7 +389,12 @@ const QuilttConnector = ({ testId, connectorId, connectionId, institution, oauth
374
389
  case 'Authenticate':
375
390
  break;
376
391
  case 'OauthRequested':
377
- handleOAuthUrl(new URL(url.searchParams.get('oauthUrl')));
392
+ handleOAuthUrl(new URL(url.searchParams.get('oauthUrl')), {
393
+ connectorId,
394
+ connectionId,
395
+ institution,
396
+ oauthRedirectUrl
397
+ });
378
398
  break;
379
399
  default:
380
400
  console.log('unhandled event', url);
@@ -384,11 +404,15 @@ const QuilttConnector = ({ testId, connectorId, connectionId, institution, oauth
384
404
  connectorId,
385
405
  initInjectedJavaScript,
386
406
  onEvent,
407
+ onLoad,
408
+ clearLocalStorage,
387
409
  onExit,
388
410
  onExitAbort,
389
411
  onExitError,
390
412
  onExitSuccess,
391
- onLoad
413
+ connectionId,
414
+ institution,
415
+ oauthRedirectUrl
392
416
  ]);
393
417
  const requestHandler = useCallback((request)=>{
394
418
  const url = new URL(request.url);
@@ -399,11 +423,20 @@ const QuilttConnector = ({ testId, connectorId, connectionId, institution, oauth
399
423
  if (shouldRender(url)) return true;
400
424
  // Plaid set oauth url by doing window.location.href = url
401
425
  // So we use `handleOAuthUrl` as a catch all and assume all url got to this step is Plaid OAuth url
402
- handleOAuthUrl(url);
426
+ handleOAuthUrl(url, {
427
+ connectorId,
428
+ connectionId,
429
+ institution,
430
+ oauthRedirectUrl
431
+ });
403
432
  return false;
404
433
  }, [
434
+ connectionId,
435
+ connectorId,
405
436
  handleQuilttEvent,
437
+ institution,
406
438
  isQuilttEvent,
439
+ oauthRedirectUrl,
407
440
  shouldRender
408
441
  ]);
409
442
  if (!preFlightCheck.checked) return /*#__PURE__*/ jsx(LoadingScreen, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quiltt/react-native",
3
- "version": "3.6.4",
3
+ "version": "3.6.6",
4
4
  "description": "React Native components for Quiltt Connector",
5
5
  "homepage": "https://github.com/quiltt/quiltt-js/tree/main/packages/react-native#readme",
6
6
  "repository": {
@@ -27,16 +27,15 @@
27
27
  ],
28
28
  "dependencies": {
29
29
  "@honeybadger-io/core": "6.6.0",
30
- "@quiltt/core": "3.6.4",
31
- "@quiltt/react": "3.6.4"
30
+ "@quiltt/core": "3.6.6",
31
+ "@quiltt/react": "3.6.6"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@apollo/client": "3.9.9",
35
35
  "@trivago/prettier-plugin-sort-imports": "4.1.1",
36
- "@types/base-64": "0.1.0",
37
- "@types/node": "20.12.7",
36
+ "@types/base-64": "1.0.2",
37
+ "@types/node": "20.12.10",
38
38
  "@types/react": "18.2.73",
39
- "@types/react-native": "0.72.5",
40
39
  "@typescript-eslint/eslint-plugin": "5.60.1",
41
40
  "@typescript-eslint/parser": "5.60.1",
42
41
  "bunchee": "4.4.8",
@@ -48,8 +47,11 @@
48
47
  "eslint-plugin-react-hooks": "4.6.0",
49
48
  "prettier": "2.8.8",
50
49
  "react": "18.2.0",
50
+ "react-native": "0.74.1",
51
+ "react-native-url-polyfill": "2.0.0",
52
+ "react-native-webview": "13.8.7",
51
53
  "rimraf": "5.0.5",
52
- "typescript": "5.4.3"
54
+ "typescript": "5.4.5"
53
55
  },
54
56
  "peerDependencies": {
55
57
  "base-64": "*",
@@ -1,24 +1,22 @@
1
+ import {
2
+ type ConnectorSDKCallbackMetadata,
3
+ type ConnectorSDKCallbacks,
4
+ ConnectorSDKEventType,
5
+ useQuilttSession,
6
+ } from '@quiltt/react'
1
7
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
2
-
3
8
  // React Native's URL implementation is incomplete
4
9
  // https://github.com/facebook/react-native/issues/16434
5
10
  import { URL } from 'react-native-url-polyfill'
6
11
  import { WebView } from 'react-native-webview'
7
12
  import type { ShouldStartLoadRequest } from 'react-native-webview/lib/WebViewTypes'
8
13
 
9
- import {
10
- ConnectorSDKCallbackMetadata,
11
- ConnectorSDKCallbacks,
12
- ConnectorSDKEventType,
13
- useQuilttSession,
14
- } from '@quiltt/react'
15
-
16
- import { version } from '@/version'
14
+ import { checkConnectorUrl, handleOAuthUrl } from '../utils'
15
+ import type { PreFlightCheck } from '../utils'
16
+ import { version } from '../version'
17
17
  import { AndroidSafeAreaView } from './AndroidSafeAreaView'
18
18
  import { ErrorScreen } from './ErrorScreen'
19
19
  import { LoadingScreen } from './LoadingScreen'
20
- import { checkConnectorUrl, handleOAuthUrl } from '@/utils'
21
- import type { PreFlightCheck } from '@/utils'
22
20
 
23
21
  type QuilttConnectorProps = {
24
22
  testId?: string
@@ -48,7 +46,7 @@ const QuilttConnector = ({
48
46
  [oauthRedirectUrl]
49
47
  )
50
48
  const connectorUrl = useMemo(() => {
51
- const url: URL = new URL(`https://${connectorId}.quiltt.app`)
49
+ const url = new URL(`https://${connectorId}.quiltt.app`)
52
50
  url.searchParams.append('mode', 'webview')
53
51
  url.searchParams.append('oauth_redirect_url', encodedOAuthRedirectUrl)
54
52
  url.searchParams.append('agent', `react-native-${version}`)
@@ -90,12 +88,7 @@ const QuilttConnector = ({
90
88
  // For other urls, we assume those are bank urls, which needs to be handle in external browser.
91
89
  // TODO: Convert it to a list from Quiltt Server to prevent MX/ Plaid changes.
92
90
  const allowedListUrl = useMemo(
93
- () => [
94
- 'quiltt.app',
95
- 'quiltt.dev',
96
- 'moneydesktop.com',
97
- 'cdn.plaid.com/link/v2/stable/link.html',
98
- ],
91
+ () => ['quiltt.app', 'quiltt.dev', 'moneydesktop.com', 'cdn.plaid.com'],
99
92
  []
100
93
  )
101
94
 
@@ -112,10 +105,10 @@ const QuilttConnector = ({
112
105
  [allowedListUrl, isQuilttEvent]
113
106
  )
114
107
 
115
- const clearLocalStorage = () => {
108
+ const clearLocalStorage = useCallback(() => {
116
109
  const script = 'localStorage.clear();'
117
110
  webViewRef.current?.injectJavaScript(script)
118
- }
111
+ }, [])
119
112
 
120
113
  const handleQuilttEvent = useCallback(
121
114
  (url: URL) => {
@@ -152,7 +145,12 @@ const QuilttConnector = ({
152
145
  // TODO: handle Authenticate
153
146
  break
154
147
  case 'OauthRequested':
155
- handleOAuthUrl(new URL(url.searchParams.get('oauthUrl') as string))
148
+ handleOAuthUrl(new URL(url.searchParams.get('oauthUrl') as string), {
149
+ connectorId,
150
+ connectionId,
151
+ institution,
152
+ oauthRedirectUrl,
153
+ })
156
154
  break
157
155
  default:
158
156
  console.log('unhandled event', url)
@@ -163,11 +161,15 @@ const QuilttConnector = ({
163
161
  connectorId,
164
162
  initInjectedJavaScript,
165
163
  onEvent,
164
+ onLoad,
165
+ clearLocalStorage,
166
166
  onExit,
167
167
  onExitAbort,
168
168
  onExitError,
169
169
  onExitSuccess,
170
- onLoad,
170
+ connectionId,
171
+ institution,
172
+ oauthRedirectUrl,
171
173
  ]
172
174
  )
173
175
 
@@ -182,10 +184,23 @@ const QuilttConnector = ({
182
184
  if (shouldRender(url)) return true
183
185
  // Plaid set oauth url by doing window.location.href = url
184
186
  // So we use `handleOAuthUrl` as a catch all and assume all url got to this step is Plaid OAuth url
185
- handleOAuthUrl(url)
187
+ handleOAuthUrl(url, {
188
+ connectorId,
189
+ connectionId,
190
+ institution,
191
+ oauthRedirectUrl,
192
+ })
186
193
  return false
187
194
  },
188
- [handleQuilttEvent, isQuilttEvent, shouldRender]
195
+ [
196
+ connectionId,
197
+ connectorId,
198
+ handleQuilttEvent,
199
+ institution,
200
+ isQuilttEvent,
201
+ oauthRedirectUrl,
202
+ shouldRender,
203
+ ]
189
204
  )
190
205
 
191
206
  if (!preFlightCheck.checked) return <LoadingScreen testId="loading-screen" />
@@ -1,5 +1,5 @@
1
- import { getErrorMessage, ErrorReporter } from '../error'
2
1
  import { Platform } from 'react-native'
2
+ import { getErrorMessage, ErrorReporter } from '../error'
3
3
 
4
4
  const errorReporter = new ErrorReporter(`${Platform.OS} ${Platform.Version}`)
5
5
  const PREFLIGHT_RETRY_COUNT = 3
@@ -1,9 +1,28 @@
1
- import { Linking } from 'react-native'
1
+ import { Linking, Platform } from 'react-native'
2
+ import { URL } from 'react-native-url-polyfill'
3
+ import { ErrorReporter } from '../error'
2
4
 
3
- export const handleOAuthUrl = (oauthUrl: URL) => {
4
- if (oauthUrl.protocol !== 'https:') {
5
- console.log(`handleOAuthUrl - Skipping non https url - ${oauthUrl.href}`)
6
- return
5
+ const errorReporter = new ErrorReporter(`${Platform.OS} ${Platform.Version}`)
6
+
7
+ export const handleOAuthUrl = async (
8
+ oauthUrl: URL,
9
+ context?: Record<string, unknown>
10
+ ): Promise<void> => {
11
+ const parsedUrl = new URL(oauthUrl.href)
12
+ try {
13
+ // Check if the URL protocol is HTTPS
14
+ if (parsedUrl.protocol !== 'https:') {
15
+ console.warn(`handleOAuthUrl - Skipping non-HTTPS URL - ${parsedUrl.href}`)
16
+ return
17
+ }
18
+
19
+ // Open the URL using Linking module
20
+ await Linking.openURL(parsedUrl.href)
21
+ } catch (error) {
22
+ console.error('handleOAuthUrl - Error opening URL:', error)
23
+
24
+ // Report error to HoneyBadger
25
+ const errorContext = { ...context, oauthUrl: parsedUrl.href, passedUrl: oauthUrl.toString() }
26
+ await errorReporter.send(error as Error, errorContext)
7
27
  }
8
- Linking.openURL(oauthUrl.href)
9
28
  }
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '3.6.4'
2
+ export const version = '3.6.6'
File without changes