@edge-markets/connect-react-native 1.4.1 → 1.5.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
@@ -133,9 +133,14 @@ React hook for EdgeLink integration.
133
133
  | `environment` | `'production' \| 'staging' \| 'sandbox'` | ✅ | Environment |
134
134
  | `redirectUri` | `string` | ✅ | Deep link URI for callback |
135
135
  | `scopes` | `EdgeScope[]` | ❌ | Requested permissions |
136
- | `linkUrl` | `string` | ❌ | Custom Link URL (dev only) |
136
+ | `linkUrl` | `string` | ❌ | Custom Link URL/origin (dev only) |
137
137
  | `useExternalBrowser` | `boolean` | ❌ | Use external browser |
138
138
 
139
+ The SDK derives the hosted Link URL from `environment`; staging defaults to
140
+ `https://oauth.staging-app.edgeboost.io/oauth/link`. `linkUrl` is only needed for
141
+ nonstandard deployments. If provided as an origin, for example
142
+ `https://oauth.example.com`, the SDK appends `/oauth/link`.
143
+
139
144
  **Returns:**
140
145
  | Property | Type | Description |
141
146
  |----------|------|-------------|
@@ -304,10 +309,3 @@ Install and import `react-native-get-random-values` before any crypto operations
304
309
 
305
310
  MIT
306
311
 
307
-
308
-
309
-
310
-
311
-
312
-
313
-
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { EdgeLinkConfigBase, EdgeEnvironment, EdgeScope, EdgeLinkSuccess, EdgeLinkEvent, SdkGeolocation, 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, SdkGeolocation, Transfer, User, formatScopesForEnvironment, getEnvironmentConfig, isApiError, isAuthenticationError, isConsentRequiredError, isNetworkError } from '@edge-markets/connect';
2
+ export { ACTIVE_EDGE_SCOPES, ALL_EDGE_SCOPES, Balance, EDGE_CONNECT_FEATURE_UNAVAILABLE_MESSAGE, EDGE_ENVIRONMENTS, EdgeApiError, EdgeAuthenticationError, EdgeConsentRequiredError, EdgeEnvironment, EdgeError, EdgeFeatureUnavailableError, EdgeLinkEvent, EdgeLinkEventName, EdgeLinkExit, EdgeLinkSuccess, EdgeNetworkError, EdgePopupBlockedError, EdgeScope, EdgeStateMismatchError, EdgeTokenExchangeError, EdgeTokens, PKCEPair, SCOPE_DESCRIPTIONS, SdkGeolocation, Transfer, User, formatScopesForEnvironment, getEnvironmentConfig, isApiError, isAuthenticationError, isConsentRequiredError, isFeatureUnavailableError, isNetworkError } from '@edge-markets/connect';
3
3
 
