react-native-otp-auto-verify 0.2.1 → 0.2.2
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 +1 -1
- package/android/src/main/java/com/otpautoverify/OtpAutoVerifyModule.kt +148 -148
- package/lib/module/NativeOtpAutoVerify.ts +37 -37
- package/package.json +183 -183
- package/src/NativeOtpAutoVerify.ts +37 -37
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# react-native-otp-auto-verify
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/react-native-otp-auto-verify) [](https://www.npmjs.com/package/react-native-otp-auto-verify) [](https://github.com/kailas-rathod/react-native-otp-auto-verify/blob/main/LICENSE) [](https://www.typescriptlang.org/)
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
**react-native-otp-auto-verify** is a lightweight and secure React Native OTP auto-verification library for Android, built on the official Google SMS Retriever API. It enables automatic OTP detection without requiring READ_SMS or RECEIVE_SMS permissions, ensuring full Google Play Store compliance and enhanced user trust. Designed for modern authentication flows, this library is ideal for fintech apps, banking applications, e-commerce platforms, and secure login systems.
|
|
6
6
|
|
|
7
7
|
- **No permissions**: It requires zero SMS permissions from the user, making it compliant with strict Google Play Store policies.
|
|
@@ -1,148 +1,148 @@
|
|
|
1
|
-
package com.otpautoverify
|
|
2
|
-
|
|
3
|
-
import android.annotation.SuppressLint
|
|
4
|
-
import android.content.IntentFilter
|
|
5
|
-
import android.os.Build
|
|
6
|
-
import android.util.Log
|
|
7
|
-
import com.facebook.react.bridge.Arguments
|
|
8
|
-
import com.facebook.react.bridge.LifecycleEventListener
|
|
9
|
-
import com.facebook.react.bridge.Promise
|
|
10
|
-
import com.facebook.react.bridge.ReactApplicationContext
|
|
11
|
-
import com.google.android.gms.auth.api.phone.SmsRetriever
|
|
12
|
-
import com.google.android.gms.tasks.OnFailureListener
|
|
13
|
-
import com.google.android.gms.tasks.OnSuccessListener
|
|
14
|
-
class OtpAutoVerifyModule(reactContext: ReactApplicationContext) :
|
|
15
|
-
NativeOtpAutoVerifySpec(reactContext), LifecycleEventListener {
|
|
16
|
-
|
|
17
|
-
companion object {
|
|
18
|
-
const val NAME = NativeOtpAutoVerifySpec.NAME
|
|
19
|
-
private const val TAG = "OtpAutoVerifyModule"
|
|
20
|
-
const val OTP_RECEIVED_EVENT = "otpReceived"
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
private var smsReceiver: SmsRetrieverBroadcastReceiver? = null
|
|
24
|
-
private var isReceiverRegistered = false
|
|
25
|
-
private var isListening = false
|
|
26
|
-
|
|
27
|
-
init {
|
|
28
|
-
reactContext.addLifecycleEventListener(this)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
override fun getTypedExportedConstants(): MutableMap<String, Any> {
|
|
32
|
-
return mutableMapOf("OTP_RECEIVED_EVENT" to OTP_RECEIVED_EVENT)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
override fun getHash(promise: Promise) {
|
|
36
|
-
try {
|
|
37
|
-
val helper = AppSignatureHelper(reactApplicationContext)
|
|
38
|
-
val signatures = helper.getAppSignatures()
|
|
39
|
-
val arr = Arguments.createArray()
|
|
40
|
-
for (s in signatures) {
|
|
41
|
-
arr.pushString(s)
|
|
42
|
-
}
|
|
43
|
-
promise.resolve(arr)
|
|
44
|
-
} catch (e: Exception) {
|
|
45
|
-
Log.e(TAG, "getHash failed", e)
|
|
46
|
-
promise.reject("GET_HASH_ERROR", e.message, e)
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
override fun startSmsRetriever(promise: Promise) {
|
|
51
|
-
val activity = currentActivity
|
|
52
|
-
if (activity == null) {
|
|
53
|
-
promise.reject("NO_ACTIVITY", "No current activity. Ensure the app is in the foreground.")
|
|
54
|
-
return
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
registerReceiverIfNecessary(activity)
|
|
58
|
-
|
|
59
|
-
val client = SmsRetriever.getClient(reactApplicationContext)
|
|
60
|
-
client.startSmsRetriever()
|
|
61
|
-
.addOnSuccessListener(OnSuccessListener {
|
|
62
|
-
Log.d(TAG, "SMS retriever started")
|
|
63
|
-
isListening = true
|
|
64
|
-
promise.resolve(true)
|
|
65
|
-
})
|
|
66
|
-
.addOnFailureListener(OnFailureListener { e ->
|
|
67
|
-
Log.e(TAG, "Failed to start SMS retriever", e)
|
|
68
|
-
promise.reject("START_SMS_RETRIEVER_ERROR", e.message, e)
|
|
69
|
-
})
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
@SuppressLint("UnspecifiedRegisterReceiverFlag")
|
|
73
|
-
private fun registerReceiverIfNecessary(activity: android.app.Activity) {
|
|
74
|
-
if (isReceiverRegistered) return
|
|
75
|
-
try {
|
|
76
|
-
smsReceiver = SmsRetrieverBroadcastReceiver(reactApplicationContext, OTP_RECEIVED_EVENT)
|
|
77
|
-
val filter = IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION)
|
|
78
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
79
|
-
activity.registerReceiver(
|
|
80
|
-
smsReceiver,
|
|
81
|
-
filter,
|
|
82
|
-
SmsRetriever.SEND_PERMISSION,
|
|
83
|
-
null,
|
|
84
|
-
android.content.Context.RECEIVER_EXPORTED
|
|
85
|
-
)
|
|
86
|
-
} else {
|
|
87
|
-
activity.registerReceiver(smsReceiver, filter)
|
|
88
|
-
}
|
|
89
|
-
isReceiverRegistered = true
|
|
90
|
-
Log.d(TAG, "SMS receiver registered")
|
|
91
|
-
} catch (e: Exception) {
|
|
92
|
-
Log.e(TAG, "Failed to register SMS receiver", e)
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
private fun unregisterReceiver() {
|
|
97
|
-
if (!isReceiverRegistered || smsReceiver == null) {
|
|
98
|
-
isListening = false
|
|
99
|
-
return
|
|
100
|
-
}
|
|
101
|
-
val activity = currentActivity
|
|
102
|
-
try {
|
|
103
|
-
if (activity != null) {
|
|
104
|
-
activity.unregisterReceiver(smsReceiver)
|
|
105
|
-
Log.d(TAG, "SMS receiver unregistered")
|
|
106
|
-
}
|
|
107
|
-
} catch (e: IllegalArgumentException) {
|
|
108
|
-
Log.w(TAG, "Receiver already unregistered", e)
|
|
109
|
-
} catch (e: Exception) {
|
|
110
|
-
Log.e(TAG, "Failed to unregister SMS receiver", e)
|
|
111
|
-
} finally {
|
|
112
|
-
isReceiverRegistered = false
|
|
113
|
-
smsReceiver = null
|
|
114
|
-
isListening = false
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
override fun addListener(eventName: String) {
|
|
119
|
-
// Required for NativeEventEmitter; no-op.
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
override fun removeListeners(count: Double) {
|
|
123
|
-
unregisterReceiver()
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
override fun onHostResume() {
|
|
127
|
-
// Optionally re-register if we were listening and activity was recreated.
|
|
128
|
-
if (isListening && currentActivity != null && !isReceiverRegistered) {
|
|
129
|
-
currentActivity?.let { registerReceiverIfNecessary(it) }
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
override fun onHostPause() {
|
|
134
|
-
// Keep the SMS receiver registered while paused so OTP can still arrive if the user
|
|
135
|
-
// briefly switches away (e.g. to read the SMS). Teardown happens in onHostDestroy / invalidate.
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
override fun onHostDestroy() {
|
|
139
|
-
unregisterReceiver()
|
|
140
|
-
reactApplicationContext.removeLifecycleEventListener(this)
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
override fun invalidate() {
|
|
144
|
-
unregisterReceiver()
|
|
145
|
-
reactApplicationContext.removeLifecycleEventListener(this)
|
|
146
|
-
super.invalidate()
|
|
147
|
-
}
|
|
148
|
-
}
|
|
1
|
+
package com.otpautoverify
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.content.IntentFilter
|
|
5
|
+
import android.os.Build
|
|
6
|
+
import android.util.Log
|
|
7
|
+
import com.facebook.react.bridge.Arguments
|
|
8
|
+
import com.facebook.react.bridge.LifecycleEventListener
|
|
9
|
+
import com.facebook.react.bridge.Promise
|
|
10
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
11
|
+
import com.google.android.gms.auth.api.phone.SmsRetriever
|
|
12
|
+
import com.google.android.gms.tasks.OnFailureListener
|
|
13
|
+
import com.google.android.gms.tasks.OnSuccessListener
|
|
14
|
+
class OtpAutoVerifyModule(reactContext: ReactApplicationContext) :
|
|
15
|
+
NativeOtpAutoVerifySpec(reactContext), LifecycleEventListener {
|
|
16
|
+
|
|
17
|
+
companion object {
|
|
18
|
+
const val NAME = NativeOtpAutoVerifySpec.NAME
|
|
19
|
+
private const val TAG = "OtpAutoVerifyModule"
|
|
20
|
+
const val OTP_RECEIVED_EVENT = "otpReceived"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private var smsReceiver: SmsRetrieverBroadcastReceiver? = null
|
|
24
|
+
private var isReceiverRegistered = false
|
|
25
|
+
private var isListening = false
|
|
26
|
+
|
|
27
|
+
init {
|
|
28
|
+
reactContext.addLifecycleEventListener(this)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
override fun getTypedExportedConstants(): MutableMap<String, Any> {
|
|
32
|
+
return mutableMapOf("OTP_RECEIVED_EVENT" to OTP_RECEIVED_EVENT)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
override fun getHash(promise: Promise) {
|
|
36
|
+
try {
|
|
37
|
+
val helper = AppSignatureHelper(reactApplicationContext)
|
|
38
|
+
val signatures = helper.getAppSignatures()
|
|
39
|
+
val arr = Arguments.createArray()
|
|
40
|
+
for (s in signatures) {
|
|
41
|
+
arr.pushString(s)
|
|
42
|
+
}
|
|
43
|
+
promise.resolve(arr)
|
|
44
|
+
} catch (e: Exception) {
|
|
45
|
+
Log.e(TAG, "getHash failed", e)
|
|
46
|
+
promise.reject("GET_HASH_ERROR", e.message, e)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
override fun startSmsRetriever(promise: Promise) {
|
|
51
|
+
val activity = currentActivity
|
|
52
|
+
if (activity == null) {
|
|
53
|
+
promise.reject("NO_ACTIVITY", "No current activity. Ensure the app is in the foreground.")
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
registerReceiverIfNecessary(activity)
|
|
58
|
+
|
|
59
|
+
val client = SmsRetriever.getClient(reactApplicationContext)
|
|
60
|
+
client.startSmsRetriever()
|
|
61
|
+
.addOnSuccessListener(OnSuccessListener {
|
|
62
|
+
Log.d(TAG, "SMS retriever started")
|
|
63
|
+
isListening = true
|
|
64
|
+
promise.resolve(true)
|
|
65
|
+
})
|
|
66
|
+
.addOnFailureListener(OnFailureListener { e ->
|
|
67
|
+
Log.e(TAG, "Failed to start SMS retriever", e)
|
|
68
|
+
promise.reject("START_SMS_RETRIEVER_ERROR", e.message, e)
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@SuppressLint("UnspecifiedRegisterReceiverFlag")
|
|
73
|
+
private fun registerReceiverIfNecessary(activity: android.app.Activity) {
|
|
74
|
+
if (isReceiverRegistered) return
|
|
75
|
+
try {
|
|
76
|
+
smsReceiver = SmsRetrieverBroadcastReceiver(reactApplicationContext, OTP_RECEIVED_EVENT)
|
|
77
|
+
val filter = IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION)
|
|
78
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
79
|
+
activity.registerReceiver(
|
|
80
|
+
smsReceiver,
|
|
81
|
+
filter,
|
|
82
|
+
SmsRetriever.SEND_PERMISSION,
|
|
83
|
+
null,
|
|
84
|
+
android.content.Context.RECEIVER_EXPORTED
|
|
85
|
+
)
|
|
86
|
+
} else {
|
|
87
|
+
activity.registerReceiver(smsReceiver, filter)
|
|
88
|
+
}
|
|
89
|
+
isReceiverRegistered = true
|
|
90
|
+
Log.d(TAG, "SMS receiver registered")
|
|
91
|
+
} catch (e: Exception) {
|
|
92
|
+
Log.e(TAG, "Failed to register SMS receiver", e)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private fun unregisterReceiver() {
|
|
97
|
+
if (!isReceiverRegistered || smsReceiver == null) {
|
|
98
|
+
isListening = false
|
|
99
|
+
return
|
|
100
|
+
}
|
|
101
|
+
val activity = currentActivity
|
|
102
|
+
try {
|
|
103
|
+
if (activity != null) {
|
|
104
|
+
activity.unregisterReceiver(smsReceiver)
|
|
105
|
+
Log.d(TAG, "SMS receiver unregistered")
|
|
106
|
+
}
|
|
107
|
+
} catch (e: IllegalArgumentException) {
|
|
108
|
+
Log.w(TAG, "Receiver already unregistered", e)
|
|
109
|
+
} catch (e: Exception) {
|
|
110
|
+
Log.e(TAG, "Failed to unregister SMS receiver", e)
|
|
111
|
+
} finally {
|
|
112
|
+
isReceiverRegistered = false
|
|
113
|
+
smsReceiver = null
|
|
114
|
+
isListening = false
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
override fun addListener(eventName: String) {
|
|
119
|
+
// Required for NativeEventEmitter; no-op.
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
override fun removeListeners(count: Double) {
|
|
123
|
+
unregisterReceiver()
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
override fun onHostResume() {
|
|
127
|
+
// Optionally re-register if we were listening and activity was recreated.
|
|
128
|
+
if (isListening && currentActivity != null && !isReceiverRegistered) {
|
|
129
|
+
currentActivity?.let { registerReceiverIfNecessary(it) }
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
override fun onHostPause() {
|
|
134
|
+
// Keep the SMS receiver registered while paused so OTP can still arrive if the user
|
|
135
|
+
// briefly switches away (e.g. to read the SMS). Teardown happens in onHostDestroy / invalidate.
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
override fun onHostDestroy() {
|
|
139
|
+
unregisterReceiver()
|
|
140
|
+
reactApplicationContext.removeLifecycleEventListener(this)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
override fun invalidate() {
|
|
144
|
+
unregisterReceiver()
|
|
145
|
+
reactApplicationContext.removeLifecycleEventListener(this)
|
|
146
|
+
super.invalidate()
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
import {
|
|
2
|
-
NativeModules,
|
|
3
|
-
TurboModuleRegistry,
|
|
4
|
-
type TurboModule,
|
|
5
|
-
} from 'react-native';
|
|
6
|
-
|
|
7
|
-
export interface Spec extends TurboModule {
|
|
8
|
-
getConstants(): { OTP_RECEIVED_EVENT: string };
|
|
9
|
-
getHash(): Promise<ReadonlyArray<string>>;
|
|
10
|
-
startSmsRetriever(): Promise<boolean>;
|
|
11
|
-
addListener(eventName: string): void;
|
|
12
|
-
removeListeners(count: number): void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function loadNativeModule(): Spec {
|
|
16
|
-
try {
|
|
17
|
-
return TurboModuleRegistry.getEnforcing<Spec>('OtpAutoVerify');
|
|
18
|
-
} catch {
|
|
19
|
-
const legacy = NativeModules.OtpAutoVerify;
|
|
20
|
-
if (!legacy) {
|
|
21
|
-
throw new Error(
|
|
22
|
-
'OtpAutoVerify native module is not available. Ensure the library is properly linked.'
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
return legacy as Spec;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
let cachedModule: Spec | null = null;
|
|
30
|
-
|
|
31
|
-
/** Resolves the native module on first use so importing this package does not throw before APIs run. */
|
|
32
|
-
export function getOtpNativeModule(): Spec {
|
|
33
|
-
if (cachedModule === null) {
|
|
34
|
-
cachedModule = loadNativeModule();
|
|
35
|
-
}
|
|
36
|
-
return cachedModule;
|
|
37
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
NativeModules,
|
|
3
|
+
TurboModuleRegistry,
|
|
4
|
+
type TurboModule,
|
|
5
|
+
} from 'react-native';
|
|
6
|
+
|
|
7
|
+
export interface Spec extends TurboModule {
|
|
8
|
+
getConstants(): { OTP_RECEIVED_EVENT: string };
|
|
9
|
+
getHash(): Promise<ReadonlyArray<string>>;
|
|
10
|
+
startSmsRetriever(): Promise<boolean>;
|
|
11
|
+
addListener(eventName: string): void;
|
|
12
|
+
removeListeners(count: number): void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function loadNativeModule(): Spec {
|
|
16
|
+
try {
|
|
17
|
+
return TurboModuleRegistry.getEnforcing<Spec>('OtpAutoVerify');
|
|
18
|
+
} catch {
|
|
19
|
+
const legacy = NativeModules.OtpAutoVerify;
|
|
20
|
+
if (!legacy) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
'OtpAutoVerify native module is not available. Ensure the library is properly linked.'
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
return legacy as Spec;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let cachedModule: Spec | null = null;
|
|
30
|
+
|
|
31
|
+
/** Resolves the native module on first use so importing this package does not throw before APIs run. */
|
|
32
|
+
export function getOtpNativeModule(): Spec {
|
|
33
|
+
if (cachedModule === null) {
|
|
34
|
+
cachedModule = loadNativeModule();
|
|
35
|
+
}
|
|
36
|
+
return cachedModule;
|
|
37
|
+
}
|
package/package.json
CHANGED
|
@@ -1,183 +1,183 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "react-native-otp-auto-verify",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "react-native-otp-auto-verify is a React Native library for automatic OTP verification on Android and iOS. It uses the Google SMS Retriever API to detect OTP codes automatically without requiring the READ_SMS permission. The library is fully Play Store compliant, improves user login experience, supports TurboModule, and works with the React Native New Architecture",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"react-native",
|
|
7
|
-
"react-native-library",
|
|
8
|
-
"react-native-otp",
|
|
9
|
-
"react-native-otp-auto-verify",
|
|
10
|
-
"react-native-sms",
|
|
11
|
-
"otp",
|
|
12
|
-
"otp-verification",
|
|
13
|
-
"otp-auto-verify",
|
|
14
|
-
"otp-auto-read",
|
|
15
|
-
"sms",
|
|
16
|
-
"sms-retriever",
|
|
17
|
-
"google-sms-retriever",
|
|
18
|
-
"android-otp",
|
|
19
|
-
"ios-otp",
|
|
20
|
-
"otp-without-permission",
|
|
21
|
-
"play-store-compliant",
|
|
22
|
-
"react-native-new-architecture",
|
|
23
|
-
"turbo-module"
|
|
24
|
-
],
|
|
25
|
-
"homepage": "https://github.com/kailas-rathod/react-native-otp-auto-verify?tab=readme-ov-file",
|
|
26
|
-
"bugs": {
|
|
27
|
-
"url": "https://github.com/kailas-rathod/react-native-otp-auto-verify/issues"
|
|
28
|
-
},
|
|
29
|
-
"repository": {
|
|
30
|
-
"type": "git",
|
|
31
|
-
"url": "git+https://github.com/kailas-rathod/react-native-otp-auto-verify.git"
|
|
32
|
-
},
|
|
33
|
-
"license": "MIT",
|
|
34
|
-
"author": "Kailas Rathod (https://github.com/kailas-rathod)",
|
|
35
|
-
"type": "commonjs",
|
|
36
|
-
"main": "./lib/module/index.js",
|
|
37
|
-
"types": "./lib/typescript/src/index.d.ts",
|
|
38
|
-
"files": [
|
|
39
|
-
"src",
|
|
40
|
-
"lib",
|
|
41
|
-
"android",
|
|
42
|
-
"ios",
|
|
43
|
-
"*.podspec",
|
|
44
|
-
"react-native.config.js",
|
|
45
|
-
"!ios/build",
|
|
46
|
-
"!android/build",
|
|
47
|
-
"!android/gradle",
|
|
48
|
-
"!android/gradlew",
|
|
49
|
-
"!android/gradlew.bat",
|
|
50
|
-
"!android/local.properties",
|
|
51
|
-
"!**/__tests__",
|
|
52
|
-
"!**/__fixtures__",
|
|
53
|
-
"!**/__mocks__",
|
|
54
|
-
"!**/.*"
|
|
55
|
-
],
|
|
56
|
-
"scripts": {
|
|
57
|
-
"prepare": "bob build",
|
|
58
|
-
"typecheck": "tsc",
|
|
59
|
-
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
60
|
-
"test": "jest",
|
|
61
|
-
"check": "yarn typecheck && yarn lint && yarn test",
|
|
62
|
-
"release": "release-it --only-version"
|
|
63
|
-
},
|
|
64
|
-
"devDependencies": {
|
|
65
|
-
"@babel/eslint-parser": "^7.28.0",
|
|
66
|
-
"@commitlint/config-conventional": "^19.8.1",
|
|
67
|
-
"@eslint/eslintrc": "^3.3.4",
|
|
68
|
-
"@eslint/js": "9.35.0",
|
|
69
|
-
"@react-native-community/eslint-config": "^3.2.0",
|
|
70
|
-
"@react-native-community/eslint-plugin": "^1.1.0",
|
|
71
|
-
"@typescript-eslint/eslint-plugin": "^8.15.0",
|
|
72
|
-
"@typescript-eslint/parser": "^8.15.0",
|
|
73
|
-
"@react-native/babel-preset": "0.83.3",
|
|
74
|
-
"@release-it/conventional-changelog": "^10.0.6",
|
|
75
|
-
"@types/jest": "^29.5.14",
|
|
76
|
-
"@types/react": "^19.2.0",
|
|
77
|
-
"commitlint": "^19.8.1",
|
|
78
|
-
"eslint": "9.35.0",
|
|
79
|
-
"eslint-config-prettier": "^9.1.0",
|
|
80
|
-
"eslint-plugin-eslint-comments": "^3.2.0",
|
|
81
|
-
"eslint-plugin-ft-flow": "^2.0.1",
|
|
82
|
-
"eslint-plugin-jest": "^28.11.0",
|
|
83
|
-
"eslint-plugin-prettier": "^5.5.4",
|
|
84
|
-
"eslint-plugin-react": "^7.37.0",
|
|
85
|
-
"eslint-plugin-react-hooks": "^4.6.0",
|
|
86
|
-
"eslint-plugin-react-native": "^5.0.0",
|
|
87
|
-
"jest": "^30.3.0",
|
|
88
|
-
"prettier": "^3.4.2",
|
|
89
|
-
"react": "19.2.5",
|
|
90
|
-
"react-native": "0.83.3",
|
|
91
|
-
"react-native-builder-bob": "0.39.1",
|
|
92
|
-
"release-it": "^19.0.4",
|
|
93
|
-
"typescript": "^5.9.3"
|
|
94
|
-
},
|
|
95
|
-
"peerDependencies": {
|
|
96
|
-
"react": "*",
|
|
97
|
-
"react-native": "*"
|
|
98
|
-
},
|
|
99
|
-
"publishConfig": {
|
|
100
|
-
"registry": "https://registry.npmjs.org/"
|
|
101
|
-
},
|
|
102
|
-
"eslintConfig": {
|
|
103
|
-
"root": true,
|
|
104
|
-
"extends": [
|
|
105
|
-
"@react-native-community",
|
|
106
|
-
"prettier"
|
|
107
|
-
],
|
|
108
|
-
"rules": {
|
|
109
|
-
"prettier/prettier": [
|
|
110
|
-
"error",
|
|
111
|
-
{
|
|
112
|
-
"quoteProps": "consistent",
|
|
113
|
-
"singleQuote": true,
|
|
114
|
-
"tabWidth": 2,
|
|
115
|
-
"trailingComma": "es5",
|
|
116
|
-
"useTabs": false
|
|
117
|
-
}
|
|
118
|
-
]
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
"eslintIgnore": [
|
|
122
|
-
"node_modules/",
|
|
123
|
-
"lib/"
|
|
124
|
-
],
|
|
125
|
-
"packageManager": "yarn@4.11.0",
|
|
126
|
-
"react-native-builder-bob": {
|
|
127
|
-
"source": "src",
|
|
128
|
-
"output": "lib",
|
|
129
|
-
"targets": [
|
|
130
|
-
[
|
|
131
|
-
"module",
|
|
132
|
-
{
|
|
133
|
-
"esm": true
|
|
134
|
-
}
|
|
135
|
-
],
|
|
136
|
-
[
|
|
137
|
-
"typescript",
|
|
138
|
-
{
|
|
139
|
-
"project": "tsconfig.build.json"
|
|
140
|
-
}
|
|
141
|
-
]
|
|
142
|
-
]
|
|
143
|
-
},
|
|
144
|
-
"codegenConfig": {
|
|
145
|
-
"name": "OtpAutoVerifySpec",
|
|
146
|
-
"type": "modules",
|
|
147
|
-
"jsSrcsDir": "src",
|
|
148
|
-
"android": {
|
|
149
|
-
"javaPackageName": "com.otpautoverify"
|
|
150
|
-
}
|
|
151
|
-
},
|
|
152
|
-
"prettier": {
|
|
153
|
-
"quoteProps": "consistent",
|
|
154
|
-
"singleQuote": true,
|
|
155
|
-
"tabWidth": 2,
|
|
156
|
-
"trailingComma": "es5",
|
|
157
|
-
"useTabs": false
|
|
158
|
-
},
|
|
159
|
-
"commitlint": {
|
|
160
|
-
"extends": [
|
|
161
|
-
"@commitlint/config-conventional"
|
|
162
|
-
]
|
|
163
|
-
},
|
|
164
|
-
"release-it": {
|
|
165
|
-
"git": {
|
|
166
|
-
"commitMessage": "chore: release ${version}",
|
|
167
|
-
"tagName": "v${version}"
|
|
168
|
-
},
|
|
169
|
-
"npm": {
|
|
170
|
-
"publish": true
|
|
171
|
-
},
|
|
172
|
-
"github": {
|
|
173
|
-
"release": true
|
|
174
|
-
},
|
|
175
|
-
"plugins": {
|
|
176
|
-
"@release-it/conventional-changelog": {
|
|
177
|
-
"preset": {
|
|
178
|
-
"name": "angular"
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "react-native-otp-auto-verify",
|
|
3
|
+
"version": "0.2.2",
|
|
4
|
+
"description": "react-native-otp-auto-verify is a React Native library for automatic OTP verification on Android and iOS. It uses the Google SMS Retriever API to detect OTP codes automatically without requiring the READ_SMS permission. The library is fully Play Store compliant, improves user login experience, supports TurboModule, and works with the React Native New Architecture",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react-native",
|
|
7
|
+
"react-native-library",
|
|
8
|
+
"react-native-otp",
|
|
9
|
+
"react-native-otp-auto-verify",
|
|
10
|
+
"react-native-sms",
|
|
11
|
+
"otp",
|
|
12
|
+
"otp-verification",
|
|
13
|
+
"otp-auto-verify",
|
|
14
|
+
"otp-auto-read",
|
|
15
|
+
"sms",
|
|
16
|
+
"sms-retriever",
|
|
17
|
+
"google-sms-retriever",
|
|
18
|
+
"android-otp",
|
|
19
|
+
"ios-otp",
|
|
20
|
+
"otp-without-permission",
|
|
21
|
+
"play-store-compliant",
|
|
22
|
+
"react-native-new-architecture",
|
|
23
|
+
"turbo-module"
|
|
24
|
+
],
|
|
25
|
+
"homepage": "https://github.com/kailas-rathod/react-native-otp-auto-verify?tab=readme-ov-file",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/kailas-rathod/react-native-otp-auto-verify/issues"
|
|
28
|
+
},
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/kailas-rathod/react-native-otp-auto-verify.git"
|
|
32
|
+
},
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"author": "Kailas Rathod (https://github.com/kailas-rathod)",
|
|
35
|
+
"type": "commonjs",
|
|
36
|
+
"main": "./lib/module/index.js",
|
|
37
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
38
|
+
"files": [
|
|
39
|
+
"src",
|
|
40
|
+
"lib",
|
|
41
|
+
"android",
|
|
42
|
+
"ios",
|
|
43
|
+
"*.podspec",
|
|
44
|
+
"react-native.config.js",
|
|
45
|
+
"!ios/build",
|
|
46
|
+
"!android/build",
|
|
47
|
+
"!android/gradle",
|
|
48
|
+
"!android/gradlew",
|
|
49
|
+
"!android/gradlew.bat",
|
|
50
|
+
"!android/local.properties",
|
|
51
|
+
"!**/__tests__",
|
|
52
|
+
"!**/__fixtures__",
|
|
53
|
+
"!**/__mocks__",
|
|
54
|
+
"!**/.*"
|
|
55
|
+
],
|
|
56
|
+
"scripts": {
|
|
57
|
+
"prepare": "bob build",
|
|
58
|
+
"typecheck": "tsc",
|
|
59
|
+
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
60
|
+
"test": "jest",
|
|
61
|
+
"check": "yarn typecheck && yarn lint && yarn test",
|
|
62
|
+
"release": "release-it --only-version"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@babel/eslint-parser": "^7.28.0",
|
|
66
|
+
"@commitlint/config-conventional": "^19.8.1",
|
|
67
|
+
"@eslint/eslintrc": "^3.3.4",
|
|
68
|
+
"@eslint/js": "9.35.0",
|
|
69
|
+
"@react-native-community/eslint-config": "^3.2.0",
|
|
70
|
+
"@react-native-community/eslint-plugin": "^1.1.0",
|
|
71
|
+
"@typescript-eslint/eslint-plugin": "^8.15.0",
|
|
72
|
+
"@typescript-eslint/parser": "^8.15.0",
|
|
73
|
+
"@react-native/babel-preset": "0.83.3",
|
|
74
|
+
"@release-it/conventional-changelog": "^10.0.6",
|
|
75
|
+
"@types/jest": "^29.5.14",
|
|
76
|
+
"@types/react": "^19.2.0",
|
|
77
|
+
"commitlint": "^19.8.1",
|
|
78
|
+
"eslint": "9.35.0",
|
|
79
|
+
"eslint-config-prettier": "^9.1.0",
|
|
80
|
+
"eslint-plugin-eslint-comments": "^3.2.0",
|
|
81
|
+
"eslint-plugin-ft-flow": "^2.0.1",
|
|
82
|
+
"eslint-plugin-jest": "^28.11.0",
|
|
83
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
84
|
+
"eslint-plugin-react": "^7.37.0",
|
|
85
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
86
|
+
"eslint-plugin-react-native": "^5.0.0",
|
|
87
|
+
"jest": "^30.3.0",
|
|
88
|
+
"prettier": "^3.4.2",
|
|
89
|
+
"react": "19.2.5",
|
|
90
|
+
"react-native": "0.83.3",
|
|
91
|
+
"react-native-builder-bob": "0.39.1",
|
|
92
|
+
"release-it": "^19.0.4",
|
|
93
|
+
"typescript": "^5.9.3"
|
|
94
|
+
},
|
|
95
|
+
"peerDependencies": {
|
|
96
|
+
"react": "*",
|
|
97
|
+
"react-native": "*"
|
|
98
|
+
},
|
|
99
|
+
"publishConfig": {
|
|
100
|
+
"registry": "https://registry.npmjs.org/"
|
|
101
|
+
},
|
|
102
|
+
"eslintConfig": {
|
|
103
|
+
"root": true,
|
|
104
|
+
"extends": [
|
|
105
|
+
"@react-native-community",
|
|
106
|
+
"prettier"
|
|
107
|
+
],
|
|
108
|
+
"rules": {
|
|
109
|
+
"prettier/prettier": [
|
|
110
|
+
"error",
|
|
111
|
+
{
|
|
112
|
+
"quoteProps": "consistent",
|
|
113
|
+
"singleQuote": true,
|
|
114
|
+
"tabWidth": 2,
|
|
115
|
+
"trailingComma": "es5",
|
|
116
|
+
"useTabs": false
|
|
117
|
+
}
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"eslintIgnore": [
|
|
122
|
+
"node_modules/",
|
|
123
|
+
"lib/"
|
|
124
|
+
],
|
|
125
|
+
"packageManager": "yarn@4.11.0",
|
|
126
|
+
"react-native-builder-bob": {
|
|
127
|
+
"source": "src",
|
|
128
|
+
"output": "lib",
|
|
129
|
+
"targets": [
|
|
130
|
+
[
|
|
131
|
+
"module",
|
|
132
|
+
{
|
|
133
|
+
"esm": true
|
|
134
|
+
}
|
|
135
|
+
],
|
|
136
|
+
[
|
|
137
|
+
"typescript",
|
|
138
|
+
{
|
|
139
|
+
"project": "tsconfig.build.json"
|
|
140
|
+
}
|
|
141
|
+
]
|
|
142
|
+
]
|
|
143
|
+
},
|
|
144
|
+
"codegenConfig": {
|
|
145
|
+
"name": "OtpAutoVerifySpec",
|
|
146
|
+
"type": "modules",
|
|
147
|
+
"jsSrcsDir": "src",
|
|
148
|
+
"android": {
|
|
149
|
+
"javaPackageName": "com.otpautoverify"
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
"prettier": {
|
|
153
|
+
"quoteProps": "consistent",
|
|
154
|
+
"singleQuote": true,
|
|
155
|
+
"tabWidth": 2,
|
|
156
|
+
"trailingComma": "es5",
|
|
157
|
+
"useTabs": false
|
|
158
|
+
},
|
|
159
|
+
"commitlint": {
|
|
160
|
+
"extends": [
|
|
161
|
+
"@commitlint/config-conventional"
|
|
162
|
+
]
|
|
163
|
+
},
|
|
164
|
+
"release-it": {
|
|
165
|
+
"git": {
|
|
166
|
+
"commitMessage": "chore: release ${version}",
|
|
167
|
+
"tagName": "v${version}"
|
|
168
|
+
},
|
|
169
|
+
"npm": {
|
|
170
|
+
"publish": true
|
|
171
|
+
},
|
|
172
|
+
"github": {
|
|
173
|
+
"release": true
|
|
174
|
+
},
|
|
175
|
+
"plugins": {
|
|
176
|
+
"@release-it/conventional-changelog": {
|
|
177
|
+
"preset": {
|
|
178
|
+
"name": "angular"
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
import {
|
|
2
|
-
NativeModules,
|
|
3
|
-
TurboModuleRegistry,
|
|
4
|
-
type TurboModule,
|
|
5
|
-
} from 'react-native';
|
|
6
|
-
|
|
7
|
-
export interface Spec extends TurboModule {
|
|
8
|
-
getConstants(): { OTP_RECEIVED_EVENT: string };
|
|
9
|
-
getHash(): Promise<ReadonlyArray<string>>;
|
|
10
|
-
startSmsRetriever(): Promise<boolean>;
|
|
11
|
-
addListener(eventName: string): void;
|
|
12
|
-
removeListeners(count: number): void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function loadNativeModule(): Spec {
|
|
16
|
-
try {
|
|
17
|
-
return TurboModuleRegistry.getEnforcing<Spec>('OtpAutoVerify');
|
|
18
|
-
} catch {
|
|
19
|
-
const legacy = NativeModules.OtpAutoVerify;
|
|
20
|
-
if (!legacy) {
|
|
21
|
-
throw new Error(
|
|
22
|
-
'OtpAutoVerify native module is not available. Ensure the library is properly linked.'
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
return legacy as Spec;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
let cachedModule: Spec | null = null;
|
|
30
|
-
|
|
31
|
-
/** Resolves the native module on first use so importing this package does not throw before APIs run. */
|
|
32
|
-
export function getOtpNativeModule(): Spec {
|
|
33
|
-
if (cachedModule === null) {
|
|
34
|
-
cachedModule = loadNativeModule();
|
|
35
|
-
}
|
|
36
|
-
return cachedModule;
|
|
37
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
NativeModules,
|
|
3
|
+
TurboModuleRegistry,
|
|
4
|
+
type TurboModule,
|
|
5
|
+
} from 'react-native';
|
|
6
|
+
|
|
7
|
+
export interface Spec extends TurboModule {
|
|
8
|
+
getConstants(): { OTP_RECEIVED_EVENT: string };
|
|
9
|
+
getHash(): Promise<ReadonlyArray<string>>;
|
|
10
|
+
startSmsRetriever(): Promise<boolean>;
|
|
11
|
+
addListener(eventName: string): void;
|
|
12
|
+
removeListeners(count: number): void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function loadNativeModule(): Spec {
|
|
16
|
+
try {
|
|
17
|
+
return TurboModuleRegistry.getEnforcing<Spec>('OtpAutoVerify');
|
|
18
|
+
} catch {
|
|
19
|
+
const legacy = NativeModules.OtpAutoVerify;
|
|
20
|
+
if (!legacy) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
'OtpAutoVerify native module is not available. Ensure the library is properly linked.'
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
return legacy as Spec;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let cachedModule: Spec | null = null;
|
|
30
|
+
|
|
31
|
+
/** Resolves the native module on first use so importing this package does not throw before APIs run. */
|
|
32
|
+
export function getOtpNativeModule(): Spec {
|
|
33
|
+
if (cachedModule === null) {
|
|
34
|
+
cachedModule = loadNativeModule();
|
|
35
|
+
}
|
|
36
|
+
return cachedModule;
|
|
37
|
+
}
|