@quiltt/react-native 3.7.4 → 3.8.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,30 @@
1
1
  # @quiltt/react-native
2
2
 
3
+ ## 3.8.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#300](https://github.com/quiltt/quiltt-js/pull/300) [`a359810`](https://github.com/quiltt/quiltt-js/commit/a3598104565b4428beef9de37f85211e9caf465b) Thanks [@zubairaziz](https://github.com/zubairaziz)! - Make @quiltt/react-native ESM only
8
+
9
+ - Updated dependencies [[`a359810`](https://github.com/quiltt/quiltt-js/commit/a3598104565b4428beef9de37f85211e9caf465b)]:
10
+ - @quiltt/react@3.8.1
11
+ - @quiltt/core@3.8.1
12
+
13
+ ## 3.8.0
14
+
15
+ ### Minor Changes
16
+
17
+ - [#298](https://github.com/quiltt/quiltt-js/pull/298) [`134b294`](https://github.com/quiltt/quiltt-js/commit/134b294019c3bdbccc1f4b5cf9af38d43ea5b3ac) Thanks [@zubairaziz](https://github.com/zubairaziz)! - - Update dependencies
18
+ - Update expo-react-native implementation
19
+ - Reorganize test files
20
+ - Fix security vulnerabilities
21
+
22
+ ### Patch Changes
23
+
24
+ - Updated dependencies [[`134b294`](https://github.com/quiltt/quiltt-js/commit/134b294019c3bdbccc1f4b5cf9af38d43ea5b3ac)]:
25
+ - @quiltt/react@3.8.0
26
+ - @quiltt/core@3.8.0
27
+
3
28
  ## 3.7.4
4
29
 
5
30
  ### Patch Changes
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import { WebView } from 'react-native-webview';
10
10
  import { generateStackTrace, makeBacktrace, getCauses } from '@honeybadger-io/core/build/src/util';
11
11
 
12
12
  // Generated by genversion.
13
- const version = '3.7.4';
13
+ const version = '3.8.1';
14
14
 
15
15
  const ErrorReporterConfig = {
16
16
  honeybadger_api_key: 'undefined'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quiltt/react-native",
3
- "version": "3.7.4",
3
+ "version": "3.8.1",
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": {
@@ -11,14 +11,12 @@
11
11
  "license": "MIT",
12
12
  "type": "module",
13
13
  "exports": {
14
- "import": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
15
16
  "default": "./dist/index.js"
16
- },
17
- "require": {
18
- "default": "./dist/index.cjs"
19
17
  }
20
18
  },
21
- "main": "./dist/index.js",
19
+ "module": "./dist/index.js",
22
20
  "types": "./dist/index.d.ts",
23
21
  "files": [
24
22
  "dist/**",
@@ -27,29 +25,29 @@
27
25
  ],
28
26
  "dependencies": {
29
27
  "@honeybadger-io/core": "6.6.0",
30
- "base-64": "1.0.0",
31
- "react-native-url-polyfill": "2.0.0",
32
- "react-native-webview": "13.10.7",
33
- "@quiltt/core": "3.7.4",
34
- "@quiltt/react": "3.7.4"
28
+ "@quiltt/core": "3.8.1",
29
+ "@quiltt/react": "3.8.1"
35
30
  },
36
31
  "devDependencies": {
37
- "@apollo/client": "3.9.11",
38
- "@biomejs/biome": "1.8.3",
32
+ "@biomejs/biome": "1.9.4",
39
33
  "@types/base-64": "1.0.2",
40
- "@types/node": "22.4.1",
41
- "@types/react": "18.3.3",
42
- "bunchee": "5.3.2",
34
+ "@types/node": "22.9.0",
35
+ "@types/react": "18.3.12",
36
+ "base-64": "1.0.0",
37
+ "bunchee": "5.6.1",
43
38
  "react": "18.3.1",
39
+ "react-native": "0.76.2",
40
+ "react-native-url-polyfill": "2.0.0",
41
+ "react-native-webview": "13.12.3",
44
42
  "rimraf": "6.0.1",
45
- "typescript": "5.5.4"
43
+ "typescript": "5.6.3"
46
44
  },
47
45
  "peerDependencies": {
48
- "base-64": "*",
49
- "react": "^18.2.0",
50
- "react-native": "^0.72.5",
51
- "react-native-url-polyfill": "*",
52
- "react-native-webview": "^13.0.0"
46
+ "base-64": "^1.0.0",
47
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
48
+ "react-native": ">=0.72.0",
49
+ "react-native-url-polyfill": "^2.0.0",
50
+ "react-native-webview": ">=13.0.0"
53
51
  },
54
52
  "publishConfig": {
55
53
  "access": "public"
@@ -60,7 +58,7 @@
60
58
  "build": "pnpm run addApiKey && pnpm run addVersion && bunchee",
61
59
  "clean": "rimraf .turbo dist",
62
60
  "dev": "bunchee --watch",
63
- "lint": "TIMING=1 biome check src/ --fix",
61
+ "lint": "TIMING=1 biome check src/ tests/ --fix",
64
62
  "typecheck": "tsc --project tsconfig.json --noEmit"
65
63
  }
66
64
  }
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '3.7.4'
2
+ export const version = '3.8.1'
package/dist/index.cjs DELETED
@@ -1,470 +0,0 @@
1
- Object.defineProperty(exports, '__esModule', { value: true });
2
-
3
- var base64 = require('base-64');
4
- var core = require('@quiltt/core');
5
- var react = require('@quiltt/react');
6
- var jsxRuntime = require('react/jsx-runtime');
7
- var react$1 = require('react');
8
- var reactNative = require('react-native');
9
- var reactNativeUrlPolyfill = require('react-native-url-polyfill');
10
- var reactNativeWebview = require('react-native-webview');
11
- var util = require('@honeybadger-io/core/build/src/util');
12
-
13
- // Generated by genversion.
14
- const version = '3.7.4';
15
-
16
- const ErrorReporterConfig = {
17
- honeybadger_api_key: 'undefined'
18
- };
19
-
20
- // Quick hack to send error to Honeybadger to debug why the connector is not routable
21
- const notifier = {
22
- name: 'Quiltt React Native SDK Reporter',
23
- url: 'https://www.quiltt.dev/guides/connector/react-native',
24
- version: version
25
- };
26
- class ErrorReporter {
27
- constructor(platform){
28
- this.noticeUrl = 'https://api.honeybadger.io/v1/notices';
29
- this.apiKey = ErrorReporterConfig.honeybadger_api_key;
30
- this.clientName = 'react-native-sdk';
31
- this.clientVersion = version;
32
- this.platform = platform;
33
- this.logger = console;
34
- this.userAgent = `${this.clientName} ${this.clientVersion}; ${this.platform}`;
35
- }
36
- async send(error, context) {
37
- const headers = {
38
- 'X-API-Key': this.apiKey,
39
- 'Content-Type': 'application/json',
40
- Accept: 'application/json',
41
- 'User-Agent': `${this.clientName} ${this.clientVersion}; ${this.platform}`
42
- };
43
- const payload = await this.buildPayload(error, context);
44
- const method = 'POST';
45
- const body = JSON.stringify(payload);
46
- const mode = 'cors';
47
- fetch(this.noticeUrl, {
48
- headers,
49
- method,
50
- body,
51
- mode
52
- }).then((response)=>{
53
- if (response.status !== 201) {
54
- this.logger.warn(`Error report failed: unknown response from server. code=${response.status}`);
55
- return;
56
- }
57
- return response.json();
58
- }).then((data)=>{
59
- if (data) {
60
- this.logger.info(`Error report sent ⚡ https://app.honeybadger.io/notice/${data?.id}`);
61
- }
62
- });
63
- }
64
- async buildPayload(error, localContext = {}) {
65
- const notice = error;
66
- notice.stack = util.generateStackTrace();
67
- notice.backtrace = util.makeBacktrace(notice.stack);
68
- return {
69
- notifier,
70
- error: {
71
- class: notice.name,
72
- message: notice.message,
73
- backtrace: notice.backtrace,
74
- // fingerprint: this.calculateFingerprint(notice),
75
- tags: notice.tags || [],
76
- causes: util.getCauses(notice, this.logger)
77
- },
78
- request: {
79
- url: notice.url,
80
- component: notice.component,
81
- action: notice.action,
82
- context: localContext || {},
83
- cgi_data: {},
84
- params: {},
85
- session: {}
86
- },
87
- server: {
88
- project_root: notice.projectRoot,
89
- environment_name: this.userAgent,
90
- revision: version,
91
- hostname: this.platform,
92
- time: new Date().toUTCString()
93
- },
94
- details: notice.details || {}
95
- };
96
- }
97
- }
98
-
99
- const getErrorMessage = (responseStatus, error)=>{
100
- if (error) return `An error occurred while checking the connector URL: ${error?.name} \n${error?.message}`;
101
- return responseStatus ? `The URL is not routable. Response status: ${responseStatus}` : 'An error occurred while checking the connector URL';
102
- };
103
-
104
- const AndroidSafeAreaView = ({ testId, children })=>/*#__PURE__*/ jsxRuntime.jsx(reactNative.SafeAreaView, {
105
- testID: testId,
106
- style: styles$1.AndroidSafeArea,
107
- children: children
108
- });
109
- const styles$1 = reactNative.StyleSheet.create({
110
- AndroidSafeArea: {
111
- flex: 1,
112
- backgroundColor: 'white',
113
- paddingTop: reactNative.Platform.OS === 'android' ? reactNative.StatusBar.currentHeight : 0
114
- }
115
- });
116
-
117
- const ErrorScreen = ({ testId, error, cta })=>/*#__PURE__*/ jsxRuntime.jsx(AndroidSafeAreaView, {
118
- testId: testId,
119
- children: /*#__PURE__*/ jsxRuntime.jsxs(reactNative.View, {
120
- style: [
121
- styles.container,
122
- styles.padding
123
- ],
124
- children: [
125
- /*#__PURE__*/ jsxRuntime.jsxs(reactNative.View, {
126
- style: {
127
- flex: 1,
128
- justifyContent: 'center'
129
- },
130
- children: [
131
- /*#__PURE__*/ jsxRuntime.jsx(reactNative.View, {
132
- style: {
133
- flexDirection: 'row',
134
- justifyContent: 'space-between',
135
- alignItems: 'center',
136
- marginVertical: 10
137
- },
138
- children: /*#__PURE__*/ jsxRuntime.jsx(reactNative.Text, {
139
- style: [
140
- styles.title
141
- ],
142
- children: "Cannot connect to the internet."
143
- })
144
- }),
145
- /*#__PURE__*/ jsxRuntime.jsx(reactNative.Text, {
146
- style: [
147
- styles.subtitle
148
- ],
149
- children: error
150
- })
151
- ]
152
- }),
153
- /*#__PURE__*/ jsxRuntime.jsx(reactNative.Pressable, {
154
- style: [
155
- styles.pressable
156
- ],
157
- onPress: cta,
158
- children: /*#__PURE__*/ jsxRuntime.jsx(reactNative.Text, {
159
- style: [
160
- styles.pressableText
161
- ],
162
- children: "Exit"
163
- })
164
- })
165
- ]
166
- })
167
- });
168
- const styles = reactNative.StyleSheet.create({
169
- container: {
170
- flex: 1,
171
- flexDirection: 'column',
172
- justifyContent: 'flex-start',
173
- alignItems: 'stretch',
174
- backgroundColor: '#F3F4F6'
175
- },
176
- title: {
177
- color: '#1F2937',
178
- fontSize: 30,
179
- fontWeight: 'bold'
180
- },
181
- subtitle: {
182
- color: 'rgba(107, 114, 128, 1)'
183
- },
184
- padding: {
185
- paddingHorizontal: 16,
186
- paddingVertical: 24
187
- },
188
- pressable: {
189
- marginTop: 20,
190
- backgroundColor: '#1F2937',
191
- padding: 10,
192
- paddingHorizontal: 25,
193
- borderRadius: 5
194
- },
195
- pressableText: {
196
- color: '#fff',
197
- textAlign: 'center'
198
- }
199
- });
200
-
201
- const LoadingScreen = ({ testId })=>/*#__PURE__*/ jsxRuntime.jsx(AndroidSafeAreaView, {
202
- testId: testId,
203
- children: /*#__PURE__*/ jsxRuntime.jsx(reactNative.View, {
204
- style: {
205
- flex: 1,
206
- justifyContent: 'center',
207
- alignItems: 'center'
208
- },
209
- children: /*#__PURE__*/ jsxRuntime.jsx(reactNative.ActivityIndicator, {
210
- testID: "activity-indicator",
211
- size: "large",
212
- color: "#5928A3"
213
- })
214
- })
215
- });
216
-
217
- const errorReporter = new ErrorReporter(`${reactNative.Platform.OS} ${reactNative.Platform.Version}`);
218
- const PREFLIGHT_RETRY_COUNT = 3;
219
- const checkConnectorUrl = async (connectorUrl, retryCount = 0)=>{
220
- let responseStatus;
221
- let error;
222
- try {
223
- const response = await fetch(connectorUrl);
224
- if (!response.ok) {
225
- responseStatus = response.status;
226
- throw new Error(`The URL ${connectorUrl} is not routable.`);
227
- }
228
- console.log(`The URL ${connectorUrl} is routable.`);
229
- return {
230
- checked: true
231
- };
232
- } catch (e) {
233
- error = e;
234
- console.error(`An error occurred while checking the connector URL: ${error}`);
235
- if (retryCount < PREFLIGHT_RETRY_COUNT) {
236
- const delay = 50 * 2 ** retryCount;
237
- await new Promise((resolve)=>setTimeout(resolve, delay));
238
- console.log(`Retrying... Attempt number ${retryCount + 1}`);
239
- return checkConnectorUrl(connectorUrl, retryCount + 1);
240
- }
241
- const errorMessage = getErrorMessage(responseStatus, error);
242
- const errorToSend = error || new Error(errorMessage);
243
- const context = {
244
- connectorUrl,
245
- responseStatus
246
- };
247
- if (responseStatus !== 404) await errorReporter.send(errorToSend, context);
248
- return {
249
- checked: true,
250
- error: errorMessage
251
- };
252
- }
253
- };
254
- const handleOAuthUrl = (oauthUrl)=>{
255
- console.log(`handleOAuthUrl - Opening URL - ${oauthUrl.toString()}`);
256
- reactNative.Linking.openURL(oauthUrl.toString());
257
- };
258
- const QuilttConnector = ({ testId, connectorId, connectionId, institution, oauthRedirectUrl, onEvent, onLoad, onExit, onExitSuccess, onExitAbort, onExitError })=>{
259
- const webViewRef = react$1.useRef(null);
260
- const { session } = react.useQuilttSession();
261
- const encodedOAuthRedirectUrl = react$1.useMemo(()=>encodeURIComponent(oauthRedirectUrl), [
262
- oauthRedirectUrl
263
- ]);
264
- const connectorUrl = react$1.useMemo(()=>{
265
- const url = new reactNativeUrlPolyfill.URL(`https://${connectorId}.quiltt.app`);
266
- url.searchParams.append('mode', 'webview');
267
- url.searchParams.append('oauth_redirect_url', encodedOAuthRedirectUrl);
268
- url.searchParams.append('agent', `react-native-${version}`);
269
- return url.toString();
270
- }, [
271
- connectorId,
272
- encodedOAuthRedirectUrl
273
- ]);
274
- const [preFlightCheck, setPreFlightCheck] = react$1.useState({
275
- checked: false
276
- });
277
- react$1.useEffect(()=>{
278
- if (preFlightCheck.checked) return;
279
- const fetchDataAndSetState = async ()=>{
280
- const connectorUrlStatus = await checkConnectorUrl(connectorUrl);
281
- setPreFlightCheck(connectorUrlStatus);
282
- };
283
- fetchDataAndSetState();
284
- }, [
285
- connectorUrl,
286
- preFlightCheck
287
- ]);
288
- const initInjectedJavaScript = react$1.useCallback(()=>{
289
- const script = `\
290
- const options = {\
291
- source: 'quiltt',\
292
- type: 'Options',\
293
- token: '${session?.token}',\
294
- connectorId: '${connectorId}',\
295
- connectionId: '${connectionId}',\
296
- institution: '${institution}', \
297
- };\
298
- const compactedOptions = Object.keys(options).reduce((acc, key) => {\
299
- if (options[key] !== 'undefined') {\
300
- acc[key] = options[key];\
301
- }\
302
- return acc;\
303
- }, {});\
304
- window.postMessage(compactedOptions);\
305
- `;
306
- webViewRef.current?.injectJavaScript(script);
307
- }, [
308
- connectionId,
309
- connectorId,
310
- institution,
311
- session?.token
312
- ]);
313
- const isQuilttEvent = react$1.useCallback((url)=>url.protocol === 'quilttconnector:', []);
314
- const shouldRender = react$1.useCallback((url)=>!isQuilttEvent(url), [
315
- isQuilttEvent
316
- ]);
317
- const clearLocalStorage = react$1.useCallback(()=>{
318
- const script = 'localStorage.clear();';
319
- webViewRef.current?.injectJavaScript(script);
320
- }, []);
321
- const handleQuilttEvent = react$1.useCallback((url)=>{
322
- url.searchParams.delete('source');
323
- url.searchParams.append('connectorId', connectorId);
324
- const metadata = Object.fromEntries(url.searchParams);
325
- const eventType = url.host;
326
- switch(eventType){
327
- case 'Load':
328
- initInjectedJavaScript();
329
- onEvent?.(react.ConnectorSDKEventType.Load, metadata);
330
- onLoad?.(metadata);
331
- break;
332
- case 'ExitAbort':
333
- clearLocalStorage();
334
- onEvent?.(react.ConnectorSDKEventType.ExitAbort, metadata);
335
- onExit?.(react.ConnectorSDKEventType.ExitAbort, metadata);
336
- onExitAbort?.(metadata);
337
- break;
338
- case 'ExitError':
339
- clearLocalStorage();
340
- onEvent?.(react.ConnectorSDKEventType.ExitError, metadata);
341
- onExit?.(react.ConnectorSDKEventType.ExitError, metadata);
342
- onExitError?.(metadata);
343
- break;
344
- case 'ExitSuccess':
345
- clearLocalStorage();
346
- onEvent?.(react.ConnectorSDKEventType.ExitSuccess, metadata);
347
- onExit?.(react.ConnectorSDKEventType.ExitSuccess, metadata);
348
- onExitSuccess?.(metadata);
349
- break;
350
- case 'Authenticate':
351
- break;
352
- case 'OauthRequested':
353
- handleOAuthUrl(new reactNativeUrlPolyfill.URL(url.searchParams.get('oauthUrl')));
354
- break;
355
- default:
356
- console.log('unhandled event', url);
357
- break;
358
- }
359
- }, [
360
- clearLocalStorage,
361
- connectorId,
362
- initInjectedJavaScript,
363
- onEvent,
364
- onExit,
365
- onExitAbort,
366
- onExitError,
367
- onExitSuccess,
368
- onLoad
369
- ]);
370
- const requestHandler = react$1.useCallback((request)=>{
371
- const url = new reactNativeUrlPolyfill.URL(request.url);
372
- if (isQuilttEvent(url)) {
373
- handleQuilttEvent(url);
374
- return false;
375
- }
376
- if (shouldRender(url)) return true;
377
- // Plaid set oauth url by doing window.location.href = url
378
- // So we use `handleOAuthUrl` as a catch all and assume all url got to this step is Plaid OAuth url
379
- handleOAuthUrl(url);
380
- return false;
381
- }, [
382
- handleQuilttEvent,
383
- isQuilttEvent,
384
- shouldRender
385
- ]);
386
- if (!preFlightCheck.checked) return /*#__PURE__*/ jsxRuntime.jsx(LoadingScreen, {
387
- testId: "loading-screen"
388
- });
389
- if (preFlightCheck.error) {
390
- return /*#__PURE__*/ jsxRuntime.jsx(ErrorScreen, {
391
- testId: "error-screen",
392
- error: preFlightCheck.error,
393
- cta: ()=>onExitError?.({
394
- connectorId
395
- })
396
- });
397
- }
398
- return /*#__PURE__*/ jsxRuntime.jsx(AndroidSafeAreaView, {
399
- testId: testId,
400
- children: /*#__PURE__*/ jsxRuntime.jsx(reactNativeWebview.WebView, {
401
- testID: "webview",
402
- ref: webViewRef,
403
- // Plaid keeps sending window.location = 'about:srcdoc' and causes some noise in RN
404
- // All whitelists are now handled in requestHandler, handleQuilttEvent and handleOAuthUrl
405
- originWhitelist: [
406
- '*'
407
- ],
408
- source: {
409
- uri: connectorUrl
410
- },
411
- onShouldStartLoadWithRequest: requestHandler,
412
- javaScriptEnabled: true,
413
- domStorageEnabled: true,
414
- webviewDebuggingEnabled: true
415
- })
416
- });
417
- };
418
- QuilttConnector.displayName = 'QuilttConnector';
419
-
420
- // Hermes doesn't have atob
421
- // https://github.com/facebook/hermes/issues/1178
422
- if (!global.atob) {
423
- global.atob = base64.decode;
424
- }
425
-
426
- Object.defineProperty(exports, "QuilttAuthProvider", {
427
- enumerable: true,
428
- get: function () { return react.QuilttAuthProvider; }
429
- });
430
- Object.defineProperty(exports, "QuilttProvider", {
431
- enumerable: true,
432
- get: function () { return react.QuilttProvider; }
433
- });
434
- Object.defineProperty(exports, "QuilttSettingsProvider", {
435
- enumerable: true,
436
- get: function () { return react.QuilttSettingsProvider; }
437
- });
438
- Object.defineProperty(exports, "useQuilttClient", {
439
- enumerable: true,
440
- get: function () { return react.useQuilttClient; }
441
- });
442
- Object.defineProperty(exports, "useQuilttConnector", {
443
- enumerable: true,
444
- get: function () { return react.useQuilttConnector; }
445
- });
446
- Object.defineProperty(exports, "useQuilttSession", {
447
- enumerable: true,
448
- get: function () { return react.useQuilttSession; }
449
- });
450
- Object.defineProperty(exports, "useQuilttSettings", {
451
- enumerable: true,
452
- get: function () { return react.useQuilttSettings; }
453
- });
454
- Object.defineProperty(exports, "useSession", {
455
- enumerable: true,
456
- get: function () { return react.useSession; }
457
- });
458
- Object.defineProperty(exports, "useStorage", {
459
- enumerable: true,
460
- get: function () { return react.useStorage; }
461
- });
462
- exports.QuilttConnector = QuilttConnector;
463
- exports.checkConnectorUrl = checkConnectorUrl;
464
- exports.handleOAuthUrl = handleOAuthUrl;
465
- Object.keys(core).forEach(function (k) {
466
- if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
467
- enumerable: true,
468
- get: function () { return core[k]; }
469
- });
470
- });