@edge-markets/connect-react-native 1.0.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/index.d.mts +1 -157
- package/dist/index.d.ts +1 -157
- package/dist/index.js +35 -43
- package/dist/index.mjs +25 -50
- package/package.json +7 -8
package/README.md
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -1,115 +1,23 @@
|
|
|
1
1
|
import { EdgeEnvironment, EdgeLinkSuccess, EdgeLinkExit, EdgeScope } from '@edge-markets/connect';
|
|
2
2
|
export { ALL_EDGE_SCOPES, Balance, EDGE_ENVIRONMENTS, EdgeApiError, EdgeAuthenticationError, EdgeConsentRequiredError, EdgeEnvironment, EdgeError, EdgeLinkExit, EdgeLinkSuccess, EdgeNetworkError, EdgePopupBlockedError, EdgeScope, EdgeStateMismatchError, EdgeTokenExchangeError, EdgeTokens, SCOPE_DESCRIPTIONS, Transfer, User, formatScopesForEnvironment, getEnvironmentConfig, isApiError, isAuthenticationError, isConsentRequiredError, isNetworkError } from '@edge-markets/connect';
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* EdgeLink for React Native - Plaid-Style Authentication Flow
|
|
6
|
-
*
|
|
7
|
-
* Unlike the browser SDK which uses popups, the React Native SDK uses:
|
|
8
|
-
* - In-App Browser (SFSafariViewController / Chrome Custom Tabs)
|
|
9
|
-
* - Deep Links for OAuth callback
|
|
10
|
-
* - Secure storage for PKCE state
|
|
11
|
-
*
|
|
12
|
-
* This provides a native, secure authentication experience similar to Plaid Link.
|
|
13
|
-
*
|
|
14
|
-
* @module @edge-markets/connect-react-native
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```typescript
|
|
18
|
-
* import { EdgeLink } from '@edge-markets/connect-react-native'
|
|
19
|
-
*
|
|
20
|
-
* const link = new EdgeLink({
|
|
21
|
-
* clientId: 'your-client-id',
|
|
22
|
-
* environment: 'staging',
|
|
23
|
-
* redirectUri: 'myapp://oauth/callback',
|
|
24
|
-
* onSuccess: async (result) => {
|
|
25
|
-
* await sendToBackend(result.code, result.codeVerifier)
|
|
26
|
-
* },
|
|
27
|
-
* onExit: (metadata) => {
|
|
28
|
-
* console.log('User exited:', metadata.reason)
|
|
29
|
-
* },
|
|
30
|
-
* })
|
|
31
|
-
*
|
|
32
|
-
* // Open from a button press
|
|
33
|
-
* <Button onPress={() => link.open()} title="Connect EdgeBoost" />
|
|
34
|
-
* ```
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Configuration for EdgeLink React Native.
|
|
39
|
-
*/
|
|
40
4
|
interface EdgeLinkConfig {
|
|
41
|
-
/**
|
|
42
|
-
* Your OAuth client ID from the EdgeBoost partner portal.
|
|
43
|
-
*/
|
|
44
5
|
clientId: string;
|
|
45
|
-
/**
|
|
46
|
-
* Environment to connect to.
|
|
47
|
-
*/
|
|
48
6
|
environment: EdgeEnvironment;
|
|
49
|
-
/**
|
|
50
|
-
* Deep link URI for OAuth callback.
|
|
51
|
-
*
|
|
52
|
-
* This must be registered in your app's URL schemes (iOS) and
|
|
53
|
-
* intent filters (Android), and in your EdgeBoost OAuth client settings.
|
|
54
|
-
*
|
|
55
|
-
* @example
|
|
56
|
-
* - Custom scheme: `myapp://oauth/callback`
|
|
57
|
-
* - Universal link: `https://myapp.com/oauth/callback`
|
|
58
|
-
*/
|
|
59
7
|
redirectUri: string;
|
|
60
|
-
/**
|
|
61
|
-
* Called when user successfully authenticates and grants consent.
|
|
62
|
-
*/
|
|
63
8
|
onSuccess: (result: EdgeLinkSuccess) => void;
|
|
64
|
-
/**
|
|
65
|
-
* Called when user exits the flow.
|
|
66
|
-
*/
|
|
67
9
|
onExit?: (metadata: EdgeLinkExit) => void;
|
|
68
|
-
/**
|
|
69
|
-
* Called for various events during the flow.
|
|
70
|
-
*/
|
|
71
10
|
onEvent?: (event: EdgeLinkEvent) => void;
|
|
72
|
-
/**
|
|
73
|
-
* OAuth scopes to request.
|
|
74
|
-
* @default All available scopes
|
|
75
|
-
*/
|
|
76
11
|
scopes?: EdgeScope[];
|
|
77
|
-
/**
|
|
78
|
-
* Custom URL for the Link page (development only).
|
|
79
|
-
*/
|
|
80
12
|
linkUrl?: string;
|
|
81
|
-
/**
|
|
82
|
-
* Use external browser instead of in-app browser.
|
|
83
|
-
* @default false
|
|
84
|
-
*/
|
|
85
13
|
useExternalBrowser?: boolean;
|
|
86
14
|
}
|
|
87
|
-
/**
|
|
88
|
-
* Event emitted during the Link flow.
|
|
89
|
-
*/
|
|
90
15
|
interface EdgeLinkEvent {
|
|
91
16
|
eventName: EdgeLinkEventName;
|
|
92
17
|
timestamp: number;
|
|
93
18
|
metadata?: Record<string, unknown>;
|
|
94
19
|
}
|
|
95
20
|
type EdgeLinkEventName = 'OPEN' | 'CLOSE' | 'HANDOFF' | 'SUCCESS' | 'ERROR' | 'REDIRECT';
|
|
96
|
-
/**
|
|
97
|
-
* EdgeLink for React Native - handles OAuth flow with in-app browser.
|
|
98
|
-
*
|
|
99
|
-
* @example
|
|
100
|
-
* ```typescript
|
|
101
|
-
* const link = new EdgeLink({
|
|
102
|
-
* clientId: 'your-client-id',
|
|
103
|
-
* environment: 'staging',
|
|
104
|
-
* redirectUri: 'myapp://oauth/callback',
|
|
105
|
-
* onSuccess: handleSuccess,
|
|
106
|
-
* onExit: handleExit,
|
|
107
|
-
* })
|
|
108
|
-
*
|
|
109
|
-
* // Later, in response to user action
|
|
110
|
-
* await link.open()
|
|
111
|
-
* ```
|
|
112
|
-
*/
|
|
113
21
|
declare class EdgeLink {
|
|
114
22
|
private readonly config;
|
|
115
23
|
private pkce;
|
|
@@ -118,31 +26,9 @@ declare class EdgeLink {
|
|
|
118
26
|
private isOpen;
|
|
119
27
|
private isDestroyed;
|
|
120
28
|
constructor(config: EdgeLinkConfig);
|
|
121
|
-
/**
|
|
122
|
-
* Opens the EdgeLink authentication flow.
|
|
123
|
-
*
|
|
124
|
-
* This launches an in-app browser with the EdgeBoost login/consent page.
|
|
125
|
-
* When complete, the browser redirects to your redirectUri and the
|
|
126
|
-
* onSuccess/onExit callback is called.
|
|
127
|
-
*/
|
|
128
29
|
open(): Promise<void>;
|
|
129
|
-
/**
|
|
130
|
-
* Manually handles a deep link URL.
|
|
131
|
-
*
|
|
132
|
-
* Use this if you're handling deep links yourself instead of relying
|
|
133
|
-
* on the automatic listener.
|
|
134
|
-
*
|
|
135
|
-
* @param url - The deep link URL received
|
|
136
|
-
* @returns true if the URL was handled, false otherwise
|
|
137
|
-
*/
|
|
138
30
|
handleDeepLink(url: string): boolean;
|
|
139
|
-
/**
|
|
140
|
-
* Closes the EdgeLink flow.
|
|
141
|
-
*/
|
|
142
31
|
close(): Promise<void>;
|
|
143
|
-
/**
|
|
144
|
-
* Destroys the EdgeLink instance.
|
|
145
|
-
*/
|
|
146
32
|
destroy(): void;
|
|
147
33
|
private buildLinkUrl;
|
|
148
34
|
private setupLinkListener;
|
|
@@ -302,54 +188,12 @@ declare function useEdgeLinkHandler(config: UseEdgeLinkHandlerConfig): UseEdgeLi
|
|
|
302
188
|
*/
|
|
303
189
|
declare function useEdgeLinkEvents(onEvent: (event: EdgeLinkEvent) => void, deps?: React.DependencyList): void;
|
|
304
190
|
|
|
305
|
-
/**
|
|
306
|
-
* PKCE (Proof Key for Code Exchange) Utilities for React Native
|
|
307
|
-
*
|
|
308
|
-
* React Native doesn't have Web Crypto API natively, so we use a
|
|
309
|
-
* compatible implementation that works across platforms.
|
|
310
|
-
*
|
|
311
|
-
* For production apps, consider installing:
|
|
312
|
-
* - `react-native-get-random-values` (polyfill for crypto.getRandomValues)
|
|
313
|
-
* - `expo-crypto` (if using Expo)
|
|
314
|
-
*
|
|
315
|
-
* @module @edge-markets/connect-react-native/pkce
|
|
316
|
-
*/
|
|
317
|
-
/**
|
|
318
|
-
* A PKCE code verifier and challenge pair.
|
|
319
|
-
*/
|
|
320
191
|
interface PKCEPair {
|
|
321
|
-
/** High-entropy random string (43-128 characters). Keep secret until token exchange. */
|
|
322
192
|
verifier: string;
|
|
323
|
-
/** SHA-256 hash of verifier, base64url encoded. Include in authorization URL. */
|
|
324
193
|
challenge: string;
|
|
325
194
|
}
|
|
326
|
-
/**
|
|
327
|
-
* Generates a PKCE code verifier and challenge pair.
|
|
328
|
-
*
|
|
329
|
-
* @example
|
|
330
|
-
* ```typescript
|
|
331
|
-
* const pkce = await generatePKCE()
|
|
332
|
-
*
|
|
333
|
-
* // Include challenge in authorization URL
|
|
334
|
-
* const authUrl = `https://auth.example.com/authorize?code_challenge=${pkce.challenge}&code_challenge_method=S256`
|
|
335
|
-
*
|
|
336
|
-
* // Later, include verifier in token exchange
|
|
337
|
-
* const tokens = await exchangeCode(code, pkce.verifier)
|
|
338
|
-
* ```
|
|
339
|
-
*/
|
|
340
195
|
declare function generatePKCE(): Promise<PKCEPair>;
|
|
341
|
-
/**
|
|
342
|
-
* Generates a random state parameter for CSRF protection.
|
|
343
|
-
*
|
|
344
|
-
* @returns 64-character hex string (32 bytes of entropy)
|
|
345
|
-
*/
|
|
346
196
|
declare function generateState(): string;
|
|
347
|
-
|
|
348
|
-
* Checks if secure crypto is available.
|
|
349
|
-
*
|
|
350
|
-
* Returns false if only Math.random fallback is being used.
|
|
351
|
-
* Use this to warn users in development.
|
|
352
|
-
*/
|
|
353
|
-
declare function isSecureCryptoAvailable(): boolean;
|
|
197
|
+
declare function isSecureCryptoAvailable(): Promise<boolean>;
|
|
354
198
|
|
|
355
199
|
export { EdgeLink, type EdgeLinkConfig, type EdgeLinkEvent, type EdgeLinkEventName, type PKCEPair, type UseEdgeLinkConfig, type UseEdgeLinkHandlerConfig, type UseEdgeLinkHandlerReturn, type UseEdgeLinkReturn, generatePKCE, generateState, isSecureCryptoAvailable, useEdgeLink, useEdgeLinkEvents, useEdgeLinkHandler };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,115 +1,23 @@
|
|
|
1
1
|
import { EdgeEnvironment, EdgeLinkSuccess, EdgeLinkExit, EdgeScope } from '@edge-markets/connect';
|
|
2
2
|
export { ALL_EDGE_SCOPES, Balance, EDGE_ENVIRONMENTS, EdgeApiError, EdgeAuthenticationError, EdgeConsentRequiredError, EdgeEnvironment, EdgeError, EdgeLinkExit, EdgeLinkSuccess, EdgeNetworkError, EdgePopupBlockedError, EdgeScope, EdgeStateMismatchError, EdgeTokenExchangeError, EdgeTokens, SCOPE_DESCRIPTIONS, Transfer, User, formatScopesForEnvironment, getEnvironmentConfig, isApiError, isAuthenticationError, isConsentRequiredError, isNetworkError } from '@edge-markets/connect';
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
* EdgeLink for React Native - Plaid-Style Authentication Flow
|
|
6
|
-
*
|
|
7
|
-
* Unlike the browser SDK which uses popups, the React Native SDK uses:
|
|
8
|
-
* - In-App Browser (SFSafariViewController / Chrome Custom Tabs)
|
|
9
|
-
* - Deep Links for OAuth callback
|
|
10
|
-
* - Secure storage for PKCE state
|
|
11
|
-
*
|
|
12
|
-
* This provides a native, secure authentication experience similar to Plaid Link.
|
|
13
|
-
*
|
|
14
|
-
* @module @edge-markets/connect-react-native
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```typescript
|
|
18
|
-
* import { EdgeLink } from '@edge-markets/connect-react-native'
|
|
19
|
-
*
|
|
20
|
-
* const link = new EdgeLink({
|
|
21
|
-
* clientId: 'your-client-id',
|
|
22
|
-
* environment: 'staging',
|
|
23
|
-
* redirectUri: 'myapp://oauth/callback',
|
|
24
|
-
* onSuccess: async (result) => {
|
|
25
|
-
* await sendToBackend(result.code, result.codeVerifier)
|
|
26
|
-
* },
|
|
27
|
-
* onExit: (metadata) => {
|
|
28
|
-
* console.log('User exited:', metadata.reason)
|
|
29
|
-
* },
|
|
30
|
-
* })
|
|
31
|
-
*
|
|
32
|
-
* // Open from a button press
|
|
33
|
-
* <Button onPress={() => link.open()} title="Connect EdgeBoost" />
|
|
34
|
-
* ```
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Configuration for EdgeLink React Native.
|
|
39
|
-
*/
|
|
40
4
|
interface EdgeLinkConfig {
|
|
41
|
-
/**
|
|
42
|
-
* Your OAuth client ID from the EdgeBoost partner portal.
|
|
43
|
-
*/
|
|
44
5
|
clientId: string;
|
|
45
|
-
/**
|
|
46
|
-
* Environment to connect to.
|
|
47
|
-
*/
|
|
48
6
|
environment: EdgeEnvironment;
|
|
49
|
-
/**
|
|
50
|
-
* Deep link URI for OAuth callback.
|
|
51
|
-
*
|
|
52
|
-
* This must be registered in your app's URL schemes (iOS) and
|
|
53
|
-
* intent filters (Android), and in your EdgeBoost OAuth client settings.
|
|
54
|
-
*
|
|
55
|
-
* @example
|
|
56
|
-
* - Custom scheme: `myapp://oauth/callback`
|
|
57
|
-
* - Universal link: `https://myapp.com/oauth/callback`
|
|
58
|
-
*/
|
|
59
7
|
redirectUri: string;
|
|
60
|
-
/**
|
|
61
|
-
* Called when user successfully authenticates and grants consent.
|
|
62
|
-
*/
|
|
63
8
|
onSuccess: (result: EdgeLinkSuccess) => void;
|
|
64
|
-
/**
|
|
65
|
-
* Called when user exits the flow.
|
|
66
|
-
*/
|
|
67
9
|
onExit?: (metadata: EdgeLinkExit) => void;
|
|
68
|
-
/**
|
|
69
|
-
* Called for various events during the flow.
|
|
70
|
-
*/
|
|
71
10
|
onEvent?: (event: EdgeLinkEvent) => void;
|
|
72
|
-
/**
|
|
73
|
-
* OAuth scopes to request.
|
|
74
|
-
* @default All available scopes
|
|
75
|
-
*/
|
|
76
11
|
scopes?: EdgeScope[];
|
|
77
|
-
/**
|
|
78
|
-
* Custom URL for the Link page (development only).
|
|
79
|
-
*/
|
|
80
12
|
linkUrl?: string;
|
|
81
|
-
/**
|
|
82
|
-
* Use external browser instead of in-app browser.
|
|
83
|
-
* @default false
|
|
84
|
-
*/
|
|
85
13
|
useExternalBrowser?: boolean;
|
|
86
14
|
}
|
|
87
|
-
/**
|
|
88
|
-
* Event emitted during the Link flow.
|
|
89
|
-
*/
|
|
90
15
|
interface EdgeLinkEvent {
|
|
91
16
|
eventName: EdgeLinkEventName;
|
|
92
17
|
timestamp: number;
|
|
93
18
|
metadata?: Record<string, unknown>;
|
|
94
19
|
}
|
|
95
20
|
type EdgeLinkEventName = 'OPEN' | 'CLOSE' | 'HANDOFF' | 'SUCCESS' | 'ERROR' | 'REDIRECT';
|
|
96
|
-
/**
|
|
97
|
-
* EdgeLink for React Native - handles OAuth flow with in-app browser.
|
|
98
|
-
*
|
|
99
|
-
* @example
|
|
100
|
-
* ```typescript
|
|
101
|
-
* const link = new EdgeLink({
|
|
102
|
-
* clientId: 'your-client-id',
|
|
103
|
-
* environment: 'staging',
|
|
104
|
-
* redirectUri: 'myapp://oauth/callback',
|
|
105
|
-
* onSuccess: handleSuccess,
|
|
106
|
-
* onExit: handleExit,
|
|
107
|
-
* })
|
|
108
|
-
*
|
|
109
|
-
* // Later, in response to user action
|
|
110
|
-
* await link.open()
|
|
111
|
-
* ```
|
|
112
|
-
*/
|
|
113
21
|
declare class EdgeLink {
|
|
114
22
|
private readonly config;
|
|
115
23
|
private pkce;
|
|
@@ -118,31 +26,9 @@ declare class EdgeLink {
|
|
|
118
26
|
private isOpen;
|
|
119
27
|
private isDestroyed;
|
|
120
28
|
constructor(config: EdgeLinkConfig);
|
|
121
|
-
/**
|
|
122
|
-
* Opens the EdgeLink authentication flow.
|
|
123
|
-
*
|
|
124
|
-
* This launches an in-app browser with the EdgeBoost login/consent page.
|
|
125
|
-
* When complete, the browser redirects to your redirectUri and the
|
|
126
|
-
* onSuccess/onExit callback is called.
|
|
127
|
-
*/
|
|
128
29
|
open(): Promise<void>;
|
|
129
|
-
/**
|
|
130
|
-
* Manually handles a deep link URL.
|
|
131
|
-
*
|
|
132
|
-
* Use this if you're handling deep links yourself instead of relying
|
|
133
|
-
* on the automatic listener.
|
|
134
|
-
*
|
|
135
|
-
* @param url - The deep link URL received
|
|
136
|
-
* @returns true if the URL was handled, false otherwise
|
|
137
|
-
*/
|
|
138
30
|
handleDeepLink(url: string): boolean;
|
|
139
|
-
/**
|
|
140
|
-
* Closes the EdgeLink flow.
|
|
141
|
-
*/
|
|
142
31
|
close(): Promise<void>;
|
|
143
|
-
/**
|
|
144
|
-
* Destroys the EdgeLink instance.
|
|
145
|
-
*/
|
|
146
32
|
destroy(): void;
|
|
147
33
|
private buildLinkUrl;
|
|
148
34
|
private setupLinkListener;
|
|
@@ -302,54 +188,12 @@ declare function useEdgeLinkHandler(config: UseEdgeLinkHandlerConfig): UseEdgeLi
|
|
|
302
188
|
*/
|
|
303
189
|
declare function useEdgeLinkEvents(onEvent: (event: EdgeLinkEvent) => void, deps?: React.DependencyList): void;
|
|
304
190
|
|
|
305
|
-
/**
|
|
306
|
-
* PKCE (Proof Key for Code Exchange) Utilities for React Native
|
|
307
|
-
*
|
|
308
|
-
* React Native doesn't have Web Crypto API natively, so we use a
|
|
309
|
-
* compatible implementation that works across platforms.
|
|
310
|
-
*
|
|
311
|
-
* For production apps, consider installing:
|
|
312
|
-
* - `react-native-get-random-values` (polyfill for crypto.getRandomValues)
|
|
313
|
-
* - `expo-crypto` (if using Expo)
|
|
314
|
-
*
|
|
315
|
-
* @module @edge-markets/connect-react-native/pkce
|
|
316
|
-
*/
|
|
317
|
-
/**
|
|
318
|
-
* A PKCE code verifier and challenge pair.
|
|
319
|
-
*/
|
|
320
191
|
interface PKCEPair {
|
|
321
|
-
/** High-entropy random string (43-128 characters). Keep secret until token exchange. */
|
|
322
192
|
verifier: string;
|
|
323
|
-
/** SHA-256 hash of verifier, base64url encoded. Include in authorization URL. */
|
|
324
193
|
challenge: string;
|
|
325
194
|
}
|
|
326
|
-
/**
|
|
327
|
-
* Generates a PKCE code verifier and challenge pair.
|
|
328
|
-
*
|
|
329
|
-
* @example
|
|
330
|
-
* ```typescript
|
|
331
|
-
* const pkce = await generatePKCE()
|
|
332
|
-
*
|
|
333
|
-
* // Include challenge in authorization URL
|
|
334
|
-
* const authUrl = `https://auth.example.com/authorize?code_challenge=${pkce.challenge}&code_challenge_method=S256`
|
|
335
|
-
*
|
|
336
|
-
* // Later, include verifier in token exchange
|
|
337
|
-
* const tokens = await exchangeCode(code, pkce.verifier)
|
|
338
|
-
* ```
|
|
339
|
-
*/
|
|
340
195
|
declare function generatePKCE(): Promise<PKCEPair>;
|
|
341
|
-
/**
|
|
342
|
-
* Generates a random state parameter for CSRF protection.
|
|
343
|
-
*
|
|
344
|
-
* @returns 64-character hex string (32 bytes of entropy)
|
|
345
|
-
*/
|
|
346
196
|
declare function generateState(): string;
|
|
347
|
-
|
|
348
|
-
* Checks if secure crypto is available.
|
|
349
|
-
*
|
|
350
|
-
* Returns false if only Math.random fallback is being used.
|
|
351
|
-
* Use this to warn users in development.
|
|
352
|
-
*/
|
|
353
|
-
declare function isSecureCryptoAvailable(): boolean;
|
|
197
|
+
declare function isSecureCryptoAvailable(): Promise<boolean>;
|
|
354
198
|
|
|
355
199
|
export { EdgeLink, type EdgeLinkConfig, type EdgeLinkEvent, type EdgeLinkEventName, type PKCEPair, type UseEdgeLinkConfig, type UseEdgeLinkHandlerConfig, type UseEdgeLinkHandlerReturn, type UseEdgeLinkReturn, generatePKCE, generateState, isSecureCryptoAvailable, useEdgeLink, useEdgeLinkEvents, useEdgeLinkHandler };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -58,7 +68,7 @@ function hasNativeCrypto() {
|
|
|
58
68
|
}
|
|
59
69
|
async function sha256Fallback(message) {
|
|
60
70
|
try {
|
|
61
|
-
const ExpoCrypto =
|
|
71
|
+
const ExpoCrypto = await import("expo-crypto");
|
|
62
72
|
const hash = await ExpoCrypto.digestStringAsync(
|
|
63
73
|
ExpoCrypto.CryptoDigestAlgorithm.SHA256,
|
|
64
74
|
message,
|
|
@@ -73,8 +83,8 @@ async function sha256Fallback(message) {
|
|
|
73
83
|
} catch {
|
|
74
84
|
}
|
|
75
85
|
try {
|
|
76
|
-
const
|
|
77
|
-
const hash = createHash("sha256").update(message).digest();
|
|
86
|
+
const quickCrypto = await import("react-native-quick-crypto");
|
|
87
|
+
const hash = quickCrypto.createHash("sha256").update(message).digest();
|
|
78
88
|
return hash.buffer;
|
|
79
89
|
} catch {
|
|
80
90
|
}
|
|
@@ -212,14 +222,14 @@ function pureJsSha256(message) {
|
|
|
212
222
|
return (x >>> n | x << 32 - n) >>> 0;
|
|
213
223
|
}
|
|
214
224
|
}
|
|
215
|
-
function getRandomBytes(byteLength) {
|
|
225
|
+
async function getRandomBytes(byteLength) {
|
|
216
226
|
const array = new Uint8Array(byteLength);
|
|
217
227
|
if (typeof globalThis.crypto?.getRandomValues === "function") {
|
|
218
228
|
globalThis.crypto.getRandomValues(array);
|
|
219
229
|
return array;
|
|
220
230
|
}
|
|
221
231
|
try {
|
|
222
|
-
const ExpoRandom =
|
|
232
|
+
const ExpoRandom = await import("expo-random");
|
|
223
233
|
return ExpoRandom.getRandomBytes(byteLength);
|
|
224
234
|
} catch {
|
|
225
235
|
}
|
|
@@ -231,8 +241,8 @@ function getRandomBytes(byteLength) {
|
|
|
231
241
|
}
|
|
232
242
|
return array;
|
|
233
243
|
}
|
|
234
|
-
function generateRandomHex(byteLength) {
|
|
235
|
-
const bytes = getRandomBytes(byteLength);
|
|
244
|
+
async function generateRandomHex(byteLength) {
|
|
245
|
+
const bytes = await getRandomBytes(byteLength);
|
|
236
246
|
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
237
247
|
}
|
|
238
248
|
async function sha256(plain) {
|
|
@@ -266,20 +276,28 @@ function base64UrlEncode(buffer) {
|
|
|
266
276
|
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
267
277
|
}
|
|
268
278
|
async function generatePKCE() {
|
|
269
|
-
const verifier = generateRandomHex(64);
|
|
279
|
+
const verifier = await generateRandomHex(64);
|
|
270
280
|
const hash = await sha256(verifier);
|
|
271
281
|
const challenge = base64UrlEncode(hash);
|
|
272
282
|
return { verifier, challenge };
|
|
273
283
|
}
|
|
274
284
|
function generateState() {
|
|
275
|
-
|
|
285
|
+
const array = new Uint8Array(32);
|
|
286
|
+
if (typeof globalThis.crypto?.getRandomValues === "function") {
|
|
287
|
+
globalThis.crypto.getRandomValues(array);
|
|
288
|
+
} else {
|
|
289
|
+
for (let i = 0; i < 32; i++) {
|
|
290
|
+
array[i] = Math.floor(Math.random() * 256);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return Array.from(array, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
276
294
|
}
|
|
277
|
-
function isSecureCryptoAvailable() {
|
|
295
|
+
async function isSecureCryptoAvailable() {
|
|
278
296
|
if (typeof globalThis.crypto?.getRandomValues === "function") {
|
|
279
297
|
return true;
|
|
280
298
|
}
|
|
281
299
|
try {
|
|
282
|
-
|
|
300
|
+
await import("expo-random");
|
|
283
301
|
return true;
|
|
284
302
|
} catch {
|
|
285
303
|
return false;
|
|
@@ -293,10 +311,10 @@ async function openInAppBrowser(url, useExternal = false) {
|
|
|
293
311
|
return;
|
|
294
312
|
}
|
|
295
313
|
try {
|
|
296
|
-
const
|
|
314
|
+
const module2 = await import("react-native-inappbrowser-reborn");
|
|
315
|
+
const InAppBrowser = module2.default;
|
|
297
316
|
if (await InAppBrowser.isAvailable()) {
|
|
298
317
|
await InAppBrowser.openAuth(url, "", {
|
|
299
|
-
// iOS options
|
|
300
318
|
dismissButtonStyle: "cancel",
|
|
301
319
|
preferredBarTintColor: "#1a1a2e",
|
|
302
320
|
preferredControlTintColor: "#00d4aa",
|
|
@@ -304,7 +322,6 @@ async function openInAppBrowser(url, useExternal = false) {
|
|
|
304
322
|
animated: true,
|
|
305
323
|
modalEnabled: true,
|
|
306
324
|
enableBarCollapsing: false,
|
|
307
|
-
// Android options
|
|
308
325
|
showTitle: true,
|
|
309
326
|
toolbarColor: "#1a1a2e",
|
|
310
327
|
secondaryToolbarColor: "#16213e",
|
|
@@ -325,7 +342,7 @@ async function openInAppBrowser(url, useExternal = false) {
|
|
|
325
342
|
} catch {
|
|
326
343
|
}
|
|
327
344
|
try {
|
|
328
|
-
const WebBrowser =
|
|
345
|
+
const WebBrowser = await import("expo-web-browser");
|
|
329
346
|
await WebBrowser.openAuthSessionAsync(url, "");
|
|
330
347
|
return;
|
|
331
348
|
} catch {
|
|
@@ -335,12 +352,12 @@ async function openInAppBrowser(url, useExternal = false) {
|
|
|
335
352
|
}
|
|
336
353
|
async function closeInAppBrowser() {
|
|
337
354
|
try {
|
|
338
|
-
const
|
|
339
|
-
|
|
355
|
+
const module2 = await import("react-native-inappbrowser-reborn");
|
|
356
|
+
module2.default.close();
|
|
340
357
|
} catch {
|
|
341
358
|
}
|
|
342
359
|
try {
|
|
343
|
-
const WebBrowser =
|
|
360
|
+
const WebBrowser = await import("expo-web-browser");
|
|
344
361
|
WebBrowser.dismissBrowser();
|
|
345
362
|
} catch {
|
|
346
363
|
}
|
|
@@ -366,13 +383,6 @@ var EdgeLink = class {
|
|
|
366
383
|
}
|
|
367
384
|
this.config = config;
|
|
368
385
|
}
|
|
369
|
-
/**
|
|
370
|
-
* Opens the EdgeLink authentication flow.
|
|
371
|
-
*
|
|
372
|
-
* This launches an in-app browser with the EdgeBoost login/consent page.
|
|
373
|
-
* When complete, the browser redirects to your redirectUri and the
|
|
374
|
-
* onSuccess/onExit callback is called.
|
|
375
|
-
*/
|
|
376
386
|
async open() {
|
|
377
387
|
if (this.isDestroyed) {
|
|
378
388
|
throw new Error("EdgeLink: Cannot open - instance has been destroyed");
|
|
@@ -402,15 +412,6 @@ var EdgeLink = class {
|
|
|
402
412
|
});
|
|
403
413
|
}
|
|
404
414
|
}
|
|
405
|
-
/**
|
|
406
|
-
* Manually handles a deep link URL.
|
|
407
|
-
*
|
|
408
|
-
* Use this if you're handling deep links yourself instead of relying
|
|
409
|
-
* on the automatic listener.
|
|
410
|
-
*
|
|
411
|
-
* @param url - The deep link URL received
|
|
412
|
-
* @returns true if the URL was handled, false otherwise
|
|
413
|
-
*/
|
|
414
415
|
handleDeepLink(url) {
|
|
415
416
|
if (!this.isOpen || !url.startsWith(this.config.redirectUri)) {
|
|
416
417
|
return false;
|
|
@@ -418,9 +419,6 @@ var EdgeLink = class {
|
|
|
418
419
|
this.processCallback(url);
|
|
419
420
|
return true;
|
|
420
421
|
}
|
|
421
|
-
/**
|
|
422
|
-
* Closes the EdgeLink flow.
|
|
423
|
-
*/
|
|
424
422
|
async close() {
|
|
425
423
|
if (!this.isOpen) return;
|
|
426
424
|
await closeInAppBrowser();
|
|
@@ -430,16 +428,10 @@ var EdgeLink = class {
|
|
|
430
428
|
reason: "user_closed"
|
|
431
429
|
});
|
|
432
430
|
}
|
|
433
|
-
/**
|
|
434
|
-
* Destroys the EdgeLink instance.
|
|
435
|
-
*/
|
|
436
431
|
destroy() {
|
|
437
432
|
this.isDestroyed = true;
|
|
438
433
|
this.cleanup();
|
|
439
434
|
}
|
|
440
|
-
// ===========================================================================
|
|
441
|
-
// PRIVATE METHODS
|
|
442
|
-
// ===========================================================================
|
|
443
435
|
buildLinkUrl() {
|
|
444
436
|
const envConfig = (0, import_connect.getEnvironmentConfig)(this.config.environment);
|
|
445
437
|
const baseUrl = this.config.linkUrl || `${envConfig.userClientUrl}/oauth/link`;
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
-
}) : x)(function(x) {
|
|
4
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
-
});
|
|
7
|
-
|
|
8
1
|
// src/index.ts
|
|
9
2
|
import {
|
|
10
3
|
getEnvironmentConfig as getEnvironmentConfig2,
|
|
@@ -40,7 +33,7 @@ function hasNativeCrypto() {
|
|
|
40
33
|
}
|
|
41
34
|
async function sha256Fallback(message) {
|
|
42
35
|
try {
|
|
43
|
-
const ExpoCrypto =
|
|
36
|
+
const ExpoCrypto = await import("expo-crypto");
|
|
44
37
|
const hash = await ExpoCrypto.digestStringAsync(
|
|
45
38
|
ExpoCrypto.CryptoDigestAlgorithm.SHA256,
|
|
46
39
|
message,
|
|
@@ -55,8 +48,8 @@ async function sha256Fallback(message) {
|
|
|
55
48
|
} catch {
|
|
56
49
|
}
|
|
57
50
|
try {
|
|
58
|
-
const
|
|
59
|
-
const hash = createHash("sha256").update(message).digest();
|
|
51
|
+
const quickCrypto = await import("react-native-quick-crypto");
|
|
52
|
+
const hash = quickCrypto.createHash("sha256").update(message).digest();
|
|
60
53
|
return hash.buffer;
|
|
61
54
|
} catch {
|
|
62
55
|
}
|
|
@@ -194,14 +187,14 @@ function pureJsSha256(message) {
|
|
|
194
187
|
return (x >>> n | x << 32 - n) >>> 0;
|
|
195
188
|
}
|
|
196
189
|
}
|
|
197
|
-
function getRandomBytes(byteLength) {
|
|
190
|
+
async function getRandomBytes(byteLength) {
|
|
198
191
|
const array = new Uint8Array(byteLength);
|
|
199
192
|
if (typeof globalThis.crypto?.getRandomValues === "function") {
|
|
200
193
|
globalThis.crypto.getRandomValues(array);
|
|
201
194
|
return array;
|
|
202
195
|
}
|
|
203
196
|
try {
|
|
204
|
-
const ExpoRandom =
|
|
197
|
+
const ExpoRandom = await import("expo-random");
|
|
205
198
|
return ExpoRandom.getRandomBytes(byteLength);
|
|
206
199
|
} catch {
|
|
207
200
|
}
|
|
@@ -213,8 +206,8 @@ function getRandomBytes(byteLength) {
|
|
|
213
206
|
}
|
|
214
207
|
return array;
|
|
215
208
|
}
|
|
216
|
-
function generateRandomHex(byteLength) {
|
|
217
|
-
const bytes = getRandomBytes(byteLength);
|
|
209
|
+
async function generateRandomHex(byteLength) {
|
|
210
|
+
const bytes = await getRandomBytes(byteLength);
|
|
218
211
|
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
219
212
|
}
|
|
220
213
|
async function sha256(plain) {
|
|
@@ -248,20 +241,28 @@ function base64UrlEncode(buffer) {
|
|
|
248
241
|
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
249
242
|
}
|
|
250
243
|
async function generatePKCE() {
|
|
251
|
-
const verifier = generateRandomHex(64);
|
|
244
|
+
const verifier = await generateRandomHex(64);
|
|
252
245
|
const hash = await sha256(verifier);
|
|
253
246
|
const challenge = base64UrlEncode(hash);
|
|
254
247
|
return { verifier, challenge };
|
|
255
248
|
}
|
|
256
249
|
function generateState() {
|
|
257
|
-
|
|
250
|
+
const array = new Uint8Array(32);
|
|
251
|
+
if (typeof globalThis.crypto?.getRandomValues === "function") {
|
|
252
|
+
globalThis.crypto.getRandomValues(array);
|
|
253
|
+
} else {
|
|
254
|
+
for (let i = 0; i < 32; i++) {
|
|
255
|
+
array[i] = Math.floor(Math.random() * 256);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return Array.from(array, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
258
259
|
}
|
|
259
|
-
function isSecureCryptoAvailable() {
|
|
260
|
+
async function isSecureCryptoAvailable() {
|
|
260
261
|
if (typeof globalThis.crypto?.getRandomValues === "function") {
|
|
261
262
|
return true;
|
|
262
263
|
}
|
|
263
264
|
try {
|
|
264
|
-
|
|
265
|
+
await import("expo-random");
|
|
265
266
|
return true;
|
|
266
267
|
} catch {
|
|
267
268
|
return false;
|
|
@@ -275,10 +276,10 @@ async function openInAppBrowser(url, useExternal = false) {
|
|
|
275
276
|
return;
|
|
276
277
|
}
|
|
277
278
|
try {
|
|
278
|
-
const
|
|
279
|
+
const module = await import("react-native-inappbrowser-reborn");
|
|
280
|
+
const InAppBrowser = module.default;
|
|
279
281
|
if (await InAppBrowser.isAvailable()) {
|
|
280
282
|
await InAppBrowser.openAuth(url, "", {
|
|
281
|
-
// iOS options
|
|
282
283
|
dismissButtonStyle: "cancel",
|
|
283
284
|
preferredBarTintColor: "#1a1a2e",
|
|
284
285
|
preferredControlTintColor: "#00d4aa",
|
|
@@ -286,7 +287,6 @@ async function openInAppBrowser(url, useExternal = false) {
|
|
|
286
287
|
animated: true,
|
|
287
288
|
modalEnabled: true,
|
|
288
289
|
enableBarCollapsing: false,
|
|
289
|
-
// Android options
|
|
290
290
|
showTitle: true,
|
|
291
291
|
toolbarColor: "#1a1a2e",
|
|
292
292
|
secondaryToolbarColor: "#16213e",
|
|
@@ -307,7 +307,7 @@ async function openInAppBrowser(url, useExternal = false) {
|
|
|
307
307
|
} catch {
|
|
308
308
|
}
|
|
309
309
|
try {
|
|
310
|
-
const WebBrowser =
|
|
310
|
+
const WebBrowser = await import("expo-web-browser");
|
|
311
311
|
await WebBrowser.openAuthSessionAsync(url, "");
|
|
312
312
|
return;
|
|
313
313
|
} catch {
|
|
@@ -317,12 +317,12 @@ async function openInAppBrowser(url, useExternal = false) {
|
|
|
317
317
|
}
|
|
318
318
|
async function closeInAppBrowser() {
|
|
319
319
|
try {
|
|
320
|
-
const
|
|
321
|
-
|
|
320
|
+
const module = await import("react-native-inappbrowser-reborn");
|
|
321
|
+
module.default.close();
|
|
322
322
|
} catch {
|
|
323
323
|
}
|
|
324
324
|
try {
|
|
325
|
-
const WebBrowser =
|
|
325
|
+
const WebBrowser = await import("expo-web-browser");
|
|
326
326
|
WebBrowser.dismissBrowser();
|
|
327
327
|
} catch {
|
|
328
328
|
}
|
|
@@ -348,13 +348,6 @@ var EdgeLink = class {
|
|
|
348
348
|
}
|
|
349
349
|
this.config = config;
|
|
350
350
|
}
|
|
351
|
-
/**
|
|
352
|
-
* Opens the EdgeLink authentication flow.
|
|
353
|
-
*
|
|
354
|
-
* This launches an in-app browser with the EdgeBoost login/consent page.
|
|
355
|
-
* When complete, the browser redirects to your redirectUri and the
|
|
356
|
-
* onSuccess/onExit callback is called.
|
|
357
|
-
*/
|
|
358
351
|
async open() {
|
|
359
352
|
if (this.isDestroyed) {
|
|
360
353
|
throw new Error("EdgeLink: Cannot open - instance has been destroyed");
|
|
@@ -384,15 +377,6 @@ var EdgeLink = class {
|
|
|
384
377
|
});
|
|
385
378
|
}
|
|
386
379
|
}
|
|
387
|
-
/**
|
|
388
|
-
* Manually handles a deep link URL.
|
|
389
|
-
*
|
|
390
|
-
* Use this if you're handling deep links yourself instead of relying
|
|
391
|
-
* on the automatic listener.
|
|
392
|
-
*
|
|
393
|
-
* @param url - The deep link URL received
|
|
394
|
-
* @returns true if the URL was handled, false otherwise
|
|
395
|
-
*/
|
|
396
380
|
handleDeepLink(url) {
|
|
397
381
|
if (!this.isOpen || !url.startsWith(this.config.redirectUri)) {
|
|
398
382
|
return false;
|
|
@@ -400,9 +384,6 @@ var EdgeLink = class {
|
|
|
400
384
|
this.processCallback(url);
|
|
401
385
|
return true;
|
|
402
386
|
}
|
|
403
|
-
/**
|
|
404
|
-
* Closes the EdgeLink flow.
|
|
405
|
-
*/
|
|
406
387
|
async close() {
|
|
407
388
|
if (!this.isOpen) return;
|
|
408
389
|
await closeInAppBrowser();
|
|
@@ -412,16 +393,10 @@ var EdgeLink = class {
|
|
|
412
393
|
reason: "user_closed"
|
|
413
394
|
});
|
|
414
395
|
}
|
|
415
|
-
/**
|
|
416
|
-
* Destroys the EdgeLink instance.
|
|
417
|
-
*/
|
|
418
396
|
destroy() {
|
|
419
397
|
this.isDestroyed = true;
|
|
420
398
|
this.cleanup();
|
|
421
399
|
}
|
|
422
|
-
// ===========================================================================
|
|
423
|
-
// PRIVATE METHODS
|
|
424
|
-
// ===========================================================================
|
|
425
400
|
buildLinkUrl() {
|
|
426
401
|
const envConfig = getEnvironmentConfig(this.config.environment);
|
|
427
402
|
const baseUrl = this.config.linkUrl || `${envConfig.userClientUrl}/oauth/link`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@edge-markets/connect-react-native",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "React Native SDK for EDGE Connect authentication flow for mobile apps",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -13,11 +13,6 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"sideEffects": false,
|
|
16
|
-
"scripts": {
|
|
17
|
-
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
18
|
-
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
19
|
-
"typecheck": "tsc --noEmit"
|
|
20
|
-
},
|
|
21
16
|
"files": [
|
|
22
17
|
"dist",
|
|
23
18
|
"README.md"
|
|
@@ -57,6 +52,10 @@
|
|
|
57
52
|
"type": "git",
|
|
58
53
|
"url": "https://github.com/edgeboost/edge-connect-sdk.git",
|
|
59
54
|
"directory": "packages/react-native"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
58
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
59
|
+
"typecheck": "tsc --noEmit"
|
|
60
60
|
}
|
|
61
|
-
}
|
|
62
|
-
|
|
61
|
+
}
|