@edge-markets/connect-react-native 1.0.3 → 1.3.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 +8 -179
- package/dist/index.d.ts +8 -179
- package/dist/index.js +33 -54
- package/dist/index.mjs +23 -61
- package/package.json +8 -9
package/README.md
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -1,115 +1,10 @@
|
|
|
1
|
-
import { EdgeEnvironment, EdgeLinkSuccess,
|
|
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';
|
|
1
|
+
import { EdgeLinkConfigBase, EdgeEnvironment, EdgeScope, EdgeLinkSuccess, EdgeLinkEvent, PKCEPair } from '@edge-markets/connect';
|
|
2
|
+
export { ALL_EDGE_SCOPES, Balance, EDGE_ENVIRONMENTS, EdgeApiError, EdgeAuthenticationError, EdgeConsentRequiredError, EdgeEnvironment, EdgeError, EdgeLinkEvent, EdgeLinkEventName, EdgeLinkExit, EdgeLinkSuccess, EdgeNetworkError, EdgePopupBlockedError, EdgeScope, EdgeStateMismatchError, EdgeTokenExchangeError, EdgeTokens, PKCEPair, 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
|
-
interface EdgeLinkConfig {
|
|
41
|
-
/**
|
|
42
|
-
* Your OAuth client ID from the EdgeBoost partner portal.
|
|
43
|
-
*/
|
|
44
|
-
clientId: string;
|
|
45
|
-
/**
|
|
46
|
-
* Environment to connect to.
|
|
47
|
-
*/
|
|
48
|
-
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
|
-
*/
|
|
4
|
+
interface EdgeLinkConfig extends EdgeLinkConfigBase {
|
|
59
5
|
redirectUri: string;
|
|
60
|
-
/**
|
|
61
|
-
* Called when user successfully authenticates and grants consent.
|
|
62
|
-
*/
|
|
63
|
-
onSuccess: (result: EdgeLinkSuccess) => void;
|
|
64
|
-
/**
|
|
65
|
-
* Called when user exits the flow.
|
|
66
|
-
*/
|
|
67
|
-
onExit?: (metadata: EdgeLinkExit) => void;
|
|
68
|
-
/**
|
|
69
|
-
* Called for various events during the flow.
|
|
70
|
-
*/
|
|
71
|
-
onEvent?: (event: EdgeLinkEvent) => void;
|
|
72
|
-
/**
|
|
73
|
-
* OAuth scopes to request.
|
|
74
|
-
* @default All available scopes
|
|
75
|
-
*/
|
|
76
|
-
scopes?: EdgeScope[];
|
|
77
|
-
/**
|
|
78
|
-
* Custom URL for the Link page (development only).
|
|
79
|
-
*/
|
|
80
|
-
linkUrl?: string;
|
|
81
|
-
/**
|
|
82
|
-
* Use external browser instead of in-app browser.
|
|
83
|
-
* @default false
|
|
84
|
-
*/
|
|
85
6
|
useExternalBrowser?: boolean;
|
|
86
7
|
}
|
|
87
|
-
/**
|
|
88
|
-
* Event emitted during the Link flow.
|
|
89
|
-
*/
|
|
90
|
-
interface EdgeLinkEvent {
|
|
91
|
-
eventName: EdgeLinkEventName;
|
|
92
|
-
timestamp: number;
|
|
93
|
-
metadata?: Record<string, unknown>;
|
|
94
|
-
}
|
|
95
|
-
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
8
|
declare class EdgeLink {
|
|
114
9
|
private readonly config;
|
|
115
10
|
private pkce;
|
|
@@ -118,31 +13,9 @@ declare class EdgeLink {
|
|
|
118
13
|
private isOpen;
|
|
119
14
|
private isDestroyed;
|
|
120
15
|
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
16
|
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
17
|
handleDeepLink(url: string): boolean;
|
|
139
|
-
/**
|
|
140
|
-
* Closes the EdgeLink flow.
|
|
141
|
-
*/
|
|
142
18
|
close(): Promise<void>;
|
|
143
|
-
/**
|
|
144
|
-
* Destroys the EdgeLink instance.
|
|
145
|
-
*/
|
|
146
19
|
destroy(): void;
|
|
147
20
|
private buildLinkUrl;
|
|
148
21
|
private setupLinkListener;
|
|
@@ -269,6 +142,8 @@ declare function useEdgeLink(config: UseEdgeLinkConfig): UseEdgeLinkReturn;
|
|
|
269
142
|
interface UseEdgeLinkHandlerConfig {
|
|
270
143
|
/** Your redirect URI prefix */
|
|
271
144
|
redirectUri: string;
|
|
145
|
+
/** PKCE code verifier from the EdgeLink instance that initiated the flow */
|
|
146
|
+
codeVerifier: string;
|
|
272
147
|
/** Called on successful auth */
|
|
273
148
|
onSuccess: (result: EdgeLinkSuccess) => void;
|
|
274
149
|
/** Called on error or user exit */
|
|
@@ -302,54 +177,8 @@ declare function useEdgeLinkHandler(config: UseEdgeLinkHandlerConfig): UseEdgeLi
|
|
|
302
177
|
*/
|
|
303
178
|
declare function useEdgeLinkEvents(onEvent: (event: EdgeLinkEvent) => void, deps?: React.DependencyList): void;
|
|
304
179
|
|
|
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
|
-
interface PKCEPair {
|
|
321
|
-
/** High-entropy random string (43-128 characters). Keep secret until token exchange. */
|
|
322
|
-
verifier: string;
|
|
323
|
-
/** SHA-256 hash of verifier, base64url encoded. Include in authorization URL. */
|
|
324
|
-
challenge: string;
|
|
325
|
-
}
|
|
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
180
|
declare function generatePKCE(): Promise<PKCEPair>;
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
*
|
|
344
|
-
* @returns 64-character hex string (32 bytes of entropy)
|
|
345
|
-
*/
|
|
346
|
-
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;
|
|
181
|
+
declare function generateState(): Promise<string>;
|
|
182
|
+
declare function isSecureCryptoAvailable(): Promise<boolean>;
|
|
354
183
|
|
|
355
|
-
export { EdgeLink, type EdgeLinkConfig, type
|
|
184
|
+
export { EdgeLink, type EdgeLinkConfig, type UseEdgeLinkConfig, type UseEdgeLinkHandlerConfig, type UseEdgeLinkHandlerReturn, type UseEdgeLinkReturn, generatePKCE, generateState, isSecureCryptoAvailable, useEdgeLink, useEdgeLinkEvents, useEdgeLinkHandler };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,115 +1,10 @@
|
|
|
1
|
-
import { EdgeEnvironment, EdgeLinkSuccess,
|
|
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';
|
|
1
|
+
import { EdgeLinkConfigBase, EdgeEnvironment, EdgeScope, EdgeLinkSuccess, EdgeLinkEvent, PKCEPair } from '@edge-markets/connect';
|
|
2
|
+
export { ALL_EDGE_SCOPES, Balance, EDGE_ENVIRONMENTS, EdgeApiError, EdgeAuthenticationError, EdgeConsentRequiredError, EdgeEnvironment, EdgeError, EdgeLinkEvent, EdgeLinkEventName, EdgeLinkExit, EdgeLinkSuccess, EdgeNetworkError, EdgePopupBlockedError, EdgeScope, EdgeStateMismatchError, EdgeTokenExchangeError, EdgeTokens, PKCEPair, 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
|
-
interface EdgeLinkConfig {
|
|
41
|
-
/**
|
|
42
|
-
* Your OAuth client ID from the EdgeBoost partner portal.
|
|
43
|
-
*/
|
|
44
|
-
clientId: string;
|
|
45
|
-
/**
|
|
46
|
-
* Environment to connect to.
|
|
47
|
-
*/
|
|
48
|
-
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
|
-
*/
|
|
4
|
+
interface EdgeLinkConfig extends EdgeLinkConfigBase {
|
|
59
5
|
redirectUri: string;
|
|
60
|
-
/**
|
|
61
|
-
* Called when user successfully authenticates and grants consent.
|
|
62
|
-
*/
|
|
63
|
-
onSuccess: (result: EdgeLinkSuccess) => void;
|
|
64
|
-
/**
|
|
65
|
-
* Called when user exits the flow.
|
|
66
|
-
*/
|
|
67
|
-
onExit?: (metadata: EdgeLinkExit) => void;
|
|
68
|
-
/**
|
|
69
|
-
* Called for various events during the flow.
|
|
70
|
-
*/
|
|
71
|
-
onEvent?: (event: EdgeLinkEvent) => void;
|
|
72
|
-
/**
|
|
73
|
-
* OAuth scopes to request.
|
|
74
|
-
* @default All available scopes
|
|
75
|
-
*/
|
|
76
|
-
scopes?: EdgeScope[];
|
|
77
|
-
/**
|
|
78
|
-
* Custom URL for the Link page (development only).
|
|
79
|
-
*/
|
|
80
|
-
linkUrl?: string;
|
|
81
|
-
/**
|
|
82
|
-
* Use external browser instead of in-app browser.
|
|
83
|
-
* @default false
|
|
84
|
-
*/
|
|
85
6
|
useExternalBrowser?: boolean;
|
|
86
7
|
}
|
|
87
|
-
/**
|
|
88
|
-
* Event emitted during the Link flow.
|
|
89
|
-
*/
|
|
90
|
-
interface EdgeLinkEvent {
|
|
91
|
-
eventName: EdgeLinkEventName;
|
|
92
|
-
timestamp: number;
|
|
93
|
-
metadata?: Record<string, unknown>;
|
|
94
|
-
}
|
|
95
|
-
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
8
|
declare class EdgeLink {
|
|
114
9
|
private readonly config;
|
|
115
10
|
private pkce;
|
|
@@ -118,31 +13,9 @@ declare class EdgeLink {
|
|
|
118
13
|
private isOpen;
|
|
119
14
|
private isDestroyed;
|
|
120
15
|
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
16
|
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
17
|
handleDeepLink(url: string): boolean;
|
|
139
|
-
/**
|
|
140
|
-
* Closes the EdgeLink flow.
|
|
141
|
-
*/
|
|
142
18
|
close(): Promise<void>;
|
|
143
|
-
/**
|
|
144
|
-
* Destroys the EdgeLink instance.
|
|
145
|
-
*/
|
|
146
19
|
destroy(): void;
|
|
147
20
|
private buildLinkUrl;
|
|
148
21
|
private setupLinkListener;
|
|
@@ -269,6 +142,8 @@ declare function useEdgeLink(config: UseEdgeLinkConfig): UseEdgeLinkReturn;
|
|
|
269
142
|
interface UseEdgeLinkHandlerConfig {
|
|
270
143
|
/** Your redirect URI prefix */
|
|
271
144
|
redirectUri: string;
|
|
145
|
+
/** PKCE code verifier from the EdgeLink instance that initiated the flow */
|
|
146
|
+
codeVerifier: string;
|
|
272
147
|
/** Called on successful auth */
|
|
273
148
|
onSuccess: (result: EdgeLinkSuccess) => void;
|
|
274
149
|
/** Called on error or user exit */
|
|
@@ -302,54 +177,8 @@ declare function useEdgeLinkHandler(config: UseEdgeLinkHandlerConfig): UseEdgeLi
|
|
|
302
177
|
*/
|
|
303
178
|
declare function useEdgeLinkEvents(onEvent: (event: EdgeLinkEvent) => void, deps?: React.DependencyList): void;
|
|
304
179
|
|
|
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
|
-
interface PKCEPair {
|
|
321
|
-
/** High-entropy random string (43-128 characters). Keep secret until token exchange. */
|
|
322
|
-
verifier: string;
|
|
323
|
-
/** SHA-256 hash of verifier, base64url encoded. Include in authorization URL. */
|
|
324
|
-
challenge: string;
|
|
325
|
-
}
|
|
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
180
|
declare function generatePKCE(): Promise<PKCEPair>;
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
*
|
|
344
|
-
* @returns 64-character hex string (32 bytes of entropy)
|
|
345
|
-
*/
|
|
346
|
-
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;
|
|
181
|
+
declare function generateState(): Promise<string>;
|
|
182
|
+
declare function isSecureCryptoAvailable(): Promise<boolean>;
|
|
354
183
|
|
|
355
|
-
export { EdgeLink, type EdgeLinkConfig, type
|
|
184
|
+
export { EdgeLink, type EdgeLinkConfig, 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,27 +222,23 @@ 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
|
}
|
|
226
|
-
|
|
227
|
-
"[EdgeLink]
|
|
236
|
+
throw new Error(
|
|
237
|
+
"[EdgeLink] No cryptographically secure random source available. Install react-native-get-random-values (and import it before EdgeLink) or expo-random."
|
|
228
238
|
);
|
|
229
|
-
for (let i = 0; i < byteLength; i++) {
|
|
230
|
-
array[i] = Math.floor(Math.random() * 256);
|
|
231
|
-
}
|
|
232
|
-
return array;
|
|
233
239
|
}
|
|
234
|
-
function generateRandomHex(byteLength) {
|
|
235
|
-
const bytes = getRandomBytes(byteLength);
|
|
240
|
+
async function generateRandomHex(byteLength) {
|
|
241
|
+
const bytes = await getRandomBytes(byteLength);
|
|
236
242
|
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
237
243
|
}
|
|
238
244
|
async function sha256(plain) {
|
|
@@ -266,20 +272,21 @@ function base64UrlEncode(buffer) {
|
|
|
266
272
|
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
267
273
|
}
|
|
268
274
|
async function generatePKCE() {
|
|
269
|
-
const verifier = generateRandomHex(64);
|
|
275
|
+
const verifier = await generateRandomHex(64);
|
|
270
276
|
const hash = await sha256(verifier);
|
|
271
277
|
const challenge = base64UrlEncode(hash);
|
|
272
278
|
return { verifier, challenge };
|
|
273
279
|
}
|
|
274
|
-
function generateState() {
|
|
275
|
-
|
|
280
|
+
async function generateState() {
|
|
281
|
+
const bytes = await getRandomBytes(32);
|
|
282
|
+
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
276
283
|
}
|
|
277
|
-
function isSecureCryptoAvailable() {
|
|
284
|
+
async function isSecureCryptoAvailable() {
|
|
278
285
|
if (typeof globalThis.crypto?.getRandomValues === "function") {
|
|
279
286
|
return true;
|
|
280
287
|
}
|
|
281
288
|
try {
|
|
282
|
-
|
|
289
|
+
await import("expo-random");
|
|
283
290
|
return true;
|
|
284
291
|
} catch {
|
|
285
292
|
return false;
|
|
@@ -293,10 +300,10 @@ async function openInAppBrowser(url, useExternal = false) {
|
|
|
293
300
|
return;
|
|
294
301
|
}
|
|
295
302
|
try {
|
|
296
|
-
const
|
|
303
|
+
const module2 = await import("react-native-inappbrowser-reborn");
|
|
304
|
+
const InAppBrowser = module2.default;
|
|
297
305
|
if (await InAppBrowser.isAvailable()) {
|
|
298
306
|
await InAppBrowser.openAuth(url, "", {
|
|
299
|
-
// iOS options
|
|
300
307
|
dismissButtonStyle: "cancel",
|
|
301
308
|
preferredBarTintColor: "#1a1a2e",
|
|
302
309
|
preferredControlTintColor: "#00d4aa",
|
|
@@ -304,7 +311,6 @@ async function openInAppBrowser(url, useExternal = false) {
|
|
|
304
311
|
animated: true,
|
|
305
312
|
modalEnabled: true,
|
|
306
313
|
enableBarCollapsing: false,
|
|
307
|
-
// Android options
|
|
308
314
|
showTitle: true,
|
|
309
315
|
toolbarColor: "#1a1a2e",
|
|
310
316
|
secondaryToolbarColor: "#16213e",
|
|
@@ -325,7 +331,7 @@ async function openInAppBrowser(url, useExternal = false) {
|
|
|
325
331
|
} catch {
|
|
326
332
|
}
|
|
327
333
|
try {
|
|
328
|
-
const WebBrowser =
|
|
334
|
+
const WebBrowser = await import("expo-web-browser");
|
|
329
335
|
await WebBrowser.openAuthSessionAsync(url, "");
|
|
330
336
|
return;
|
|
331
337
|
} catch {
|
|
@@ -335,12 +341,12 @@ async function openInAppBrowser(url, useExternal = false) {
|
|
|
335
341
|
}
|
|
336
342
|
async function closeInAppBrowser() {
|
|
337
343
|
try {
|
|
338
|
-
const
|
|
339
|
-
|
|
344
|
+
const module2 = await import("react-native-inappbrowser-reborn");
|
|
345
|
+
module2.default.close();
|
|
340
346
|
} catch {
|
|
341
347
|
}
|
|
342
348
|
try {
|
|
343
|
-
const WebBrowser =
|
|
349
|
+
const WebBrowser = await import("expo-web-browser");
|
|
344
350
|
WebBrowser.dismissBrowser();
|
|
345
351
|
} catch {
|
|
346
352
|
}
|
|
@@ -366,13 +372,6 @@ var EdgeLink = class {
|
|
|
366
372
|
}
|
|
367
373
|
this.config = config;
|
|
368
374
|
}
|
|
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
375
|
async open() {
|
|
377
376
|
if (this.isDestroyed) {
|
|
378
377
|
throw new Error("EdgeLink: Cannot open - instance has been destroyed");
|
|
@@ -385,7 +384,7 @@ var EdgeLink = class {
|
|
|
385
384
|
this.isOpen = true;
|
|
386
385
|
try {
|
|
387
386
|
this.pkce = await generatePKCE();
|
|
388
|
-
this.state = generateState();
|
|
387
|
+
this.state = await generateState();
|
|
389
388
|
this.setupLinkListener();
|
|
390
389
|
const url = this.buildLinkUrl();
|
|
391
390
|
this.emitEvent("HANDOFF", { url });
|
|
@@ -402,15 +401,6 @@ var EdgeLink = class {
|
|
|
402
401
|
});
|
|
403
402
|
}
|
|
404
403
|
}
|
|
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
404
|
handleDeepLink(url) {
|
|
415
405
|
if (!this.isOpen || !url.startsWith(this.config.redirectUri)) {
|
|
416
406
|
return false;
|
|
@@ -418,9 +408,6 @@ var EdgeLink = class {
|
|
|
418
408
|
this.processCallback(url);
|
|
419
409
|
return true;
|
|
420
410
|
}
|
|
421
|
-
/**
|
|
422
|
-
* Closes the EdgeLink flow.
|
|
423
|
-
*/
|
|
424
411
|
async close() {
|
|
425
412
|
if (!this.isOpen) return;
|
|
426
413
|
await closeInAppBrowser();
|
|
@@ -430,16 +417,10 @@ var EdgeLink = class {
|
|
|
430
417
|
reason: "user_closed"
|
|
431
418
|
});
|
|
432
419
|
}
|
|
433
|
-
/**
|
|
434
|
-
* Destroys the EdgeLink instance.
|
|
435
|
-
*/
|
|
436
420
|
destroy() {
|
|
437
421
|
this.isDestroyed = true;
|
|
438
422
|
this.cleanup();
|
|
439
423
|
}
|
|
440
|
-
// ===========================================================================
|
|
441
|
-
// PRIVATE METHODS
|
|
442
|
-
// ===========================================================================
|
|
443
424
|
buildLinkUrl() {
|
|
444
425
|
const envConfig = (0, import_connect.getEnvironmentConfig)(this.config.environment);
|
|
445
426
|
const baseUrl = this.config.linkUrl || `${envConfig.userClientUrl}/oauth/link`;
|
|
@@ -638,7 +619,6 @@ function useEdgeLinkHandler(config) {
|
|
|
638
619
|
const state = parsed.searchParams.get("state");
|
|
639
620
|
const error = parsed.searchParams.get("error");
|
|
640
621
|
const errorDescription = parsed.searchParams.get("error_description");
|
|
641
|
-
const codeVerifier = parsed.searchParams.get("code_verifier");
|
|
642
622
|
if (error) {
|
|
643
623
|
config.onError?.({
|
|
644
624
|
code: error,
|
|
@@ -649,8 +629,7 @@ function useEdgeLinkHandler(config) {
|
|
|
649
629
|
if (code && state) {
|
|
650
630
|
config.onSuccess({
|
|
651
631
|
code,
|
|
652
|
-
codeVerifier: codeVerifier
|
|
653
|
-
// Might be empty if not passed in URL
|
|
632
|
+
codeVerifier: config.codeVerifier,
|
|
654
633
|
state
|
|
655
634
|
});
|
|
656
635
|
return true;
|
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,27 +187,23 @@ 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
|
}
|
|
208
|
-
|
|
209
|
-
"[EdgeLink]
|
|
201
|
+
throw new Error(
|
|
202
|
+
"[EdgeLink] No cryptographically secure random source available. Install react-native-get-random-values (and import it before EdgeLink) or expo-random."
|
|
210
203
|
);
|
|
211
|
-
for (let i = 0; i < byteLength; i++) {
|
|
212
|
-
array[i] = Math.floor(Math.random() * 256);
|
|
213
|
-
}
|
|
214
|
-
return array;
|
|
215
204
|
}
|
|
216
|
-
function generateRandomHex(byteLength) {
|
|
217
|
-
const bytes = getRandomBytes(byteLength);
|
|
205
|
+
async function generateRandomHex(byteLength) {
|
|
206
|
+
const bytes = await getRandomBytes(byteLength);
|
|
218
207
|
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
219
208
|
}
|
|
220
209
|
async function sha256(plain) {
|
|
@@ -248,20 +237,21 @@ function base64UrlEncode(buffer) {
|
|
|
248
237
|
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
249
238
|
}
|
|
250
239
|
async function generatePKCE() {
|
|
251
|
-
const verifier = generateRandomHex(64);
|
|
240
|
+
const verifier = await generateRandomHex(64);
|
|
252
241
|
const hash = await sha256(verifier);
|
|
253
242
|
const challenge = base64UrlEncode(hash);
|
|
254
243
|
return { verifier, challenge };
|
|
255
244
|
}
|
|
256
|
-
function generateState() {
|
|
257
|
-
|
|
245
|
+
async function generateState() {
|
|
246
|
+
const bytes = await getRandomBytes(32);
|
|
247
|
+
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
258
248
|
}
|
|
259
|
-
function isSecureCryptoAvailable() {
|
|
249
|
+
async function isSecureCryptoAvailable() {
|
|
260
250
|
if (typeof globalThis.crypto?.getRandomValues === "function") {
|
|
261
251
|
return true;
|
|
262
252
|
}
|
|
263
253
|
try {
|
|
264
|
-
|
|
254
|
+
await import("expo-random");
|
|
265
255
|
return true;
|
|
266
256
|
} catch {
|
|
267
257
|
return false;
|
|
@@ -275,10 +265,10 @@ async function openInAppBrowser(url, useExternal = false) {
|
|
|
275
265
|
return;
|
|
276
266
|
}
|
|
277
267
|
try {
|
|
278
|
-
const
|
|
268
|
+
const module = await import("react-native-inappbrowser-reborn");
|
|
269
|
+
const InAppBrowser = module.default;
|
|
279
270
|
if (await InAppBrowser.isAvailable()) {
|
|
280
271
|
await InAppBrowser.openAuth(url, "", {
|
|
281
|
-
// iOS options
|
|
282
272
|
dismissButtonStyle: "cancel",
|
|
283
273
|
preferredBarTintColor: "#1a1a2e",
|
|
284
274
|
preferredControlTintColor: "#00d4aa",
|
|
@@ -286,7 +276,6 @@ async function openInAppBrowser(url, useExternal = false) {
|
|
|
286
276
|
animated: true,
|
|
287
277
|
modalEnabled: true,
|
|
288
278
|
enableBarCollapsing: false,
|
|
289
|
-
// Android options
|
|
290
279
|
showTitle: true,
|
|
291
280
|
toolbarColor: "#1a1a2e",
|
|
292
281
|
secondaryToolbarColor: "#16213e",
|
|
@@ -307,7 +296,7 @@ async function openInAppBrowser(url, useExternal = false) {
|
|
|
307
296
|
} catch {
|
|
308
297
|
}
|
|
309
298
|
try {
|
|
310
|
-
const WebBrowser =
|
|
299
|
+
const WebBrowser = await import("expo-web-browser");
|
|
311
300
|
await WebBrowser.openAuthSessionAsync(url, "");
|
|
312
301
|
return;
|
|
313
302
|
} catch {
|
|
@@ -317,12 +306,12 @@ async function openInAppBrowser(url, useExternal = false) {
|
|
|
317
306
|
}
|
|
318
307
|
async function closeInAppBrowser() {
|
|
319
308
|
try {
|
|
320
|
-
const
|
|
321
|
-
|
|
309
|
+
const module = await import("react-native-inappbrowser-reborn");
|
|
310
|
+
module.default.close();
|
|
322
311
|
} catch {
|
|
323
312
|
}
|
|
324
313
|
try {
|
|
325
|
-
const WebBrowser =
|
|
314
|
+
const WebBrowser = await import("expo-web-browser");
|
|
326
315
|
WebBrowser.dismissBrowser();
|
|
327
316
|
} catch {
|
|
328
317
|
}
|
|
@@ -348,13 +337,6 @@ var EdgeLink = class {
|
|
|
348
337
|
}
|
|
349
338
|
this.config = config;
|
|
350
339
|
}
|
|
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
340
|
async open() {
|
|
359
341
|
if (this.isDestroyed) {
|
|
360
342
|
throw new Error("EdgeLink: Cannot open - instance has been destroyed");
|
|
@@ -367,7 +349,7 @@ var EdgeLink = class {
|
|
|
367
349
|
this.isOpen = true;
|
|
368
350
|
try {
|
|
369
351
|
this.pkce = await generatePKCE();
|
|
370
|
-
this.state = generateState();
|
|
352
|
+
this.state = await generateState();
|
|
371
353
|
this.setupLinkListener();
|
|
372
354
|
const url = this.buildLinkUrl();
|
|
373
355
|
this.emitEvent("HANDOFF", { url });
|
|
@@ -384,15 +366,6 @@ var EdgeLink = class {
|
|
|
384
366
|
});
|
|
385
367
|
}
|
|
386
368
|
}
|
|
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
369
|
handleDeepLink(url) {
|
|
397
370
|
if (!this.isOpen || !url.startsWith(this.config.redirectUri)) {
|
|
398
371
|
return false;
|
|
@@ -400,9 +373,6 @@ var EdgeLink = class {
|
|
|
400
373
|
this.processCallback(url);
|
|
401
374
|
return true;
|
|
402
375
|
}
|
|
403
|
-
/**
|
|
404
|
-
* Closes the EdgeLink flow.
|
|
405
|
-
*/
|
|
406
376
|
async close() {
|
|
407
377
|
if (!this.isOpen) return;
|
|
408
378
|
await closeInAppBrowser();
|
|
@@ -412,16 +382,10 @@ var EdgeLink = class {
|
|
|
412
382
|
reason: "user_closed"
|
|
413
383
|
});
|
|
414
384
|
}
|
|
415
|
-
/**
|
|
416
|
-
* Destroys the EdgeLink instance.
|
|
417
|
-
*/
|
|
418
385
|
destroy() {
|
|
419
386
|
this.isDestroyed = true;
|
|
420
387
|
this.cleanup();
|
|
421
388
|
}
|
|
422
|
-
// ===========================================================================
|
|
423
|
-
// PRIVATE METHODS
|
|
424
|
-
// ===========================================================================
|
|
425
389
|
buildLinkUrl() {
|
|
426
390
|
const envConfig = getEnvironmentConfig(this.config.environment);
|
|
427
391
|
const baseUrl = this.config.linkUrl || `${envConfig.userClientUrl}/oauth/link`;
|
|
@@ -620,7 +584,6 @@ function useEdgeLinkHandler(config) {
|
|
|
620
584
|
const state = parsed.searchParams.get("state");
|
|
621
585
|
const error = parsed.searchParams.get("error");
|
|
622
586
|
const errorDescription = parsed.searchParams.get("error_description");
|
|
623
|
-
const codeVerifier = parsed.searchParams.get("code_verifier");
|
|
624
587
|
if (error) {
|
|
625
588
|
config.onError?.({
|
|
626
589
|
code: error,
|
|
@@ -631,8 +594,7 @@ function useEdgeLinkHandler(config) {
|
|
|
631
594
|
if (code && state) {
|
|
632
595
|
config.onSuccess({
|
|
633
596
|
code,
|
|
634
|
-
codeVerifier: codeVerifier
|
|
635
|
-
// Might be empty if not passed in URL
|
|
597
|
+
codeVerifier: config.codeVerifier,
|
|
636
598
|
state
|
|
637
599
|
});
|
|
638
600
|
return true;
|
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.3.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"
|
|
@@ -35,7 +30,7 @@
|
|
|
35
30
|
"author": "EdgeBoost",
|
|
36
31
|
"license": "MIT",
|
|
37
32
|
"dependencies": {
|
|
38
|
-
"@edge-markets/connect": "
|
|
33
|
+
"@edge-markets/connect": "1.3.0"
|
|
39
34
|
},
|
|
40
35
|
"peerDependencies": {
|
|
41
36
|
"react": ">=18.0.0",
|
|
@@ -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
|
+
}
|