@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 CHANGED
@@ -305,3 +305,9 @@ Install and import `react-native-get-random-values` before any crypto operations
305
305
  MIT
306
306
 
307
307
 
308
+
309
+
310
+
311
+
312
+
313
+
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 = require("expo-crypto");
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 { createHash } = require("react-native-quick-crypto");
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 = require("expo-random");
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
- return generateRandomHex(32);
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
- require("expo-random");
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 InAppBrowser = require("react-native-inappbrowser-reborn").default;
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 = require("expo-web-browser");
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 InAppBrowser = require("react-native-inappbrowser-reborn").default;
339
- InAppBrowser.close();
355
+ const module2 = await import("react-native-inappbrowser-reborn");
356
+ module2.default.close();
340
357
  } catch {
341
358
  }
342
359
  try {
343
- const WebBrowser = require("expo-web-browser");
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 = __require("expo-crypto");
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 { createHash } = __require("react-native-quick-crypto");
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 = __require("expo-random");
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
- return generateRandomHex(32);
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
- __require("expo-random");
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 InAppBrowser = __require("react-native-inappbrowser-reborn").default;
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 = __require("expo-web-browser");
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 InAppBrowser = __require("react-native-inappbrowser-reborn").default;
321
- InAppBrowser.close();
320
+ const module = await import("react-native-inappbrowser-reborn");
321
+ module.default.close();
322
322
  } catch {
323
323
  }
324
324
  try {
325
- const WebBrowser = __require("expo-web-browser");
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",
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
+ }