react-native-nitro-auth 0.5.6 → 0.5.8

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 (36) hide show
  1. package/README.md +288 -907
  2. package/android/src/main/cpp/PlatformAuth+Android.cpp +1 -1
  3. package/android/src/main/java/com/auth/AuthAdapter.kt +65 -27
  4. package/cpp/HybridAuth.cpp +58 -7
  5. package/cpp/HybridAuth.hpp +1 -0
  6. package/ios/AuthAdapter.swift +45 -16
  7. package/ios/PlatformAuth+iOS.mm +20 -1
  8. package/lib/commonjs/service.js +21 -17
  9. package/lib/commonjs/service.js.map +1 -1
  10. package/lib/commonjs/use-auth.js +26 -10
  11. package/lib/commonjs/use-auth.js.map +1 -1
  12. package/lib/commonjs/utils/auth-error.js +9 -2
  13. package/lib/commonjs/utils/auth-error.js.map +1 -1
  14. package/lib/module/service.js +21 -17
  15. package/lib/module/service.js.map +1 -1
  16. package/lib/module/use-auth.js +26 -10
  17. package/lib/module/use-auth.js.map +1 -1
  18. package/lib/module/utils/auth-error.js +9 -2
  19. package/lib/module/utils/auth-error.js.map +1 -1
  20. package/lib/typescript/commonjs/Auth.nitro.d.ts +2 -2
  21. package/lib/typescript/commonjs/Auth.nitro.d.ts.map +1 -1
  22. package/lib/typescript/commonjs/service.d.ts.map +1 -1
  23. package/lib/typescript/commonjs/use-auth.d.ts.map +1 -1
  24. package/lib/typescript/commonjs/utils/auth-error.d.ts.map +1 -1
  25. package/lib/typescript/module/Auth.nitro.d.ts +2 -2
  26. package/lib/typescript/module/Auth.nitro.d.ts.map +1 -1
  27. package/lib/typescript/module/service.d.ts.map +1 -1
  28. package/lib/typescript/module/use-auth.d.ts.map +1 -1
  29. package/lib/typescript/module/utils/auth-error.d.ts.map +1 -1
  30. package/nitro.json +4 -1
  31. package/nitrogen/generated/ios/NitroAuth+autolinking.rb +2 -0
  32. package/package.json +10 -8
  33. package/src/Auth.nitro.ts +3 -1
  34. package/src/service.ts +22 -17
  35. package/src/use-auth.ts +35 -6
  36. package/src/utils/auth-error.ts +12 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-nitro-auth",
3
- "version": "0.5.6",
3
+ "version": "0.5.8",
4
4
  "description": "High-performance authentication library for React Native with Google Sign-In, Apple Sign-In, and Microsoft Sign-In support, powered by Nitro Modules (JSI)",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -33,14 +33,16 @@
33
33
  "build": "bob build",
34
34
  "clean": "rimraf lib nitrogen/generated",
35
35
  "codegen": "nitrogen --logLevel=\"debug\"",
36
+ "format:check": "eslint .",
36
37
  "lint": "eslint .",
37
38
  "typecheck": "tsc --noEmit",
38
- "test": "jest",
39
+ "test": "jest",
39
40
  "test:coverage": "jest --coverage",
40
41
  "test:cpp": "node scripts/test-cpp.js",
41
- "prepublishOnly": "bun run clean && bun run build",
42
- "prepack": "node -e \"const fs=require('fs'); fs.copyFileSync('../../README.md','./README.md'); try{fs.copyFileSync('../../LICENSE','./LICENSE')}catch(e){}\"",
43
- "postpack": "node -e \"const fs=require('fs'); ['./README.md','./LICENSE'].forEach(f=>fs.existsSync(f)&&fs.unlinkSync(f))\""
42
+ "prepublishOnly": "bun run clean && bun run codegen && bun run build && bun run typecheck && bun run lint && bun run test && bun run test:cpp",
43
+ "prepack": "bun ../../scripts/sync-package-docs.ts",
44
+ "pack:dry-run": "bun pm pack --dry-run",
45
+ "publish:dry-run": "bun publish --dry-run --access public"
44
46
  },
45
47
  "keywords": [
46
48
  "react-native",
@@ -79,14 +81,14 @@
79
81
  "access": "public"
80
82
  },
