@dynamic-labs/react-native-extension 4.0.0-alpha.3 → 4.0.0-alpha.30

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/index.js ADDED
@@ -0,0 +1,299 @@
1
+ import { assertPackageVersion } from '@dynamic-labs/assert-package-version';
2
+ import { StyleSheet, Platform } from 'react-native';
3
+ import { useRef, useEffect, useCallback, useState } from 'react';
4
+ import { WebView as WebView$1 } from 'react-native-webview';
5
+ import { parseMessageTransportData, createRequestChannel } from '@dynamic-labs/message-transport';
6
+ import { Logger } from '@dynamic-labs/logger';
7
+ import { jsx } from 'react/jsx-runtime';
8
+ import { createPasskey, PasskeyStamper } from '@turnkey/react-native-passkey-stamper';
9
+ import { createURL, openURL } from 'expo-linking';
10
+ import { openAuthSessionAsync } from 'expo-web-browser';
11
+ import { getItemAsync, deleteItemAsync, setItemAsync } from 'expo-secure-store';
12
+
13
+ var version = "4.0.0-alpha.30";
14
+
15
+ function _extends() {
16
+ return _extends = Object.assign ? Object.assign.bind() : function (n) {
17
+ for (var e = 1; e < arguments.length; e++) {
18
+ var t = arguments[e];
19
+ for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
20
+ }
21
+ return n;
22
+ }, _extends.apply(null, arguments);
23
+ }
24
+
25
+ const logger = new Logger('react-native-extension');
26
+
27
+ const useIsMounted = () => {
28
+ const isMountedRef = useRef(true);
29
+ useEffect(() => () => {
30
+ isMountedRef.current = false;
31
+ }, []);
32
+ return useCallback(() => isMountedRef.current, [isMountedRef]);
33
+ };
34
+
35
+ const useMessageTransportWebViewBridge = (core, webViewRef) => {
36
+ const canBroadcastMessages = useIsMounted();
37
+ /**
38
+ * Receive a message from the webview and forward it to the client
39
+ * message transport
40
+ */
41
+ const onMessageHandler = event => {
42
+ if (!canBroadcastMessages()) return;
43
+ let parsedData = null;
44
+ try {
45
+ parsedData = JSON.parse(event.nativeEvent.data);
46
+ } catch (err) {
47
+ logger.debug('error parsing data', err);
48
+ return;
49
+ }
50
+ const message = parseMessageTransportData(parsedData);
51
+ if (!message) {
52
+ logger.debug('invalid message', message);
53
+ return;
54
+ }
55
+ /**
56
+ * Only forward messages from the created by the webview
57
+ */
58
+ if (message.origin === 'webview') {
59
+ core.messageTransport.emit(message);
60
+ }
61
+ };
62
+ /**
63
+ * Send messages created by the client to the webview
64
+ */
65
+ useEffect(() => {
66
+ const sendMessageToWebView = message => {
67
+ if (!canBroadcastMessages()) return;
68
+ /**
69
+ * Only forward messages to the webview
70
+ * that where created by the client/host
71
+ */
72
+ if (message.origin === 'host' && webViewRef.current) {
73
+ webViewRef.current.postMessage(JSON.stringify(message));
74
+ }
75
+ };
76
+ core.messageTransport.on(sendMessageToWebView);
77
+ return () => {
78
+ core.messageTransport.off(sendMessageToWebView);
79
+ };
80
+ }, [core.messageTransport, webViewRef, canBroadcastMessages]);
81
+ return {
82
+ onMessageHandler
83
+ };
84
+ };
85
+
86
+ const useWebViewVisibility = core => {
87
+ const webViewVisibilityRequestChannelRef = useRef(createRequestChannel(core.messageTransport));
88
+ const [visible, setVisible] = useState(false);
89
+ useEffect(() => webViewVisibilityRequestChannelRef.current.handle('setVisibility', setVisible), [setVisible]);
90
+ return {
91
+ visible
92
+ };
93
+ };
94
+
95
+ const styles = StyleSheet.create({
96
+ container: {
97
+ backgroundColor: 'transparent',
98
+ bottom: 0,
99
+ flex: 1,
100
+ left: 0,
101
+ position: 'absolute',
102
+ right: 0,
103
+ top: 0,
104
+ width: '100%'
105
+ },
106
+ hide: {
107
+ elevation: 0,
108
+ opacity: 0,
109
+ zIndex: -10000
110
+ },
111
+ show: {
112
+ elevation: 10000,
113
+ opacity: 1,
114
+ zIndex: 10000
115
+ },
116
+ webview: {
117
+ backgroundColor: 'transparent',
118
+ flex: 1
119
+ }
120
+ });
121
+
122
+ const WebView = ({
123
+ webviewUrl,
124
+ core,
125
+ webviewDebuggingEnabled: _webviewDebuggingEnabled = false
126
+ }) => {
127
+ const webViewRef = useRef(null);
128
+ const {
129
+ visible
130
+ } = useWebViewVisibility(core);
131
+ const {
132
+ onMessageHandler
133
+ } = useMessageTransportWebViewBridge(core, webViewRef);
134
+ const containerStyles = [styles['container'], visible ? styles.show : styles.hide];
135
+ return /*#__PURE__*/jsx(WebView$1, {
136
+ ref: webViewRef,
137
+ source: {
138
+ uri: webviewUrl
139
+ },
140
+ containerStyle: containerStyles,
141
+ style: styles['webview'],
142
+ onMessage: onMessageHandler,
143
+ hideKeyboardAccessoryView: true,
144
+ webviewDebuggingEnabled: _webviewDebuggingEnabled,
145
+ onError: () => core.initialization.error = new Error('Could not load Dynamic WebView')
146
+ }, 'webview');
147
+ };
148
+ const createWebView = props => {
149
+ const WebViewWrapper = () => /*#__PURE__*/jsx(WebView, _extends({}, props));
150
+ return WebViewWrapper;
151
+ };
152
+
153
+ /******************************************************************************
154
+ Copyright (c) Microsoft Corporation.
155
+
156
+ Permission to use, copy, modify, and/or distribute this software for any
157
+ purpose with or without fee is hereby granted.
158
+
159
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
160
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
161
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
162
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
163
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
164
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
165
+ PERFORMANCE OF THIS SOFTWARE.
166
+ ***************************************************************************** */
167
+
168
+ function __awaiter(thisArg, _arguments, P, generator) {
169
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
170
+ return new (P || (P = Promise))(function (resolve, reject) {
171
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
172
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
173
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
174
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
175
+ });
176
+ }
177
+
178
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
179
+ var e = new Error(message);
180
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
181
+ };
182
+
183
+ const setupPasskeyHandler = core => {
184
+ const passkeysRequestChannel = createRequestChannel(core.messageTransport);
185
+ passkeysRequestChannel.handle('createPasskey', _a => __awaiter(void 0, [_a], void 0, function* ({
186
+ publicKey
187
+ }) {
188
+ try {
189
+ const {
190
+ attestation
191
+ } = yield createPasskey(publicKey);
192
+ return {
193
+ attestation
194
+ };
195
+ } catch (err) {
196
+ logger.error(err);
197
+ throw err;
198
+ }
199
+ }));
200
+ passkeysRequestChannel.handle('passkeyStamp', (rpId, payload) => __awaiter(void 0, void 0, void 0, function* () {
201
+ try {
202
+ const stamper = new PasskeyStamper({
203
+ rpId
204
+ });
205
+ const stamped = yield stamper.stamp(payload);
206
+ return stamped;
207
+ } catch (err) {
208
+ logger.error(err);
209
+ throw err;
210
+ }
211
+ }));
212
+ };
213
+
214
+ const setupPlatformHandler = core => {
215
+ const platformChannel = createRequestChannel(core.messageTransport);
216
+ core.manifest.setPlatform('react-native');
217
+ core.manifest.setRedirectUrl(createURL(''));
218
+ platformChannel.handle('openURL', url => __awaiter(void 0, void 0, void 0, function* () {
219
+ yield openURL(url);
220
+ }));
221
+ platformChannel.handle('openAuthenticationWindow', _a => __awaiter(void 0, [_a], void 0, function* ({
222
+ url,
223
+ redirectUrl
224
+ }) {
225
+ const result = yield openAuthSessionAsync(url, redirectUrl);
226
+ // When not a success, result can only have a type which is a string describing
227
+ // what happened in a single word.
228
+ if (result.type !== 'success') throw new Error(result.type);
229
+ return result.url;
230
+ }));
231
+ };
232
+
233
+ const assertValidSource = source => {
234
+ if (source !== 'secureStorage') {
235
+ throw new Error(`Invalid storage source "${source}"`);
236
+ }
237
+ };
238
+ const setupStorageHandler = core => {
239
+ const storageRequestChannel = createRequestChannel(core.messageTransport);
240
+ storageRequestChannel.handle('getItem', _a => __awaiter(void 0, [_a], void 0, function* ({
241
+ key,
242
+ source
243
+ }) {
244
+ assertValidSource(source);
245
+ return getItemAsync(key);
246
+ }));
247
+ storageRequestChannel.handle('deleteItem', _b => __awaiter(void 0, [_b], void 0, function* ({
248
+ key,
249
+ source
250
+ }) {
251
+ assertValidSource(source);
252
+ return deleteItemAsync(key);
253
+ }));
254
+ storageRequestChannel.handle('setItem', _c => __awaiter(void 0, [_c], void 0, function* ({
255
+ key,
256
+ data,
257
+ source
258
+ }) {
259
+ assertValidSource(source);
260
+ return setItemAsync(key, data);
261
+ }));
262
+ };
263
+
264
+ const defaultWebviewUrl = `https://webview.dynamicauth.com/${version}`;
265
+ const ReactNativeExtension = ({
266
+ webviewUrl: _webviewUrl = defaultWebviewUrl,
267
+ webviewDebuggingEnabled,
268
+ appOrigin
269
+ } = {}) => (_, core) => {
270
+ const isPlatformSupportedByWebView = Platform.OS === 'android' || Platform.OS === 'ios';
271
+ /**
272
+ * If react-native-webview does not supported it will return
273
+ * a dummy webview component so it does not break expo for web
274
+ */
275
+ if (!isPlatformSupportedByWebView) {
276
+ return {
277
+ reactNative: {
278
+ WebView: () => null
279
+ }
280
+ };
281
+ }
282
+ if (appOrigin) core.manifest.setAppOrigin(appOrigin);
283
+ setupPasskeyHandler(core);
284
+ setupPlatformHandler(core);
285
+ setupStorageHandler(core);
286
+ return {
287
+ reactNative: {
288
+ WebView: createWebView({
289
+ core,
290
+ webviewDebuggingEnabled,
291
+ webviewUrl: _webviewUrl
292
+ })
293
+ }
294
+ };
295
+ };
296
+
297
+ assertPackageVersion('@dynamic-labs/react-native-extension', version);
298
+
299
+ export { ReactNativeExtension };
package/package.json CHANGED
@@ -1,23 +1,24 @@
1
1
  {
2
2
  "name": "@dynamic-labs/react-native-extension",
3
- "version": "4.0.0-alpha.3",
3
+ "version": "4.0.0-alpha.30",
4
4
  "main": "./index.cjs",
5
- "module": "./src/index.js",
5
+ "module": "./index.js",
6
6
  "types": "./src/index.d.ts",
7
- "type": "commonjs",
7
+ "type": "module",
8
8
  "exports": {
9
9
  ".": {
10
10
  "types": "./src/index.d.ts",
11
- "import": "./src/index.js",
12
- "require": "./src/index.cjs"
11
+ "import": "./index.js",
12
+ "require": "./index.cjs"
13
13
  },
14
14
  "./package.json": "./package.json"
15
15
  },
16
16
  "dependencies": {
17
- "@turnkey/react-native-passkey-stamper": "0.2.5",
18
- "@dynamic-labs/client": "4.0.0-alpha.3",
19
- "@dynamic-labs/logger": "4.0.0-alpha.3",
20
- "@dynamic-labs/message-transport": "4.0.0-alpha.3"
17
+ "@turnkey/react-native-passkey-stamper": "0.2.15",
18
+ "@dynamic-labs/assert-package-version": "4.0.0-alpha.30",
19
+ "@dynamic-labs/client": "4.0.0-alpha.30",
20
+ "@dynamic-labs/logger": "4.0.0-alpha.30",
21
+ "@dynamic-labs/message-transport": "4.0.0-alpha.30"
21
22
  },
22
23
  "peerDependencies": {
23
24
  "react": "^18.2.0",
@@ -16,7 +16,7 @@ export type ReactNativeExtensionProps = {
16
16
  };
17
17
  export type IReactNativeExtension = {
18
18
  reactNative: {
19
- WebView: () => JSX.Element;
19
+ WebView: () => JSX.Element | null;
20
20
  };
21
21
  };
22
22
  export declare const ReactNativeExtension: ({ webviewUrl, webviewDebuggingEnabled, appOrigin, }?: ReactNativeExtensionProps) => Extension<IReactNativeExtension>;
@@ -0,0 +1 @@
1
+ export { setupStorageHandler } from './setupStorageHandler';
@@ -0,0 +1,2 @@
1
+ import { Core } from '@dynamic-labs/client';
2
+ export declare const setupStorageHandler: (core: Core) => void;
@@ -1 +0,0 @@
1
- export { setupFetchHandler } from './setupFetchHandler';
@@ -1,2 +0,0 @@
1
- import { Core } from '@dynamic-labs/client';
2
- export declare const setupFetchHandler: (core: Core) => void;
@@ -1 +0,0 @@
1
- export { setupSecureStorageHandler } from './setupSecureStorageHandler';
@@ -1,2 +0,0 @@
1
- import { Core } from '@dynamic-labs/client';
2
- export declare const setupSecureStorageHandler: (core: Core) => void;