@quiltt/react-native 5.0.0 → 5.0.1

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,23 @@
1
1
  # @quiltt/react-native
2
2
 
3
+ ## 5.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#403](https://github.com/quiltt/quiltt-js/pull/403) [`b714ff3`](https://github.com/quiltt/quiltt-js/commit/b714ff3b3ee878445ca8e09903153ac0b43d693b) Thanks [@zubairaziz](https://github.com/zubairaziz)! - Prevent Infinite Re-Renders in QuilttProvider
8
+
9
+ - [#399](https://github.com/quiltt/quiltt-js/pull/399) [`77d11b6`](https://github.com/quiltt/quiltt-js/commit/77d11b69ceb950da9ca500aa73bae7a3abdfb3a2) Thanks [@CarltonHowell](https://github.com/CarltonHowell)! - Output commonJS
10
+
11
+ - [#402](https://github.com/quiltt/quiltt-js/pull/402) [`97eccbe`](https://github.com/quiltt/quiltt-js/commit/97eccbe6df42843307a11d28a0a8b5a36e43f3d9) Thanks [@zubairaziz](https://github.com/zubairaziz)! - Remove Node.js Dependencies in React Native Builds
12
+
13
+ - [#401](https://github.com/quiltt/quiltt-js/pull/401) [`2bf07c3`](https://github.com/quiltt/quiltt-js/commit/2bf07c36bf8dc573f01db8f4c69a48e05d313b8b) Thanks [@zubairaziz](https://github.com/zubairaziz)! - Improve expired auth token detection and clearing
14
+
15
+ - [#404](https://github.com/quiltt/quiltt-js/pull/404) [`45eb8c9`](https://github.com/quiltt/quiltt-js/commit/45eb8c907f51c0c8c5a3c069c35e0f301a4c374f) Thanks [@zubairaziz](https://github.com/zubairaziz)! - Add Subpath Exports and Reorganize Core Modules
16
+
17
+ - Updated dependencies [[`b714ff3`](https://github.com/quiltt/quiltt-js/commit/b714ff3b3ee878445ca8e09903153ac0b43d693b), [`77d11b6`](https://github.com/quiltt/quiltt-js/commit/77d11b69ceb950da9ca500aa73bae7a3abdfb3a2), [`97eccbe`](https://github.com/quiltt/quiltt-js/commit/97eccbe6df42843307a11d28a0a8b5a36e43f3d9), [`2bf07c3`](https://github.com/quiltt/quiltt-js/commit/2bf07c36bf8dc573f01db8f4c69a48e05d313b8b), [`45eb8c9`](https://github.com/quiltt/quiltt-js/commit/45eb8c907f51c0c8c5a3c069c35e0f301a4c374f)]:
18
+ - @quiltt/react@5.0.1
19
+ - @quiltt/core@5.0.1
20
+
3
21
  ## 5.0.0
4
22
 
5
23
  ### Major Changes
package/README.md CHANGED
@@ -43,6 +43,12 @@ Launch the [Quiltt Connector](https://www.quiltt.dev/connector) in a webview.
43
43
 
44
44
  `@quiltt/react-native` does not ship with a navigation library, so you might want to navigate to a new "page" when using QuilttConnector.
45
45
 
46
+ For better tree-shaking, you can import components from subpaths:
47
+
48
+ ```tsx
49
+ import { QuilttConnector } from '@quiltt/react-native/components'
50
+ ```
51
+
46
52
  #### Example
47
53
 
48
54
  ```tsx
@@ -0,0 +1,534 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var react = require('react');
5
+ var reactNative = require('react-native');
6
+ var react$1 = require('@quiltt/react');
7
+ var reactNativeUrlPolyfill = require('react-native-url-polyfill');
8
+ var reactNativeWebview = require('react-native-webview');
9
+ var index_cjs = require('../utils/index.cjs');
10
+
11
+ var version = "5.0.1";
12
+
13
+ const AndroidSafeAreaView = ({ testId, children })=>/*#__PURE__*/ jsxRuntime.jsx(reactNative.SafeAreaView, {
14
+ testID: testId,
15
+ style: styles$2.AndroidSafeArea,
16
+ children: children
17
+ });
18
+ const styles$2 = reactNative.StyleSheet.create({
19
+ AndroidSafeArea: {
20
+ flex: 1,
21
+ backgroundColor: 'white',
22
+ paddingTop: reactNative.Platform.OS === 'android' ? reactNative.StatusBar.currentHeight : 0
23
+ }
24
+ });
25
+
26
+ const ErrorScreen = ({ testId, error, cta })=>/*#__PURE__*/ jsxRuntime.jsx(AndroidSafeAreaView, {
27
+ testId: testId,
28
+ children: /*#__PURE__*/ jsxRuntime.jsxs(reactNative.View, {
29
+ style: [
30
+ styles$1.container,
31
+ styles$1.padding
32
+ ],
33
+ children: [
34
+ /*#__PURE__*/ jsxRuntime.jsxs(reactNative.View, {
35
+ style: {
36
+ flex: 1,
37
+ justifyContent: 'center'
38
+ },
39
+ children: [
40
+ /*#__PURE__*/ jsxRuntime.jsx(reactNative.View, {
41
+ style: {
42
+ flexDirection: 'row',
43
+ justifyContent: 'space-between',
44
+ alignItems: 'center',
45
+ marginVertical: 10
46
+ },
47
+ children: /*#__PURE__*/ jsxRuntime.jsx(reactNative.Text, {
48
+ style: [
49
+ styles$1.title
50
+ ],
51
+ children: "Cannot connect to the internet."
52
+ })
53
+ }),
54
+ /*#__PURE__*/ jsxRuntime.jsx(reactNative.Text, {
55
+ style: [
56
+ styles$1.subtitle
57
+ ],
58
+ children: error
59
+ })
60
+ ]
61
+ }),
62
+ /*#__PURE__*/ jsxRuntime.jsx(reactNative.Pressable, {
63
+ style: [
64
+ styles$1.pressable
65
+ ],
66
+ onPress: cta,
67
+ children: /*#__PURE__*/ jsxRuntime.jsx(reactNative.Text, {
68
+ style: [
69
+ styles$1.pressableText
70
+ ],
71
+ children: "Exit"
72
+ })
73
+ })
74
+ ]
75
+ })
76
+ });
77
+ const styles$1 = reactNative.StyleSheet.create({
78
+ container: {
79
+ flex: 1,
80
+ flexDirection: 'column',
81
+ justifyContent: 'flex-start',
82
+ alignItems: 'stretch',
83
+ backgroundColor: '#F3F4F6'
84
+ },
85
+ title: {
86
+ color: '#1F2937',
87
+ fontSize: 30,
88
+ fontWeight: 'bold'
89
+ },
90
+ subtitle: {
91
+ color: 'rgba(107, 114, 128, 1)'
92
+ },
93
+ padding: {
94
+ paddingHorizontal: 16,
95
+ paddingVertical: 24
96
+ },
97
+ pressable: {
98
+ marginTop: 20,
99
+ backgroundColor: '#1F2937',
100
+ padding: 10,
101
+ paddingHorizontal: 25,
102
+ borderRadius: 5
103
+ },
104
+ pressableText: {
105
+ color: '#fff',
106
+ textAlign: 'center'
107
+ }
108
+ });
109
+
110
+ const LoadingScreen = ({ testId })=>/*#__PURE__*/ jsxRuntime.jsx(AndroidSafeAreaView, {
111
+ testId: testId,
112
+ children: /*#__PURE__*/ jsxRuntime.jsx(reactNative.View, {
113
+ style: {
114
+ flex: 1,
115
+ justifyContent: 'center',
116
+ alignItems: 'center'
117
+ },
118
+ children: /*#__PURE__*/ jsxRuntime.jsx(reactNative.ActivityIndicator, {
119
+ testID: "activity-indicator",
120
+ size: "large",
121
+ color: "#5928A3"
122
+ })
123
+ })
124
+ });
125
+
126
+ const PREFLIGHT_RETRY_COUNT = 3;
127
+ const parseMetadata = (url, connectorId)=>{
128
+ const metadata = {
129
+ connectorId: url.searchParams.get('connectorId') ?? connectorId
130
+ };
131
+ const profileId = url.searchParams.get('profileId');
132
+ if (profileId) metadata.profileId = profileId;
133
+ const connectionId = url.searchParams.get('connectionId');
134
+ if (connectionId) metadata.connectionId = connectionId;
135
+ const connectorSessionId = url.searchParams.get('connectorSession');
136
+ if (connectorSessionId) metadata.connectorSession = {
137
+ id: connectorSessionId
138
+ };
139
+ return metadata;
140
+ };
141
+ const checkConnectorUrl = async (connectorUrl, errorReporter, retryCount = 0)=>{
142
+ let responseStatus;
143
+ try {
144
+ const response = await fetch(connectorUrl);
145
+ switch(response.status){
146
+ case 200:
147
+ return {
148
+ checked: true
149
+ };
150
+ case 400:
151
+ console.log('Invalid configuration');
152
+ return {
153
+ checked: true
154
+ };
155
+ case 404:
156
+ console.error('Connector not found');
157
+ return {
158
+ checked: true
159
+ };
160
+ default:
161
+ throw new Error('Connector URL is not routable.');
162
+ }
163
+ } catch (error) {
164
+ // Log error for debugging
165
+ console.error(error);
166
+ // Try again
167
+ if (retryCount < PREFLIGHT_RETRY_COUNT) {
168
+ const delay = 50 * 2 ** retryCount;
169
+ await new Promise((resolve)=>setTimeout(resolve, delay));
170
+ console.log(`Retrying connection... Attempt ${retryCount + 1}`);
171
+ return checkConnectorUrl(connectorUrl, errorReporter, retryCount + 1);
172
+ }
173
+ // Report error after retries exhausted
174
+ const errorMessage = index_cjs.getErrorMessage(responseStatus, error);
175
+ const errorToSend = error || new Error(errorMessage);
176
+ const context = {
177
+ connectorUrl,
178
+ responseStatus
179
+ };
180
+ await errorReporter.notify(errorToSend, context);
181
+ // Return errored preflight check
182
+ return {
183
+ checked: true,
184
+ error: errorMessage
185
+ };
186
+ }
187
+ };
188
+ /**
189
+ * Handle opening OAuth URLs with proper encoding detection and normalization
190
+ */ const handleOAuthUrl = (oauthUrl)=>{
191
+ try {
192
+ // Throw error if oauthUrl is null or undefined
193
+ if (oauthUrl == null) {
194
+ throw new Error('OAuth URL missing');
195
+ }
196
+ // Convert to string if it's a URL object
197
+ const urlString = oauthUrl.toString();
198
+ // Throw error if the resulting string is empty
199
+ if (!urlString || urlString.trim() === '') {
200
+ throw new Error('Empty OAuth URL');
201
+ }
202
+ // Normalize the URL encoding
203
+ const normalizedUrl = index_cjs.normalizeUrlEncoding(urlString);
204
+ // Open the normalized URL
205
+ reactNative.Linking.openURL(normalizedUrl);
206
+ } catch (_error) {
207
+ console.error('OAuth URL handling error');
208
+ // Only try the fallback if oauthUrl is not null
209
+ if (oauthUrl != null) {
210
+ try {
211
+ const fallbackUrl = typeof oauthUrl === 'string' ? oauthUrl : oauthUrl.toString();
212
+ console.log('Attempting fallback OAuth opening');
213
+ reactNative.Linking.openURL(fallbackUrl);
214
+ } catch (_fallbackError) {
215
+ console.error('Fallback OAuth opening failed');
216
+ }
217
+ }
218
+ }
219
+ };
220
+ const QuilttConnector = /*#__PURE__*/ react.forwardRef(({ connectorId, connectionId, institution, oauthRedirectUrl, onEvent, onLoad, onExit, onExitSuccess, onExitAbort, onExitError, testId }, ref)=>{
221
+ const webViewRef = react.useRef(null);
222
+ const { session } = react$1.useQuilttSession();
223
+ const [preFlightCheck, setPreFlightCheck] = react.useState({
224
+ checked: false
225
+ });
226
+ const [errorReporter, setErrorReporter] = react.useState(null);
227
+ const [userAgent, setUserAgent] = react.useState('');
228
+ // Initialize error reporter and user agent
229
+ react.useEffect(()=>{
230
+ let mounted = true;
231
+ const init = async ()=>{
232
+ const agent = await index_cjs.getUserAgent(version);
233
+ if (mounted) {
234
+ setUserAgent(agent);
235
+ setErrorReporter(new index_cjs.ErrorReporter(agent));
236
+ }
237
+ };
238
+ init();
239
+ return ()=>{
240
+ mounted = false;
241
+ };
242
+ }, []);
243
+ // Script to disable scrolling on header
244
+ const disableHeaderScrollScript = `
245
+ (function() {
246
+ const header = document.querySelector('header');
247
+ if (header) {
248
+ header.style.position = 'fixed';
249
+ header.style.top = '0';
250
+ header.style.left = '0';
251
+ header.style.right = '0';
252
+ header.style.zIndex = '1000';
253
+ }
254
+ })();
255
+ `;
256
+ const onLoadEnd = react.useCallback(()=>{
257
+ if (reactNative.Platform.OS === 'ios') {
258
+ webViewRef.current?.injectJavaScript(disableHeaderScrollScript);
259
+ }
260
+ }, []);
261
+ // Ensure oauthRedirectUrl is encoded properly - only once
262
+ const safeOAuthRedirectUrl = react.useMemo(()=>{
263
+ return index_cjs.smartEncodeURIComponent(oauthRedirectUrl);
264
+ }, [
265
+ oauthRedirectUrl
266
+ ]);
267
+ const connectorUrl = react.useMemo(()=>{
268
+ if (!userAgent) return null;
269
+ const url = new reactNativeUrlPolyfill.URL(`https://${connectorId}.quiltt.app`);
270
+ // For normal parameters, just append them directly
271
+ url.searchParams.append('mode', 'webview');
272
+ url.searchParams.append('agent', userAgent);
273
+ // For the oauth_redirect_url, we need to be careful
274
+ // If it's already encoded, we need to decode it once to prevent
275
+ // the automatic encoding that happens with searchParams.append
276
+ if (index_cjs.isEncoded(safeOAuthRedirectUrl)) {
277
+ const decodedOnce = decodeURIComponent(safeOAuthRedirectUrl);
278
+ url.searchParams.append('oauth_redirect_url', decodedOnce);
279
+ } else {
280
+ url.searchParams.append('oauth_redirect_url', safeOAuthRedirectUrl);
281
+ }
282
+ return url.toString();
283
+ }, [
284
+ connectorId,
285
+ safeOAuthRedirectUrl,
286
+ userAgent
287
+ ]);
288
+ react.useEffect(()=>{
289
+ if (preFlightCheck.checked || !connectorUrl || !errorReporter) return;
290
+ const fetchDataAndSetState = async ()=>{
291
+ const connectorUrlStatus = await checkConnectorUrl(connectorUrl, errorReporter);
292
+ setPreFlightCheck(connectorUrlStatus);
293
+ };
294
+ fetchDataAndSetState();
295
+ }, [
296
+ connectorUrl,
297
+ preFlightCheck,
298
+ errorReporter
299
+ ]);
300
+ const initInjectedJavaScript = react.useCallback(()=>{
301
+ const script = `\
302
+ const options = {\
303
+ source: 'quiltt',\
304
+ type: 'Options',\
305
+ token: '${session?.token}',\
306
+ connectorId: '${connectorId}',\
307
+ connectionId: '${connectionId}',\
308
+ institution: '${institution}', \
309
+ };\
310
+ const compactedOptions = Object.keys(options).reduce((acc, key) => {\
311
+ if (options[key] !== 'undefined') {\
312
+ acc[key] = options[key];\
313
+ }\
314
+ return acc;\
315
+ }, {});\
316
+ window.postMessage(compactedOptions);\
317
+ `;
318
+ webViewRef.current?.injectJavaScript(script);
319
+ }, [
320
+ connectionId,
321
+ connectorId,
322
+ institution,
323
+ session?.token
324
+ ]);
325
+ const isQuilttEvent = react.useCallback((url)=>url.protocol === 'quilttconnector:', []);
326
+ const shouldRender = react.useCallback((url)=>!isQuilttEvent(url), [
327
+ isQuilttEvent
328
+ ]);
329
+ const clearLocalStorage = react.useCallback(()=>{
330
+ const script = 'localStorage.clear();';
331
+ webViewRef.current?.injectJavaScript(script);
332
+ }, []);
333
+ const handleQuilttEvent = react.useCallback((url)=>{
334
+ url.searchParams.delete('source');
335
+ url.searchParams.append('connectorId', connectorId);
336
+ const metadata = parseMetadata(url, connectorId);
337
+ requestAnimationFrame(()=>{
338
+ const eventType = url.host;
339
+ switch(eventType){
340
+ case 'Load':
341
+ console.log('Event: Load');
342
+ initInjectedJavaScript();
343
+ onEvent?.(react$1.ConnectorSDKEventType.Load, metadata);
344
+ onLoad?.(metadata);
345
+ break;
346
+ case 'ExitAbort':
347
+ console.log('Event: ExitAbort');
348
+ clearLocalStorage();
349
+ onEvent?.(react$1.ConnectorSDKEventType.ExitAbort, metadata);
350
+ onExit?.(react$1.ConnectorSDKEventType.ExitAbort, metadata);
351
+ onExitAbort?.(metadata);
352
+ break;
353
+ case 'ExitError':
354
+ console.log('Event: ExitError');
355
+ clearLocalStorage();
356
+ onEvent?.(react$1.ConnectorSDKEventType.ExitError, metadata);
357
+ onExit?.(react$1.ConnectorSDKEventType.ExitError, metadata);
358
+ onExitError?.(metadata);
359
+ break;
360
+ case 'ExitSuccess':
361
+ console.log('Event: ExitSuccess');
362
+ clearLocalStorage();
363
+ onEvent?.(react$1.ConnectorSDKEventType.ExitSuccess, metadata);
364
+ onExit?.(react$1.ConnectorSDKEventType.ExitSuccess, metadata);
365
+ onExitSuccess?.(metadata);
366
+ break;
367
+ case 'Authenticate':
368
+ console.log('Event: Authenticate');
369
+ break;
370
+ case 'Navigate':
371
+ {
372
+ console.log('Event: Navigate');
373
+ const navigateUrl = url.searchParams.get('url');
374
+ if (navigateUrl) {
375
+ if (index_cjs.isEncoded(navigateUrl)) {
376
+ try {
377
+ const decodedUrl = decodeURIComponent(navigateUrl);
378
+ handleOAuthUrl(decodedUrl);
379
+ } catch (_error) {
380
+ console.error('Navigate URL decoding failed, using original');
381
+ handleOAuthUrl(navigateUrl);
382
+ }
383
+ } else {
384
+ handleOAuthUrl(navigateUrl);
385
+ }
386
+ } else {
387
+ console.error('Navigate URL missing from request');
388
+ }
389
+ break;
390
+ }
391
+ // NOTE: The `OauthRequested` is deprecated and should not be used
392
+ default:
393
+ console.log(`Unhandled event: ${eventType}`);
394
+ break;
395
+ }
396
+ });
397
+ }, [
398
+ clearLocalStorage,
399
+ connectorId,
400
+ initInjectedJavaScript,
401
+ onEvent,
402
+ onExit,
403
+ onExitAbort,
404
+ onExitError,
405
+ onExitSuccess,
406
+ onLoad
407
+ ]);
408
+ const requestHandler = react.useCallback((request)=>{
409
+ const url = new reactNativeUrlPolyfill.URL(request.url);
410
+ if (isQuilttEvent(url)) {
411
+ handleQuilttEvent(url);
412
+ return false;
413
+ }
414
+ if (shouldRender(url)) {
415
+ return true;
416
+ }
417
+ // Plaid set oauth url by doing window.location.href = url
418
+ // So we use `handleOAuthUrl` as a catch all and assume all url got to this step is Plaid OAuth url
419
+ handleOAuthUrl(url);
420
+ return false;
421
+ }, [
422
+ handleQuilttEvent,
423
+ isQuilttEvent,
424
+ shouldRender
425
+ ]);
426
+ // Expose method to handle OAuth callbacks from parent component
427
+ react.useImperativeHandle(ref, ()=>({
428
+ handleOAuthCallback: (callbackUrl)=>{
429
+ try {
430
+ console.log('Handling OAuth callback:', callbackUrl);
431
+ const url = new reactNativeUrlPolyfill.URL(callbackUrl);
432
+ // Extract OAuth callback parameters
433
+ const oauthParams = {};
434
+ url.searchParams.forEach((value, key)=>{
435
+ oauthParams[key] = value;
436
+ });
437
+ // Send OAuth callback data to the connector via postMessage
438
+ // This preserves the connector's state and allows events to fire properly
439
+ const message = {
440
+ source: 'quiltt',
441
+ type: 'OAuthCallback',
442
+ data: {
443
+ url: callbackUrl,
444
+ params: oauthParams
445
+ }
446
+ };
447
+ const script = `
448
+ (function() {
449
+ try {
450
+ window.postMessage(${JSON.stringify(message)});
451
+ console.log('OAuth callback message sent to connector');
452
+ } catch (e) {
453
+ console.error('Failed to send OAuth callback message:', e);
454
+ }
455
+ })();
456
+ true;
457
+ `;
458
+ webViewRef.current?.injectJavaScript(script);
459
+ } catch (error) {
460
+ console.error('Error handling OAuth callback:', error);
461
+ }
462
+ }
463
+ }), []);
464
+ if (!preFlightCheck.checked || !connectorUrl) {
465
+ return /*#__PURE__*/ jsxRuntime.jsx(LoadingScreen, {
466
+ testId: "loading-screen"
467
+ });
468
+ }
469
+ if (preFlightCheck.error) {
470
+ return /*#__PURE__*/ jsxRuntime.jsx(ErrorScreen, {
471
+ testId: "error-screen",
472
+ error: preFlightCheck.error,
473
+ cta: ()=>onExitError?.({
474
+ connectorId
475
+ })
476
+ });
477
+ }
478
+ return /*#__PURE__*/ jsxRuntime.jsx(AndroidSafeAreaView, {
479
+ testId: testId,
480
+ children: /*#__PURE__*/ jsxRuntime.jsx(reactNativeWebview.WebView, {
481
+ ref: webViewRef,
482
+ // Plaid keeps sending window.location = 'about:srcdoc' and causes some noise in RN
483
+ domStorageEnabled: true,
484
+ javaScriptEnabled: true,
485
+ onLoadEnd: onLoadEnd,
486
+ onShouldStartLoadWithRequest: requestHandler,
487
+ originWhitelist: [
488
+ '*'
489
+ ],
490
+ scrollEnabled: true,
491
+ showsHorizontalScrollIndicator: false,
492
+ showsVerticalScrollIndicator: false,
493
+ source: {
494
+ uri: connectorUrl
495
+ },
496
+ style: styles.webview,
497
+ testID: "webview",
498
+ webviewDebuggingEnabled: true,
499
+ ...reactNative.Platform.OS === 'ios' ? {
500
+ allowsBackForwardNavigationGestures: false,
501
+ allowsInlineMediaPlayback: true,
502
+ automaticallyAdjustContentInsets: false,
503
+ bounces: false,
504
+ contentInsetAdjustmentBehavior: 'never',
505
+ dataDetectorTypes: 'none',
506
+ decelerationRate: 'normal',
507
+ keyboardDisplayRequiresUserAction: false,
508
+ scrollEventThrottle: 16,
509
+ startInLoadingState: true
510
+ } : {
511
+ androidLayerType: 'hardware',
512
+ cacheEnabled: true,
513
+ cacheMode: 'LOAD_CACHE_ELSE_NETWORK',
514
+ overScrollMode: 'never'
515
+ }
516
+ })
517
+ });
518
+ });
519
+ // Add styles for the WebView container
520
+ const styles = reactNative.StyleSheet.create({
521
+ webviewContainer: {
522
+ flex: 1,
523
+ backgroundColor: '#ffffff'
524
+ },
525
+ webview: {
526
+ flex: 1,
527
+ overflow: 'hidden'
528
+ }
529
+ });
530
+ QuilttConnector.displayName = 'QuilttConnector';
531
+
532
+ exports.QuilttConnector = QuilttConnector;
533
+ exports.checkConnectorUrl = checkConnectorUrl;
534
+ exports.handleOAuthUrl = handleOAuthUrl;
@@ -0,0 +1,27 @@
1
+ import * as react from 'react';
2
+ import { ConnectorSDKCallbacks } from '@quiltt/react';
3
+ import { URL } from 'react-native-url-polyfill';
4
+ import { ErrorReporter } from '../utils/index.js';
5
+
6
+ type PreFlightCheck = {
7
+ checked: boolean;
8
+ error?: string;
9
+ };
10
+ declare const checkConnectorUrl: (connectorUrl: string, errorReporter: ErrorReporter, retryCount?: number) => Promise<PreFlightCheck>;
11
+ /**
12
+ * Handle opening OAuth URLs with proper encoding detection and normalization
13
+ */
14
+ declare const handleOAuthUrl: (oauthUrl: URL | string | null | undefined) => void;
15
+ type QuilttConnectorHandle = {
16
+ handleOAuthCallback: (url: string) => void;
17
+ };
18
+ declare const QuilttConnector: react.ForwardRefExoticComponent<{
19
+ connectorId: string;
20
+ connectionId?: string;
21
+ institution?: string;
22
+ oauthRedirectUrl: string;
23
+ testId?: string;
24
+ } & ConnectorSDKCallbacks & react.RefAttributes<QuilttConnectorHandle>>;
25
+
26
+ export { QuilttConnector, checkConnectorUrl, handleOAuthUrl };
27
+ export type { PreFlightCheck, QuilttConnectorHandle };