react-native-otp-auto-verify 0.1.4 → 0.1.6

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/LICENSE CHANGED
@@ -1,6 +1,7 @@
1
1
  MIT License
2
2
 
3
3
  Copyright (c) 2026 Kailas Rathod
4
+
4
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
5
6
  of this software and associated documentation files (the "Software"), to deal
6
7
  in the Software without restriction, including without limitation the rights
package/README.md CHANGED
@@ -1,31 +1,39 @@
1
1
  # react-native-otp-auto-verify
2
2
 
3
- <div align="center">
4
3
 
5
- [![npm version](https://img.shields.io/npm/v/react-native-otp-auto-verify.svg?style=flat-square)](https://www.npmjs.com/package/react-native-otp-auto-verify)
6
- [![typescript](https://img.shields.io/badge/TypeScript-Ready-blue.svg?style=flat-square)](https://www.typescriptlang.org/)
7
- [![license](https://img.shields.io/npm/l/react-native-otp-auto-verify.svg?style=flat-square)](https://github.com/kailas-rathod/react-native-otp-auto-verify/blob/main/LICENSE)
4
+ [![npm version](https://img.shields.io/npm/v/react-native-otp-auto-verify.svg?style=flat-square)](https://www.npmjs.com/package/react-native-otp-auto-verify) [![npm downloads](https://img.shields.io/npm/dm/react-native-otp-auto-verify.svg?style=flat-square)](https://www.npmjs.com/package/react-native-otp-auto-verify) [![license](https://img.shields.io/npm/l/react-native-otp-auto-verify.svg?style=flat-square)](https://github.com/kailas-rathod/react-native-otp-auto-verify/blob/main/LICENSE) [![typescript](https://img.shields.io/badge/TypeScript-Ready-blue.svg?style=flat-square)](https://www.typescriptlang.org/)
8
5
 
6
+ **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.
9
7
 
10
- </div>
8
+ With minimal dependencies and clean architecture, it integrates seamlessly into both React Native Old Architecture and the New Architecture (TurboModule) environments. The solution improves user experience by eliminating manual OTP entry on Android while maintaining strong server-side validation standards.
11
9
 
10
+ Works best for onboarding/login flows in **banking**, **fintech**, and authentication-heavy apps.
11
+ Supports both RN Old Architecture and React Native **New Architecture** (TurboModule).
12
+ **Android**: automatic OTP detection.
13
+ **iOS**: auto-OTP is not supported—use manual OTP entry as fallback.
12
14
 
15
+ **Connect:** [GitHub](https://github.com/kailas-rathod/react-native-otp-auto-verify) · [npm](https://www.npmjs.com/package/react-native-otp-auto-verify) · [Issues](https://github.com/kailas-rathod/react-native-otp-auto-verify/issues) · [License](https://github.com/kailas-rathod/react-native-otp-auto-verify/blob/main/LICENSE)
13
16
 
14
- ## Features
17
+ ---
18
+ <img width="1536" height="1024" alt="otp" src="https://github.com/user-attachments/assets/e4908e99-e7d1-4a96-a6d2-b92c50090db0" />
15
19
 
16
- Automatic SMS Verification with the SMS Retriever API (Android Only)
17
- Phone Number Retrieving using the Phone Number Hint API (Android Only)
18
- Automatic SMS Verification with the SMS Retriever API, you can perform SMS-based user verification in your Android app automatically, without requiring the user to manually type verification codes, and without requiring any extra app permissions.
19
20
 
20
- Message Format/Structure
21
- In order to detect the message, SMS message must include a hash that identifies your app. This hash can be obtained by using the getHash() method below.
21
+ ## Features
22
22
 
23
+ - ✅ **Automatic OTP detection**: receives OTP from matching SMS and exposes it as `otp` (hook) or `extractedOtp` (listener)
24
+ - ✅ **No SMS permissions**: no access to inbox, avoids sensitive permissions and reduces compliance friction
25
+ - ✅ **App hash security**: OTP SMS must end with your **11-character hash** (only your app can receive it)
26
+ - ✅ **Hook + Imperative API**: `useOtpVerification()` for screens, `activateOtpListener()` for custom flows
27
+ - ✅ **TypeScript**: typed options and return values
28
+ - ✅ **New Architecture ready**: TurboModule implementation; works with Old Architecture too
29
+ ---
23
30
 
24
- ## Platform support
31
+ ## Platform Support
25
32
 
26
- | Platform | Support | Notes |
27
- | -------- | ------- | --------------------------------------- |
28
- | Android | ✅ | Requires Google Play services on device |
33
+ | Platform | Support | Notes |
34
+ |----------|----------|-------|
35
+ | Android | ✅ | Requires Google Play Services on device |
36
+ | iOS | ✅ Native Only | Uses iOS Security Code AutoFill (manual tap required) |
29
37
 
30
38
  ## Requirements
31
39
 
@@ -69,9 +77,10 @@ Requirements:
69
77
  Recommended format:
70
78
 
71
79
  ```
72
- <#> Your verification code is 123456
73
- AbCdEfGhIjK
80
+ Dear Kailas Rathod, 321500 is your OTP for mobile authentication. This OTP is valid for the next 15 minutes. Please DO NOT share it with anyone.
81
+ uW87Uq6teXc
74
82
  ```
83
+ Note: You do not need `<#>` at the start of the message.
75
84
 
76
85
  ### 3) Hook usage (recommended)
77
86
 
@@ -83,7 +92,7 @@ import { Text, View } from 'react-native';
83
92
  import { useOtpVerification } from 'react-native-otp-auto-verify';
84
93
 
85
94
  export function OtpScreen() {
86
- const { hashCode, otp, timeoutError, startListening, stopListening } =
95
+ const { hashCode, otp, timeoutError, error, startListening, stopListening } =
87
96
  useOtpVerification({ numberOfDigits: 6 });
88
97
 
89
98
  React.useEffect(() => {
@@ -96,6 +105,7 @@ export function OtpScreen() {
96
105
  {!!hashCode && <Text>Hash: {hashCode}</Text>}
97
106
  {!!otp && <Text>OTP: {otp}</Text>}
98
107
  {timeoutError && <Text>Timeout. Tap resend and try again.</Text>}
108
+ {!!error && <Text>Error: {error.message}</Text>}
99
109
  </View>
100
110
  );
101
111
  }
@@ -124,19 +134,69 @@ sub.remove();
124
134
  removeListener();
125
135
  ```
126
136
 
127
- ## API
137
+ # iOS OTP AutoFill (Native)
138
+
139
+ iOS does **not** allow third-party libraries to read SMS messages.
140
+
141
+ Automatic SMS reading is restricted by Apple for privacy and security reasons.
142
+ Instead, iOS provides a native feature called **Security Code AutoFill**, which suggests the OTP above the keyboard when properly configured.
143
+
144
+ This library does **not** auto-read OTP on iOS.
145
+
146
+ ---
147
+
148
+ ## How iOS OTP AutoFill Works
149
+
150
+ 1. User receives an SMS containing an OTP.
151
+ 2. iOS detects the code.
152
+ 3. The OTP appears above the keyboard.
153
+ 4. User taps the suggestion.
154
+ 5. The code fills automatically into the input field.
155
+
156
+ No SMS permissions required.
157
+
158
+ ---
159
+
160
+ ## React Native Setup
161
+
162
+ Use the following configuration in your OTP input field:
163
+
164
+ ```tsx
165
+ <TextInput
166
+ style={styles.input}
167
+ keyboardType="number-pad"
168
+ textContentType="oneTimeCode"
169
+ autoComplete="sms-otp"
170
+ importantForAutofill="yes"
171
+ maxLength={6}
172
+ />
173
+
174
+ ```
175
+
176
+
177
+ ## react-native-otp-auto-verify Architecture Flow
178
+ <img width="1536" height="1024" alt="react-native-otp-auto-verify Architecture Flow" src="https://github.com/user-attachments/assets/11582523-81cb-4904-9de0-56af05b3a3b4" />
179
+
180
+ ## API Reference
128
181
 
129
182
  ### `useOtpVerification(options?)`
130
183
 
131
- - **options**
132
- - `numberOfDigits?: 4 | 5 | 6` (default `6`)
133
- - **returns**
134
- - `hashCode: string`
135
- - `otp: string | null`
136
- - `sms: string | null`
137
- - `timeoutError: boolean`
138
- - `startListening(): Promise<void>`
139
- - `stopListening(): void`
184
+ Use this on your OTP screen. It manages:
185
+ - getting the app hash (`hashCode`)
186
+ - starting/stopping the SMS Retriever listener
187
+ - extracting OTP and exposing it as `otp`
188
+
189
+ | Property | Type | Default | Description |
190
+ |----------|------|---------|-------------|
191
+ | `numberOfDigits` | `4 \| 5 \| 6` | `6` | OTP length to extract |
192
+ | `hashCode` | `string` | `''` | App hash (send to backend) |
193
+ | `otp` | `string \| null` | `null` | Extracted OTP |
194
+ | `sms` | `string \| null` | `null` | Full SMS text |
195
+ | `timeoutError` | `boolean` | `false` | Timeout occurred |
196
+ | `error` | `Error \| null` | `null` | Set when getHash or startListening fails |
197
+ | `startListening` | `() => Promise<void>` | — | Start listening |
198
+ | `stopListening` | `() => void` | — | Stop listening |
199
+
140
200
 
141
201
  ### `getHash(): Promise<string[]>`
142
202
 
@@ -228,6 +288,13 @@ See [`./example`](./example).
228
288
 
229
289
  See [`CONTRIBUTING.md`](CONTRIBUTING.md).
230
290
 
291
+ ## Publishing
292
+
293
+ Maintainers: see [RELEASE_CHECKLIST.md](./RELEASE_CHECKLIST.md) before publishing a new version to npm.
294
+
295
+ ## Keywords
296
+ react native otp auto verify, react native sms retriever api, automatic otp detection android, react native otp autofill, sms retriever react native, otp verification library react native, google play compliant otp library
297
+
231
298
  ## License
232
299
 
233
- MIT
300
+ [MIT](./LICENSE) — see [LICENSE](./LICENSE) in the repo.
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ import { TurboModuleRegistry } from 'react-native';
4
+ export default TurboModuleRegistry.getEnforcing('OtpAutoVerify');
5
+ //# sourceMappingURL=NativeOtpAutoVerify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"..\\..\\src","sources":["NativeOtpAutoVerify.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;AAUpE,eAAeA,mBAAmB,CAACC,YAAY,CAAO,eAAe,CAAC","ignoreList":[]}
@@ -2,7 +2,7 @@
2
2
 
3
3
  import * as React from 'react';
4
4
  import { NativeEventEmitter, NativeModules, Platform } from 'react-native';
5
- import NativeOtpAutoVerify from './NativeOtpAutoVerify';
5
+ import NativeOtpAutoVerify from "./NativeOtpAutoVerify.js";
6
6
  const {
7
7
  OtpAutoVerify
8
8
  } = NativeModules;
@@ -18,7 +18,9 @@ const OTP_REGEX = {
18
18
  /** Extracts a numeric OTP of 4–6 digits from SMS text. */
19
19
  export function extractOtp(sms, numberOfDigits = DEFAULT_DIGITS) {
20
20
  if (!sms || typeof sms !== 'string') return null;
21
- const match = sms.match(OTP_REGEX[numberOfDigits]);
21
+ const trimmed = sms.trim();
22
+ if (!trimmed) return null;
23
+ const match = trimmed.match(OTP_REGEX[numberOfDigits]);
22
24
  return match ? match[1] : null;
23
25
  }
24
26
 
@@ -55,13 +57,14 @@ export function removeListener() {
55
57
  }
56
58
  }
57
59
 
58
- /** Hook for OTP verification. Stops listener on unmount. */
60
+ /** Hook for OTP verification. Call startListening() to begin; listener is stopped on unmount. */
59
61
  export function useOtpVerification(options = {}) {
60
62
  const numberOfDigits = options.numberOfDigits ?? DEFAULT_DIGITS;
61
63
  const [hashCode, setHashCode] = React.useState('');
62
64
  const [otp, setOtp] = React.useState(null);
63
65
  const [sms, setSms] = React.useState(null);
64
66
  const [timeoutError, setTimeoutError] = React.useState(false);
67
+ const [error, setError] = React.useState(null);
65
68
  const subscriptionRef = React.useRef(null);
66
69
  const stopListening = React.useCallback(() => {
67
70
  subscriptionRef.current?.remove();
@@ -73,11 +76,12 @@ export function useOtpVerification(options = {}) {
73
76
  setOtp(null);
74
77
  setSms(null);
75
78
  setTimeoutError(false);
79
+ setError(null);
76
80
  try {
77
81
  const hashes = await getHash();
78
82
  setHashCode(hashes[0] ?? '');
79
- } catch {
80
- // getHash failed; continue to start listener
83
+ } catch (err) {
84
+ setError(err instanceof Error ? err : new Error(String(err)));
81
85
  }
82
86
  try {
83
87
  const sub = await activateOtpListener((smsText, extractedOtp) => {
@@ -91,9 +95,13 @@ export function useOtpVerification(options = {}) {
91
95
  numberOfDigits
92
96
  });
93
97
  subscriptionRef.current = sub;
94
- } catch {
98
+ } catch (err) {
95
99
  subscriptionRef.current = null;
96
- throw new Error('Failed to start OTP listener');
100
+ const wrapped = new Error('Failed to start OTP listener', {
101
+ cause: err
102
+ });
103
+ setError(wrapped);
104
+ throw wrapped;
97
105
  }
98
106
  }, [numberOfDigits]);
99
107
  React.useEffect(() => () => stopListening(), [stopListening]);
@@ -102,9 +110,10 @@ export function useOtpVerification(options = {}) {
102
110
  otp,
103
111
  sms,
104
112
  timeoutError,
113
+ error,
105
114
  startListening,
106
115
  stopListening
107
- }), [hashCode, otp, sms, timeoutError, startListening, stopListening]);
116
+ }), [hashCode, otp, sms, timeoutError, error, startListening, stopListening]);
108
117
  }
109
118
  export { OTP_RECEIVED_EVENT };
110
119
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["React","NativeEventEmitter","NativeModules","Platform","NativeOtpAutoVerify","OtpAutoVerify","eventEmitter","OS","OTP_RECEIVED_EVENT","getConstants","TIMEOUT_MESSAGE","DEFAULT_DIGITS","OTP_REGEX","extractOtp","sms","numberOfDigits","match","getHash","arr","Array","from","activateOtpListener","handler","options","Error","subscription","addListener","args","smsText","String","startSmsRetriever","remove","removeListeners","removeListener","useOtpVerification","hashCode","setHashCode","useState","otp","setOtp","setSms","timeoutError","setTimeoutError","subscriptionRef","useRef","stopListening","useCallback","current","startListening","hashes","sub","extractedOtp","useEffect","useMemo"],"sourceRoot":"..\\..\\src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["React","NativeEventEmitter","NativeModules","Platform","NativeOtpAutoVerify","OtpAutoVerify","eventEmitter","OS","OTP_RECEIVED_EVENT","getConstants","TIMEOUT_MESSAGE","DEFAULT_DIGITS","OTP_REGEX","extractOtp","sms","numberOfDigits","trimmed","trim","match","getHash","arr","Array","from","activateOtpListener","handler","options","Error","subscription","addListener","args","smsText","String","startSmsRetriever","remove","removeListeners","removeListener","useOtpVerification","hashCode","setHashCode","useState","otp","setOtp","setSms","timeoutError","setTimeoutError","error","setError","subscriptionRef","useRef","stopListening","useCallback","current","startListening","hashes","err","sub","extractedOtp","wrapped","cause","useEffect","useMemo"],"sourceRoot":"..\\..\\src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
@@ -13,6 +13,8 @@ export interface UseOtpVerificationResult {
13
13
  sms: string | null;
14
14
  /** True when the 5-minute SMS Retriever timeout occurred. */
15
15
  timeoutError: boolean;
16
+ /** Set when getHash fails (non-fatal) or when startListening fails. Cleared when startListening is called again. */
17
+ error: Error | null;
16
18
  /** Start listening for OTP again (e.g. after timeout or error). */
17
19
  startListening: () => Promise<void>;
18
20
  /** Stop listening and clean up. Call on unmount. */
@@ -31,7 +33,7 @@ export declare function activateOtpListener(handler: (sms: string, extractedOtp?
31
33
  }): Promise<OtpListenerSubscription>;
32
34
  /** Stops SMS listening and removes all listeners. */
33
35
  export declare function removeListener(): void;
34
- /** Hook for OTP verification. Stops listener on unmount. */
36
+ /** Hook for OTP verification. Call startListening() to begin; listener is stopped on unmount. */
35
37
  export declare function useOtpVerification(options?: UseOtpVerificationOptions): UseOtpVerificationResult;
36
38
  export { OTP_RECEIVED_EVENT };
37
39
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAUA,QAAA,MAAM,kBAAkB,QAET,CAAC;AAKhB,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAQlC,MAAM,WAAW,yBAAyB;IACxC,uFAAuF;IACvF,cAAc,CAAC,EAAE,SAAS,CAAC;CAC5B;AAED,MAAM,WAAW,wBAAwB;IACvC,oFAAoF;IACpF,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,mCAAmC;IACnC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,6DAA6D;IAC7D,YAAY,EAAE,OAAO,CAAC;IACtB,mEAAmE;IACnE,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,oDAAoD;IACpD,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAED,0DAA0D;AAC1D,wBAAgB,UAAU,CACxB,GAAG,EAAE,MAAM,EACX,cAAc,GAAE,SAA0B,GACzC,MAAM,GAAG,IAAI,CAIf;AAED,kFAAkF;AAClF,wBAAsB,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAIjD;AAED,6FAA6F;AAC7F,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,EAC5D,OAAO,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,SAAS,CAAA;CAAE,GACvC,OAAO,CAAC,uBAAuB,CAAC,CAqBlC;AAED,qDAAqD;AACrD,wBAAgB,cAAc,IAAI,IAAI,CAIrC;AAED,4DAA4D;AAC5D,wBAAgB,kBAAkB,CAChC,OAAO,GAAE,yBAA8B,GACtC,wBAAwB,CAyD1B;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAUA,QAAA,MAAM,kBAAkB,QAET,CAAC;AAKhB,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAQlC,MAAM,WAAW,yBAAyB;IACxC,uFAAuF;IACvF,cAAc,CAAC,EAAE,SAAS,CAAC;CAC5B;AAED,MAAM,WAAW,wBAAwB;IACvC,oFAAoF;IACpF,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,mCAAmC;IACnC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,6DAA6D;IAC7D,YAAY,EAAE,OAAO,CAAC;IACtB,oHAAoH;IACpH,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,mEAAmE;IACnE,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,oDAAoD;IACpD,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAED,0DAA0D;AAC1D,wBAAgB,UAAU,CACxB,GAAG,EAAE,MAAM,EACX,cAAc,GAAE,SAA0B,GACzC,MAAM,GAAG,IAAI,CAMf;AAED,kFAAkF;AAClF,wBAAsB,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAIjD;AAED,6FAA6F;AAC7F,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,EAC5D,OAAO,CAAC,EAAE;IAAE,cAAc,CAAC,EAAE,SAAS,CAAA;CAAE,GACvC,OAAO,CAAC,uBAAuB,CAAC,CAqBlC;AAED,qDAAqD;AACrD,wBAAgB,cAAc,IAAI,IAAI,CAIrC;AAED,iGAAiG;AACjG,wBAAgB,kBAAkB,CAChC,OAAO,GAAE,yBAA8B,GACtC,wBAAwB,CA8D1B;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,13 +1,28 @@
1
1
  {
2
2
  "name": "react-native-otp-auto-verify",
3
- "version": "0.1.4",
4
- "description": "react-native-otp-auto-verify is a React Native library for automatic OTP detection and verification on Android using the Google SMS Retriever API. It enables secure, permission-less OTP auto-reading without requiring READ_SMS, making it fully Play Store compliant.",
3
+ "version": "0.1.6",
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
5
  "keywords": [
6
6
  "react-native",
7
- "ios",
8
- "android"
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"
9
24
  ],
10
- "homepage": "https://github.com/kailas-rathod/react-native-otp-auto-verify#readme",
25
+ "homepage": "https://github.com/kailas-rathod/react-native-otp-auto-verify?tab=readme-ov-file",
11
26
  "bugs": {
12
27
  "url": "https://github.com/kailas-rathod/react-native-otp-auto-verify/issues"
13
28
  },
@@ -17,20 +32,15 @@
17
32
  },
18
33
  "license": "MIT",
19
34
  "author": "Kailas Rathod (https://github.com/kailas-rathod)",
20
- "type": "commonjs",
21
- "exports": {
22
- ".": {
23
- "source": "./src/index.tsx",
24
- "types": "./lib/typescript/src/index.d.ts",
25
- "default": "./lib/module/index.js"
26
- },
27
- "./package.json": "./package.json"
35
+ "engines": {
36
+ "node": ">=18"
28
37
  },
38
+ "workspaces": [
39
+ "example"
40
+ ],
41
+ "type": "commonjs",
29
42
  "main": "./lib/module/index.js",
30
43
  "types": "./lib/typescript/src/index.d.ts",
31
- "directories": {
32
- "example": "example"
33
- },
34
44
  "files": [
35
45
  "src",
36
46
  "lib",
@@ -50,50 +60,26 @@
50
60
  "!**/__mocks__",
51
61
  "!**/.*"
52
62
  ],
53
- "workspaces": [
54
- "example"
55
- ],
56
63
  "scripts": {
57
- "example": "yarn workspace react-native-otp-auto-verify-example",
58
- "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
59
64
  "prepare": "bob build",
60
- "typecheck": "tsc",
61
- "lint": "eslint \"**/*.{js,ts,tsx}\"",
62
- "test": "jest",
63
- "release": "release-it --only-version"
64
- },
65
- "dependencies": {
66
-
65
+ "prepublishOnly": "bob build",
66
+ "typecheck": "tsc"
67
67
  },
68
68
  "devDependencies": {
69
- "@commitlint/config-conventional": "^19.8.1",
70
- "@eslint/compat": "^1.3.2",
71
- "@eslint/eslintrc": "^3.3.1",
72
- "@eslint/js": "^9.35.0",
73
- "@react-native/babel-preset": "0.83.0",
74
- "@react-native/eslint-config": "0.83.0",
75
- "@release-it/conventional-changelog": "^10.0.1",
76
- "@types/jest": "^29.5.14",
69
+ "@react-native/babel-preset": "0.83.2",
77
70
  "@types/react": "^19.2.0",
78
- "commitlint": "^19.8.1",
79
- "del-cli": "^6.0.0",
80
- "eslint": "^9.35.0",
81
- "eslint-config-prettier": "^10.1.8",
82
- "eslint-plugin-prettier": "^5.5.4",
83
- "jest": "^29.7.0",
84
- "lefthook": "^2.0.3",
85
- "prettier": "^2.8.8",
86
71
  "react": "19.2.0",
87
- "react-native": "0.83.0",
88
- "react-native-builder-bob": "0.39.1",
89
- "release-it": "^19.0.4",
90
- "turbo": "^2.5.6",
72
+ "react-native": "0.83.2",
73
+ "react-native-builder-bob": "0.40.18",
91
74
  "typescript": "^5.9.2"
92
75
  },
93
76
  "peerDependencies": {
94
77
  "react": "*",
95
78
  "react-native": "*"
96
79
  },
80
+ "resolutions": {
81
+ "glob": "11.1.0"
82
+ },
97
83
  "publishConfig": {
98
84
  "registry": "https://registry.npmjs.org/"
99
85
  },
@@ -123,54 +109,5 @@
123
109
  "android": {
124
110
  "javaPackageName": "com.otpautoverify"
125
111
  }
126
- },
127
- "prettier": {
128
- "quoteProps": "consistent",
129
- "singleQuote": true,
130
- "tabWidth": 2,
131
- "trailingComma": "es5",
132
- "useTabs": false
133
- },
134
- "jest": {
135
- "preset": "react-native",
136
- "modulePathIgnorePatterns": [
137
- "<rootDir>/example/node_modules",
138
- "<rootDir>/lib/"
139
- ]
140
- },
141
- "commitlint": {
142
- "extends": [
143
- "@commitlint/config-conventional"
144
- ]
145
- },
146
- "release-it": {
147
- "git": {
148
- "commitMessage": "chore: release ${version}",
149
- "tagName": "v${version}"
150
- },
151
- "npm": {
152
- "publish": true
153
- },
154
- "github": {
155
- "release": true
156
- },
157
- "plugins": {
158
- "@release-it/conventional-changelog": {
159
- "preset": {
160
- "name": "angular"
161
- }
162
- }
163
- }
164
- },
165
- "create-react-native-library": {
166
- "type": "turbo-module",
167
- "languages": "kotlin-objc",
168
- "tools": [
169
- "eslint",
170
- "jest",
171
- "lefthook",
172
- "release-it"
173
- ],
174
- "version": "0.57.0"
175
112
  }
176
113
  }
package/src/index.tsx CHANGED
@@ -37,6 +37,8 @@ export interface UseOtpVerificationResult {
37
37
  sms: string | null;
38
38
  /** True when the 5-minute SMS Retriever timeout occurred. */
39
39
  timeoutError: boolean;
40
+ /** Set when getHash fails (non-fatal) or when startListening fails. Cleared when startListening is called again. */
41
+ error: Error | null;
40
42
  /** Start listening for OTP again (e.g. after timeout or error). */
41
43
  startListening: () => Promise<void>;
42
44
  /** Stop listening and clean up. Call on unmount. */
@@ -53,7 +55,9 @@ export function extractOtp(
53
55
  numberOfDigits: OtpDigits = DEFAULT_DIGITS
54
56
  ): string | null {
55
57
  if (!sms || typeof sms !== 'string') return null;
56
- const match = sms.match(OTP_REGEX[numberOfDigits]);
58
+ const trimmed = sms.trim();
59
+ if (!trimmed) return null;
60
+ const match = trimmed.match(OTP_REGEX[numberOfDigits]);
57
61
  return match ? match[1]! : null;
58
62
  }
59
63
 
@@ -98,7 +102,7 @@ export function removeListener(): void {
98
102
  }
99
103
  }
100
104
 
101
- /** Hook for OTP verification. Stops listener on unmount. */
105
+ /** Hook for OTP verification. Call startListening() to begin; listener is stopped on unmount. */
102
106
  export function useOtpVerification(
103
107
  options: UseOtpVerificationOptions = {}
104
108
  ): UseOtpVerificationResult {
@@ -107,6 +111,7 @@ export function useOtpVerification(
107
111
  const [otp, setOtp] = React.useState<string | null>(null);
108
112
  const [sms, setSms] = React.useState<string | null>(null);
109
113
  const [timeoutError, setTimeoutError] = React.useState(false);
114
+ const [error, setError] = React.useState<Error | null>(null);
110
115
  const subscriptionRef = React.useRef<OtpListenerSubscription | null>(null);
111
116
 
112
117
  const stopListening = React.useCallback(() => {
@@ -120,15 +125,16 @@ export function useOtpVerification(
120
125
  setOtp(null);
121
126
  setSms(null);
122
127
  setTimeoutError(false);
128
+ setError(null);
123
129
  try {
124
130
  const hashes = await getHash();
125
131
  setHashCode(hashes[0] ?? '');
126
- } catch {
127
- // getHash failed; continue to start listener
132
+ } catch (err) {
133
+ setError(err instanceof Error ? err : new Error(String(err)));
128
134
  }
129
135
  try {
130
136
  const sub = await activateOtpListener(
131
- (smsText: string, extractedOtp: string | null | undefined) => {
137
+ (smsText, extractedOtp) => {
132
138
  setSms(smsText);
133
139
  if (smsText === TIMEOUT_MESSAGE) {
134
140
  setTimeoutError(true);
@@ -139,9 +145,11 @@ export function useOtpVerification(
139
145
  { numberOfDigits }
140
146
  );
141
147
  subscriptionRef.current = sub;
142
- } catch {
148
+ } catch (err) {
143
149
  subscriptionRef.current = null;
144
- throw new Error('Failed to start OTP listener');
150
+ const wrapped = new Error('Failed to start OTP listener', { cause: err });
151
+ setError(wrapped);
152
+ throw wrapped;
145
153
  }
146
154
  }, [numberOfDigits]);
147
155
 
@@ -153,10 +161,11 @@ export function useOtpVerification(
153
161
  otp,
154
162
  sms,
155
163
  timeoutError,
164
+ error,
156
165
  startListening,
157
166
  stopListening,
158
167
  }),
159
- [hashCode, otp, sms, timeoutError, startListening, stopListening]
168
+ [hashCode, otp, sms, timeoutError, error, startListening, stopListening]
160
169
  );
161
170
  }
162
171
 
@@ -1,11 +0,0 @@
1
- import { TurboModuleRegistry, type TurboModule } from 'react-native';
2
-
3
- export interface Spec extends TurboModule {
4
- getConstants(): { OTP_RECEIVED_EVENT: string };
5
- getHash(): Promise<ReadonlyArray<string>>;
6
- startSmsRetriever(): Promise<boolean>;
7
- addListener(eventName: string): void;
8
- removeListeners(count: number): void;
9
- }
10
-
11
- export default TurboModuleRegistry.getEnforcing<Spec>('OtpAutoVerify');