@savers_app/react-native-sandbox-sdk 1.2.6 → 1.2.8
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/README.md +22 -151
- package/lib/module/core/runtime.js +14 -0
- package/lib/module/core/runtime.js.map +1 -1
- package/lib/module/index.js +2 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/services/url/urlGenerator.js +20 -6
- package/lib/module/services/url/urlGenerator.js.map +1 -1
- package/lib/module/services/webview/DualWebViewBridgeController.js +267 -0
- package/lib/module/services/webview/DualWebViewBridgeController.js.map +1 -0
- package/lib/module/services/webview/dualWebViewBridge.types.js +19 -0
- package/lib/module/services/webview/dualWebViewBridge.types.js.map +1 -0
- package/lib/module/utils/config.js +2 -0
- package/lib/module/utils/config.js.map +1 -1
- package/lib/typescript/src/core/runtime.d.ts +4 -0
- package/lib/typescript/src/core/runtime.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/services/url/urlGenerator.d.ts +0 -1
- package/lib/typescript/src/services/url/urlGenerator.d.ts.map +1 -1
- package/lib/typescript/src/services/webview/DualWebViewBridgeController.d.ts +15 -0
- package/lib/typescript/src/services/webview/DualWebViewBridgeController.d.ts.map +1 -0
- package/lib/typescript/src/services/webview/dualWebViewBridge.types.d.ts +20 -0
- package/lib/typescript/src/services/webview/dualWebViewBridge.types.d.ts.map +1 -0
- package/lib/typescript/src/utils/config.d.ts.map +1 -1
- package/package.json +17 -9
- package/src/core/runtime.ts +21 -0
- package/src/index.tsx +2 -0
- package/src/services/url/urlGenerator.ts +18 -7
- package/src/services/webview/DualWebViewBridgeController.tsx +330 -0
- package/src/services/webview/dualWebViewBridge.types.ts +32 -0
- package/src/utils/config.ts +1 -0
- package/lib/module/services/device/location.js +0 -47
- package/lib/module/services/device/location.js.map +0 -1
- package/lib/typescript/src/services/device/location.d.ts +0 -8
- package/lib/typescript/src/services/device/location.d.ts.map +0 -1
- package/src/services/device/location.ts +0 -51
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React, { useCallback, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import { Image, StyleSheet, TouchableOpacity, View } from 'react-native';
|
|
5
|
+
import WebView from 'react-native-webview';
|
|
6
|
+
import { parseDualWebViewEnvelope } from "./dualWebViewBridge.types.js";
|
|
7
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
|
+
const DEFAULT_TRAVEL_PORTAL_URL = 'https://sandbox.travelercashback.com';
|
|
9
|
+
|
|
10
|
+
/** Must match `applicationNameForUserAgent` on clo-app WebViews (DualWebViewBridgeController). */
|
|
11
|
+
const WEBVIEW_UA_MARKER = 'CloAppWebView';
|
|
12
|
+
|
|
13
|
+
/** Legacy / Hub: open travel from first WebView without JSON envelope. */
|
|
14
|
+
const TRAVEL_DEEP_LINK = 'saversapp://travel';
|
|
15
|
+
const LEGACY_OPEN_TRAVEL_ACTIONS = ['OPEN_TRAVEL_PORTAL', 'OPEN_TRAVEL'];
|
|
16
|
+
function buildInjectNativeBridgeScript(detail) {
|
|
17
|
+
return `
|
|
18
|
+
(function(){
|
|
19
|
+
var detail = ${JSON.stringify(detail)};
|
|
20
|
+
window.dispatchEvent(new CustomEvent('nativeBridge', { detail: detail }));
|
|
21
|
+
true;
|
|
22
|
+
})();
|
|
23
|
+
`;
|
|
24
|
+
}
|
|
25
|
+
export const DualWebViewBridgeController = ({
|
|
26
|
+
saversAppUrl,
|
|
27
|
+
travelPortalUrl = DEFAULT_TRAVEL_PORTAL_URL,
|
|
28
|
+
partnerLogo,
|
|
29
|
+
renderTravelBackIcon,
|
|
30
|
+
initialSurface = 'savers',
|
|
31
|
+
onSaversSdkMessage,
|
|
32
|
+
onLoadEndSavers,
|
|
33
|
+
onLoadEndTravel
|
|
34
|
+
}) => {
|
|
35
|
+
const saversRef = useRef(null);
|
|
36
|
+
const travelRef = useRef(null);
|
|
37
|
+
const [surface, setSurface] = useState(initialSurface);
|
|
38
|
+
const [saversKey, setSaversKey] = useState(0);
|
|
39
|
+
const [travelKey, setTravelKey] = useState(0);
|
|
40
|
+
const openTravel = useCallback(() => {
|
|
41
|
+
setSurface('travel');
|
|
42
|
+
setTravelKey(k => k + 1);
|
|
43
|
+
}, []);
|
|
44
|
+
const backToSavers = useCallback(() => {
|
|
45
|
+
setSurface('savers');
|
|
46
|
+
setSaversKey(k => k + 1);
|
|
47
|
+
}, []);
|
|
48
|
+
const relayTo = useCallback((target, payload, from) => {
|
|
49
|
+
const detail = {
|
|
50
|
+
bridge: 'dual-webview',
|
|
51
|
+
from,
|
|
52
|
+
action: 'relay',
|
|
53
|
+
payload
|
|
54
|
+
};
|
|
55
|
+
const ref = target === 'savers' ? saversRef : travelRef;
|
|
56
|
+
ref.current?.injectJavaScript(buildInjectNativeBridgeScript(detail));
|
|
57
|
+
}, []);
|
|
58
|
+
const handleBridgeEnvelope = useCallback(env => {
|
|
59
|
+
switch (env.action) {
|
|
60
|
+
case 'open_travel':
|
|
61
|
+
openTravel();
|
|
62
|
+
return true;
|
|
63
|
+
case 'close_travel':
|
|
64
|
+
backToSavers();
|
|
65
|
+
return true;
|
|
66
|
+
case 'relay':
|
|
67
|
+
if (env.to === 'savers') {
|
|
68
|
+
relayTo('savers', env.payload, env.from);
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
if (env.to === 'travel') {
|
|
72
|
+
relayTo('travel', env.payload, env.from);
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
default:
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}, [backToSavers, openTravel, relayTo]);
|
|
80
|
+
const tryLegacyOpenTravel = useCallback(raw => {
|
|
81
|
+
if (!raw || typeof raw !== 'string') {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
const data = JSON.parse(raw);
|
|
86
|
+
if (data?.action === 'OPEN_TRAVEL_PORTAL' || data?.type === 'OPEN_TRAVEL' || data?.openTravel === true) {
|
|
87
|
+
openTravel();
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
} catch {
|
|
91
|
+
/* ignore */
|
|
92
|
+
}
|
|
93
|
+
if (LEGACY_OPEN_TRAVEL_ACTIONS.some(s => raw.includes(s))) {
|
|
94
|
+
openTravel();
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}, [openTravel]);
|
|
99
|
+
const onMessageSavers = useCallback(e => {
|
|
100
|
+
const raw = e?.nativeEvent?.data ?? '';
|
|
101
|
+
const env = parseDualWebViewEnvelope(raw);
|
|
102
|
+
if (env && env.from === 'savers' && handleBridgeEnvelope(env)) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (tryLegacyOpenTravel(raw)) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const postBack = data => {
|
|
109
|
+
const detail = {
|
|
110
|
+
bridge: 'dual-webview',
|
|
111
|
+
from: 'native',
|
|
112
|
+
action: 'relay',
|
|
113
|
+
payload: data
|
|
114
|
+
};
|
|
115
|
+
saversRef.current?.injectJavaScript(buildInjectNativeBridgeScript(detail));
|
|
116
|
+
};
|
|
117
|
+
onSaversSdkMessage?.(raw, postBack);
|
|
118
|
+
}, [handleBridgeEnvelope, onSaversSdkMessage, tryLegacyOpenTravel]);
|
|
119
|
+
const onMessageTravel = useCallback(e => {
|
|
120
|
+
const raw = e?.nativeEvent?.data ?? '';
|
|
121
|
+
const env = parseDualWebViewEnvelope(raw);
|
|
122
|
+
if (env && env.from === 'travel' && handleBridgeEnvelope(env)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (tryLegacyOpenTravel(raw)) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
}, [handleBridgeEnvelope, tryLegacyOpenTravel]);
|
|
129
|
+
const onShouldStartLoadSavers = useCallback(request => {
|
|
130
|
+
const {
|
|
131
|
+
url
|
|
132
|
+
} = request;
|
|
133
|
+
if (url.startsWith(TRAVEL_DEEP_LINK) || url === 'saversapp://travel/') {
|
|
134
|
+
openTravel();
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
return true;
|
|
138
|
+
}, [openTravel]);
|
|
139
|
+
const travelSource = useMemo(() => ({
|
|
140
|
+
uri: travelPortalUrl
|
|
141
|
+
}), [travelPortalUrl]);
|
|
142
|
+
const saversSource = useMemo(() => ({
|
|
143
|
+
uri: saversAppUrl
|
|
144
|
+
}), [saversAppUrl]);
|
|
145
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
146
|
+
style: styles.root,
|
|
147
|
+
children: [surface === 'savers' ? /*#__PURE__*/_jsx(WebView, {
|
|
148
|
+
ref: saversRef,
|
|
149
|
+
source: saversSource,
|
|
150
|
+
originWhitelist: ['*'],
|
|
151
|
+
applicationNameForUserAgent: WEBVIEW_UA_MARKER,
|
|
152
|
+
onMessage: onMessageSavers,
|
|
153
|
+
onShouldStartLoadWithRequest: onShouldStartLoadSavers,
|
|
154
|
+
onLoadEnd: onLoadEndSavers,
|
|
155
|
+
style: styles.webview,
|
|
156
|
+
sharedCookiesEnabled: true,
|
|
157
|
+
incognito: false,
|
|
158
|
+
webviewDebuggingEnabled: __DEV__
|
|
159
|
+
}, saversKey) : null, surface === 'travel' ? /*#__PURE__*/_jsxs(View, {
|
|
160
|
+
style: styles.travelColumn,
|
|
161
|
+
children: [/*#__PURE__*/_jsxs(View, {
|
|
162
|
+
style: styles.header,
|
|
163
|
+
children: [/*#__PURE__*/_jsx(TouchableOpacity, {
|
|
164
|
+
onPress: backToSavers,
|
|
165
|
+
hitSlop: 16,
|
|
166
|
+
accessibilityRole: "button",
|
|
167
|
+
accessibilityLabel: "Back",
|
|
168
|
+
style: styles.backButton,
|
|
169
|
+
children: renderTravelBackIcon ? renderTravelBackIcon() : /*#__PURE__*/_jsxs(View, {
|
|
170
|
+
style: styles.backIconWrapper,
|
|
171
|
+
children: [/*#__PURE__*/_jsx(View, {
|
|
172
|
+
style: styles.backIconShaft
|
|
173
|
+
}), /*#__PURE__*/_jsx(View, {
|
|
174
|
+
style: styles.backIconHead
|
|
175
|
+
})]
|
|
176
|
+
})
|
|
177
|
+
}), /*#__PURE__*/_jsx(View, {
|
|
178
|
+
style: styles.headerSpacer
|
|
179
|
+
}), partnerLogo ? /*#__PURE__*/_jsx(Image, {
|
|
180
|
+
source: {
|
|
181
|
+
uri: partnerLogo
|
|
182
|
+
},
|
|
183
|
+
resizeMode: "contain",
|
|
184
|
+
style: styles.logo
|
|
185
|
+
}) : /*#__PURE__*/_jsx(View, {
|
|
186
|
+
style: styles.logoPlaceholder
|
|
187
|
+
})]
|
|
188
|
+
}), /*#__PURE__*/_jsx(WebView, {
|
|
189
|
+
ref: travelRef,
|
|
190
|
+
source: travelSource,
|
|
191
|
+
originWhitelist: ['*'],
|
|
192
|
+
applicationNameForUserAgent: WEBVIEW_UA_MARKER,
|
|
193
|
+
onMessage: onMessageTravel,
|
|
194
|
+
onLoadEnd: onLoadEndTravel,
|
|
195
|
+
style: styles.webview,
|
|
196
|
+
sharedCookiesEnabled: true,
|
|
197
|
+
incognito: false,
|
|
198
|
+
webviewDebuggingEnabled: __DEV__
|
|
199
|
+
}, travelKey)]
|
|
200
|
+
}) : null]
|
|
201
|
+
});
|
|
202
|
+
};
|
|
203
|
+
const styles = StyleSheet.create({
|
|
204
|
+
root: {
|
|
205
|
+
flex: 1
|
|
206
|
+
},
|
|
207
|
+
travelColumn: {
|
|
208
|
+
flex: 1
|
|
209
|
+
},
|
|
210
|
+
webview: {
|
|
211
|
+
flex: 1
|
|
212
|
+
},
|
|
213
|
+
header: {
|
|
214
|
+
flexDirection: 'row',
|
|
215
|
+
alignItems: 'center',
|
|
216
|
+
backgroundColor: '#fff',
|
|
217
|
+
paddingHorizontal: 16,
|
|
218
|
+
paddingTop: 12,
|
|
219
|
+
paddingBottom: 12,
|
|
220
|
+
borderBottomWidth: StyleSheet.hairlineWidth,
|
|
221
|
+
borderBottomColor: '#E5E5E5'
|
|
222
|
+
},
|
|
223
|
+
backButton: {
|
|
224
|
+
width: 32,
|
|
225
|
+
height: 32,
|
|
226
|
+
justifyContent: 'center',
|
|
227
|
+
alignItems: 'center'
|
|
228
|
+
},
|
|
229
|
+
backIconWrapper: {
|
|
230
|
+
width: 20,
|
|
231
|
+
height: 16,
|
|
232
|
+
justifyContent: 'center',
|
|
233
|
+
position: 'relative'
|
|
234
|
+
},
|
|
235
|
+
backIconShaft: {
|
|
236
|
+
position: 'absolute',
|
|
237
|
+
left: 6,
|
|
238
|
+
right: 0,
|
|
239
|
+
height: 2,
|
|
240
|
+
backgroundColor: '#111827',
|
|
241
|
+
borderRadius: 1
|
|
242
|
+
},
|
|
243
|
+
backIconHead: {
|
|
244
|
+
width: 10,
|
|
245
|
+
height: 10,
|
|
246
|
+
borderLeftWidth: 2,
|
|
247
|
+
borderBottomWidth: 2,
|
|
248
|
+
borderColor: '#111827',
|
|
249
|
+
transform: [{
|
|
250
|
+
rotate: '45deg'
|
|
251
|
+
}],
|
|
252
|
+
marginLeft: 1
|
|
253
|
+
},
|
|
254
|
+
headerSpacer: {
|
|
255
|
+
flex: 1
|
|
256
|
+
},
|
|
257
|
+
logo: {
|
|
258
|
+
width: 120,
|
|
259
|
+
height: 32
|
|
260
|
+
},
|
|
261
|
+
logoPlaceholder: {
|
|
262
|
+
width: 120,
|
|
263
|
+
height: 32
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
export default DualWebViewBridgeController;
|
|
267
|
+
//# sourceMappingURL=DualWebViewBridgeController.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","useCallback","useMemo","useRef","useState","Image","StyleSheet","TouchableOpacity","View","WebView","parseDualWebViewEnvelope","jsx","_jsx","jsxs","_jsxs","DEFAULT_TRAVEL_PORTAL_URL","WEBVIEW_UA_MARKER","TRAVEL_DEEP_LINK","LEGACY_OPEN_TRAVEL_ACTIONS","buildInjectNativeBridgeScript","detail","JSON","stringify","DualWebViewBridgeController","saversAppUrl","travelPortalUrl","partnerLogo","renderTravelBackIcon","initialSurface","onSaversSdkMessage","onLoadEndSavers","onLoadEndTravel","saversRef","travelRef","surface","setSurface","saversKey","setSaversKey","travelKey","setTravelKey","openTravel","k","backToSavers","relayTo","target","payload","from","bridge","action","ref","current","injectJavaScript","handleBridgeEnvelope","env","to","tryLegacyOpenTravel","raw","data","parse","type","some","s","includes","onMessageSavers","e","nativeEvent","postBack","onMessageTravel","onShouldStartLoadSavers","request","url","startsWith","travelSource","uri","saversSource","style","styles","root","children","source","originWhitelist","applicationNameForUserAgent","onMessage","onShouldStartLoadWithRequest","onLoadEnd","webview","sharedCookiesEnabled","incognito","webviewDebuggingEnabled","__DEV__","travelColumn","header","onPress","hitSlop","accessibilityRole","accessibilityLabel","backButton","backIconWrapper","backIconShaft","backIconHead","headerSpacer","resizeMode","logo","logoPlaceholder","create","flex","flexDirection","alignItems","backgroundColor","paddingHorizontal","paddingTop","paddingBottom","borderBottomWidth","hairlineWidth","borderBottomColor","width","height","justifyContent","position","left","right","borderRadius","borderLeftWidth","borderColor","transform","rotate","marginLeft"],"sourceRoot":"../../../../src","sources":["services/webview/DualWebViewBridgeController.tsx"],"mappings":";;AAAA,OAAOA,KAAK,IAAIC,WAAW,EAAEC,OAAO,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,OAAO;AACrE,SAASC,KAAK,EAAEC,UAAU,EAAEC,gBAAgB,EAAEC,IAAI,QAAQ,cAAc;AACxE,OAAOC,OAAO,MAAM,sBAAsB;AAC1C,SAEEC,wBAAwB,QACnB,8BAA2B;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,IAAA,IAAAC,KAAA;AAEnC,MAAMC,yBAAyB,GAAG,sCAAsC;;AAExE;AACA,MAAMC,iBAAiB,GAAG,eAAe;;AAEzC;AACA,MAAMC,gBAAgB,GAAG,oBAAoB;AAC7C,MAAMC,0BAA0B,GAAG,CAAC,oBAAoB,EAAE,aAAa,CAAC;AAexE,SAASC,6BAA6BA,CACpCC,MAA+B,EACvB;EACR,OAAO;AACT;AACA,qBAAqBC,IAAI,CAACC,SAAS,CAACF,MAAM,CAAC;AAC3C;AACA;AACA;AACA,GAAG;AACH;AAEA,OAAO,MAAMG,2BAEZ,GAAGA,CAAC;EACHC,YAAY;EACZC,eAAe,GAAGV,yBAAyB;EAC3CW,WAAW;EACXC,oBAAoB;EACpBC,cAAc,GAAG,QAAQ;EACzBC,kBAAkB;EAClBC,eAAe;EACfC;AACF,CAAC,KAAK;EACJ,MAAMC,SAAS,GAAG7B,MAAM,CAAU,IAAI,CAAC;EACvC,MAAM8B,SAAS,GAAG9B,MAAM,CAAU,IAAI,CAAC;EAEvC,MAAM,CAAC+B,OAAO,EAAEC,UAAU,CAAC,GAAG/B,QAAQ,CAAUwB,cAAc,CAAC;EAC/D,MAAM,CAACQ,SAAS,EAAEC,YAAY,CAAC,GAAGjC,QAAQ,CAAC,CAAC,CAAC;EAC7C,MAAM,CAACkC,SAAS,EAAEC,YAAY,CAAC,GAAGnC,QAAQ,CAAC,CAAC,CAAC;EAE7C,MAAMoC,UAAU,GAAGvC,WAAW,CAAC,MAAM;IACnCkC,UAAU,CAAC,QAAQ,CAAC;IACpBI,YAAY,CAAEE,CAAC,IAAKA,CAAC,GAAG,CAAC,CAAC;EAC5B,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMC,YAAY,GAAGzC,WAAW,CAAC,MAAM;IACrCkC,UAAU,CAAC,QAAQ,CAAC;IACpBE,YAAY,CAAEI,CAAC,IAAKA,CAAC,GAAG,CAAC,CAAC;EAC5B,CAAC,EAAE,EAAE,CAAC;EAEN,MAAME,OAAO,GAAG1C,WAAW,CACzB,CACE2C,MAA2B,EAC3BC,OAAgB,EAChBC,IAAyB,KACtB;IACH,MAAM1B,MAAM,GAAG;MACb2B,MAAM,EAAE,cAAc;MACtBD,IAAI;MACJE,MAAM,EAAE,OAAgB;MACxBH;IACF,CAAC;IACD,MAAMI,GAAG,GAAGL,MAAM,KAAK,QAAQ,GAAGZ,SAAS,GAAGC,SAAS;IACvDgB,GAAG,CAACC,OAAO,EAAEC,gBAAgB,CAAChC,6BAA6B,CAACC,MAAM,CAAC,CAAC;EACtE,CAAC,EACD,EACF,CAAC;EAED,MAAMgC,oBAAoB,GAAGnD,WAAW,CACrCoD,GAA8B,IAAc;IAC3C,QAAQA,GAAG,CAACL,MAAM;MAChB,KAAK,aAAa;QAChBR,UAAU,CAAC,CAAC;QACZ,OAAO,IAAI;MACb,KAAK,cAAc;QACjBE,YAAY,CAAC,CAAC;QACd,OAAO,IAAI;MACb,KAAK,OAAO;QACV,IAAIW,GAAG,CAACC,EAAE,KAAK,QAAQ,EAAE;UACvBX,OAAO,CAAC,QAAQ,EAAEU,GAAG,CAACR,OAAO,EAAEQ,GAAG,CAACP,IAAI,CAAC;UACxC,OAAO,IAAI;QACb;QACA,IAAIO,GAAG,CAACC,EAAE,KAAK,QAAQ,EAAE;UACvBX,OAAO,CAAC,QAAQ,EAAEU,GAAG,CAACR,OAAO,EAAEQ,GAAG,CAACP,IAAI,CAAC;UACxC,OAAO,IAAI;QACb;QACA,OAAO,KAAK;MACd;QACE,OAAO,KAAK;IAChB;EACF,CAAC,EACD,CAACJ,YAAY,EAAEF,UAAU,EAAEG,OAAO,CACpC,CAAC;EAED,MAAMY,mBAAmB,GAAGtD,WAAW,CACpCuD,GAAW,IAAc;IACxB,IAAI,CAACA,GAAG,IAAI,OAAOA,GAAG,KAAK,QAAQ,EAAE;MACnC,OAAO,KAAK;IACd;IACA,IAAI;MACF,MAAMC,IAAI,GAAGpC,IAAI,CAACqC,KAAK,CAACF,GAAG,CAAC;MAC5B,IACEC,IAAI,EAAET,MAAM,KAAK,oBAAoB,IACrCS,IAAI,EAAEE,IAAI,KAAK,aAAa,IAC5BF,IAAI,EAAEjB,UAAU,KAAK,IAAI,EACzB;QACAA,UAAU,CAAC,CAAC;QACZ,OAAO,IAAI;MACb;IACF,CAAC,CAAC,MAAM;MACN;IAAA;IAEF,IAAItB,0BAA0B,CAAC0C,IAAI,CAAEC,CAAC,IAAKL,GAAG,CAACM,QAAQ,CAACD,CAAC,CAAC,CAAC,EAAE;MAC3DrB,UAAU,CAAC,CAAC;MACZ,OAAO,IAAI;IACb;IACA,OAAO,KAAK;EACd,CAAC,EACD,CAACA,UAAU,CACb,CAAC;EAED,MAAMuB,eAAe,GAAG9D,WAAW,CAChC+D,CAAoC,IAAK;IACxC,MAAMR,GAAG,GAAGQ,CAAC,EAAEC,WAAW,EAAER,IAAI,IAAI,EAAE;IACtC,MAAMJ,GAAG,GAAG3C,wBAAwB,CAAC8C,GAAG,CAAC;IAEzC,IAAIH,GAAG,IAAIA,GAAG,CAACP,IAAI,KAAK,QAAQ,IAAIM,oBAAoB,CAACC,GAAG,CAAC,EAAE;MAC7D;IACF;IACA,IAAIE,mBAAmB,CAACC,GAAG,CAAC,EAAE;MAC5B;IACF;IAEA,MAAMU,QAAQ,GAAIT,IAAa,IAAK;MAClC,MAAMrC,MAAM,GAAG;QACb2B,MAAM,EAAE,cAAc;QACtBD,IAAI,EAAE,QAAQ;QACdE,MAAM,EAAE,OAAO;QACfH,OAAO,EAAEY;MACX,CAAC;MACDzB,SAAS,CAACkB,OAAO,EAAEC,gBAAgB,CACjChC,6BAA6B,CAACC,MAAM,CACtC,CAAC;IACH,CAAC;IACDS,kBAAkB,GAAG2B,GAAG,EAAEU,QAAQ,CAAC;EACrC,CAAC,EACD,CAACd,oBAAoB,EAAEvB,kBAAkB,EAAE0B,mBAAmB,CAChE,CAAC;EAED,MAAMY,eAAe,GAAGlE,WAAW,CAChC+D,CAAoC,IAAK;IACxC,MAAMR,GAAG,GAAGQ,CAAC,EAAEC,WAAW,EAAER,IAAI,IAAI,EAAE;IACtC,MAAMJ,GAAG,GAAG3C,wBAAwB,CAAC8C,GAAG,CAAC;IAEzC,IAAIH,GAAG,IAAIA,GAAG,CAACP,IAAI,KAAK,QAAQ,IAAIM,oBAAoB,CAACC,GAAG,CAAC,EAAE;MAC7D;IACF;IACA,IAAIE,mBAAmB,CAACC,GAAG,CAAC,EAAE;MAC5B;IACF;EACF,CAAC,EACD,CAACJ,oBAAoB,EAAEG,mBAAmB,CAC5C,CAAC;EAED,MAAMa,uBAAuB,GAAGnE,WAAW,CACxCoE,OAAwB,IAAK;IAC5B,MAAM;MAAEC;IAAI,CAAC,GAAGD,OAAO;IACvB,IAAIC,GAAG,CAACC,UAAU,CAACtD,gBAAgB,CAAC,IAAIqD,GAAG,KAAK,qBAAqB,EAAE;MACrE9B,UAAU,CAAC,CAAC;MACZ,OAAO,KAAK;IACd;IACA,OAAO,IAAI;EACb,CAAC,EACD,CAACA,UAAU,CACb,CAAC;EAED,MAAMgC,YAAY,GAAGtE,OAAO,CAC1B,OAAO;IAAEuE,GAAG,EAAEhD;EAAgB,CAAC,CAAC,EAChC,CAACA,eAAe,CAClB,CAAC;EACD,MAAMiD,YAAY,GAAGxE,OAAO,CAAC,OAAO;IAAEuE,GAAG,EAAEjD;EAAa,CAAC,CAAC,EAAE,CAACA,YAAY,CAAC,CAAC;EAE3E,oBACEV,KAAA,CAACN,IAAI;IAACmE,KAAK,EAAEC,MAAM,CAACC,IAAK;IAAAC,QAAA,GACtB5C,OAAO,KAAK,QAAQ,gBACnBtB,IAAA,CAACH,OAAO;MAENwC,GAAG,EAAEjB,SAAU;MACf+C,MAAM,EAAEL,YAAa;MACrBM,eAAe,EAAE,CAAC,GAAG,CAAE;MACvBC,2BAA2B,EAAEjE,iBAAkB;MAC/CkE,SAAS,EAAEnB,eAAgB;MAC3BoB,4BAA4B,EAAEf,uBAAwB;MACtDgB,SAAS,EAAEtD,eAAgB;MAC3B6C,KAAK,EAAEC,MAAM,CAACS,OAAQ;MACtBC,oBAAoB;MACpBC,SAAS,EAAE,KAAM;MACjBC,uBAAuB,EAAEC;IAAQ,GAX5BrD,SAYN,CAAC,GACA,IAAI,EAEPF,OAAO,KAAK,QAAQ,gBACnBpB,KAAA,CAACN,IAAI;MAACmE,KAAK,EAAEC,MAAM,CAACc,YAAa;MAAAZ,QAAA,gBAC/BhE,KAAA,CAACN,IAAI;QAACmE,KAAK,EAAEC,MAAM,CAACe,MAAO;QAAAb,QAAA,gBACzBlE,IAAA,CAACL,gBAAgB;UACfqF,OAAO,EAAElD,YAAa;UACtBmD,OAAO,EAAE,EAAG;UACZC,iBAAiB,EAAC,QAAQ;UAC1BC,kBAAkB,EAAC,MAAM;UACzBpB,KAAK,EAAEC,MAAM,CAACoB,UAAW;UAAAlB,QAAA,EAExBnD,oBAAoB,GACnBA,oBAAoB,CAAC,CAAC,gBAEtBb,KAAA,CAACN,IAAI;YAACmE,KAAK,EAAEC,MAAM,CAACqB,eAAgB;YAAAnB,QAAA,gBAClClE,IAAA,CAACJ,IAAI;cAACmE,KAAK,EAAEC,MAAM,CAACsB;YAAc,CAAE,CAAC,eACrCtF,IAAA,CAACJ,IAAI;cAACmE,KAAK,EAAEC,MAAM,CAACuB;YAAa,CAAE,CAAC;UAAA,CAChC;QACP,CACe,CAAC,eAEnBvF,IAAA,CAACJ,IAAI;UAACmE,KAAK,EAAEC,MAAM,CAACwB;QAAa,CAAE,CAAC,EAEnC1E,WAAW,gBACVd,IAAA,CAACP,KAAK;UACJ0E,MAAM,EAAE;YAAEN,GAAG,EAAE/C;UAAY,CAAE;UAC7B2E,UAAU,EAAC,SAAS;UACpB1B,KAAK,EAAEC,MAAM,CAAC0B;QAAK,CACpB,CAAC,gBAEF1F,IAAA,CAACJ,IAAI;UAACmE,KAAK,EAAEC,MAAM,CAAC2B;QAAgB,CAAE,CACvC;MAAA,CACG,CAAC,eACP3F,IAAA,CAACH,OAAO;QAENwC,GAAG,EAAEhB,SAAU;QACf8C,MAAM,EAAEP,YAAa;QACrBQ,eAAe,EAAE,CAAC,GAAG,CAAE;QACvBC,2BAA2B,EAAEjE,iBAAkB;QAC/CkE,SAAS,EAAEf,eAAgB;QAC3BiB,SAAS,EAAErD,eAAgB;QAC3B4C,KAAK,EAAEC,MAAM,CAACS,OAAQ;QACtBC,oBAAoB;QACpBC,SAAS,EAAE,KAAM;QACjBC,uBAAuB,EAAEC;MAAQ,GAV5BnD,SAWN,CAAC;IAAA,CACE,CAAC,GACL,IAAI;EAAA,CACJ,CAAC;AAEX,CAAC;AAED,MAAMsC,MAAM,GAAGtE,UAAU,CAACkG,MAAM,CAAC;EAC/B3B,IAAI,EAAE;IAAE4B,IAAI,EAAE;EAAE,CAAC;EACjBf,YAAY,EAAE;IAAEe,IAAI,EAAE;EAAE,CAAC;EACzBpB,OAAO,EAAE;IAAEoB,IAAI,EAAE;EAAE,CAAC;EACpBd,MAAM,EAAE;IACNe,aAAa,EAAE,KAAK;IACpBC,UAAU,EAAE,QAAQ;IACpBC,eAAe,EAAE,MAAM;IACvBC,iBAAiB,EAAE,EAAE;IACrBC,UAAU,EAAE,EAAE;IACdC,aAAa,EAAE,EAAE;IACjBC,iBAAiB,EAAE1G,UAAU,CAAC2G,aAAa;IAC3CC,iBAAiB,EAAE;EACrB,CAAC;EACDlB,UAAU,EAAE;IACVmB,KAAK,EAAE,EAAE;IACTC,MAAM,EAAE,EAAE;IACVC,cAAc,EAAE,QAAQ;IACxBV,UAAU,EAAE;EACd,CAAC;EACDV,eAAe,EAAE;IACfkB,KAAK,EAAE,EAAE;IACTC,MAAM,EAAE,EAAE;IACVC,cAAc,EAAE,QAAQ;IACxBC,QAAQ,EAAE;EACZ,CAAC;EACDpB,aAAa,EAAE;IACboB,QAAQ,EAAE,UAAU;IACpBC,IAAI,EAAE,CAAC;IACPC,KAAK,EAAE,CAAC;IACRJ,MAAM,EAAE,CAAC;IACTR,eAAe,EAAE,SAAS;IAC1Ba,YAAY,EAAE;EAChB,CAAC;EACDtB,YAAY,EAAE;IACZgB,KAAK,EAAE,EAAE;IACTC,MAAM,EAAE,EAAE;IACVM,eAAe,EAAE,CAAC;IAClBV,iBAAiB,EAAE,CAAC;IACpBW,WAAW,EAAE,SAAS;IACtBC,SAAS,EAAE,CAAC;MAAEC,MAAM,EAAE;IAAQ,CAAC,CAAC;IAChCC,UAAU,EAAE;EACd,CAAC;EACD1B,YAAY,EAAE;IACZK,IAAI,EAAE;EACR,CAAC;EACDH,IAAI,EAAE;IACJa,KAAK,EAAE,GAAG;IACVC,MAAM,EAAE;EACV,CAAC;EACDb,eAAe,EAAE;IACfY,KAAK,EAAE,GAAG;IACVC,MAAM,EAAE;EACV;AACF,CAAC,CAAC;AAEF,eAAe7F,2BAA2B","ignoreList":[]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Messages posted from either WebView via ReactNativeWebView.postMessage(string).
|
|
5
|
+
* Pages should JSON.stringify envelopes before posting.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export function parseDualWebViewEnvelope(raw) {
|
|
9
|
+
try {
|
|
10
|
+
const o = JSON.parse(raw);
|
|
11
|
+
if (o?.bridge === 'dual-webview' && o?.from && o?.action) {
|
|
12
|
+
return o;
|
|
13
|
+
}
|
|
14
|
+
} catch {
|
|
15
|
+
/* not JSON */
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=dualWebViewBridge.types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["parseDualWebViewEnvelope","raw","o","JSON","parse","bridge","from","action"],"sourceRoot":"../../../../src","sources":["services/webview/dualWebViewBridge.types.ts"],"mappings":";;AAAA;AACA;AACA;AACA;;AAgBA,OAAO,SAASA,wBAAwBA,CACtCC,GAAW,EACuB;EAClC,IAAI;IACF,MAAMC,CAAC,GAAGC,IAAI,CAACC,KAAK,CAACH,GAAG,CAA8B;IACtD,IAAIC,CAAC,EAAEG,MAAM,KAAK,cAAc,IAAIH,CAAC,EAAEI,IAAI,IAAIJ,CAAC,EAAEK,MAAM,EAAE;MACxD,OAAOL,CAAC;IACV;EACF,CAAC,CAAC,MAAM;IACN;EAAA;EAEF,OAAO,IAAI;AACb","ignoreList":[]}
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
// Default environment (build-time injected)
|
|
6
6
|
const injectedEnv = 'sandbox';
|
|
7
7
|
const DEFAULT_ENVIRONMENT = injectedEnv === 'production' ? 'production' : 'sandbox';
|
|
8
|
+
|
|
9
|
+
/** Hosted merchant web origins; aligned with `SaversSdkHostedEnvironment` via `setEnvironment` in SDK init. */
|
|
8
10
|
const ENV_URLS = {
|
|
9
11
|
sandbox: 'https://testm.saversapp.com/',
|
|
10
12
|
production: 'https://m.saversapp.com/'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["injectedEnv","DEFAULT_ENVIRONMENT","ENV_URLS","sandbox","production","currentEnvironment","BASE_URL","setEnvironment","env","getEnvironment","getBaseUrl"],"sourceRoot":"../../../src","sources":["utils/config.ts"],"mappings":";;AAAA;;AAIA;AACA,MAAMA,WAAW,GAAG,SAAmB;AACvC,MAAMC,mBAAgC,GACpCD,WAAW,KAAK,YAAY,GAAG,YAAY,GAAG,SAAS;
|
|
1
|
+
{"version":3,"names":["injectedEnv","DEFAULT_ENVIRONMENT","ENV_URLS","sandbox","production","currentEnvironment","BASE_URL","setEnvironment","env","getEnvironment","getBaseUrl"],"sourceRoot":"../../../src","sources":["utils/config.ts"],"mappings":";;AAAA;;AAIA;AACA,MAAMA,WAAW,GAAG,SAAmB;AACvC,MAAMC,mBAAgC,GACpCD,WAAW,KAAK,YAAY,GAAG,YAAY,GAAG,SAAS;;AAEzD;AACA,MAAME,QAAqC,GAAG;EAC5CC,OAAO,EAAE,8BAA8B;EACvCC,UAAU,EAAE;AACd,CAAC;;AAED;AACA,IAAIC,kBAA+B,GAAGJ,mBAAmB;;AAEzD;AACA,IAAIK,QAAgB,GAAGJ,QAAQ,CAACG,kBAAkB,CAAC;;AAEnD;AACA,OAAO,MAAME,cAAc,GAAIC,GAAgB,IAAK;EAClDH,kBAAkB,GAAGG,GAAG;EACxBF,QAAQ,GAAGJ,QAAQ,CAACM,GAAG,CAAC;AAC1B,CAAC;;AAED;AACA,OAAO,MAAMC,cAAc,GAAGA,CAAA,KAAmB;EAC/C,OAAOJ,kBAAkB;AAC3B,CAAC;;AAED;AACA,OAAO,MAAMK,UAAU,GAAGA,CAAA,KAAc;EACtC,OAAOJ,QAAQ;AACjB,CAAC","ignoreList":[]}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
/** Controls which hosted merchant web origin `generateUrl` uses. */
|
|
2
|
+
export type SaversSdkHostedEnvironment = 'SANDBOX' | 'PROD';
|
|
1
3
|
export declare function initializeSDK(providedKeys: {
|
|
2
4
|
apiKey: string;
|
|
3
5
|
encryptionKey: string;
|
|
4
6
|
pRefCode: string;
|
|
5
7
|
authMode: string;
|
|
6
8
|
navigationRef: any;
|
|
9
|
+
/** When set, `generateUrl` uses testm (SANDBOX) or m (PROD). When omitted, build-time default from config applies. */
|
|
10
|
+
environment?: SaversSdkHostedEnvironment;
|
|
7
11
|
}): void;
|
|
8
12
|
export declare const SaversAppSDK: {
|
|
9
13
|
initialized: typeof initializeSDK;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../src/core/runtime.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../../src/core/runtime.ts"],"names":[],"mappings":"AAoBA,oEAAoE;AACpE,MAAM,MAAM,0BAA0B,GAAG,SAAS,GAAG,MAAM,CAAC;AAE5D,wBAAgB,aAAa,CAAC,YAAY,EAAE;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,GAAG,CAAC;IACnB,sHAAsH;IACtH,WAAW,CAAC,EAAE,0BAA0B,CAAC;CAC1C,QAqEA;AAED,eAAO,MAAM,YAAY;;CAExB,CAAC"}
|
|
@@ -6,6 +6,8 @@ export * from './utils/errors';
|
|
|
6
6
|
export * from './utils/logger';
|
|
7
7
|
export * from './utils/validator';
|
|
8
8
|
export * from './services/webview/messageHandler';
|
|
9
|
+
export * from './services/webview/DualWebViewBridgeController';
|
|
10
|
+
export * from './services/webview/dualWebViewBridge.types';
|
|
9
11
|
export * from './data/storage/deviceIdManager';
|
|
10
12
|
export * from './services/navigation/dialPad';
|
|
11
13
|
export * from './services/navigation/openBrowser';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wCAAwC,CAAC;AACvD,cAAc,0CAA0C,CAAC;AACzD,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wCAAwC,CAAC;AACvD,cAAc,0CAA0C,CAAC;AACzD,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mCAAmC,CAAC;AAClD,cAAc,gDAAgD,CAAC;AAC/D,cAAc,4CAA4C,CAAC;AAC3D,cAAc,gCAAgC,CAAC;AAC/C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,gCAAgC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"urlGenerator.d.ts","sourceRoot":"","sources":["../../../../../src/services/url/urlGenerator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"urlGenerator.d.ts","sourceRoot":"","sources":["../../../../../src/services/url/urlGenerator.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,SAAS,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AACvD,MAAM,MAAM,MAAM,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,SAAS,EAAE,CAAA;CAAE,CAAC;AACjE,MAAM,MAAM,OAAO,GAAG;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC;IACf,EAAE,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AACF,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,CAAC;AACtD,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CACzC,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AACF,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,GAAG;IAC9C,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAmCA;AAED,wBAAsB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAoElE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type Surface = 'savers' | 'travel';
|
|
3
|
+
export type DualWebViewBridgeControllerProps = {
|
|
4
|
+
saversAppUrl: string;
|
|
5
|
+
travelPortalUrl?: string;
|
|
6
|
+
partnerLogo?: string;
|
|
7
|
+
renderTravelBackIcon?: () => React.ReactNode;
|
|
8
|
+
initialSurface?: Surface;
|
|
9
|
+
onSaversSdkMessage?: (raw: string, postBack: (data: unknown) => void) => void;
|
|
10
|
+
onLoadEndSavers?: () => void;
|
|
11
|
+
onLoadEndTravel?: () => void;
|
|
12
|
+
};
|
|
13
|
+
export declare const DualWebViewBridgeController: React.FC<DualWebViewBridgeControllerProps>;
|
|
14
|
+
export default DualWebViewBridgeController;
|
|
15
|
+
//# sourceMappingURL=DualWebViewBridgeController.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DualWebViewBridgeController.d.ts","sourceRoot":"","sources":["../../../../../src/services/webview/DualWebViewBridgeController.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAiBtE,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE1C,MAAM,MAAM,gCAAgC,GAAG;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,MAAM,KAAK,CAAC,SAAS,CAAC;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,KAAK,IAAI,CAAC;IAC9E,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;CAC9B,CAAC;AAcF,eAAO,MAAM,2BAA2B,EAAE,KAAK,CAAC,EAAE,CAChD,gCAAgC,CAoOjC,CAAC;AA0DF,eAAe,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Messages posted from either WebView via ReactNativeWebView.postMessage(string).
|
|
3
|
+
* Pages should JSON.stringify envelopes before posting.
|
|
4
|
+
*/
|
|
5
|
+
export type DualWebViewBridgeEnvelope = {
|
|
6
|
+
bridge: 'dual-webview';
|
|
7
|
+
/** Who sent this message (set by the page). */
|
|
8
|
+
from: 'savers' | 'travel';
|
|
9
|
+
/**
|
|
10
|
+
* relay — forward payload to the other WebView via injectJavaScript + CustomEvent.
|
|
11
|
+
* open_travel — show travel surface (reloads travel WebView).
|
|
12
|
+
* close_travel — same as native back (reloads Savers WebView).
|
|
13
|
+
*/
|
|
14
|
+
action: 'relay' | 'open_travel' | 'close_travel';
|
|
15
|
+
/** For relay: which surface should receive the event. */
|
|
16
|
+
to?: 'savers' | 'travel';
|
|
17
|
+
payload?: unknown;
|
|
18
|
+
};
|
|
19
|
+
export declare function parseDualWebViewEnvelope(raw: string): DualWebViewBridgeEnvelope | null;
|
|
20
|
+
//# sourceMappingURL=dualWebViewBridge.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dualWebViewBridge.types.d.ts","sourceRoot":"","sources":["../../../../../src/services/webview/dualWebViewBridge.types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,MAAM,EAAE,cAAc,CAAC;IACvB,+CAA+C;IAC/C,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B;;;;OAIG;IACH,MAAM,EAAE,OAAO,GAAG,aAAa,GAAG,cAAc,CAAC;IACjD,yDAAyD;IACzD,EAAE,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,MAAM,GACV,yBAAyB,GAAG,IAAI,CAUlC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../src/utils/config.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../src/utils/config.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,YAAY,CAAC;AAoBnD,eAAO,MAAM,cAAc,GAAI,KAAK,WAAW,SAG9C,CAAC;AAGF,eAAO,MAAM,cAAc,QAAO,WAEjC,CAAC;AAGF,eAAO,MAAM,UAAU,QAAO,MAE7B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@savers_app/react-native-sandbox-sdk",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.8",
|
|
4
4
|
"description": "Cross-platform React Native SDK exposing native features (maps, dial pad, browser), device ID/location and session utilities, a URL generator, and a WebView message bridge to trigger actions from web content.",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"react-native": "./src/index.tsx",
|
|
@@ -33,14 +33,18 @@
|
|
|
33
33
|
"!**/.*"
|
|
34
34
|
],
|
|
35
35
|
"scripts": {
|
|
36
|
-
"
|
|
37
|
-
"
|
|
36
|
+
"example:android:yarn": "yarn workspace @saversapp/react-native-sdk-example android",
|
|
37
|
+
"example:ios:yarn": "yarn workspace @saversapp/react-native-sdk-example ios",
|
|
38
|
+
"example:android:npm": "npm run -w @saversapp/react-native-sdk-example android",
|
|
39
|
+
"example:ios:npm": "npm run -w @saversapp/react-native-sdk-example ios",
|
|
38
40
|
"clean": "del-cli lib",
|
|
39
41
|
"prepare": "bob build",
|
|
40
42
|
"set:sandbox": "cross-env SDK_ENV=sandbox SDK_PACKAGE=@savers_app/react-native-sandbox-sdk node scripts/replace-config.js",
|
|
41
43
|
"set:production": "cross-env SDK_ENV=production SDK_PACKAGE=@savers_app/react-native-sdk node scripts/replace-config.js",
|
|
42
|
-
"prepare:sandbox": "yarn set:sandbox && yarn install && yarn prepare",
|
|
43
|
-
"prepare:production": "yarn set:production && yarn install && yarn prepare",
|
|
44
|
+
"prepare:sandbox:yarn": "del-cli package-lock.json && cross-env PKG_MGR=yarn yarn set:sandbox && yarn install && yarn prepare",
|
|
45
|
+
"prepare:production:yarn": "del-cli package-lock.json && cross-env PKG_MGR=yarn yarn set:production && yarn install && yarn prepare",
|
|
46
|
+
"prepare:sandbox:npm": "cross-env PKG_MGR=npm npm run set:sandbox && npm install && npm run prepare && del-cli package-lock.json && cross-env PKG_MGR=yarn npm run set:sandbox",
|
|
47
|
+
"prepare:production:npm": "cross-env PKG_MGR=npm npm run set:production && npm install && npm run prepare && del-cli package-lock.json && cross-env PKG_MGR=yarn npm run set:production",
|
|
44
48
|
"typecheck": "tsc",
|
|
45
49
|
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
46
50
|
"test": "jest",
|
|
@@ -62,8 +66,8 @@
|
|
|
62
66
|
},
|
|
63
67
|
"homepage": "https://github.com/pm-code/savers-react-native-sdk#readme",
|
|
64
68
|
"publishConfig": {
|
|
65
|
-
|
|
66
|
-
|
|
69
|
+
"access": "public",
|
|
70
|
+
"registry": "https://registry.npmjs.org/"
|
|
67
71
|
},
|
|
68
72
|
"devDependencies": {
|
|
69
73
|
"@commitlint/config-conventional": "^19.8.1",
|
|
@@ -84,11 +88,13 @@
|
|
|
84
88
|
"eslint-config-prettier": "^10.1.8",
|
|
85
89
|
"eslint-plugin-prettier": "^5.5.4",
|
|
86
90
|
"jest": "^29.7.0",
|
|
87
|
-
"lefthook
|
|
91
|
+
"lefthook": "^2.1.4",
|
|
88
92
|
"prettier": "^3.8.1",
|
|
89
93
|
"react": "19.1.0",
|
|
90
94
|
"react-native": "0.81.5",
|
|
91
95
|
"react-native-builder-bob": "^0.40.13",
|
|
96
|
+
"react-native-safe-area-context": "^5.5.2",
|
|
97
|
+
"react-native-webview": "^13.16.0",
|
|
92
98
|
"release-it": "^19.0.4",
|
|
93
99
|
"typescript": "^5.9.2"
|
|
94
100
|
},
|
|
@@ -100,7 +106,9 @@
|
|
|
100
106
|
"react": "*",
|
|
101
107
|
"react-native": "*",
|
|
102
108
|
"react-native-aes-gcm-crypto": "*",
|
|
103
|
-
"react-native-device-info": "*"
|
|
109
|
+
"react-native-device-info": "*",
|
|
110
|
+
"react-native-safe-area-context": "*",
|
|
111
|
+
"react-native-webview": "*"
|
|
104
112
|
},
|
|
105
113
|
"workspaces": [
|
|
106
114
|
"example",
|
package/src/core/runtime.ts
CHANGED
|
@@ -12,15 +12,23 @@ import {
|
|
|
12
12
|
import { getDeviceId } from '../data/storage/deviceIdManager';
|
|
13
13
|
import { setReactRef } from '../data/storage/reactRefManager';
|
|
14
14
|
|
|
15
|
+
// Hosted app base URL (test vs production merchant web)
|
|
16
|
+
import { setEnvironment } from '../utils/config';
|
|
17
|
+
|
|
15
18
|
// Services
|
|
16
19
|
// import { getDeviceLocation } from '../services/device/location';
|
|
17
20
|
|
|
21
|
+
/** Controls which hosted merchant web origin `generateUrl` uses. */
|
|
22
|
+
export type SaversSdkHostedEnvironment = 'SANDBOX' | 'PROD';
|
|
23
|
+
|
|
18
24
|
export function initializeSDK(providedKeys: {
|
|
19
25
|
apiKey: string;
|
|
20
26
|
encryptionKey: string;
|
|
21
27
|
pRefCode: string;
|
|
22
28
|
authMode: string;
|
|
23
29
|
navigationRef: any;
|
|
30
|
+
/** When set, `generateUrl` uses testm (SANDBOX) or m (PROD). When omitted, build-time default from config applies. */
|
|
31
|
+
environment?: SaversSdkHostedEnvironment;
|
|
24
32
|
}) {
|
|
25
33
|
const keys = providedKeys;
|
|
26
34
|
const missing: string[] = [];
|
|
@@ -35,6 +43,19 @@ export function initializeSDK(providedKeys: {
|
|
|
35
43
|
logger.warn(msg);
|
|
36
44
|
throw new Error(msg);
|
|
37
45
|
}
|
|
46
|
+
|
|
47
|
+
if (keys.environment !== undefined) {
|
|
48
|
+
if (keys.environment !== 'SANDBOX' && keys.environment !== 'PROD') {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`[SDK] Invalid environment: ${String(keys.environment)}. Use 'SANDBOX' or 'PROD'.`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
setEnvironment(keys.environment === 'SANDBOX' ? 'sandbox' : 'production');
|
|
54
|
+
logger.info('[SDK] Hosted app environment', {
|
|
55
|
+
environment: keys.environment,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
38
59
|
setApiKey(keys.apiKey);
|
|
39
60
|
setEncryptionKey(keys.encryptionKey);
|
|
40
61
|
setPRefCode(keys.pRefCode);
|
package/src/index.tsx
CHANGED
|
@@ -6,6 +6,8 @@ export * from './utils/errors';
|
|
|
6
6
|
export * from './utils/logger';
|
|
7
7
|
export * from './utils/validator';
|
|
8
8
|
export * from './services/webview/messageHandler';
|
|
9
|
+
export * from './services/webview/DualWebViewBridgeController';
|
|
10
|
+
export * from './services/webview/dualWebViewBridge.types';
|
|
9
11
|
export * from './data/storage/deviceIdManager';
|
|
10
12
|
export * from './services/navigation/dialPad';
|
|
11
13
|
export * from './services/navigation/openBrowser';
|
|
@@ -9,6 +9,7 @@ import { getLocationCoordinates } from '../../data/storage/locationManager';
|
|
|
9
9
|
import { getEncryptionKey, getPRefCode } from '../../data/storage/keysManager';
|
|
10
10
|
|
|
11
11
|
import { getBaseUrl } from '../../utils/config';
|
|
12
|
+
import { ApiService } from '../../data/network/apiService';
|
|
12
13
|
|
|
13
14
|
export type Attribute = { key: string; value: string };
|
|
14
15
|
export type Screen = { name?: string; attributes?: Attribute[] };
|
|
@@ -38,7 +39,6 @@ export type UrlInput = {
|
|
|
38
39
|
authType?: AuthType;
|
|
39
40
|
deviceInfo?: DeviceInfo;
|
|
40
41
|
sessionId?: string;
|
|
41
|
-
nonce: string;
|
|
42
42
|
};
|
|
43
43
|
export function validateInput(input: UrlInput): {
|
|
44
44
|
ok: boolean;
|
|
@@ -49,7 +49,6 @@ export function validateInput(input: UrlInput): {
|
|
|
49
49
|
if (!input.profile) errors.push('profile is mandatory');
|
|
50
50
|
if (!input.profile?.userId) errors.push('userId is mandatory');
|
|
51
51
|
if (!input.profile?.email) errors.push('email is mandatory');
|
|
52
|
-
if (!input.nonce) errors.push('nonce is mandatory');
|
|
53
52
|
|
|
54
53
|
const pv = input.profile?.pv;
|
|
55
54
|
const ev = input.profile?.ev;
|
|
@@ -86,6 +85,22 @@ export async function generateUrl(input: UrlInput): Promise<string> {
|
|
|
86
85
|
const storedLocation = await getLocationCoordinates();
|
|
87
86
|
const sessionId = await getSessionId();
|
|
88
87
|
|
|
88
|
+
const programCode = await getPRefCode();
|
|
89
|
+
if (!programCode || programCode === '-') {
|
|
90
|
+
throw new SDKError('pRefCode is mandatory. Initialize SDK with pRefCode.');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// get nonce -- start
|
|
94
|
+
const generator = new ApiService().getNonce({
|
|
95
|
+
extUserId: input.profile?.userId ?? '',
|
|
96
|
+
partnerCode: programCode,
|
|
97
|
+
});
|
|
98
|
+
const { value } = await generator.next();
|
|
99
|
+
if (value?.error) throw new SDKError(String(value.error));
|
|
100
|
+
if (!value?.token) throw new SDKError('Nonce not received');
|
|
101
|
+
const resolvedNonce = value.token;
|
|
102
|
+
// get nonce -- end
|
|
103
|
+
|
|
89
104
|
const deviceInfo: DeviceInfo =
|
|
90
105
|
storedLocation != null
|
|
91
106
|
? { dId: deviceId, location: storedLocation }
|
|
@@ -101,7 +116,7 @@ export async function generateUrl(input: UrlInput): Promise<string> {
|
|
|
101
116
|
authType: input.authType ?? 'PHONE',
|
|
102
117
|
sessionId: sessionId ?? '',
|
|
103
118
|
deviceInfo,
|
|
104
|
-
nonce:
|
|
119
|
+
nonce: resolvedNonce,
|
|
105
120
|
};
|
|
106
121
|
|
|
107
122
|
const validation = validateInput({
|
|
@@ -130,10 +145,6 @@ export async function generateUrl(input: UrlInput): Promise<string> {
|
|
|
130
145
|
}
|
|
131
146
|
const encoded = await aesEncrypt(json, key);
|
|
132
147
|
|
|
133
|
-
const programCode = await getPRefCode();
|
|
134
|
-
if (!programCode || programCode === '-') {
|
|
135
|
-
throw new SDKError('pRefCode is mandatory. Initialize SDK with pRefCode.');
|
|
136
|
-
}
|
|
137
148
|
return `${getBaseUrl()}?pRefCode=${encodeURIComponent(
|
|
138
149
|
programCode
|
|
139
150
|
)}&qP=${encodeURIComponent(encoded)}`;
|