react-native-nitro-auth 0.5.5 → 0.5.7

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.
Files changed (96) hide show
  1. package/README.md +30 -19
  2. package/android/proguard-rules.pro +7 -1
  3. package/android/src/main/AndroidManifest.xml +12 -0
  4. package/android/src/main/cpp/PlatformAuth+Android.cpp +261 -68
  5. package/android/src/main/java/com/auth/AuthAdapter.kt +250 -157
  6. package/android/src/main/java/com/auth/GoogleSignInActivity.kt +9 -5
  7. package/cpp/HybridAuth.cpp +79 -64
  8. package/cpp/HybridAuth.hpp +9 -7
  9. package/cpp/JSONSerializer.hpp +3 -0
  10. package/ios/AuthAdapter.swift +208 -66
  11. package/ios/PlatformAuth+iOS.mm +30 -4
  12. package/lib/commonjs/Auth.web.js +50 -10
  13. package/lib/commonjs/Auth.web.js.map +1 -1
  14. package/lib/commonjs/index.web.js +30 -12
  15. package/lib/commonjs/index.web.js.map +1 -1
  16. package/lib/commonjs/service.js +25 -19
  17. package/lib/commonjs/service.js.map +1 -1
  18. package/lib/commonjs/service.web.js +65 -13
  19. package/lib/commonjs/service.web.js.map +1 -1
  20. package/lib/commonjs/ui/social-button.js +19 -14
  21. package/lib/commonjs/ui/social-button.js.map +1 -1
  22. package/lib/commonjs/ui/social-button.web.js +16 -10
  23. package/lib/commonjs/ui/social-button.web.js.map +1 -1
  24. package/lib/commonjs/use-auth.js +34 -10
  25. package/lib/commonjs/use-auth.js.map +1 -1
  26. package/lib/commonjs/utils/auth-error.js +1 -1
  27. package/lib/commonjs/utils/auth-error.js.map +1 -1
  28. package/lib/commonjs/utils/logger.js +1 -0
  29. package/lib/commonjs/utils/logger.js.map +1 -1
  30. package/lib/module/Auth.web.js +50 -10
  31. package/lib/module/Auth.web.js.map +1 -1
  32. package/lib/module/global.d.js.map +1 -1
  33. package/lib/module/index.js.map +1 -1
  34. package/lib/module/index.web.js +2 -1
  35. package/lib/module/index.web.js.map +1 -1
  36. package/lib/module/service.js +25 -19
  37. package/lib/module/service.js.map +1 -1
  38. package/lib/module/service.web.js +65 -13
  39. package/lib/module/service.web.js.map +1 -1
  40. package/lib/module/ui/social-button.js +19 -14
  41. package/lib/module/ui/social-button.js.map +1 -1
  42. package/lib/module/ui/social-button.web.js +16 -10
  43. package/lib/module/ui/social-button.web.js.map +1 -1
  44. package/lib/module/use-auth.js +34 -10
  45. package/lib/module/use-auth.js.map +1 -1
  46. package/lib/module/utils/auth-error.js +1 -1
  47. package/lib/module/utils/auth-error.js.map +1 -1
  48. package/lib/module/utils/logger.js +1 -0
  49. package/lib/module/utils/logger.js.map +1 -1
  50. package/lib/typescript/commonjs/Auth.nitro.d.ts +2 -2
  51. package/lib/typescript/commonjs/Auth.nitro.d.ts.map +1 -1
  52. package/lib/typescript/commonjs/Auth.web.d.ts +5 -1
  53. package/lib/typescript/commonjs/Auth.web.d.ts.map +1 -1
  54. package/lib/typescript/commonjs/index.d.ts +1 -1
  55. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  56. package/lib/typescript/commonjs/index.web.d.ts +2 -1
  57. package/lib/typescript/commonjs/index.web.d.ts.map +1 -1
  58. package/lib/typescript/commonjs/service.d.ts.map +1 -1
  59. package/lib/typescript/commonjs/service.web.d.ts +2 -18
  60. package/lib/typescript/commonjs/service.web.d.ts.map +1 -1
  61. package/lib/typescript/commonjs/ui/social-button.d.ts.map +1 -1
  62. package/lib/typescript/commonjs/ui/social-button.web.d.ts.map +1 -1
  63. package/lib/typescript/commonjs/use-auth.d.ts.map +1 -1
  64. package/lib/typescript/commonjs/utils/auth-error.d.ts.map +1 -1
  65. package/lib/typescript/commonjs/utils/logger.d.ts.map +1 -1
  66. package/lib/typescript/module/Auth.nitro.d.ts +2 -2
  67. package/lib/typescript/module/Auth.nitro.d.ts.map +1 -1
  68. package/lib/typescript/module/Auth.web.d.ts +5 -1
  69. package/lib/typescript/module/Auth.web.d.ts.map +1 -1
  70. package/lib/typescript/module/index.d.ts +1 -1
  71. package/lib/typescript/module/index.d.ts.map +1 -1
  72. package/lib/typescript/module/index.web.d.ts +2 -1
  73. package/lib/typescript/module/index.web.d.ts.map +1 -1
  74. package/lib/typescript/module/service.d.ts.map +1 -1
  75. package/lib/typescript/module/service.web.d.ts +2 -18
  76. package/lib/typescript/module/service.web.d.ts.map +1 -1
  77. package/lib/typescript/module/ui/social-button.d.ts.map +1 -1
  78. package/lib/typescript/module/ui/social-button.web.d.ts.map +1 -1
  79. package/lib/typescript/module/use-auth.d.ts.map +1 -1
  80. package/lib/typescript/module/utils/auth-error.d.ts.map +1 -1
  81. package/lib/typescript/module/utils/logger.d.ts.map +1 -1
  82. package/nitro.json +4 -1
  83. package/nitrogen/generated/ios/NitroAuth+autolinking.rb +2 -0
  84. package/package.json +3 -4
  85. package/src/Auth.nitro.ts +3 -1
  86. package/src/Auth.web.ts +77 -11
  87. package/src/global.d.ts +0 -11
  88. package/src/index.ts +5 -1
  89. package/src/index.web.ts +6 -1
  90. package/src/service.ts +26 -19
  91. package/src/service.web.ts +84 -15
  92. package/src/ui/social-button.tsx +21 -9
  93. package/src/ui/social-button.web.tsx +17 -4
  94. package/src/use-auth.ts +65 -9
  95. package/src/utils/auth-error.ts +2 -0
  96. package/src/utils/logger.ts +1 -0
