@quiltt/react-native 3.3.1 → 3.3.3

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
+ ## 3.3.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 48a50d0: Fix handle plaid oauth link bug
8
+ - Updated dependencies [48a50d0]
9
+ - @quiltt/core@3.3.3
10
+ - @quiltt/react@3.3.3
11
+
12
+ ## 3.3.2
13
+
14
+ ### Patch Changes
15
+
16
+ - 4a9118b: React Native sdk to support Plaid Oauth url
17
+ - Updated dependencies [4a9118b]
18
+ - @quiltt/core@3.3.2
19
+ - @quiltt/react@3.3.2
20
+
3
21
  ## 3.3.1
4
22
 
5
23
  ### Patch Changes
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var h=Object.defineProperty;var W=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var L=Object.prototype.hasOwnProperty;var Q=(r,a)=>{for(var s in a)h(r,s,{get:a[s],enumerable:!0})},T=(r,a,s,t)=>{if(a&&typeof a=="object"||typeof a=="function")for(let c of D(a))!L.call(r,c)&&c!==s&&h(r,c,{get:()=>a[c],enumerable:!(t=W(a,c))||t.enumerable});return r};var K=r=>T(h({},"__esModule",{value:!0}),r);var M={};Q(M,{QuilttConnector:()=>k,default:()=>j});module.exports=K(M);var F=require("core-js/stable/atob"),G=require("core-js/stable/url");var p=require("@quiltt/core"),n=require("react"),y=require("react-native"),A=require("react-native-webview");var l=require("react-native"),C=require("react/jsx-runtime"),g=({children:r})=>(0,C.jsx)(l.SafeAreaView,{style:U.AndroidSafeArea,children:r}),U=l.StyleSheet.create({AndroidSafeArea:{flex:1,backgroundColor:"white",paddingTop:l.Platform.OS==="android"?l.StatusBar.currentHeight:0}});var P=require("@quiltt/react"),w=require("react/jsx-runtime"),$=({connectorId:r,connectionId:a,oauthRedirectUrl:s,onEvent:t,onLoad:c,onExit:i,onExitSuccess:u,onExitAbort:m,onExitError:f})=>{let S=(0,n.useRef)(null),{session:d}=(0,P.useQuilttSession)();s=encodeURIComponent(s);let R=`https://${r}.quiltt.app/?mode=webview&oauth_redirect_url=${s}&sdk=react-native`,V=(0,n.useCallback)(()=>{var e;let o=` const options = { source: 'quiltt', type: 'Options', token: '${d==null?void 0:d.token}', connectorId: '${r}', connectionId: '${a}', }; const compactedOptions = Object.keys(options).reduce((acc, key) => { if (options[key] !== 'undefined') { acc[key] = options[key]; } return acc; }, {}); window.postMessage(compactedOptions); `;(e=S.current)==null||e.injectJavaScript(o)},[a,r,d==null?void 0:d.token]),q=o=>{let e=new URL(o.url);return e.protocol==="quilttconnector:"?(O(e),!1):!0},b=()=>{var e;let o="localStorage.clear();";(e=S.current)==null||e.injectJavaScript(o)},O=o=>{o.searchParams.delete("source"),o.searchParams.append("connectorId",r);let e=Object.fromEntries(o.searchParams);switch(o.host){case"Load":V(),t==null||t(p.ConnectorSDKEventType.Load,e),c==null||c(e);break;case"ExitAbort":b(),t==null||t(p.ConnectorSDKEventType.ExitAbort,e),i==null||i(p.ConnectorSDKEventType.ExitAbort,e),m==null||m(e);break;case"ExitError":b(),t==null||t(p.ConnectorSDKEventType.ExitError,e),i==null||i(p.ConnectorSDKEventType.ExitError,e),f==null||f(e);break;case"ExitSuccess":b(),t==null||t(p.ConnectorSDKEventType.ExitSuccess,e),i==null||i(p.ConnectorSDKEventType.ExitSuccess,e),u==null||u(e);break;case"OauthRequested":y.Linking.openURL(o.searchParams.get("oauthUrl"));break;default:console.log("unhandled event",o);break}};return(0,w.jsx)(g,{children:(0,w.jsx)(A.WebView,{ref:S,originWhitelist:["https://*","quilttconnector://*"],source:{uri:R},onShouldStartLoadWithRequest:q,javaScriptEnabled:!0,domStorageEnabled:!0,webviewDebuggingEnabled:!0})})},k=$;var j=k;0&&(module.exports={QuilttConnector});
1
+ "use strict";var b=Object.defineProperty;var Q=Object.getOwnPropertyDescriptor;var T=Object.getOwnPropertyNames;var $=Object.prototype.hasOwnProperty;var K=(a,o)=>{for(var c in o)b(a,c,{get:o[c],enumerable:!0})},j=(a,o,c,r)=>{if(o&&typeof o=="object"||typeof o=="function")for(let s of T(o))!$.call(a,s)&&s!==c&&b(a,s,{get:()=>o[s],enumerable:!(r=Q(o,s))||r.enumerable});return a};var M=a=>j(b({},"__esModule",{value:!0}),a);var C=(a,o,c)=>new Promise((r,s)=>{var i=l=>{try{d(c.next(l))}catch(u){s(u)}},m=l=>{try{d(c.throw(l))}catch(u){s(u)}},d=l=>l.done?r(l.value):Promise.resolve(l.value).then(i,m);d((c=c.apply(a,o)).next())});var _={};K(_,{QuilttConnector:()=>g,default:()=>H});module.exports=M(_);var v=require("core-js/stable/atob"),x=require("core-js/stable/url");var n=require("@quiltt/core"),h=require("react"),k=require("react-native"),q=require("react-native-webview");var p=require("react-native"),R=require("react/jsx-runtime"),A=({children:a})=>(0,R.jsx)(p.SafeAreaView,{style:I.AndroidSafeArea,children:a}),I=p.StyleSheet.create({AndroidSafeArea:{flex:1,backgroundColor:"white",paddingTop:p.Platform.OS==="android"?p.StatusBar.currentHeight:0}});var L=require("@quiltt/react");var w=require("react/jsx-runtime"),J=({connectorId:a,connectionId:o,oauthRedirectUrl:c,onEvent:r,onLoad:s,onExit:i,onExitSuccess:m,onExitAbort:d,onExitError:l})=>{let u=(0,h.useRef)(null),{session:f}=(0,L.useQuilttSession)();c=encodeURIComponent(c);let O=`https://${a}.quiltt.app/?mode=webview&oauth_redirect_url=${c}&sdk=react-native`,P=(0,h.useCallback)(()=>{var e;let t=` const options = { source: 'quiltt', type: 'Options', token: '${f==null?void 0:f.token}', connectorId: '${a}', connectionId: '${o}', }; const compactedOptions = Object.keys(options).reduce((acc, key) => { if (options[key] !== 'undefined') { acc[key] = options[key]; } return acc; }, {}); window.postMessage(compactedOptions); `;(e=u.current)==null||e.injectJavaScript(t)},[o,a,f==null?void 0:f.token]),U=["quiltt.app","quiltt.dev","moneydesktop.com","cdn.plaid.com/link/v2/stable/link.html"],V=t=>U.some(e=>t.href.includes(e)),W=t=>{let e=new URL(t.url);return V(e)?!0:e.protocol==="quilttconnector:"?(D(e),!1):(y(e),!1)},S=()=>{var e;let t="localStorage.clear();";(e=u.current)==null||e.injectJavaScript(t)},D=t=>{t.searchParams.delete("source"),t.searchParams.append("connectorId",a);let e=Object.fromEntries(t.searchParams);switch(t.host){case"Load":P(),r==null||r(n.ConnectorSDKEventType.Load,e),s==null||s(e);break;case"ExitAbort":S(),r==null||r(n.ConnectorSDKEventType.ExitAbort,e),i==null||i(n.ConnectorSDKEventType.ExitAbort,e),d==null||d(e);break;case"ExitError":S(),r==null||r(n.ConnectorSDKEventType.ExitError,e),i==null||i(n.ConnectorSDKEventType.ExitError,e),l==null||l(e);break;case"ExitSuccess":S(),r==null||r(n.ConnectorSDKEventType.ExitSuccess,e),i==null||i(n.ConnectorSDKEventType.ExitSuccess,e),m==null||m(e);break;case"Authenticate":break;case"OauthRequested":y(new URL(t.searchParams.get("oauthUrl")));break;default:console.log("unhandled event",t);break}},y=t=>C(void 0,null,function*(){if(t.protocol!=="https:"){console.log(`handleOAuthUrl - Skipping non https url - ${t.href}`);return}(yield k.Linking.canOpenURL(t.href))&&k.Linking.openURL(t.href)});return(0,w.jsx)(A,{children:(0,w.jsx)(q.WebView,{ref:u,originWhitelist:["https://*","quilttconnector://*"],source:{uri:O},onShouldStartLoadWithRequest:W,javaScriptEnabled:!0,domStorageEnabled:!0,webviewDebuggingEnabled:!0})})},g=J;var H=g;0&&(module.exports={QuilttConnector});
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/QuilttConnector.tsx","../src/components/AndroidSafeAreaView.tsx"],"sourcesContent":["// Hermes doesn't have atob\n// https://github.com/facebook/hermes/issues/1178\nimport 'core-js/stable/atob'\n// React Native's URL implementation is incomplete\n// https://github.com/facebook/react-native/issues/16434\nimport 'core-js/stable/url'\nimport QuilttConnector from './components/QuilttConnector'\n\nexport { QuilttConnector }\nexport default QuilttConnector\n","import {\n ConnectorSDKCallbackMetadata,\n ConnectorSDKCallbacks,\n ConnectorSDKEventType,\n} from '@quiltt/core'\nimport { useCallback, useRef } from 'react'\nimport { Linking } from 'react-native'\nimport { WebView } from 'react-native-webview'\nimport { AndroidSafeAreaView } from './AndroidSafeAreaView'\nimport type { ShouldStartLoadRequest } from 'react-native-webview/lib/WebViewTypes'\nimport { useQuilttSession } from '@quiltt/react'\n\ntype QuilttConnectorProps = {\n connectorId: string\n connectionId?: string\n oauthRedirectUrl: string\n} & ConnectorSDKCallbacks\n\nexport const QuilttConnector = ({\n connectorId,\n connectionId,\n oauthRedirectUrl,\n onEvent,\n onLoad,\n onExit,\n onExitSuccess,\n onExitAbort,\n onExitError,\n}: QuilttConnectorProps) => {\n const webViewRef = useRef<WebView>(null)\n const { session } = useQuilttSession()\n oauthRedirectUrl = encodeURIComponent(oauthRedirectUrl)\n const connectorUrl = `https://${connectorId}.quiltt.app/?mode=webview&oauth_redirect_url=${oauthRedirectUrl}&sdk=react-native` // @todo append version from package.json\n\n const initInjectedJavaScript = useCallback(() => {\n const script = `\\\n const options = {\\\n source: 'quiltt',\\\n type: 'Options',\\\n token: '${session?.token}',\\\n connectorId: '${connectorId}',\\\n connectionId: '${connectionId}',\\\n };\\\n const compactedOptions = Object.keys(options).reduce((acc, key) => {\\\n if (options[key] !== 'undefined') {\\\n acc[key] = options[key];\\\n }\\\n return acc;\\\n }, {});\\\n window.postMessage(compactedOptions);\\\n `\n webViewRef.current?.injectJavaScript(script)\n }, [connectionId, connectorId, session?.token])\n\n const eventHandler = (request: ShouldStartLoadRequest) => {\n const url = new URL(request.url)\n if (url.protocol === 'quilttconnector:') {\n handleQuilttEvent(url)\n return false\n }\n return true\n }\n\n const clearLocalStorage = () => {\n const script = 'localStorage.clear();'\n webViewRef.current?.injectJavaScript(script)\n }\n\n const handleQuilttEvent = (url: URL) => {\n url.searchParams.delete('source')\n url.searchParams.append('connectorId', connectorId)\n const metadata = Object.fromEntries(url.searchParams) as ConnectorSDKCallbackMetadata\n\n const eventType = url.host\n switch (eventType) {\n case 'Load':\n initInjectedJavaScript()\n onEvent?.(ConnectorSDKEventType.Load, metadata)\n onLoad?.(metadata)\n break\n case 'ExitAbort':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitAbort, metadata)\n onExit?.(ConnectorSDKEventType.ExitAbort, metadata)\n onExitAbort?.(metadata)\n break\n case 'ExitError':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitError, metadata)\n onExit?.(ConnectorSDKEventType.ExitError, metadata)\n onExitError?.(metadata)\n break\n case 'ExitSuccess':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitSuccess, metadata)\n onExit?.(ConnectorSDKEventType.ExitSuccess, metadata)\n onExitSuccess?.(metadata)\n break\n case 'OauthRequested':\n Linking.openURL(url.searchParams.get('oauthUrl') as string)\n break\n default:\n console.log('unhandled event', url)\n break\n }\n }\n\n return (\n <AndroidSafeAreaView>\n <WebView\n ref={webViewRef}\n originWhitelist={['https://*', 'quilttconnector://*']} // Maybe relax this to *?\n source={{ uri: connectorUrl }}\n onShouldStartLoadWithRequest={eventHandler}\n javaScriptEnabled\n domStorageEnabled // To enable localStorage in Android webview\n webviewDebuggingEnabled // Not sure if this works\n />\n </AndroidSafeAreaView>\n )\n}\n\nexport default QuilttConnector\n","import { SafeAreaView, StyleSheet, Platform, StatusBar } from 'react-native'\nimport { PropsWithChildren } from 'react'\n\nexport const AndroidSafeAreaView = ({ children }: PropsWithChildren) => (\n <SafeAreaView style={styles.AndroidSafeArea}>{children}</SafeAreaView>\n)\n\nconst styles = StyleSheet.create({\n AndroidSafeArea: {\n flex: 1,\n backgroundColor: 'white',\n paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0,\n },\n})\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,qBAAAE,EAAA,YAAAC,IAAA,eAAAC,EAAAJ,GAEA,IAAAK,EAAO,+BAGPC,EAAO,8BCLP,IAAAC,EAIO,wBACPC,EAAoC,iBACpCC,EAAwB,wBACxBC,EAAwB,gCCPxB,IAAAC,EAA8D,wBAI5DC,EAAA,6BADWC,EAAsB,CAAC,CAAE,SAAAC,CAAS,OAC7C,OAAC,gBAAa,MAAOC,EAAO,gBAAkB,SAAAD,EAAS,EAGnDC,EAAS,aAAW,OAAO,CAC/B,gBAAiB,CACf,KAAM,EACN,gBAAiB,QACjB,WAAY,WAAS,KAAO,UAAY,YAAU,cAAgB,CACpE,CACF,CAAC,EDHD,IAAAC,EAAiC,yBAmG3BC,EAAA,6BA3FOC,EAAkB,CAAC,CAC9B,YAAAC,EACA,aAAAC,EACA,iBAAAC,EACA,QAAAC,EACA,OAAAC,EACA,OAAAC,EACA,cAAAC,EACA,YAAAC,EACA,YAAAC,CACF,IAA4B,CAC1B,IAAMC,KAAa,UAAgB,IAAI,EACjC,CAAE,QAAAC,CAAQ,KAAI,oBAAiB,EACrCR,EAAmB,mBAAmBA,CAAgB,EACtD,IAAMS,EAAe,WAAWX,iDAA2DE,qBAErFU,KAAyB,eAAY,IAAM,CAlCnD,IAAAC,EAmCI,IAAMC,EAAS,2FAIDJ,GAAA,YAAAA,EAAS,gCACHV,6BACCC,8PAUrBY,EAAAJ,EAAW,UAAX,MAAAI,EAAoB,iBAAiBC,EACvC,EAAG,CAACb,EAAcD,EAAaU,GAAA,YAAAA,EAAS,KAAK,CAAC,EAExCK,EAAgBC,GAAoC,CACxD,IAAMC,EAAM,IAAI,IAAID,EAAQ,GAAG,EAC/B,OAAIC,EAAI,WAAa,oBACnBC,EAAkBD,CAAG,EACd,IAEF,EACT,EAEME,EAAoB,IAAM,CA/DlC,IAAAN,EAgEI,IAAMC,EAAS,yBACfD,EAAAJ,EAAW,UAAX,MAAAI,EAAoB,iBAAiBC,EACvC,EAEMI,EAAqBD,GAAa,CACtCA,EAAI,aAAa,OAAO,QAAQ,EAChCA,EAAI,aAAa,OAAO,cAAejB,CAAW,EAClD,IAAMoB,EAAW,OAAO,YAAYH,EAAI,YAAY,EAGpD,OADkBA,EAAI,KACH,CACjB,IAAK,OACHL,EAAuB,EACvBT,GAAA,MAAAA,EAAU,wBAAsB,KAAMiB,GACtChB,GAAA,MAAAA,EAASgB,GACT,MACF,IAAK,YACHD,EAAkB,EAClBhB,GAAA,MAAAA,EAAU,wBAAsB,UAAWiB,GAC3Cf,GAAA,MAAAA,EAAS,wBAAsB,UAAWe,GAC1Cb,GAAA,MAAAA,EAAca,GACd,MACF,IAAK,YACHD,EAAkB,EAClBhB,GAAA,MAAAA,EAAU,wBAAsB,UAAWiB,GAC3Cf,GAAA,MAAAA,EAAS,wBAAsB,UAAWe,GAC1CZ,GAAA,MAAAA,EAAcY,GACd,MACF,IAAK,cACHD,EAAkB,EAClBhB,GAAA,MAAAA,EAAU,wBAAsB,YAAaiB,GAC7Cf,GAAA,MAAAA,EAAS,wBAAsB,YAAae,GAC5Cd,GAAA,MAAAA,EAAgBc,GAChB,MACF,IAAK,iBACH,UAAQ,QAAQH,EAAI,aAAa,IAAI,UAAU,CAAW,EAC1D,MACF,QACE,QAAQ,IAAI,kBAAmBA,CAAG,EAClC,KACJ,CACF,EAEA,SACE,OAACI,EAAA,CACC,mBAAC,WACC,IAAKZ,EACL,gBAAiB,CAAC,YAAa,qBAAqB,EACpD,OAAQ,CAAE,IAAKE,CAAa,EAC5B,6BAA8BI,EAC9B,kBAAiB,GACjB,kBAAiB,GACjB,wBAAuB,GACzB,EACF,CAEJ,EAEOO,EAAQvB,EDjHf,IAAOwB,EAAQC","names":["src_exports","__export","QuilttConnector_default","src_default","__toCommonJS","import_atob","import_url","import_core","import_react","import_react_native","import_react_native_webview","import_react_native","import_jsx_runtime","AndroidSafeAreaView","children","styles","import_react","import_jsx_runtime","QuilttConnector","connectorId","connectionId","oauthRedirectUrl","onEvent","onLoad","onExit","onExitSuccess","onExitAbort","onExitError","webViewRef","session","connectorUrl","initInjectedJavaScript","_a","script","eventHandler","request","url","handleQuilttEvent","clearLocalStorage","metadata","AndroidSafeAreaView","QuilttConnector_default","src_default","QuilttConnector_default"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/components/QuilttConnector.tsx","../src/components/AndroidSafeAreaView.tsx"],"sourcesContent":["// Hermes doesn't have atob\n// https://github.com/facebook/hermes/issues/1178\nimport 'core-js/stable/atob'\n// React Native's URL implementation is incomplete\n// https://github.com/facebook/react-native/issues/16434\nimport 'core-js/stable/url'\nimport QuilttConnector from './components/QuilttConnector'\n\nexport { QuilttConnector }\nexport default QuilttConnector\n","import {\n ConnectorSDKCallbackMetadata,\n ConnectorSDKCallbacks,\n ConnectorSDKEventType,\n} from '@quiltt/core'\nimport { useCallback, useRef } from 'react'\nimport { Linking } from 'react-native'\nimport { WebView } from 'react-native-webview'\nimport { AndroidSafeAreaView } from './AndroidSafeAreaView'\nimport type { ShouldStartLoadRequest } from 'react-native-webview/lib/WebViewTypes'\nimport { useQuilttSession } from '@quiltt/react'\n\ntype QuilttConnectorProps = {\n connectorId: string\n connectionId?: string\n oauthRedirectUrl: string\n} & ConnectorSDKCallbacks\n\nexport const QuilttConnector = ({\n connectorId,\n connectionId,\n oauthRedirectUrl,\n onEvent,\n onLoad,\n onExit,\n onExitSuccess,\n onExitAbort,\n onExitError,\n}: QuilttConnectorProps) => {\n const webViewRef = useRef<WebView>(null)\n const { session } = useQuilttSession()\n oauthRedirectUrl = encodeURIComponent(oauthRedirectUrl)\n const connectorUrl = `https://${connectorId}.quiltt.app/?mode=webview&oauth_redirect_url=${oauthRedirectUrl}&sdk=react-native` // @todo append version from package.json\n\n const initInjectedJavaScript = useCallback(() => {\n const script = `\\\n const options = {\\\n source: 'quiltt',\\\n type: 'Options',\\\n token: '${session?.token}',\\\n connectorId: '${connectorId}',\\\n connectionId: '${connectionId}',\\\n };\\\n const compactedOptions = Object.keys(options).reduce((acc, key) => {\\\n if (options[key] !== 'undefined') {\\\n acc[key] = options[key];\\\n }\\\n return acc;\\\n }, {});\\\n window.postMessage(compactedOptions);\\\n `\n webViewRef.current?.injectJavaScript(script)\n }, [connectionId, connectorId, session?.token])\n\n // allowedListUrl & shouldRender ensure we are only rendering Quiltt, MX and Plaid content in Webview\n // For other urls, we assume those are bank urls, which needs to be handle in external browser.\n // @todo Convert it to a list from Quiltt Server to prevent MX/ Plaid changes.\n const allowedListUrl = [\n 'quiltt.app',\n 'quiltt.dev',\n 'moneydesktop.com',\n 'cdn.plaid.com/link/v2/stable/link.html',\n ]\n const shouldRender = (url: URL) => allowedListUrl.some((href) => url.href.includes(href))\n\n const requestHandler = (request: ShouldStartLoadRequest) => {\n const url = new URL(request.url)\n if (shouldRender(url)) return true\n if (url.protocol === 'quilttconnector:') {\n handleQuilttEvent(url)\n return false\n }\n // Plaid set oauth url by doing window.location.href = url\n // This is the only way I know to handle this.\n handleOAuthUrl(url)\n return false\n }\n\n const clearLocalStorage = () => {\n const script = 'localStorage.clear();'\n webViewRef.current?.injectJavaScript(script)\n }\n\n const handleQuilttEvent = (url: URL) => {\n url.searchParams.delete('source')\n url.searchParams.append('connectorId', connectorId)\n const metadata = Object.fromEntries(url.searchParams) as ConnectorSDKCallbackMetadata\n\n const eventType = url.host\n switch (eventType) {\n case 'Load':\n initInjectedJavaScript()\n onEvent?.(ConnectorSDKEventType.Load, metadata)\n onLoad?.(metadata)\n break\n case 'ExitAbort':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitAbort, metadata)\n onExit?.(ConnectorSDKEventType.ExitAbort, metadata)\n onExitAbort?.(metadata)\n break\n case 'ExitError':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitError, metadata)\n onExit?.(ConnectorSDKEventType.ExitError, metadata)\n onExitError?.(metadata)\n break\n case 'ExitSuccess':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitSuccess, metadata)\n onExit?.(ConnectorSDKEventType.ExitSuccess, metadata)\n onExitSuccess?.(metadata)\n break\n case 'Authenticate':\n // @todo handle Authenticate\n break\n case 'OauthRequested':\n handleOAuthUrl(new URL(url.searchParams.get('oauthUrl') as string))\n break\n default:\n console.log('unhandled event', url)\n break\n }\n }\n\n const handleOAuthUrl = async (oauthUrl: URL) => {\n if (oauthUrl.protocol !== 'https:') {\n console.log(`handleOAuthUrl - Skipping non https url - ${oauthUrl.href}`)\n return\n }\n if (await Linking.canOpenURL(oauthUrl.href)) {\n Linking.openURL(oauthUrl.href)\n }\n }\n\n return (\n <AndroidSafeAreaView>\n <WebView\n ref={webViewRef}\n originWhitelist={['https://*', 'quilttconnector://*']} // Maybe relax this to *?\n source={{ uri: connectorUrl }}\n onShouldStartLoadWithRequest={requestHandler}\n javaScriptEnabled\n domStorageEnabled // To enable localStorage in Android webview\n webviewDebuggingEnabled // Not sure if this works\n />\n </AndroidSafeAreaView>\n )\n}\n\nexport default QuilttConnector\n","import { SafeAreaView, StyleSheet, Platform, StatusBar } from 'react-native'\nimport { PropsWithChildren } from 'react'\n\nexport const AndroidSafeAreaView = ({ children }: PropsWithChildren) => (\n <SafeAreaView style={styles.AndroidSafeArea}>{children}</SafeAreaView>\n)\n\nconst styles = StyleSheet.create({\n AndroidSafeArea: {\n flex: 1,\n backgroundColor: 'white',\n paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0,\n },\n})\n"],"mappings":"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","names":["src_exports","__export","QuilttConnector_default","src_default","__toCommonJS","import_atob","import_url","import_core","import_react","import_react_native","import_react_native_webview","import_react_native","import_jsx_runtime","AndroidSafeAreaView","children","styles","import_react","import_jsx_runtime","QuilttConnector","connectorId","connectionId","oauthRedirectUrl","onEvent","onLoad","onExit","onExitSuccess","onExitAbort","onExitError","webViewRef","session","connectorUrl","initInjectedJavaScript","_a","script","allowedListUrl","shouldRender","url","href","requestHandler","request","handleQuilttEvent","handleOAuthUrl","clearLocalStorage","metadata","oauthUrl","__async","AndroidSafeAreaView","QuilttConnector_default","src_default","QuilttConnector_default"]}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import"core-js/stable/atob";import"core-js/stable/url";import{ConnectorSDKEventType as o}from"@quiltt/core";import{useCallback as O,useRef as W}from"react";import{Linking as D}from"react-native";import{WebView as L}from"react-native-webview";import{SafeAreaView as y,StyleSheet as A,Platform as P,StatusBar as R}from"react-native";import{jsx as q}from"react/jsx-runtime";var S=({children:c})=>q(y,{style:V.AndroidSafeArea,children:c}),V=A.create({AndroidSafeArea:{flex:1,backgroundColor:"white",paddingTop:P.OS==="android"?R.currentHeight:0}});import{useQuilttSession as Q}from"@quiltt/react";import{jsx as b}from"react/jsx-runtime";var T=({connectorId:c,connectionId:f,oauthRedirectUrl:s,onEvent:t,onLoad:l,onExit:a,onExitSuccess:p,onExitAbort:d,onExitError:n})=>{let u=W(null),{session:i}=Q();s=encodeURIComponent(s);let w=`https://${c}.quiltt.app/?mode=webview&oauth_redirect_url=${s}&sdk=react-native`,k=O(()=>{var e;let r=` const options = { source: 'quiltt', type: 'Options', token: '${i==null?void 0:i.token}', connectorId: '${c}', connectionId: '${f}', }; const compactedOptions = Object.keys(options).reduce((acc, key) => { if (options[key] !== 'undefined') { acc[key] = options[key]; } return acc; }, {}); window.postMessage(compactedOptions); `;(e=u.current)==null||e.injectJavaScript(r)},[f,c,i==null?void 0:i.token]),g=r=>{let e=new URL(r.url);return e.protocol==="quilttconnector:"?(C(e),!1):!0},m=()=>{var e;let r="localStorage.clear();";(e=u.current)==null||e.injectJavaScript(r)},C=r=>{r.searchParams.delete("source"),r.searchParams.append("connectorId",c);let e=Object.fromEntries(r.searchParams);switch(r.host){case"Load":k(),t==null||t(o.Load,e),l==null||l(e);break;case"ExitAbort":m(),t==null||t(o.ExitAbort,e),a==null||a(o.ExitAbort,e),d==null||d(e);break;case"ExitError":m(),t==null||t(o.ExitError,e),a==null||a(o.ExitError,e),n==null||n(e);break;case"ExitSuccess":m(),t==null||t(o.ExitSuccess,e),a==null||a(o.ExitSuccess,e),p==null||p(e);break;case"OauthRequested":D.openURL(r.searchParams.get("oauthUrl"));break;default:console.log("unhandled event",r);break}};return b(S,{children:b(L,{ref:u,originWhitelist:["https://*","quilttconnector://*"],source:{uri:w},onShouldStartLoadWithRequest:g,javaScriptEnabled:!0,domStorageEnabled:!0,webviewDebuggingEnabled:!0})})},h=T;var v=h;export{h as QuilttConnector,v as default};
1
+ var S=(c,f,s)=>new Promise((r,n)=>{var a=o=>{try{i(s.next(o))}catch(l){n(l)}},u=o=>{try{i(s.throw(o))}catch(l){n(l)}},i=o=>o.done?r(o.value):Promise.resolve(o.value).then(a,u);i((s=s.apply(c,f)).next())});import"core-js/stable/atob";import"core-js/stable/url";import{ConnectorSDKEventType as p}from"@quiltt/core";import{useCallback as Q,useRef as T}from"react";import{Linking as k}from"react-native";import{WebView as $}from"react-native-webview";import{SafeAreaView as O,StyleSheet as P,Platform as U,StatusBar as V}from"react-native";import{jsx as D}from"react/jsx-runtime";var b=({children:c})=>D(O,{style:W.AndroidSafeArea,children:c}),W=P.create({AndroidSafeArea:{flex:1,backgroundColor:"white",paddingTop:U.OS==="android"?V.currentHeight:0}});import{useQuilttSession as K}from"@quiltt/react";import{jsx as w}from"react/jsx-runtime";var j=({connectorId:c,connectionId:f,oauthRedirectUrl:s,onEvent:r,onLoad:n,onExit:a,onExitSuccess:u,onExitAbort:i,onExitError:o})=>{let l=T(null),{session:d}=K();s=encodeURIComponent(s);let y=`https://${c}.quiltt.app/?mode=webview&oauth_redirect_url=${s}&sdk=react-native`,C=Q(()=>{var e;let t=` const options = { source: 'quiltt', type: 'Options', token: '${d==null?void 0:d.token}', connectorId: '${c}', connectionId: '${f}', }; const compactedOptions = Object.keys(options).reduce((acc, key) => { if (options[key] !== 'undefined') { acc[key] = options[key]; } return acc; }, {}); window.postMessage(compactedOptions); `;(e=l.current)==null||e.injectJavaScript(t)},[f,c,d==null?void 0:d.token]),A=["quiltt.app","quiltt.dev","moneydesktop.com","cdn.plaid.com/link/v2/stable/link.html"],R=t=>A.some(e=>t.href.includes(e)),q=t=>{let e=new URL(t.url);return R(e)?!0:e.protocol==="quilttconnector:"?(L(e),!1):(h(e),!1)},m=()=>{var e;let t="localStorage.clear();";(e=l.current)==null||e.injectJavaScript(t)},L=t=>{t.searchParams.delete("source"),t.searchParams.append("connectorId",c);let e=Object.fromEntries(t.searchParams);switch(t.host){case"Load":C(),r==null||r(p.Load,e),n==null||n(e);break;case"ExitAbort":m(),r==null||r(p.ExitAbort,e),a==null||a(p.ExitAbort,e),i==null||i(e);break;case"ExitError":m(),r==null||r(p.ExitError,e),a==null||a(p.ExitError,e),o==null||o(e);break;case"ExitSuccess":m(),r==null||r(p.ExitSuccess,e),a==null||a(p.ExitSuccess,e),u==null||u(e);break;case"Authenticate":break;case"OauthRequested":h(new URL(t.searchParams.get("oauthUrl")));break;default:console.log("unhandled event",t);break}},h=t=>S(void 0,null,function*(){if(t.protocol!=="https:"){console.log(`handleOAuthUrl - Skipping non https url - ${t.href}`);return}(yield k.canOpenURL(t.href))&&k.openURL(t.href)});return w(b,{children:w($,{ref:l,originWhitelist:["https://*","quilttconnector://*"],source:{uri:y},onShouldStartLoadWithRequest:q,javaScriptEnabled:!0,domStorageEnabled:!0,webviewDebuggingEnabled:!0})})},g=j;var ae=g;export{g as QuilttConnector,ae as default};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/QuilttConnector.tsx","../src/components/AndroidSafeAreaView.tsx"],"sourcesContent":["// Hermes doesn't have atob\n// https://github.com/facebook/hermes/issues/1178\nimport 'core-js/stable/atob'\n// React Native's URL implementation is incomplete\n// https://github.com/facebook/react-native/issues/16434\nimport 'core-js/stable/url'\nimport QuilttConnector from './components/QuilttConnector'\n\nexport { QuilttConnector }\nexport default QuilttConnector\n","import {\n ConnectorSDKCallbackMetadata,\n ConnectorSDKCallbacks,\n ConnectorSDKEventType,\n} from '@quiltt/core'\nimport { useCallback, useRef } from 'react'\nimport { Linking } from 'react-native'\nimport { WebView } from 'react-native-webview'\nimport { AndroidSafeAreaView } from './AndroidSafeAreaView'\nimport type { ShouldStartLoadRequest } from 'react-native-webview/lib/WebViewTypes'\nimport { useQuilttSession } from '@quiltt/react'\n\ntype QuilttConnectorProps = {\n connectorId: string\n connectionId?: string\n oauthRedirectUrl: string\n} & ConnectorSDKCallbacks\n\nexport const QuilttConnector = ({\n connectorId,\n connectionId,\n oauthRedirectUrl,\n onEvent,\n onLoad,\n onExit,\n onExitSuccess,\n onExitAbort,\n onExitError,\n}: QuilttConnectorProps) => {\n const webViewRef = useRef<WebView>(null)\n const { session } = useQuilttSession()\n oauthRedirectUrl = encodeURIComponent(oauthRedirectUrl)\n const connectorUrl = `https://${connectorId}.quiltt.app/?mode=webview&oauth_redirect_url=${oauthRedirectUrl}&sdk=react-native` // @todo append version from package.json\n\n const initInjectedJavaScript = useCallback(() => {\n const script = `\\\n const options = {\\\n source: 'quiltt',\\\n type: 'Options',\\\n token: '${session?.token}',\\\n connectorId: '${connectorId}',\\\n connectionId: '${connectionId}',\\\n };\\\n const compactedOptions = Object.keys(options).reduce((acc, key) => {\\\n if (options[key] !== 'undefined') {\\\n acc[key] = options[key];\\\n }\\\n return acc;\\\n }, {});\\\n window.postMessage(compactedOptions);\\\n `\n webViewRef.current?.injectJavaScript(script)\n }, [connectionId, connectorId, session?.token])\n\n const eventHandler = (request: ShouldStartLoadRequest) => {\n const url = new URL(request.url)\n if (url.protocol === 'quilttconnector:') {\n handleQuilttEvent(url)\n return false\n }\n return true\n }\n\n const clearLocalStorage = () => {\n const script = 'localStorage.clear();'\n webViewRef.current?.injectJavaScript(script)\n }\n\n const handleQuilttEvent = (url: URL) => {\n url.searchParams.delete('source')\n url.searchParams.append('connectorId', connectorId)\n const metadata = Object.fromEntries(url.searchParams) as ConnectorSDKCallbackMetadata\n\n const eventType = url.host\n switch (eventType) {\n case 'Load':\n initInjectedJavaScript()\n onEvent?.(ConnectorSDKEventType.Load, metadata)\n onLoad?.(metadata)\n break\n case 'ExitAbort':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitAbort, metadata)\n onExit?.(ConnectorSDKEventType.ExitAbort, metadata)\n onExitAbort?.(metadata)\n break\n case 'ExitError':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitError, metadata)\n onExit?.(ConnectorSDKEventType.ExitError, metadata)\n onExitError?.(metadata)\n break\n case 'ExitSuccess':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitSuccess, metadata)\n onExit?.(ConnectorSDKEventType.ExitSuccess, metadata)\n onExitSuccess?.(metadata)\n break\n case 'OauthRequested':\n Linking.openURL(url.searchParams.get('oauthUrl') as string)\n break\n default:\n console.log('unhandled event', url)\n break\n }\n }\n\n return (\n <AndroidSafeAreaView>\n <WebView\n ref={webViewRef}\n originWhitelist={['https://*', 'quilttconnector://*']} // Maybe relax this to *?\n source={{ uri: connectorUrl }}\n onShouldStartLoadWithRequest={eventHandler}\n javaScriptEnabled\n domStorageEnabled // To enable localStorage in Android webview\n webviewDebuggingEnabled // Not sure if this works\n />\n </AndroidSafeAreaView>\n )\n}\n\nexport default QuilttConnector\n","import { SafeAreaView, StyleSheet, Platform, StatusBar } from 'react-native'\nimport { PropsWithChildren } from 'react'\n\nexport const AndroidSafeAreaView = ({ children }: PropsWithChildren) => (\n <SafeAreaView style={styles.AndroidSafeArea}>{children}</SafeAreaView>\n)\n\nconst styles = StyleSheet.create({\n AndroidSafeArea: {\n flex: 1,\n backgroundColor: 'white',\n paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0,\n },\n})\n"],"mappings":"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","names":["ConnectorSDKEventType","useCallback","useRef","Linking","WebView","SafeAreaView","StyleSheet","Platform","StatusBar","jsx","AndroidSafeAreaView","children","styles","useQuilttSession","jsx","QuilttConnector","connectorId","connectionId","oauthRedirectUrl","onEvent","onLoad","onExit","onExitSuccess","onExitAbort","onExitError","webViewRef","useRef","session","connectorUrl","initInjectedJavaScript","useCallback","_a","script","eventHandler","request","url","handleQuilttEvent","clearLocalStorage","metadata","ConnectorSDKEventType","Linking","AndroidSafeAreaView","WebView","QuilttConnector_default","src_default","QuilttConnector_default"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/components/QuilttConnector.tsx","../src/components/AndroidSafeAreaView.tsx"],"sourcesContent":["// Hermes doesn't have atob\n// https://github.com/facebook/hermes/issues/1178\nimport 'core-js/stable/atob'\n// React Native's URL implementation is incomplete\n// https://github.com/facebook/react-native/issues/16434\nimport 'core-js/stable/url'\nimport QuilttConnector from './components/QuilttConnector'\n\nexport { QuilttConnector }\nexport default QuilttConnector\n","import {\n ConnectorSDKCallbackMetadata,\n ConnectorSDKCallbacks,\n ConnectorSDKEventType,\n} from '@quiltt/core'\nimport { useCallback, useRef } from 'react'\nimport { Linking } from 'react-native'\nimport { WebView } from 'react-native-webview'\nimport { AndroidSafeAreaView } from './AndroidSafeAreaView'\nimport type { ShouldStartLoadRequest } from 'react-native-webview/lib/WebViewTypes'\nimport { useQuilttSession } from '@quiltt/react'\n\ntype QuilttConnectorProps = {\n connectorId: string\n connectionId?: string\n oauthRedirectUrl: string\n} & ConnectorSDKCallbacks\n\nexport const QuilttConnector = ({\n connectorId,\n connectionId,\n oauthRedirectUrl,\n onEvent,\n onLoad,\n onExit,\n onExitSuccess,\n onExitAbort,\n onExitError,\n}: QuilttConnectorProps) => {\n const webViewRef = useRef<WebView>(null)\n const { session } = useQuilttSession()\n oauthRedirectUrl = encodeURIComponent(oauthRedirectUrl)\n const connectorUrl = `https://${connectorId}.quiltt.app/?mode=webview&oauth_redirect_url=${oauthRedirectUrl}&sdk=react-native` // @todo append version from package.json\n\n const initInjectedJavaScript = useCallback(() => {\n const script = `\\\n const options = {\\\n source: 'quiltt',\\\n type: 'Options',\\\n token: '${session?.token}',\\\n connectorId: '${connectorId}',\\\n connectionId: '${connectionId}',\\\n };\\\n const compactedOptions = Object.keys(options).reduce((acc, key) => {\\\n if (options[key] !== 'undefined') {\\\n acc[key] = options[key];\\\n }\\\n return acc;\\\n }, {});\\\n window.postMessage(compactedOptions);\\\n `\n webViewRef.current?.injectJavaScript(script)\n }, [connectionId, connectorId, session?.token])\n\n // allowedListUrl & shouldRender ensure we are only rendering Quiltt, MX and Plaid content in Webview\n // For other urls, we assume those are bank urls, which needs to be handle in external browser.\n // @todo Convert it to a list from Quiltt Server to prevent MX/ Plaid changes.\n const allowedListUrl = [\n 'quiltt.app',\n 'quiltt.dev',\n 'moneydesktop.com',\n 'cdn.plaid.com/link/v2/stable/link.html',\n ]\n const shouldRender = (url: URL) => allowedListUrl.some((href) => url.href.includes(href))\n\n const requestHandler = (request: ShouldStartLoadRequest) => {\n const url = new URL(request.url)\n if (shouldRender(url)) return true\n if (url.protocol === 'quilttconnector:') {\n handleQuilttEvent(url)\n return false\n }\n // Plaid set oauth url by doing window.location.href = url\n // This is the only way I know to handle this.\n handleOAuthUrl(url)\n return false\n }\n\n const clearLocalStorage = () => {\n const script = 'localStorage.clear();'\n webViewRef.current?.injectJavaScript(script)\n }\n\n const handleQuilttEvent = (url: URL) => {\n url.searchParams.delete('source')\n url.searchParams.append('connectorId', connectorId)\n const metadata = Object.fromEntries(url.searchParams) as ConnectorSDKCallbackMetadata\n\n const eventType = url.host\n switch (eventType) {\n case 'Load':\n initInjectedJavaScript()\n onEvent?.(ConnectorSDKEventType.Load, metadata)\n onLoad?.(metadata)\n break\n case 'ExitAbort':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitAbort, metadata)\n onExit?.(ConnectorSDKEventType.ExitAbort, metadata)\n onExitAbort?.(metadata)\n break\n case 'ExitError':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitError, metadata)\n onExit?.(ConnectorSDKEventType.ExitError, metadata)\n onExitError?.(metadata)\n break\n case 'ExitSuccess':\n clearLocalStorage()\n onEvent?.(ConnectorSDKEventType.ExitSuccess, metadata)\n onExit?.(ConnectorSDKEventType.ExitSuccess, metadata)\n onExitSuccess?.(metadata)\n break\n case 'Authenticate':\n // @todo handle Authenticate\n break\n case 'OauthRequested':\n handleOAuthUrl(new URL(url.searchParams.get('oauthUrl') as string))\n break\n default:\n console.log('unhandled event', url)\n break\n }\n }\n\n const handleOAuthUrl = async (oauthUrl: URL) => {\n if (oauthUrl.protocol !== 'https:') {\n console.log(`handleOAuthUrl - Skipping non https url - ${oauthUrl.href}`)\n return\n }\n if (await Linking.canOpenURL(oauthUrl.href)) {\n Linking.openURL(oauthUrl.href)\n }\n }\n\n return (\n <AndroidSafeAreaView>\n <WebView\n ref={webViewRef}\n originWhitelist={['https://*', 'quilttconnector://*']} // Maybe relax this to *?\n source={{ uri: connectorUrl }}\n onShouldStartLoadWithRequest={requestHandler}\n javaScriptEnabled\n domStorageEnabled // To enable localStorage in Android webview\n webviewDebuggingEnabled // Not sure if this works\n />\n </AndroidSafeAreaView>\n )\n}\n\nexport default QuilttConnector\n","import { SafeAreaView, StyleSheet, Platform, StatusBar } from 'react-native'\nimport { PropsWithChildren } from 'react'\n\nexport const AndroidSafeAreaView = ({ children }: PropsWithChildren) => (\n <SafeAreaView style={styles.AndroidSafeArea}>{children}</SafeAreaView>\n)\n\nconst styles = StyleSheet.create({\n AndroidSafeArea: {\n flex: 1,\n backgroundColor: 'white',\n paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0,\n },\n})\n"],"mappings":"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","names":["ConnectorSDKEventType","useCallback","useRef","Linking","WebView","SafeAreaView","StyleSheet","Platform","StatusBar","jsx","AndroidSafeAreaView","children","styles","useQuilttSession","jsx","QuilttConnector","connectorId","connectionId","oauthRedirectUrl","onEvent","onLoad","onExit","onExitSuccess","onExitAbort","onExitError","webViewRef","useRef","session","useQuilttSession","connectorUrl","initInjectedJavaScript","useCallback","_a","script","allowedListUrl","shouldRender","url","href","requestHandler","request","handleQuilttEvent","handleOAuthUrl","clearLocalStorage","metadata","ConnectorSDKEventType","oauthUrl","__async","Linking","AndroidSafeAreaView","WebView","QuilttConnector_default","src_default","QuilttConnector_default"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quiltt/react-native",
3
- "version": "3.3.1",
3
+ "version": "3.3.3",
4
4
  "description": "React Native components for Quiltt Connector",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -23,8 +23,8 @@