4
4
  interface EdgeLinkConfig extends EdgeLinkConfigBase {
5
5
  redirectUri: string;
@@ -18,6 +18,8 @@ declare class EdgeLink {
18
18
  close(): Promise<void>;
19
19
  destroy(): void;
20
20
  private buildLinkUrl;
21
+ private getScopes;
22
+ private assertActiveScopes;
21
23
  private setupLinkListener;
22
24
  private removeLinkListener;
23
25
  private processCallback;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { EdgeLinkConfigBase, EdgeEnvironment, EdgeScope, EdgeLinkSuccess, EdgeLinkEvent, SdkGeolocation, 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, SdkGeolocation, Transfer, User, formatScopesForEnvironment, getEnvironmentConfig, isApiError, isAuthenticationError, isConsentRequiredError, isNetworkError } from '@edge-markets/connect';
2
+ export { ACTIVE_EDGE_SCOPES, ALL_EDGE_SCOPES, Balance, EDGE_CONNECT_FEATURE_UNAVAILABLE_MESSAGE, EDGE_ENVIRONMENTS, EdgeApiError, EdgeAuthenticationError, EdgeConsentRequiredError, EdgeEnvironment, EdgeError, EdgeFeatureUnavailableError, EdgeLinkEvent, EdgeLinkEventName, EdgeLinkExit, EdgeLinkSuccess, EdgeNetworkError, EdgePopupBlockedError, EdgeScope, EdgeStateMismatchError, EdgeTokenExchangeError, EdgeTokens, PKCEPair, SCOPE_DESCRIPTIONS, SdkGeolocation, Transfer, User, formatScopesForEnvironment, getEnvironmentConfig, isApiError, isAuthenticationError, isConsentRequiredError, isFeatureUnavailableError, isNetworkError } from '@edge-markets/connect';
3
3
 
4
4
  interface EdgeLinkConfig extends EdgeLinkConfigBase {
5
5
  redirectUri: string;
@@ -18,6 +18,8 @@ declare class EdgeLink {
18
18
  close(): Promise<void>;
19
19
  destroy(): void;
20
20
  private buildLinkUrl;
21
+ private getScopes;
22
+ private assertActiveScopes;
21
23
  private setupLinkListener;
22
24
  private removeLinkListener;
23
25
  private processCallback;
package/dist/index.js CHANGED
@@ -30,12 +30,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ ACTIVE_EDGE_SCOPES: () => import_connect2.ACTIVE_EDGE_SCOPES,
33
34
  ALL_EDGE_SCOPES: () => import_connect2.ALL_EDGE_SCOPES,
35
+ EDGE_CONNECT_FEATURE_UNAVAILABLE_MESSAGE: () => import_connect2.EDGE_CONNECT_FEATURE_UNAVAILABLE_MESSAGE,
34
36
  EDGE_ENVIRONMENTS: () => import_connect2.EDGE_ENVIRONMENTS,
35
37
  EdgeApiError: () => import_connect2.EdgeApiError,
36
38
  EdgeAuthenticationError: () => import_connect2.EdgeAuthenticationError,
37
39
  EdgeConsentRequiredError: () => import_connect2.EdgeConsentRequiredError,
38
40
  EdgeError: () => import_connect2.EdgeError,
41
+ EdgeFeatureUnavailableError: () => import_connect2.EdgeFeatureUnavailableError,
39
42
  EdgeLink: () => EdgeLink,
40
43
  EdgeNetworkError: () => import_connect2.EdgeNetworkError,
41
44
  EdgePopupBlockedError: () => import_connect2.EdgePopupBlockedError,
@@ -50,6 +53,7 @@ __export(index_exports, {
50
53
  isApiError: () => import_connect2.isApiError,
51
54
  isAuthenticationError: () => import_connect2.isAuthenticationError,
52
55
  isConsentRequiredError: () => import_connect2.isConsentRequiredError,
56
+ isFeatureUnavailableError: () => import_connect2.isFeatureUnavailableError,
53
57
  isNetworkError: () => import_connect2.isNetworkError,
54
58
  isSecureCryptoAvailable: () => isSecureCryptoAvailable,
55
59
  useEdgeLink: () => useEdgeLink,
@@ -60,8 +64,8 @@ module.exports = __toCommonJS(index_exports);
60
64
  var import_connect2 = require("@edge-markets/connect");
61
65
 
62
66
  // src/edge-link.ts
63
- var import_react_native = require("react-native");
64
67
  var import_connect = require("@edge-markets/connect");
68
+ var import_react_native = require("react-native");
65
69
 
66
70
  // src/pkce.ts
67
71
  function hasNativeCrypto() {
@@ -381,6 +385,8 @@ var EdgeLink = class {
381
385
  console.warn("[EdgeLink] Already open");
382
386
  return;
383
387
  }
388
+ const scopes = this.getScopes();
389
+ this.assertActiveScopes(scopes);
384
390
  this.emitEvent("OPEN");
385
391
  this.isOpen = true;
386
392
  try {
@@ -423,10 +429,8 @@ var EdgeLink = class {
423
429
  this.cleanup();
424
430
  }
425
431
  buildLinkUrl() {
426
- const envConfig = (0, import_connect.getEnvironmentConfig)(this.config.environment);
427
- const baseUrl = this.config.linkUrl || `${envConfig.userClientUrl}/oauth/link`;
428
- const url = new URL(baseUrl);
429
- const scopes = this.config.scopes || import_connect.ALL_EDGE_SCOPES;
432
+ const url = new URL((0, import_connect.getLinkUrl)(this.config.environment, this.config.linkUrl));
433
+ const scopes = this.getScopes();
430
434
  url.searchParams.set("client_id", this.config.clientId);
431
435
  url.searchParams.set("state", this.state);
432
436
  url.searchParams.set("code_challenge", this.pkce.challenge);
@@ -438,6 +442,14 @@ var EdgeLink = class {
438
442
  url.searchParams.set("flow", "redirect");
439
443
  return url.toString();
440
444
  }
445
+ getScopes() {
446
+ return this.config.scopes || import_connect.ACTIVE_EDGE_SCOPES;
447
+ }
448
+ assertActiveScopes(scopes) {
449
+ if (scopes.some((scope) => (0, import_connect.isTransferWriteScope)(scope))) {
450
+ throw new import_connect.EdgeFeatureUnavailableError();
451
+ }
452
+ }
441
453
  setupLinkListener() {
442
454
  this.removeLinkListener();
443
455
  this.linkListener = import_react_native.Linking.addEventListener("url", ({ url }) => {
@@ -570,21 +582,23 @@ function useEdgeLink(config) {
570
582
  linkRef.current?.destroy();
571
583
  linkRef.current = null;
572
584
  };
573
- }, [
574
- config.clientId,
575
- config.environment,
576
- config.redirectUri,
577
- config.scopes,
578
- config.linkUrl,
579
- config.useExternalBrowser
580
- ]);
585
+ }, [config.clientId, config.environment, config.redirectUri, config.scopes, config.linkUrl, config.useExternalBrowser]);
581
586
  const open = (0, import_react.useCallback)(async () => {
582
587
  if (!linkRef.current) return;
583
588
  setIsOpen(true);
584
589
  setIsSuccess(false);
585
590
  setIsError(false);
586
591
  setError(null);
587
- await linkRef.current.open();
592
+ try {
593
+ await linkRef.current.open();
594
+ } catch (err) {
595
+ setIsOpen(false);
596
+ setIsError(true);
597
+ setError({
598
+ code: err instanceof Error && "code" in err ? String(err.code) : "open_failed",
599
+ message: err instanceof Error ? err.message : "Failed to open EdgeLink"
600
+ });
601
+ }
588
602
  }, []);
589
603
  const close = (0, import_react.useCallback)(async () => {
590
604
  if (!linkRef.current) return;
@@ -696,12 +710,15 @@ async function collectGeolocation() {
696
710
  }
697
711
  // Annotate the CommonJS export names for ESM import in node:
698
712
  0 && (module.exports = {
713
+ ACTIVE_EDGE_SCOPES,
699
714
  ALL_EDGE_SCOPES,
715
+ EDGE_CONNECT_FEATURE_UNAVAILABLE_MESSAGE,
700
716
  EDGE_ENVIRONMENTS,
701
717
  EdgeApiError,
702
718
  EdgeAuthenticationError,
703
719
  EdgeConsentRequiredError,
704
720
  EdgeError,
721
+ EdgeFeatureUnavailableError,
705
722
  EdgeLink,
706
723
  EdgeNetworkError,
707
724
  EdgePopupBlockedError,
@@ -716,6 +733,7 @@ async function collectGeolocation() {
716
733
  isApiError,
717
734
  isAuthenticationError,
718
735
  isConsentRequiredError,
736
+ isFeatureUnavailableError,
719
737
  isNetworkError,
720
738
  isSecureCryptoAvailable,
721
739
  useEdgeLink,
package/dist/index.mjs CHANGED
@@ -1,31 +1,37 @@
1
1
  // src/index.ts
2
2
  import {
3
- ALL_EDGE_SCOPES as ALL_EDGE_SCOPES2,
3
+ ACTIVE_EDGE_SCOPES as ACTIVE_EDGE_SCOPES2,
4
+ ALL_EDGE_SCOPES,
5
+ EDGE_CONNECT_FEATURE_UNAVAILABLE_MESSAGE,
4
6
  EDGE_ENVIRONMENTS,
5
7
  EdgeApiError,
6
8
  EdgeAuthenticationError,
7
9
  EdgeConsentRequiredError,
8
10
  EdgeError,
11
+ EdgeFeatureUnavailableError as EdgeFeatureUnavailableError2,
9
12
  EdgeNetworkError,
10
13
  EdgePopupBlockedError,
11
14
  EdgeStateMismatchError,
12
15
  EdgeTokenExchangeError,
13
16
  SCOPE_DESCRIPTIONS,
14
17
  formatScopesForEnvironment as formatScopesForEnvironment2,
15
- getEnvironmentConfig as getEnvironmentConfig2,
18
+ getEnvironmentConfig,
16
19
  isApiError,
17
20
  isAuthenticationError,
18
21
  isConsentRequiredError,
22
+ isFeatureUnavailableError,
19
23
  isNetworkError
20
24
  } from "@edge-markets/connect";
21
25
 
22
26
  // src/edge-link.ts
23
- import { Linking, Platform } from "react-native";
24
27
  import {
25
- getEnvironmentConfig,
26
- ALL_EDGE_SCOPES,
27
- formatScopesForEnvironment
28
+ ACTIVE_EDGE_SCOPES,
29
+ EdgeFeatureUnavailableError,
30
+ formatScopesForEnvironment,
31
+ getLinkUrl,
32
+ isTransferWriteScope
28
33
  } from "@edge-markets/connect";
34
+ import { Linking, Platform } from "react-native";
29
35
 
30
36
  // src/pkce.ts
31
37
  function hasNativeCrypto() {
@@ -345,6 +351,8 @@ var EdgeLink = class {
345
351
  console.warn("[EdgeLink] Already open");
346
352
  return;
347
353
  }
354
+ const scopes = this.getScopes();
355
+ this.assertActiveScopes(scopes);
348
356
  this.emitEvent("OPEN");
349
357
  this.isOpen = true;
350
358
  try {
@@ -387,10 +395,8 @@ var EdgeLink = class {
387
395
  this.cleanup();
388
396
  }
389
397
  buildLinkUrl() {
390
- const envConfig = getEnvironmentConfig(this.config.environment);
391
- const baseUrl = this.config.linkUrl || `${envConfig.userClientUrl}/oauth/link`;
392
- const url = new URL(baseUrl);
393
- const scopes = this.config.scopes || ALL_EDGE_SCOPES;
398
+ const url = new URL(getLinkUrl(this.config.environment, this.config.linkUrl));
399
+ const scopes = this.getScopes();
394
400
  url.searchParams.set("client_id", this.config.clientId);
395
401
  url.searchParams.set("state", this.state);
396
402
  url.searchParams.set("code_challenge", this.pkce.challenge);
@@ -402,6 +408,14 @@ var EdgeLink = class {
402
408
  url.searchParams.set("flow", "redirect");
403
409
  return url.toString();
404
410
  }
411
+ getScopes() {
412
+ return this.config.scopes || ACTIVE_EDGE_SCOPES;
413
+ }
414
+ assertActiveScopes(scopes) {
415
+ if (scopes.some((scope) => isTransferWriteScope(scope))) {
416
+ throw new EdgeFeatureUnavailableError();
417
+ }
418
+ }
405
419
  setupLinkListener() {
406
420
  this.removeLinkListener();
407
421
  this.linkListener = Linking.addEventListener("url", ({ url }) => {
@@ -534,21 +548,23 @@ function useEdgeLink(config) {
534
548
  linkRef.current?.destroy();
535
549
  linkRef.current = null;
536
550
  };
537
- }, [
538
- config.clientId,
539
- config.environment,
540
- config.redirectUri,
541
- config.scopes,
542
- config.linkUrl,
543
- config.useExternalBrowser
544
- ]);
551
+ }, [config.clientId, config.environment, config.redirectUri, config.scopes, config.linkUrl, config.useExternalBrowser]);
545
552
  const open = useCallback(async () => {
546
553
  if (!linkRef.current) return;
547
554
  setIsOpen(true);
548
555
  setIsSuccess(false);
549
556
  setIsError(false);
550
557
  setError(null);
551
- await linkRef.current.open();
558
+ try {
559
+ await linkRef.current.open();
560
+ } catch (err) {
561
+ setIsOpen(false);
562
+ setIsError(true);
563
+ setError({
564
+ code: err instanceof Error && "code" in err ? String(err.code) : "open_failed",
565
+ message: err instanceof Error ? err.message : "Failed to open EdgeLink"
566
+ });
567
+ }
552
568
  }, []);
553
569
  const close = useCallback(async () => {
554
570
  if (!linkRef.current) return;
@@ -659,12 +675,15 @@ async function collectGeolocation() {
659
675
  return null;
660
676
  }
661
677
  export {
662
- ALL_EDGE_SCOPES2 as ALL_EDGE_SCOPES,
678
+ ACTIVE_EDGE_SCOPES2 as ACTIVE_EDGE_SCOPES,
679
+ ALL_EDGE_SCOPES,
680
+ EDGE_CONNECT_FEATURE_UNAVAILABLE_MESSAGE,
663
681
  EDGE_ENVIRONMENTS,
664
682
  EdgeApiError,
665
683
  EdgeAuthenticationError,
666
684
  EdgeConsentRequiredError,
667
685
  EdgeError,
686
+ EdgeFeatureUnavailableError2 as EdgeFeatureUnavailableError,
668
687
  EdgeLink,
669
688
  EdgeNetworkError,
670
689
  EdgePopupBlockedError,
@@ -675,10 +694,11 @@ export {
675
694
  formatScopesForEnvironment2 as formatScopesForEnvironment,
676
695
  generatePKCE,
677
696
  generateState,
678
- getEnvironmentConfig2 as getEnvironmentConfig,
697
+ getEnvironmentConfig,
679
698
  isApiError,
680
699
  isAuthenticationError,
681
700
  isConsentRequiredError,
701
+ isFeatureUnavailableError,
682
702
  isNetworkError,
683
703
  isSecureCryptoAvailable,
684
704
  useEdgeLink,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edge-markets/connect-react-native",
3
- "version": "1.4.1",
3
+ "version": "1.5.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",
@@ -30,7 +30,7 @@
30
30
  "author": "EdgeBoost",
31
31
  "license": "MIT",
32
32
  "dependencies": {
33
- "@edge-markets/connect": "^1.5.1"
33
+ "@edge-markets/connect": "^1.8.0"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "react": ">=18.0.0",