81
83
  "devDependencies": {
82
- "@expo/config-plugins": "^55.0.6",
84
+ "@expo/config-plugins": "^55.0.8",
83
85
  "@react-native/babel-preset": "^0.83.0",
84
86
  "@testing-library/react": "^16.3.2",
85
87
  "@types/node": "^22.19.11",
86
88
  "jest-environment-jsdom": "^29.7.0",
87
89
  "react": "19.2.0",
88
- "react-native": "0.83.2",
89
- "react-native-nitro-modules": "^0.35.0",
90
+ "react-native": "0.83.4",
91
+ "react-native-nitro-modules": "^0.35.4",
90
92
  "react-native-web": "^0.21.2",
91
93
  "typescript": "^5.9.3"
92
94
  },
package/src/Auth.nitro.ts CHANGED
@@ -8,6 +8,8 @@ export type AuthErrorCode =
8
8
  | "popup_blocked"
9
9
  | "network_error"
10
10
  | "configuration_error"
11
+ | "not_signed_in"
12
+ | "operation_in_progress"
11
13
  | "unsupported_provider"
12
14
  | "invalid_state"
13
15
  | "invalid_nonce"
@@ -25,7 +27,7 @@ export interface LoginOptions {
25
27
  useOneTap?: boolean;
26
28
  /** (iOS only) Use native sign-in sheet */
27
29
  useSheet?: boolean;
28
- /** Force account picker to show, ignoring any cached session or loginHint */
30
+ /** Force account picker to show, ignoring any cached session or loginHint. On Android Google, this uses the legacy chooser path. */
29
31
  forceAccountPicker?: boolean;
30
32
  /** (Android only) Use legacy Google Sign-In flow (e.g. for serverAuthCode) */
31
33
  useLegacyGoogleSignIn?: boolean;
package/src/service.ts CHANGED
@@ -8,28 +8,33 @@ 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
- await nitroAuth.login(provider, options);
37
+ await getNitroAuth().login(provider, options);
33
38
  return;
34
39
  } catch (e) {
35
40
  throw AuthError.from(e);
@@ -38,7 +43,7 @@ export const AuthService: Auth = {
38
43
 
39
44
  async requestScopes(scopes: string[]) {
40
45
  try {
41
- await nitroAuth.requestScopes(scopes);
46
+ await getNitroAuth().requestScopes(scopes);
42
47
  return;
43
48
  } catch (e) {
44
49
  throw AuthError.from(e);
@@ -47,7 +52,7 @@ export const AuthService: Auth = {
47
52
 
48
53
  async revokeScopes(scopes: string[]) {
49
54
  try {
50
- await nitroAuth.revokeScopes(scopes);
55
+ await getNitroAuth().revokeScopes(scopes);
51
56
  return;
52
57
  } catch (e) {
53
58
  throw AuthError.from(e);
@@ -56,7 +61,7 @@ export const AuthService: Auth = {
56
61
 
57
62
  async getAccessToken() {
58
63
  try {
59
- return await nitroAuth.getAccessToken();
64
+ return await getNitroAuth().getAccessToken();
60
65
  } catch (e) {
61
66
  throw AuthError.from(e);
62
67
  }
@@ -64,19 +69,19 @@ export const AuthService: Auth = {
64
69
 
65
70
  async refreshToken() {
66
71
  try {
67
- return await nitroAuth.refreshToken();
72
+ return await getNitroAuth().refreshToken();
68
73
  } catch (e) {
69
74
  throw AuthError.from(e);
70
75
  }
71
76
  },
72
77
 
73
78
  logout() {
74
- nitroAuth.logout();
79
+ getNitroAuth().logout();
75
80
  },
76
81
 
77
82
  async silentRestore() {
78
83
  try {
79
- await nitroAuth.silentRestore();
84
+ await getNitroAuth().silentRestore();
80
85
  return;
81
86
  } catch (e) {
82
87
  throw AuthError.from(e);
@@ -84,22 +89,22 @@ export const AuthService: Auth = {
84
89
  },
85
90
 
86
91
  onAuthStateChanged(callback: (user: AuthUser | undefined) => void) {
87
- return nitroAuth.onAuthStateChanged(callback);
92
+ return getNitroAuth().onAuthStateChanged(callback);
88
93
  },
89
94
 
90
95
  onTokensRefreshed(callback: (tokens: AuthTokens) => void) {
91
- return nitroAuth.onTokensRefreshed(callback);
96
+ return getNitroAuth().onTokensRefreshed(callback);
92
97
  },
93
98
 
94
99
  setLoggingEnabled(enabled: boolean) {
95
- nitroAuth.setLoggingEnabled(enabled);
100
+ getNitroAuth().setLoggingEnabled(enabled);
96
101
  },
97
102
 
98
103
  dispose() {
99
- nitroAuth.dispose();
104
+ getNitroAuth().dispose();
100
105
  },
101
106
 
102
107
  equals(other: Parameters<Auth["equals"]>[0]): boolean {
103
- return nitroAuth.equals(other);
108
+ return getNitroAuth().equals(other);
104
109
  },
105
110
  };
package/src/use-auth.ts CHANGED
@@ -8,6 +8,8 @@ import type {
8
8
  import { AuthService } from "./service";
9
9
  import { AuthError } from "./utils/auth-error";
10
10
 
11
+ const EMPTY_SCOPES: string[] = [];
12
+
11
13
  type AuthState = {
12
14
  user: AuthUser | undefined;
13
15
  scopes: string[];
@@ -16,13 +18,25 @@ type AuthState = {
16
18
  };
17
19
 
18
20
  const areScopesEqual = (left: string[], right: string[]): boolean => {
21
+ if (left === right) return true;
19
22
  if (left.length !== right.length) return false;
20
- const sortedLeft = [...left].sort();
21
- const sortedRight = [...right].sort();
22
- for (let i = 0; i < sortedLeft.length; i += 1) {
23
- if (sortedLeft[i] !== sortedRight[i]) return false;
23
+
24
+ let matchesInOrder = true;
25
+ for (let i = 0; i < left.length; i += 1) {
26
+ if (left[i] !== right[i]) {
27
+ matchesInOrder = false;
28
+ break;
29
+ }
30
+ }
31
+ if (matchesInOrder) return true;
32
+
33
+ const remaining = new Set(left);
34
+ for (const scope of right) {
35
+ if (!remaining.delete(scope)) {
36
+ return false;
37
+ }
24
38
  }
25
- return true;
39
+ return remaining.size === 0;
26
40
  };
27
41
 
28
42
  export type UseAuthReturn = AuthState & {
@@ -85,7 +99,22 @@ export function useAuth(): UseAuthReturn {
85
99
 
86
100
  const logout = useCallback(() => {
87
101
  AuthService.logout();
88
- setState({ user: undefined, scopes: [], loading: false, error: undefined });
102
+ setState((prev) => {
103
+ if (
104
+ prev.user === undefined &&
105
+ prev.scopes.length === 0 &&
106
+ prev.loading === false &&
107
+ prev.error === undefined
108
+ ) {
109
+ return prev;
110
+ }
111
+ return {
112
+ user: undefined,
113
+ scopes: EMPTY_SCOPES,
114
+ loading: false,
115
+ error: undefined,
116
+ };
117
+ });
89
118
  }, []);
90
119
 
91
120
  const requestScopes = useCallback(
@@ -6,6 +6,8 @@ const AUTH_ERROR_CODES: ReadonlySet<string> = new Set<AuthErrorCode>([
6
6
  "popup_blocked",
7
7
  "network_error",
8
8
  "configuration_error",
9
+ "not_signed_in",
10
+ "operation_in_progress",
9
11
  "unsupported_provider",
10
12
  "invalid_state",
11
13
  "invalid_nonce",
@@ -21,7 +23,16 @@ export function isAuthErrorCode(value: string): value is AuthErrorCode {
21
23
  }
22
24
 
23
25
  export function toAuthErrorCode(raw: string): AuthErrorCode {
24
- return isAuthErrorCode(raw) ? raw : "unknown";
26
+ if (isAuthErrorCode(raw)) {
27
+ return raw;
28
+ }
29
+
30
+ const prefix = raw.split(":", 1)[0]?.trim();
31
+ if (prefix && isAuthErrorCode(prefix)) {
32
+ return prefix;
33
+ }
34
+
35
+ return "unknown";
25
36
  }
26
37
 
27
38
  /**