23
23
  "dependencies": {
24
24
  "core-js": "3.33.2",
25
25
  "react-native-webview": "13.6.2",
26
- "@quiltt/core": "3.3.1",
27
- "@quiltt/react": "3.3.1"
26
+ "@quiltt/core": "3.3.3",
27
+ "@quiltt/react": "3.3.3"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@apollo/client": "3.7.16",
@@ -52,13 +52,28 @@ export const QuilttConnector = ({
52
52
  webViewRef.current?.injectJavaScript(script)
53
53
  }, [connectionId, connectorId, session?.token])
54
54
 
55
- const eventHandler = (request: ShouldStartLoadRequest) => {
55
+ // allowedListUrl & shouldRender ensure we are only rendering Quiltt, MX and Plaid content in Webview
56
+ // For other urls, we assume those are bank urls, which needs to be handle in external browser.
57
+ // @todo Convert it to a list from Quiltt Server to prevent MX/ Plaid changes.
58
+ const allowedListUrl = [
59
+ 'quiltt.app',
60
+ 'quiltt.dev',
61
+ 'moneydesktop.com',
62
+ 'cdn.plaid.com/link/v2/stable/link.html',
63
+ ]
64
+ const shouldRender = (url: URL) => allowedListUrl.some((href) => url.href.includes(href))
65
+
66
+ const requestHandler = (request: ShouldStartLoadRequest) => {
56
67
  const url = new URL(request.url)
68
+ if (shouldRender(url)) return true
57
69
  if (url.protocol === 'quilttconnector:') {
58
70
  handleQuilttEvent(url)
59
71
  return false
60
72
  }
61
- return true
73
+ // Plaid set oauth url by doing window.location.href = url
74
+ // This is the only way I know to handle this.
75
+ handleOAuthUrl(url)
76
+ return false
62
77
  }
63
78
 
64
79
  const clearLocalStorage = () => {
@@ -96,8 +111,11 @@ export const QuilttConnector = ({
96
111
  onExit?.(ConnectorSDKEventType.ExitSuccess, metadata)
97
112
  onExitSuccess?.(metadata)
98
113
  break
114
+ case 'Authenticate':
115
+ // @todo handle Authenticate
116
+ break
99
117
  case 'OauthRequested':
100
- Linking.openURL(url.searchParams.get('oauthUrl') as string)
118
+ handleOAuthUrl(new URL(url.searchParams.get('oauthUrl') as string))
101
119
  break
102
120
  default:
103
121
  console.log('unhandled event', url)
@@ -105,13 +123,23 @@ export const QuilttConnector = ({
105
123
  }
106
124
  }
107
125
 
126
+ const handleOAuthUrl = async (oauthUrl: URL) => {
127
+ if (oauthUrl.protocol !== 'https:') {
128
+ console.log(`handleOAuthUrl - Skipping non https url - ${oauthUrl.href}`)
129
+ return
130
+ }
131
+ if (await Linking.canOpenURL(oauthUrl.href)) {
132
+ Linking.openURL(oauthUrl.href)
133
+ }
134
+ }
135
+
108
136
  return (
109
137
  <AndroidSafeAreaView>
110
138
  <WebView
111
139
  ref={webViewRef}
112
140
  originWhitelist={['https://*', 'quilttconnector://*']} // Maybe relax this to *?
113
141
  source={{ uri: connectorUrl }}
114
- onShouldStartLoadWithRequest={eventHandler}
142
+ onShouldStartLoadWithRequest={requestHandler}
115
143
  javaScriptEnabled
116
144
  domStorageEnabled // To enable localStorage in Android webview
117
145
  webviewDebuggingEnabled // Not sure if this works