package/src/Auth.web.ts CHANGED
@@ -24,6 +24,7 @@ const WEB_STORAGE_MODES = new Set([
24
24
  STORAGE_MODE_MEMORY,
25
25
  ] as const);
26
26
  const inMemoryWebStorage = new Map<string, string>();
27
+ let _appleSdkLoadPromise: Promise<void> | undefined;
27
28
 
28
29
  type WebStorageDriver = {
29
30
  save(key: string, value: string): void;
@@ -152,6 +153,7 @@ const parseAuthWebExtraConfig = (value: unknown): AuthWebExtraConfig => {
152
153
 
153
154
  const getConfig = (): AuthWebExtraConfig => {
154
155
  try {
156
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
155
157
  const Constants = require("expo-constants").default;
156
158
  return parseAuthWebExtraConfig(Constants.expoConfig?.extra);
157
159
  } catch (error) {
@@ -175,7 +177,8 @@ class AuthWeb implements Auth {
175
177
  private _browserStorageResolved = false;
176
178
  private _browserStorageCache: Storage | undefined;
177
179
  private _refreshPromise: Promise<AuthTokens> | undefined;
178
- private _appleSdkLoadPromise: Promise<void> | undefined;
180
+ private _pendingGoogleNonce: string | undefined;
181
+ private _loginInFlight: boolean = false;
179
182
 
180
183
  constructor() {
181
184
  this._config = getConfig();
@@ -303,6 +306,7 @@ class AuthWeb implements Auth {
303
306
  const storage = this.getBrowserStorage();
304
307
  if (storage) {
305
308
  storage.removeItem(key);
309
+ return;
306
310
  }
307
311
  inMemoryWebStorage.delete(key);
308
312
  }
@@ -539,7 +543,7 @@ class AuthWeb implements Auth {
539
543
  const refreshToken = this.loadRefreshToken();
540
544
 
541
545
  if (!refreshToken) {
542
- throw new Error("No refresh token available");
546
+ throw new AuthWebError("refresh_failed", "No refresh token available");
543
547
  }
544
548
 
545
549
  const clientId = this._config.microsoftClientId;
@@ -645,13 +649,27 @@ class AuthWeb implements Auth {
645
649
 
646
650
  if (msg.includes("cancel") || msg.includes("popup_closed")) {
647
651
  mappedMsg = "cancelled";
652
+ } else if (msg.includes("access_denied")) {
653
+ mappedMsg = "cancelled";
648
654
  } else if (msg.includes("timeout")) {
649
655
  mappedMsg = "timeout";
650
656
  } else if (msg.includes("popup blocked")) {
651
657
  mappedMsg = "popup_blocked";
652
- } else if (msg.includes("network")) {
658
+ } else if (
659
+ msg.includes("network") ||
660
+ msg.includes("server_error") ||
661
+ msg.includes("temporarily_unavailable")
662
+ ) {
653
663
  mappedMsg = "network_error";
654
- } else if (msg.includes("client id") || msg.includes("config")) {
664
+ } else if (msg.includes("invalid_grant") || msg.includes("invalid_token")) {
665
+ mappedMsg = "refresh_failed";
666
+ } else if (
667
+ msg.includes("invalid_scope") ||
668
+ msg.includes("unauthorized_client") ||
669
+ msg.includes("invalid_client") ||
670
+ msg.includes("client id") ||
671
+ msg.includes("config")
672
+ ) {
655
673
  mappedMsg = "configuration_error";
656
674
  }
657
675
 
@@ -746,6 +764,24 @@ class AuthWeb implements Auth {
746
764
  private async loginGoogle(
747
765
  scopes: string[],
748
766
  loginHint?: string,
767
+ ): Promise<void> {
768
+ if (this._loginInFlight) {
769
+ throw new AuthWebError(
770
+ "cancelled",
771
+ "Another login is already in progress",
772
+ );
773
+ }
774
+ this._loginInFlight = true;
775
+ try {
776
+ await this._loginGoogleInner(scopes, loginHint);
777
+ } finally {
778
+ this._loginInFlight = false;
779
+ }
780
+ }
781
+
782
+ private async _loginGoogleInner(
783
+ scopes: string[],
784
+ loginHint?: string,
749
785
  ): Promise<void> {
750
786
  const clientId = this._config.googleWebClientId;
751
787
 
@@ -755,6 +791,8 @@ class AuthWeb implements Auth {
755
791
  );
756
792
  }
757
793
 
794
+ const nonce = crypto.randomUUID();
795
+ this._pendingGoogleNonce = nonce;
758
796
  return new Promise((resolve, reject) => {
759
797
  const redirectUri = window.location.origin;
760
798
  const authUrl = new URL("https://accounts.google.com/o/oauth2/v2/auth");
@@ -762,7 +800,7 @@ class AuthWeb implements Auth {
762
800
  authUrl.searchParams.set("redirect_uri", redirectUri);
763
801
  authUrl.searchParams.set("response_type", "id_token token code");
764
802
  authUrl.searchParams.set("scope", scopes.join(" "));
765
- authUrl.searchParams.set("nonce", crypto.randomUUID());
803
+ authUrl.searchParams.set("nonce", nonce);
766
804
  authUrl.searchParams.set("access_type", "offline");
767
805
  authUrl.searchParams.set("prompt", "consent");
768
806
 
@@ -798,6 +836,13 @@ class AuthWeb implements Auth {
798
836
  throw new Error("No id_token in response");
799
837
  }
800
838
 
839
+ const decoded = this.parseJwtPayload(idToken);
840
+ if (decoded["nonce"] !== this._pendingGoogleNonce) {
841
+ this._pendingGoogleNonce = undefined;
842
+ throw new Error("Nonce mismatch - possible replay attack");
843
+ }
844
+ this._pendingGoogleNonce = undefined;
845
+
801
846
  this._grantedScopes = scopes;
802
847
  this.saveValue(SCOPES_KEY, JSON.stringify(scopes));
803
848
 
@@ -842,6 +887,26 @@ class AuthWeb implements Auth {
842
887
  loginHint?: string,
843
888
  tenant?: string,
844
889
  prompt?: string,
890
+ ): Promise<void> {
891
+ if (this._loginInFlight) {
892
+ throw new AuthWebError(
893
+ "cancelled",
894
+ "Another login is already in progress",
895
+ );
896
+ }
897
+ this._loginInFlight = true;
898
+ try {
899
+ await this._loginMicrosoftInner(scopes, loginHint, tenant, prompt);
900
+ } finally {
901
+ this._loginInFlight = false;
902
+ }
903
+ }
904
+
905
+ private async _loginMicrosoftInner(
906
+ scopes: string[],
907
+ loginHint?: string,
908
+ tenant?: string,
909
+ prompt?: string,
845
910
  ): Promise<void> {
846
911
  const clientId = this._config.microsoftClientId;
847
912
 
@@ -1074,11 +1139,11 @@ class AuthWeb implements Auth {
1074
1139
  return;
1075
1140
  }
1076
1141
 
1077
- if (this._appleSdkLoadPromise) {
1078
- return this._appleSdkLoadPromise;
1142
+ if (_appleSdkLoadPromise) {
1143
+ return _appleSdkLoadPromise;
1079
1144
  }
1080
1145
 
1081
- this._appleSdkLoadPromise = new Promise<void>((resolve, reject) => {
1146
+ _appleSdkLoadPromise = new Promise<void>((resolve, reject) => {
1082
1147
  const scriptId = "nitro-auth-apple-sdk";
1083
1148
  const existingScript = document.getElementById(
1084
1149
  scriptId,
@@ -1102,7 +1167,7 @@ class AuthWeb implements Auth {
1102
1167
  existingScript.addEventListener(
1103
1168
  "error",
1104
1169
  () => {
1105
- this._appleSdkLoadPromise = undefined;
1170
+ _appleSdkLoadPromise = undefined;
1106
1171
  reject(new Error("Failed to load Apple SDK"));
1107
1172
  },
1108
1173
  { once: true },
@@ -1119,13 +1184,13 @@ class AuthWeb implements Auth {
1119
1184
  resolve();
1120
1185
  };
1121
1186
  script.onerror = () => {
1122
- this._appleSdkLoadPromise = undefined;
1187
+ _appleSdkLoadPromise = undefined;
1123
1188
  reject(new Error("Failed to load Apple SDK"));
1124
1189
  };
1125
1190
  document.head.appendChild(script);
1126
1191
  });
1127
1192
 
1128
- return this._appleSdkLoadPromise;
1193
+ return _appleSdkLoadPromise;
1129
1194
  }
1130
1195
 
1131
1196
  private async loginApple(): Promise<void> {
@@ -1199,6 +1264,7 @@ class AuthWeb implements Auth {
1199
1264
  logger.setEnabled(enabled);
1200
1265
  }
1201
1266
 
1267
+ /** @internal Reserved for future use — not part of the public API */
1202
1268
  setWebStorageAdapter(adapter: JSStorageAdapter | undefined): void {
1203
1269
  this._storageAdapter = adapter
1204
1270
  ? this.createWebStorageDriver(adapter)
package/src/global.d.ts CHANGED
@@ -1,16 +1,5 @@
1
1
  declare global {
2
2
  interface Window {
3
- google?: {
4
- accounts: {
5
- id: {
6
- initialize: (config: {
7
- client_id: string;
8
- callback: (response: { credential: string }) => void;
9
- }) => void;
10
- prompt: () => void;
11
- };
12
- };
13
- };
14
3
  AppleID?: {
15
4
  auth: {
16
5
  init: (config: {
package/src/index.ts CHANGED
@@ -2,4 +2,8 @@ export * from "./Auth.nitro";
2
2
  export * from "./ui/social-button";
3
3
  export { useAuth, type UseAuthReturn } from "./use-auth";
4
4
  export { AuthService } from "./service";
5
- export { AuthError, isAuthErrorCode, toAuthErrorCode } from "./utils/auth-error";
5
+ export {
6
+ AuthError,
7
+ isAuthErrorCode,
8
+ toAuthErrorCode,
9
+ } from "./utils/auth-error";
package/src/index.web.ts CHANGED
@@ -1,4 +1,9 @@
1
1
  export * from "./Auth.nitro";
2
2
  export * from "./ui/social-button.web";
3
- export * from "./use-auth";
3
+ export { useAuth, type UseAuthReturn } from "./use-auth";
4
4
  export { AuthService } from "./service.web";
5
+ export {
6
+ AuthError,
7
+ isAuthErrorCode,
8
+ toAuthErrorCode,
9
+ } from "./utils/auth-error";
package/src/service.ts CHANGED
@@ -8,28 +8,34 @@ import type {
8
8
  } from "./Auth.nitro";
9
9
  import { AuthError } from "./utils/auth-error";
10
10
 
11
- const nitroAuth = NitroModules.createHybridObject<Auth>("Auth");
11
+ let nitroAuth: Auth | undefined;
12
+
13
+ function getNitroAuth(): Auth {
14
+ nitroAuth ??= NitroModules.createHybridObject<Auth>("Auth");
15
+ return nitroAuth;
16
+ }
12
17
 
13
18
  export const AuthService: Auth = {
14
19
  get name() {
15
- return nitroAuth.name;
20
+ return getNitroAuth().name;
16
21
  },
17
22
 
18
23
  get currentUser() {
19
- return nitroAuth.currentUser;
24
+ return getNitroAuth().currentUser;
20
25
  },
21
26
 
22
27
  get grantedScopes() {
23
- return nitroAuth.grantedScopes;
28
+ return getNitroAuth().grantedScopes;
24
29
  },
25
30
 
26
31
  get hasPlayServices() {
27
- return nitroAuth.hasPlayServices;
32
+ return getNitroAuth().hasPlayServices;
28
33
  },
29
34
 
30
35
  async login(provider: AuthProvider, options?: LoginOptions) {
31
36
  try {
32
- return await nitroAuth.login(provider, options);
37
+ await getNitroAuth().login(provider, options);
38
+ return;
33
39
  } catch (e) {
34
40
  throw AuthError.from(e);
35
41
  }
@@ -37,7 +43,8 @@ export const AuthService: Auth = {
37
43
 
38
44
  async requestScopes(scopes: string[]) {
39
45
  try {
40
- return await nitroAuth.requestScopes(scopes);
46
+ await getNitroAuth().requestScopes(scopes);
47
+ return;
41
48
  } catch (e) {
42
49
  throw AuthError.from(e);
43
50
  }
@@ -45,7 +52,8 @@ export const AuthService: Auth = {
45
52
 
46
53
  async revokeScopes(scopes: string[]) {
47
54
  try {
48
- return await nitroAuth.revokeScopes(scopes);
55
+ await getNitroAuth().revokeScopes(scopes);
56
+ return;
49
57
  } catch (e) {
50
58
  throw AuthError.from(e);
51
59
  }
@@ -53,7 +61,7 @@ export const AuthService: Auth = {
53
61
 
54
62
  async getAccessToken() {
55
63
  try {
56
- return await nitroAuth.getAccessToken();
64
+ return await getNitroAuth().getAccessToken();
57
65
  } catch (e) {
58
66
  throw AuthError.from(e);
59
67
  }
@@ -61,43 +69,42 @@ export const AuthService: Auth = {
61
69
 
62
70
  async refreshToken() {
63
71
  try {
64
- return await nitroAuth.refreshToken();
72
+ return await getNitroAuth().refreshToken();
65
73
  } catch (e) {
66
74
  throw AuthError.from(e);
67
75
  }
68
76
  },
69
77
 
70
78
  logout() {
71
- nitroAuth.logout();
79
+ getNitroAuth().logout();
72
80
  },
73
81
 
74
82
  async silentRestore() {
75
83
  try {
76
- return await nitroAuth.silentRestore();
84
+ await getNitroAuth().silentRestore();
85
+ return;
77
86
  } catch (e) {
78
87
  throw AuthError.from(e);
79
88
  }
80
89
  },
81
90
 
82
91
  onAuthStateChanged(callback: (user: AuthUser | undefined) => void) {
83
- return nitroAuth.onAuthStateChanged((user) => {
84
- callback(user);
85
- });
92
+ return getNitroAuth().onAuthStateChanged(callback);
86
93
  },
87
94
 
88
95
  onTokensRefreshed(callback: (tokens: AuthTokens) => void) {
89
- return nitroAuth.onTokensRefreshed(callback);
96
+ return getNitroAuth().onTokensRefreshed(callback);
90
97
  },
91
98
 
92
99
  setLoggingEnabled(enabled: boolean) {
93
- nitroAuth.setLoggingEnabled(enabled);
100
+ getNitroAuth().setLoggingEnabled(enabled);
94
101
  },
95
102
 
96
103
  dispose() {
97
- nitroAuth.dispose();
104
+ getNitroAuth().dispose();
98
105
  },
99
106
 
100
107
  equals(other: Parameters<Auth["equals"]>[0]): boolean {
101
- return nitroAuth.equals(other);
108
+ return getNitroAuth().equals(other);
102
109
  },
103
110
  };
@@ -1,8 +1,14 @@
1
+ import type {
2
+ Auth,
3
+ AuthProvider,
4
+ AuthTokens,
5
+ LoginOptions,
6
+ AuthUser,
7
+ } from "./Auth.nitro";
1
8
  import { AuthModule } from "./Auth.web";
9
+ import { AuthError } from "./utils/auth-error";
2
10
 
3
- export const AuthService = {
4
- ...AuthModule,
5
-
11
+ export const AuthService: Auth = {
6
12
  get name() {
7
13
  return AuthModule.name;
8
14
  },
@@ -19,16 +25,79 @@ export const AuthService = {
19
25
  return AuthModule.hasPlayServices;
20
26
  },
21
27
 
22
- login: AuthModule.login.bind(AuthModule),
23
- logout: AuthModule.logout.bind(AuthModule),
24
- requestScopes: AuthModule.requestScopes.bind(AuthModule),
25
- revokeScopes: AuthModule.revokeScopes.bind(AuthModule),
26
- getAccessToken: AuthModule.getAccessToken.bind(AuthModule),
27
- refreshToken: AuthModule.refreshToken.bind(AuthModule),
28
- silentRestore: AuthModule.silentRestore.bind(AuthModule),
29
- onAuthStateChanged: AuthModule.onAuthStateChanged.bind(AuthModule),
30
- onTokensRefreshed: AuthModule.onTokensRefreshed.bind(AuthModule),
31
- setLoggingEnabled: AuthModule.setLoggingEnabled.bind(AuthModule),
32
- dispose: AuthModule.dispose.bind(AuthModule),
33
- equals: AuthModule.equals.bind(AuthModule),
28
+ async login(provider: AuthProvider, options?: LoginOptions) {
29
+ try {
30
+ await AuthModule.login(provider, options);
31
+ return;
32
+ } catch (e) {
33
+ throw AuthError.from(e);
34
+ }
35
+ },
36
+
37
+ async requestScopes(scopes: string[]) {
38
+ try {
39
+ await AuthModule.requestScopes(scopes);
40
+ return;
41
+ } catch (e) {
42
+ throw AuthError.from(e);
43
+ }
44
+ },
45
+
46
+ async revokeScopes(scopes: string[]) {
47
+ try {
48
+ await AuthModule.revokeScopes(scopes);
49
+ return;
50
+ } catch (e) {
51
+ throw AuthError.from(e);
52
+ }
53
+ },
54
+
55
+ async getAccessToken() {
56
+ try {
57
+ return await AuthModule.getAccessToken();
58
+ } catch (e) {
59
+ throw AuthError.from(e);
60
+ }
61
+ },
62
+
63
+ async refreshToken() {
64
+ try {
65
+ return await AuthModule.refreshToken();
66
+ } catch (e) {
67
+ throw AuthError.from(e);
68
+ }
69
+ },
70
+
71
+ logout() {
72
+ AuthModule.logout();
73
+ },
74
+
75
+ async silentRestore() {
76
+ try {
77
+ await AuthModule.silentRestore();
78
+ return;
79
+ } catch (e) {
80
+ throw AuthError.from(e);
81
+ }
82
+ },
83
+
84
+ onAuthStateChanged(callback: (user: AuthUser | undefined) => void) {
85
+ return AuthModule.onAuthStateChanged(callback);
86
+ },
87
+
88
+ onTokensRefreshed(callback: (tokens: AuthTokens) => void) {
89
+ return AuthModule.onTokensRefreshed(callback);
90
+ },
91
+
92
+ setLoggingEnabled(enabled: boolean) {
93
+ AuthModule.setLoggingEnabled(enabled);
94
+ },
95
+
96
+ dispose() {
97
+ AuthModule.dispose();
98
+ },
99
+
100
+ equals(other: Parameters<Auth["equals"]>[0]): boolean {
101
+ return AuthModule.equals(other);
102
+ },
34
103
  };
@@ -7,8 +7,9 @@ import {
7
7
  View,
8
8
  ActivityIndicator,
9
9
  } from "react-native";
10
- import { NitroModules } from "react-native-nitro-modules";
11
- import type { Auth, AuthProvider, AuthUser } from "../Auth.nitro";
10
+ import { AuthService } from "../service";
11
+ import { logger } from "../utils/logger";
12
+ import type { AuthProvider, AuthUser } from "../Auth.nitro";
12
13
 
13
14
  export type SocialButtonVariant = "primary" | "outline" | "white" | "black";
14
15
 
@@ -56,8 +57,7 @@ const getTextColor = (variant: SocialButtonVariant): string =>
56
57
  variant === "white" || variant === "outline" ? "#000000" : "#FFFFFF";
57
58
 
58
59
  async function performLogin(provider: AuthProvider): Promise<void> {
59
- const auth = NitroModules.createHybridObject<Auth>("Auth");
60
- await auth.login(provider);
60
+ await AuthService.login(provider);
61
61
  }
62
62
 
63
63
  export const SocialButton = ({
@@ -83,12 +83,16 @@ export const SocialButton = ({
83
83
  setLoading(true);
84
84
  try {
85
85
  await performLogin(provider);
86
- const user = NitroModules.createHybridObject<Auth>("Auth").currentUser;
86
+ const user = AuthService.currentUser;
87
87
  if (user) {
88
88
  onSuccess?.(user);
89
89
  }
90
90
  } catch (error) {
91
- onError?.(error);
91
+ if (onError) {
92
+ onError(error);
93
+ } else if (__DEV__) {
94
+ logger.error("SocialButton unhandled error:", error);
95
+ }
92
96
  } finally {
93
97
  setLoading(false);
94
98
  }
@@ -126,19 +130,21 @@ export const SocialButton = ({
126
130
  <>
127
131
  {provider === "google" && variant !== "primary" && (
128
132
  <View style={styles.iconPlaceholder}>
129
- <Text style={{ fontSize: 18 }}>G</Text>
133
+ <Text style={styles.iconText}>G</Text>
130
134
  </View>
131
135
  )}
132
136
  {provider === "apple" && variant !== "primary" && (
133
137
  <View style={styles.iconPlaceholder}>
134
- <Text style={{ fontSize: 18, color: getTextColor(variant) }}>
138
+ <Text
139
+ style={[styles.iconText, { color: getTextColor(variant) }]}
140
+ >
135
141
 
136
142
  </Text>
137
143
  </View>
138
144
  )}
139
145
  {provider === "microsoft" && variant !== "primary" && (
140
146
  <View style={styles.iconPlaceholder}>
141
- <Text style={{ fontSize: 16 }}>⊞</Text>
147
+ <Text style={styles.microsoftIconText}>⊞</Text>
142
148
  </View>
143
149
  )}
144
150
  <Text
@@ -179,4 +185,10 @@ const styles = StyleSheet.create({
179
185
  fontSize: 16,
180
186
  fontWeight: "600",
181
187
  },
188
+ iconText: {
189
+ fontSize: 18,
190
+ },
191
+ microsoftIconText: {
192
+ fontSize: 16,
193
+ },
182
194
  });
@@ -8,6 +8,7 @@ import {
8
8
  ActivityIndicator,
9
9
  } from "react-native";
10
10
  import { AuthModule } from "../Auth.web";
11
+ import { logger } from "../utils/logger";
11
12
  import type { AuthProvider, AuthUser } from "../Auth.nitro";
12
13
 
13
14
  export type SocialButtonVariant = "primary" | "outline" | "white" | "black";
@@ -87,7 +88,11 @@ export const SocialButton = ({
87
88
  onSuccess?.(user);
88
89
  }
89
90
  } catch (error) {
90
- onError?.(error);
91
+ if (onError) {
92
+ onError(error);
93
+ } else if (process.env.NODE_ENV !== "production") {
94
+ logger.error("SocialButton unhandled error:", error);
95
+ }
91
96
  } finally {
92
97
  setLoading(false);
93
98
  }
@@ -125,19 +130,21 @@ export const SocialButton = ({
125
130
  <>
126
131
  {provider === "google" && variant !== "primary" && (
127
132
  <View style={styles.iconPlaceholder}>
128
- <Text style={{ fontSize: 18 }}>G</Text>
133
+ <Text style={styles.iconText}>G</Text>
129
134
  </View>
130
135
  )}
131
136
  {provider === "apple" && variant !== "primary" && (
132
137
  <View style={styles.iconPlaceholder}>
133
- <Text style={{ fontSize: 18, color: getTextColor(variant) }}>
138
+ <Text
139
+ style={[styles.iconText, { color: getTextColor(variant) }]}
140
+ >
134
141
 
135
142
  </Text>
136
143
  </View>
137
144
  )}
138
145
  {provider === "microsoft" && variant !== "primary" && (
139
146
  <View style={styles.iconPlaceholder}>
140
- <Text style={{ fontSize: 16 }}>⊞</Text>
147
+ <Text style={styles.microsoftIconText}>⊞</Text>
141
148
  </View>
142
149
  )}
143
150
  <Text
@@ -178,4 +185,10 @@ const styles = StyleSheet.create({
178
185
  fontSize: 16,
179
186
  fontWeight: "600",
180
187
  },
188
+ iconText: {
189
+ fontSize: 18,
190
+ },
191
+ microsoftIconText: {
192
+ fontSize: 16,
193
+ },
181
194
  });