@quiltt/react 4.3.2 → 4.4.0

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,55 @@
1
1
  # @quiltt/react
2
2
 
3
+ ## 4.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#378](https://github.com/quiltt/quiltt-js/pull/378) [`0af4e66`](https://github.com/quiltt/quiltt-js/commit/0af4e6622d1542e0c0c02ac7e897e3e4f9219cbd) Thanks [@sirwolfgang](https://github.com/sirwolfgang)! - Add connector institution search and provider migration support.
8
+
9
+ ## New APIs
10
+
11
+ ### `useQuilttResolvable` Hook
12
+
13
+ Check if external provider institution IDs (e.g., Plaid) can be migrated to your connector.
14
+
15
+ ```typescript
16
+ import { useQuilttResolvable } from "@quiltt/react";
17
+ import { useEffect } from "react";
18
+
19
+ function ResolvableConnector({ plaidInstitutionId, children }) {
20
+ const { checkResolvable, isResolvable, isLoading } =
21
+ useQuilttResolvable("my-connector-id");
22
+
23
+ useEffect(() => {
24
+ checkResolvable({ plaid: plaidInstitutionId });
25
+ }, [plaidInstitutionId]);
26
+
27
+ if (isLoading) return <div>Checking...</div>;
28
+ if (!isResolvable) return null;
29
+
30
+ return <>{children}</>;
31
+ }
32
+
33
+ // Usage
34
+ <ResolvableConnector plaidInstitutionId="ins_3">
35
+ <QuilttButton connectorId="my-connector-id" />
36
+ </ResolvableConnector>;
37
+ ```
38
+
39
+ ### Patch Changes
40
+
41
+ - Updated dependencies [[`0af4e66`](https://github.com/quiltt/quiltt-js/commit/0af4e6622d1542e0c0c02ac7e897e3e4f9219cbd)]:
42
+ - @quiltt/core@4.4.0
43
+
44
+ ## 4.3.3
45
+
46
+ ### Patch Changes
47
+
48
+ - [#375](https://github.com/quiltt/quiltt-js/pull/375) [`fdc91e3`](https://github.com/quiltt/quiltt-js/commit/fdc91e3efb3f63659580f2d1d2ea0ff7fcaee8f5) Thanks [@sirwolfgang](https://github.com/sirwolfgang)! - Add 403 callback to Auth useIdentifySession
49
+
50
+ - Updated dependencies [[`fdc91e3`](https://github.com/quiltt/quiltt-js/commit/fdc91e3efb3f63659580f2d1d2ea0ff7fcaee8f5)]:
51
+ - @quiltt/core@4.3.3
52
+
3
53
  ## 4.3.2
4
54
 
5
55
  ### Patch Changes
@@ -7,7 +7,7 @@ import './useSession-12s-7GOn4sUn.js';
7
7
  import 'use-debounce';
8
8
  import { jsx } from 'react/jsx-runtime';
9
9
  import { ApolloProvider } from '@apollo/client/react/context/ApolloProvider.js';
10
- import { u as useQuilttSession } from './useQuilttSession-12s-CwVw-aOM.js';
10
+ import { u as useQuilttSession } from './useQuilttSession-12s-BCq3OL9S.js';
11
11
 
12
12
  const useAuthenticateSession = (auth, setSession)=>{
13
13
  const authenticateSession = useCallback(async (payload, callbacks)=>{
@@ -44,6 +44,9 @@ const useIdentifySession = (auth, setSession)=>{
44
44
  case 202:
45
45
  if (callbacks.onChallenged) return callbacks.onChallenged();
46
46
  break;
47
+ case 403:
48
+ if (callbacks.onForbidden) return callbacks.onForbidden();
49
+ break;
47
50
  case 422:
48
51
  if (callbacks.onError) return callbacks.onError(response.data);
49
52
  break;
package/dist/index.d.ts CHANGED
@@ -94,6 +94,7 @@ type IdentifySessionCallbacks = {
94
94
  onSuccess?: () => unknown;
95
95
  onChallenged?: () => unknown;
96
96
  onError?: (errors: UnprocessableData) => unknown;
97
+ onForbidden?: () => unknown;
97
98
  };
98
99
  type IdentifySession = (payload: UsernamePayload, callbacks: IdentifySessionCallbacks) => Promise<unknown>;
99
100
  type UseIdentifySession = (auth: AuthAPI, setSession: SetSession) => IdentifySession;
@@ -116,6 +117,20 @@ declare const useQuilttConnector: (connectorId?: string, options?: ConnectorSDKC
116
117
  open: () => void;
117
118
  };
118
119
 
120
+ type UseQuilttResolvable = (connectorId: string, onErrorCallback?: (msg: string) => void) => {
121
+ checkResolvable: (providerId: {
122
+ plaid?: string;
123
+ mock?: string;
124
+ mx?: string;
125
+ finicity?: string;
126
+ akoya?: string;
127
+ }) => Promise<boolean | null>;
128
+ isLoading: boolean;
129
+ isResolvable: boolean | null;
130
+ error: string | null;
131
+ };
132
+ declare const useQuilttResolvable: UseQuilttResolvable;
133
+
119
134
  type UseQuilttInstitutions = (connectorId: string, onErrorCallback?: (msg: string) => void) => {
120
135
  searchTerm: string;
121
136
  searchResults: InstitutionsData;
@@ -181,5 +196,5 @@ declare const QuilttSettingsProvider: FC<QuilttSettingsProviderProps>;
181
196
  type QuilttProviderProps = QuilttSettingsProviderProps & QuilttAuthProviderProps;
182
197
  declare const QuilttProvider: FC<QuilttProviderProps>;
183
198
 
184
- export { QuilttAuthProvider, QuilttButton, QuilttContainer, QuilttProvider, QuilttSettingsProvider, useAuthenticateSession, useEventListener, useIdentifySession, useImportSession, useIsomorphicLayoutEffect, useQuilttClient, useQuilttConnector, useQuilttInstitutions, useQuilttSession, useQuilttSettings, useRevokeSession, useSession, useStorage };
185
- export type { AuthenticateSession, IdentifySession, ImportSession, QuilttAuthProviderProps, QuilttSettingsProviderProps, RevokeSession, SetSession, UseQuilttInstitutions, UseQuilttSession };
199
+ export { QuilttAuthProvider, QuilttButton, QuilttContainer, QuilttProvider, QuilttSettingsProvider, useAuthenticateSession, useEventListener, useIdentifySession, useImportSession, useIsomorphicLayoutEffect, useQuilttClient, useQuilttConnector, useQuilttInstitutions, useQuilttResolvable, useQuilttSession, useQuilttSettings, useRevokeSession, useSession, useStorage };
200
+ export type { AuthenticateSession, IdentifySession, ImportSession, QuilttAuthProviderProps, QuilttSettingsProviderProps, RevokeSession, SetSession, UseQuilttInstitutions, UseQuilttResolvable, UseQuilttSession };
package/dist/index.js CHANGED
@@ -1,14 +1,15 @@
1
1
  export * from '@quiltt/core';
2
2
  import { jsx } from 'react/jsx-runtime';
3
3
  import { useRef, useEffect } from 'react';
4
- import { u as useQuilttConnector } from './useQuilttConnector-12s-BJljrsWT.js';
5
- import { i as isDeepEqual, Q as QuilttAuthProvider } from './QuilttAuthProvider-12s-D-Wr7LUT.js';
6
- export { b as useAuthenticateSession, a as useIdentifySession, u as useImportSession, c as useRevokeSession } from './QuilttAuthProvider-12s-D-Wr7LUT.js';
4
+ import { u as useQuilttConnector } from './useQuilttConnector-12s-BiIbmt7I.js';
5
+ import { i as isDeepEqual, Q as QuilttAuthProvider } from './QuilttAuthProvider-12s-4hQ7iysR.js';
6
+ export { b as useAuthenticateSession, a as useIdentifySession, u as useImportSession, c as useRevokeSession } from './QuilttAuthProvider-12s-4hQ7iysR.js';
7
7
  export { u as useEventListener } from './useEventListener-12s-D_-6QIXa.js';
8
8
  export { u as useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect-12s-DeTHOKz1.js';
9
9
  export { u as useQuilttClient } from './useQuilttClient-12s-CAAUait1.js';
10
- export { u as useQuilttInstitutions } from './useQuilttInstitutions-12s-PJd2C3BF.js';
11
- export { u as useQuilttSession } from './useQuilttSession-12s-CwVw-aOM.js';
10
+ export { u as useQuilttResolvable } from './useQuilttResolvable-12s-C2mjy5zs.js';
11
+ export { u as useQuilttInstitutions } from './useQuilttInstitutions-12s-0_y37UHg.js';
12
+ export { u as useQuilttSession } from './useQuilttSession-12s-BCq3OL9S.js';
12
13
  export { u as useQuilttSettings } from './useQuilttSettings-12s--rCJoNHD.js';
13
14
  export { u as useSession } from './useSession-12s-7GOn4sUn.js';
14
15
  export { u as useStorage } from './useStorage-12s-DHcq3Kuh.js';
@@ -1,11 +1,11 @@
1
1
  'use client';
2
2
  import { useState, useRef, useEffect, useCallback } from 'react';
3
3
  import { cdnBase } from '@quiltt/core';
4
- import { u as useQuilttSession } from './useQuilttSession-12s-CwVw-aOM.js';
4
+ import { u as useQuilttSession } from './useQuilttSession-12s-BCq3OL9S.js';
5
5
  import { u as useScript } from './useScript-12s-JCgaTW9n.js';
6
- import { i as isDeepEqual } from './QuilttAuthProvider-12s-D-Wr7LUT.js';
6
+ import { i as isDeepEqual } from './QuilttAuthProvider-12s-4hQ7iysR.js';
7
7
 
8
- var version = "4.3.2";
8
+ var version = "4.4.0";
9
9
 
10
10
  const useQuilttConnector = (connectorId, options)=>{
11
11
  const status = useScript(`${cdnBase}/v1/connector.js?agent=react-${version}`, {
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
  import { useMemo, useState, useRef, useEffect, useCallback } from 'react';
3
- import { InstitutionsAPI } from '@quiltt/core';
3
+ import { ConnectorsAPI } from '@quiltt/core';
4
4
  import { useDebounce } from 'use-debounce';
5
- import { v as version } from './useQuilttConnector-12s-BJljrsWT.js';
5
+ import { v as version } from './useQuilttConnector-12s-BiIbmt7I.js';
6
6
  import { u as useSession } from './useSession-12s-7GOn4sUn.js';
7
7
 
8
8
  const useQuilttInstitutions = (connectorId, onErrorCallback)=>{
@@ -18,7 +18,7 @@ const useQuilttInstitutions = (connectorId, onErrorCallback)=>{
18
18
  typeof navigator !== 'undefined');
19
19
  return isReactNative ? `react-native-${version}` : `react-${version}`;
20
20
  }, []);
21
- const institutionsAPI = useMemo(()=>new InstitutionsAPI(connectorId, agent), [
21
+ const connectorsAPI = useMemo(()=>new ConnectorsAPI(connectorId, agent), [
22
22
  connectorId,
23
23
  agent
24
24
  ]);
@@ -58,7 +58,7 @@ const useQuilttInstitutions = (connectorId, onErrorCallback)=>{
58
58
  return;
59
59
  }
60
60
  const abortController = new AbortController();
61
- institutionsAPI.search(session?.token, connectorId, searchTerm, abortController.signal).then((response)=>{
61
+ connectorsAPI.searchInstitutions(session?.token, connectorId, searchTerm, abortController.signal).then((response)=>{
62
62
  if (!abortController.signal.aborted) {
63
63
  if (response.status === 200) {
64
64
  setSearchResults(response.data);
@@ -78,7 +78,7 @@ const useQuilttInstitutions = (connectorId, onErrorCallback)=>{
78
78
  session?.token,
79
79
  connectorId,
80
80
  searchTerm,
81
- institutionsAPI,
81
+ connectorsAPI,
82
82
  handleError
83
83
  ]);
84
84
  return {
@@ -0,0 +1,79 @@
1
+ 'use client';
2
+ import { useMemo, useState, useCallback } from 'react';
3
+ import { ConnectorsAPI } from '@quiltt/core';
4
+ import { v as version } from './useQuilttConnector-12s-BiIbmt7I.js';
5
+ import { u as useSession } from './useSession-12s-7GOn4sUn.js';
6
+
7
+ const useQuilttResolvable = (connectorId, onErrorCallback)=>{
8
+ const agent = useMemo(()=>{
9
+ // Try deprecated navigator.product first (still used in some RN versions)
10
+ if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
11
+ return `react-native-${version}`;
12
+ }
13
+ // Detect React Native by its unique environment characteristics
14
+ const isReactNative = !!// Has window (unlike Node.js)
15
+ (typeof window !== 'undefined' && // No document in window (unlike browsers)
16
+ typeof window.document === 'undefined' && // Has navigator (unlike Node.js)
17
+ typeof navigator !== 'undefined');
18
+ return isReactNative ? `react-native-${version}` : `react-${version}`;
19
+ }, []);
20
+ const connectorsAPI = useMemo(()=>new ConnectorsAPI(connectorId, agent), [
21
+ connectorId,
22
+ agent
23
+ ]);
24
+ const [session] = useSession();
25
+ const [isLoading, setIsLoading] = useState(false);
26
+ const [isResolvable, setIsResolvable] = useState(null);
27
+ const [error, setError] = useState(null);
28
+ const handleError = useCallback((message)=>{
29
+ const errorMessage = message || 'Unknown error occurred while checking resolvability';
30
+ setError(errorMessage);
31
+ console.error('Quiltt Connector Resolvable Error:', errorMessage);
32
+ if (onErrorCallback) onErrorCallback(errorMessage);
33
+ }, [
34
+ onErrorCallback
35
+ ]);
36
+ const checkResolvable = useCallback(async (providerId)=>{
37
+ if (!session?.token || !connectorId) {
38
+ handleError('Missing session token or connector ID');
39
+ return null;
40
+ }
41
+ const hasProviderId = Object.values(providerId).some((id)=>!!id);
42
+ if (!hasProviderId) {
43
+ handleError('No provider ID specified');
44
+ return null;
45
+ }
46
+ setIsLoading(true);
47
+ setError(null);
48
+ try {
49
+ const response = await connectorsAPI.checkResolvable(session.token, connectorId, providerId);
50
+ if (response.status === 200) {
51
+ const result = response.data.resolvable;
52
+ setIsResolvable(result);
53
+ return result;
54
+ }
55
+ handleError(response.data.message || 'Failed to check resolvability');
56
+ setIsResolvable(null);
57
+ return null;
58
+ } catch (error) {
59
+ handleError(error?.message);
60
+ setIsResolvable(null);
61
+ return null;
62
+ } finally{
63
+ setIsLoading(false);
64
+ }
65
+ }, [
66
+ session?.token,
67
+ connectorId,
68
+ connectorsAPI,
69
+ handleError
70
+ ]);
71
+ return {
72
+ checkResolvable,
73
+ isLoading,
74
+ isResolvable,
75
+ error
76
+ };
77
+ };
78
+
79
+ export { useQuilttResolvable as u };
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { useCallback } from 'react';
3
3
  import { AuthAPI } from '@quiltt/core';
4
- import { u as useImportSession, a as useIdentifySession, b as useAuthenticateSession, c as useRevokeSession } from './QuilttAuthProvider-12s-D-Wr7LUT.js';
4
+ import { u as useImportSession, a as useIdentifySession, b as useAuthenticateSession, c as useRevokeSession } from './QuilttAuthProvider-12s-4hQ7iysR.js';
5
5
  import { u as useQuilttSettings } from './useQuilttSettings-12s--rCJoNHD.js';
6
6
  import { u as useSession } from './useSession-12s-7GOn4sUn.js';
7
7
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quiltt/react",
3
- "version": "4.3.2",
3
+ "version": "4.4.0",
4
4
  "description": "React Components and Hooks for Quiltt Connector",
5
5
  "keywords": [
6
6
  "quiltt",
@@ -36,7 +36,7 @@
36
36
  "dependencies": {
37
37
  "@apollo/client": "^3.14.0",
38
38
  "use-debounce": "^10.0.4",
39
- "@quiltt/core": "4.3.2"
39
+ "@quiltt/core": "4.4.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@biomejs/biome": "2.2.4",
@@ -2,6 +2,7 @@ export * from './helpers'
2
2
  export * from './session'
3
3
  export * from './useQuilttClient'
4
4
  export * from './useQuilttConnector'
5
+ export * from './useQuilttResolvable'
5
6
  export * from './useQuilttInstitutions'
6
7
  export * from './useQuilttSession'
7
8
  export * from './useQuilttSettings'
@@ -14,6 +14,7 @@ type IdentifySessionCallbacks = {
14
14
  onSuccess?: () => unknown
15
15
  onChallenged?: () => unknown
16
16
  onError?: (errors: UnprocessableData) => unknown
17
+ onForbidden?: () => unknown
17
18
  }
18
19
  export type IdentifySession = (
19
20
  payload: UsernamePayload,
@@ -37,6 +38,10 @@ export const useIdentifySession: UseIdentifySession = (auth, setSession) => {
37
38
  if (callbacks.onChallenged) return callbacks.onChallenged()
38
39
  break
39
40
 
41
+ case 403: // Forbidden (signups disabled)
42
+ if (callbacks.onForbidden) return callbacks.onForbidden()
43
+ break
44
+
40
45
  case 422: // Unprocessable Content
41
46
  if (callbacks.onError) return callbacks.onError((response as UnprocessableResponse).data)
42
47
  break
@@ -3,7 +3,7 @@
3
3
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
4
4
 
5
5
  import type { ErrorData, InstitutionsData } from '@quiltt/core'
6
- import { InstitutionsAPI } from '@quiltt/core'
6
+ import { ConnectorsAPI } from '@quiltt/core'
7
7
  import { useDebounce } from 'use-debounce'
8
8
 
9
9
  import { version } from '../version'
@@ -41,10 +41,7 @@ export const useQuilttInstitutions: UseQuilttInstitutions = (connectorId, onErro
41
41
  return isReactNative ? `react-native-${version}` : `react-${version}`
42
42
  }, [])
43
43
 
44
- const institutionsAPI = useMemo(
45
- () => new InstitutionsAPI(connectorId, agent),
46
- [connectorId, agent]
47
- )
44
+ const connectorsAPI = useMemo(() => new ConnectorsAPI(connectorId, agent), [connectorId, agent])
48
45
  const [session] = useSession()
49
46
 
50
47
  const [searchTermInput, setSearchTermInput] = useState('')
@@ -93,8 +90,8 @@ export const useQuilttInstitutions: UseQuilttInstitutions = (connectorId, onErro
93
90
 
94
91
  const abortController = new AbortController()
95
92
 
96
- institutionsAPI
97
- .search(session?.token, connectorId, searchTerm, abortController.signal)
93
+ connectorsAPI
94
+ .searchInstitutions(session?.token, connectorId, searchTerm, abortController.signal)
98
95
  .then((response) => {
99
96
  if (!abortController.signal.aborted) {
100
97
  if (response.status === 200) {
@@ -113,7 +110,7 @@ export const useQuilttInstitutions: UseQuilttInstitutions = (connectorId, onErro
113
110
  })
114
111
 
115
112
  return () => abortController.abort()
116
- }, [session?.token, connectorId, searchTerm, institutionsAPI, handleError])
113
+ }, [session?.token, connectorId, searchTerm, connectorsAPI, handleError])
117
114
 
118
115
  return {
119
116
  searchTerm,
@@ -0,0 +1,127 @@
1
+ 'use client'
2
+
3
+ import { useCallback, useMemo, useState } from 'react'
4
+
5
+ import type { ErrorData, ResolvableData } from '@quiltt/core'
6
+ import { ConnectorsAPI } from '@quiltt/core'
7
+
8
+ import { version } from '../version'
9
+ import useSession from './useSession'
10
+
11
+ export type UseQuilttResolvable = (
12
+ connectorId: string,
13
+ onErrorCallback?: (msg: string) => void,
14
+ ) => {
15
+ checkResolvable: (providerId: {
16
+ plaid?: string
17
+ mock?: string
18
+ mx?: string
19
+ finicity?: string
20
+ akoya?: string
21
+ }) => Promise<boolean | null>
22
+ isLoading: boolean
23
+ isResolvable: boolean | null
24
+ error: string | null
25
+ }
26
+
27
+ export const useQuilttResolvable: UseQuilttResolvable = (
28
+ connectorId,
29
+ onErrorCallback,
30
+ ) => {
31
+ const agent = useMemo(() => {
32
+ // Try deprecated navigator.product first (still used in some RN versions)
33
+ if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
34
+ return `react-native-${version}`
35
+ }
36
+
37
+ // Detect React Native by its unique environment characteristics
38
+ const isReactNative = !!(
39
+ // Has window (unlike Node.js)
40
+ (
41
+ typeof window !== 'undefined' &&
42
+ // No document in window (unlike browsers)
43
+ typeof window.document === 'undefined' &&
44
+ // Has navigator (unlike Node.js)
45
+ typeof navigator !== 'undefined'
46
+ )
47
+ )
48
+
49
+ return isReactNative ? `react-native-${version}` : `react-${version}`
50
+ }, [])
51
+
52
+ const connectorsAPI = useMemo(() => new ConnectorsAPI(connectorId, agent), [connectorId, agent])
53
+ const [session] = useSession()
54
+
55
+ const [isLoading, setIsLoading] = useState(false)
56
+ const [isResolvable, setIsResolvable] = useState<boolean | null>(null)
57
+ const [error, setError] = useState<string | null>(null)
58
+
59
+ const handleError = useCallback(
60
+ (message: string) => {
61
+ const errorMessage = message || 'Unknown error occurred while checking resolvability'
62
+
63
+ setError(errorMessage)
64
+ console.error('Quiltt Connector Resolvable Error:', errorMessage)
65
+ if (onErrorCallback) onErrorCallback(errorMessage)
66
+ },
67
+ [onErrorCallback],
68
+ )
69
+
70
+ const checkResolvable = useCallback(
71
+ async (providerId: {
72
+ plaid?: string
73
+ mock?: string
74
+ mx?: string
75
+ finicity?: string
76
+ akoya?: string
77
+ }): Promise<boolean | null> => {
78
+ if (!session?.token || !connectorId) {
79
+ handleError('Missing session token or connector ID')
80
+ return null
81
+ }
82
+
83
+ const hasProviderId = Object.values(providerId).some((id) => !!id)
84
+ if (!hasProviderId) {
85
+ handleError('No provider ID specified')
86
+ return null
87
+ }
88
+
89
+ setIsLoading(true)
90
+ setError(null)
91
+
92
+ try {
93
+ const response = await connectorsAPI.checkResolvable(
94
+ session.token,
95
+ connectorId,
96
+ providerId,
97
+ )
98
+
99
+ if (response.status === 200) {
100
+ const result = (response.data as ResolvableData).resolvable
101
+ setIsResolvable(result)
102
+ return result
103
+ }
104
+
105
+ handleError((response.data as ErrorData).message || 'Failed to check resolvability')
106
+ setIsResolvable(null)
107
+ return null
108
+ } catch (error: any) {
109
+ handleError(error?.message)
110
+ setIsResolvable(null)
111
+ return null
112
+ } finally {
113
+ setIsLoading(false)
114
+ }
115
+ },
116
+ [session?.token, connectorId, connectorsAPI, handleError],
117
+ )
118
+
119
+ return {
120
+ checkResolvable,
121
+ isLoading,
122
+ isResolvable,
123
+ error,
124
+ }
125
+ }
126
+
127
+ export default useQuilttResolvable