sms-verification-api 0.9.1

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 (50) hide show
  1. package/.env.example +20 -0
  2. package/DEPLOYMENT.md +151 -0
  3. package/README.md +475 -0
  4. package/docs/app/(home)/layout.tsx +7 -0
  5. package/docs/app/(home)/page.tsx +38 -0
  6. package/docs/app/docs/[[...slug]]/page.tsx +59 -0
  7. package/docs/app/docs/layout.tsx +12 -0
  8. package/docs/app/docs-og/[...slug]/route.ts +24 -0
  9. package/docs/app/globals.css +587 -0
  10. package/docs/app/layout.config.tsx +13 -0
  11. package/docs/app/layout.tsx +27 -0
  12. package/docs/app/logo.tsx +35 -0
  13. package/docs/content/docs/API_AUTHENTICATION.md +91 -0
  14. package/docs/content/docs/DEPLOYMENT.md +181 -0
  15. package/docs/content/docs/api/post.mdx +35 -0
  16. package/docs/content/docs/api/verify.mdx +34 -0
  17. package/docs/content/docs/meta.json +8 -0
  18. package/docs/content/docs/verify-legal-name.md +339 -0
  19. package/docs/lib/source.ts +14 -0
  20. package/docs/mdx-components.tsx +12 -0
  21. package/docs/next.config.mjs +51 -0
  22. package/docs/openapi.json +329 -0
  23. package/docs/package.json +37 -0
  24. package/docs/postcss.config.mjs +5 -0
  25. package/docs/scripts/generate-docs.mjs +23 -0
  26. package/docs/source.config.ts +5 -0
  27. package/docs/tsconfig.json +29 -0
  28. package/docs/worker.js +35 -0
  29. package/docs/wrangler.toml +26 -0
  30. package/examples/client.js +119 -0
  31. package/examples/demo.html +325 -0
  32. package/examples/libphonenumber-example.js +120 -0
  33. package/openapi.json +329 -0
  34. package/package.json +71 -0
  35. package/scripts/deploy.sh +63 -0
  36. package/src/identity-verification-server.ts +553 -0
  37. package/src/index.js +8 -0
  38. package/src/sns.js +236 -0
  39. package/src/verify-phone-server.js +448 -0
  40. package/src/verify-phone.ts +551 -0
  41. package/test/api.test.js +201 -0
  42. package/test/integration.test.js +152 -0
  43. package/test/metadata-test.js +73 -0
  44. package/test/server.test.js +143 -0
  45. package/test/setup.js +32 -0
  46. package/test/utils.test.js +186 -0
  47. package/test/verify.test.js +23 -0
  48. package/test/voip.test.js +112 -0
  49. package/vitest.config.js +10 -0
  50. package/wrangler.toml +27 -0
@@ -0,0 +1,325 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>SMS Verification API Demo</title>
7
+ <style>
8
+ body {
9
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
10
+ max-width: 800px;
11
+ margin: 0 auto;
12
+ padding: 20px;
13
+ background-color: #f5f5f5;
14
+ }
15
+ .container {
16
+ background: white;
17
+ padding: 30px;
18
+ border-radius: 10px;
19
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
20
+ }
21
+ h1 {
22
+ color: #333;
23
+ text-align: center;
24
+ margin-bottom: 30px;
25
+ }
26
+ .form-group {
27
+ margin-bottom: 20px;
28
+ }
29
+ label {
30
+ display: block;
31
+ margin-bottom: 5px;
32
+ font-weight: 600;
33
+ color: #555;
34
+ }
35
+ input, textarea, select {
36
+ width: 100%;
37
+ padding: 10px;
38
+ border: 1px solid #ddd;
39
+ border-radius: 5px;
40
+ font-size: 16px;
41
+ box-sizing: border-box;
42
+ }
43
+ button {
44
+ background: #007bff;
45
+ color: white;
46
+ padding: 12px 24px;
47
+ border: none;
48
+ border-radius: 5px;
49
+ cursor: pointer;
50
+ font-size: 16px;
51
+ margin-right: 10px;
52
+ }
53
+ button:hover {
54
+ background: #0056b3;
55
+ }
56
+ button:disabled {
57
+ background: #ccc;
58
+ cursor: not-allowed;
59
+ }
60
+ .result {
61
+ margin-top: 20px;
62
+ padding: 15px;
63
+ border-radius: 5px;
64
+ white-space: pre-wrap;
65
+ font-family: monospace;
66
+ font-size: 14px;
67
+ }
68
+ .success {
69
+ background: #d4edda;
70
+ border: 1px solid #c3e6cb;
71
+ color: #155724;
72
+ }
73
+ .error {
74
+ background: #f8d7da;
75
+ border: 1px solid #f5c6cb;
76
+ color: #721c24;
77
+ }
78
+ .info {
79
+ background: #d1ecf1;
80
+ border: 1px solid #bee5eb;
81
+ color: #0c5460;
82
+ }
83
+ .tabs {
84
+ display: flex;
85
+ margin-bottom: 20px;
86
+ }
87
+ .tab {
88
+ padding: 10px 20px;
89
+ cursor: pointer;
90
+ border: 1px solid #ddd;
91
+ background: #f8f9fa;
92
+ border-bottom: none;
93
+ }
94
+ .tab.active {
95
+ background: white;
96
+ border-bottom: 1px solid white;
97
+ }
98
+ .tab-content {
99
+ display: none;
100
+ }
101
+ .tab-content.active {
102
+ display: block;
103
+ }
104
+ .checkbox-group {
105
+ display: flex;
106
+ align-items: center;
107
+ gap: 10px;
108
+ }
109
+ .checkbox-group input[type="checkbox"] {
110
+ width: auto;
111
+ }
112
+ </style>
113
+ </head>
114
+ <body>
115
+ <div class="container">
116
+ <h1>SMS Verification API Demo</h1>
117
+
118
+ <div class="tabs">
119
+ <div class="tab active" onclick="showTab('send')">Send Verification</div>
120
+ <div class="tab" onclick="showTab('verify')">Verify Code</div>
121
+ <div class="tab" onclick="showTab('sms')">Send SMS</div>
122
+ </div>
123
+
124
+ <!-- Send Verification Tab -->
125
+ <div id="send" class="tab-content active">
126
+ <div class="form-group">
127
+ <label for="sendPhone">Phone Number:</label>
128
+ <input type="tel" id="sendPhone" placeholder="+1234567890" value="+1234567890">
129
+ </div>
130
+ <div class="form-group">
131
+ <label for="sendCode">Verification Code (optional):</label>
132
+ <input type="text" id="sendCode" placeholder="Leave empty for auto-generated">
133
+ </div>
134
+ <div class="form-group">
135
+ <label for="sendSenderId">Sender ID:</label>
136
+ <input type="text" id="sendSenderId" placeholder="Verify" value="Verify">
137
+ </div>
138
+ <div class="form-group">
139
+ <label for="sendMessageTemplate">Message Template:</label>
140
+ <textarea id="sendMessageTemplate" rows="3" placeholder="Your verification code is: {code}">Your verification code is: {code}</textarea>
141
+ </div>
142
+ <div class="form-group">
143
+ <label for="sendSmsType">SMS Type:</label>
144
+ <select id="sendSmsType">
145
+ <option value="Transactional">Transactional</option>
146
+ <option value="Promotional">Promotional</option>
147
+ </select>
148
+ </div>
149
+ <div class="form-group">
150
+ <div class="checkbox-group">
151
+ <input type="checkbox" id="blockVoip">
152
+ <label for="blockVoip">Block VoIP Numbers</label>
153
+ </div>
154
+ </div>
155
+ <button onclick="sendVerification()">Send Verification Code</button>
156
+ <div id="sendResult" class="result" style="display: none;"></div>
157
+ </div>
158
+
159
+ <!-- Verify Code Tab -->
160
+ <div id="verify" class="tab-content">
161
+ <div class="form-group">
162
+ <label for="verifyPhone">Phone Number:</label>
163
+ <input type="tel" id="verifyPhone" placeholder="+1234567890" value="+1234567890">
164
+ </div>
165
+ <div class="form-group">
166
+ <label for="verifyCode">Verification Code:</label>
167
+ <input type="text" id="verifyCode" placeholder="Enter the code you received">
168
+ </div>
169
+ <button onclick="verifyCode()">Verify Code</button>
170
+ <div id="verifyResult" class="result" style="display: none;"></div>
171
+ </div>
172
+
173
+ <!-- Send SMS Tab -->
174
+ <div id="sms" class="tab-content">
175
+ <div class="form-group">
176
+ <label for="smsPhone">Phone Number:</label>
177
+ <input type="tel" id="smsPhone" placeholder="+1234567890" value="+1234567890">
178
+ </div>
179
+ <div class="form-group">
180
+ <label for="smsMessage">Message:</label>
181
+ <textarea id="smsMessage" rows="4" placeholder="Enter your message here">Hello from the SMS API demo!</textarea>
182
+ </div>
183
+ <div class="form-group">
184
+ <label for="smsSenderId">Sender ID:</label>
185
+ <input type="text" id="smsSenderId" placeholder="Verify" value="Verify">
186
+ </div>
187
+ <div class="form-group">
188
+ <label for="smsType">SMS Type:</label>
189
+ <select id="smsType">
190
+ <option value="Transactional">Transactional</option>
191
+ <option value="Promotional">Promotional</option>
192
+ </select>
193
+ </div>
194
+ <button onclick="sendSMS()">Send SMS</button>
195
+ <div id="smsResult" class="result" style="display: none;"></div>
196
+ </div>
197
+ </div>
198
+
199
+ <script>
200
+ // Configuration
201
+ const API_BASE_URL = 'http://localhost:8787'; // Change to your deployed URL
202
+ const API_KEY = 'sms_1234567890abcdef1234567890abcdef'; // Change to your API key
203
+
204
+ function showTab(tabName) {
205
+ // Hide all tab contents
206
+ document.querySelectorAll('.tab-content').forEach(content => {
207
+ content.classList.remove('active');
208
+ });
209
+
210
+ // Remove active class from all tabs
211
+ document.querySelectorAll('.tab').forEach(tab => {
212
+ tab.classList.remove('active');
213
+ });
214
+
215
+ // Show selected tab content
216
+ document.getElementById(tabName).classList.add('active');
217
+
218
+ // Add active class to clicked tab
219
+ event.target.classList.add('active');
220
+ }
221
+
222
+ function showResult(elementId, data, isSuccess = true) {
223
+ const element = document.getElementById(elementId);
224
+ element.style.display = 'block';
225
+ element.className = `result ${isSuccess ? 'success' : 'error'}`;
226
+ element.textContent = JSON.stringify(data, null, 2);
227
+ }
228
+
229
+ async function sendVerification() {
230
+ const phoneNumber = document.getElementById('sendPhone').value;
231
+ const code = document.getElementById('sendCode').value;
232
+ const senderId = document.getElementById('sendSenderId').value;
233
+ const messageTemplate = document.getElementById('sendMessageTemplate').value;
234
+ const smsType = document.getElementById('sendSmsType').value;
235
+ const blockVoip = document.getElementById('blockVoip').checked;
236
+
237
+ try {
238
+ const response = await fetch(`${API_BASE_URL}/api/send`, {
239
+ method: 'POST',
240
+ headers: {
241
+ 'Content-Type': 'application/json',
242
+ 'X-API-Key': API_KEY
243
+ },
244
+ body: JSON.stringify({
245
+ phoneNumber,
246
+ code: code || undefined,
247
+ senderId,
248
+ messageTemplate,
249
+ smsType,
250
+ blockVoip
251
+ })
252
+ });
253
+
254
+ const result = await response.json();
255
+ showResult('sendResult', result, result.success);
256
+ } catch (error) {
257
+ showResult('sendResult', { error: error.message }, false);
258
+ }
259
+ }
260
+
261
+ async function verifyCode() {
262
+ const phoneNumber = document.getElementById('verifyPhone').value;
263
+ const code = document.getElementById('verifyCode').value;
264
+
265
+ try {
266
+ const response = await fetch(`${API_BASE_URL}/api/verify`, {
267
+ method: 'POST',
268
+ headers: {
269
+ 'Content-Type': 'application/json',
270
+ 'X-API-Key': API_KEY
271
+ },
272
+ body: JSON.stringify({
273
+ phoneNumber,
274
+ code
275
+ })
276
+ });
277
+
278
+ const result = await response.json();
279
+ showResult('verifyResult', result, result.success);
280
+ } catch (error) {
281
+ showResult('verifyResult', { error: error.message }, false);
282
+ }
283
+ }
284
+
285
+ async function sendSMS() {
286
+ const phoneNumber = document.getElementById('smsPhone').value;
287
+ const message = document.getElementById('smsMessage').value;
288
+ const senderId = document.getElementById('smsSenderId').value;
289
+ const smsType = document.getElementById('smsType').value;
290
+
291
+ try {
292
+ const response = await fetch(`${API_BASE_URL}/api/sms`, {
293
+ method: 'POST',
294
+ headers: {
295
+ 'Content-Type': 'application/json',
296
+ 'X-API-Key': API_KEY
297
+ },
298
+ body: JSON.stringify({
299
+ phoneNumber,
300
+ message,
301
+ senderId,
302
+ smsType
303
+ })
304
+ });
305
+
306
+ const result = await response.json();
307
+ showResult('smsResult', result, result.success);
308
+ } catch (error) {
309
+ showResult('smsResult', { error: error.message }, false);
310
+ }
311
+ }
312
+
313
+ // Check server health on page load
314
+ window.addEventListener('load', async () => {
315
+ try {
316
+ const response = await fetch(`${API_BASE_URL}/health`);
317
+ const health = await response.json();
318
+ console.log('Server health:', health);
319
+ } catch (error) {
320
+ console.error('Server health check failed:', error);
321
+ }
322
+ });
323
+ </script>
324
+ </body>
325
+ </html>
@@ -0,0 +1,120 @@
1
+ import verifyPhone from '../src/verify-phone.js';
2
+
3
+ // Example 1: Using libphonenumber-js for VoIP detection with full metadata
4
+ async function exampleWithLibPhoneNumberVoipDetection() {
5
+ try {
6
+ const result = await verifyPhone({
7
+ phoneNumber: '+1-800-555-0123',
8
+ code: '123456',
9
+ blockVoip: true,
10
+ voipDetectionMethod: 'libphonenumber', // Use local analysis instead of external API
11
+ useLibPhoneNumber: true, // Also use libphonenumber-js for formatting/validation
12
+ metadataType: 'full', // Use full metadata (140KB) for better phone type detection
13
+ messageTemplate: 'Your verification code is: {code}. Valid for 10 minutes.'
14
+ });
15
+
16
+ console.log('Result:', result);
17
+ } catch (error) {
18
+ console.error('Error:', error);
19
+ }
20
+ }
21
+
22
+ // Example 2: Using libphonenumber-js for phone number formatting and validation only
23
+ async function exampleWithLibPhoneNumberFormatting() {
24
+ try {
25
+ const result = await verifyPhone({
26
+ phoneNumber: '555-123-4567', // US number without country code
27
+ code: '789012',
28
+ blockVoip: false, // Don't block VoIP numbers
29
+ useLibPhoneNumber: true, // Use libphonenumber-js for formatting/validation
30
+ senderId: 'MyApp',
31
+ smsType: 'Transactional'
32
+ });
33
+
34
+ console.log('Result:', result);
35
+ } catch (error) {
36
+ console.error('Error:', error);
37
+ }
38
+ }
39
+
40
+ // Example 3: Traditional approach (external API for VoIP detection)
41
+ async function exampleWithExternalApi() {
42
+ try {
43
+ const result = await verifyPhone({
44
+ phoneNumber: '+44 20 7946 0958', // UK number
45
+ code: 'ABCDEF',
46
+ blockVoip: true,
47
+ voipDetectionMethod: 'api', // Use external API (default)
48
+ useLibPhoneNumber: false, // Use basic formatting/validation
49
+ messageTemplate: 'Welcome! Your code: {code}'
50
+ });
51
+
52
+ console.log('Result:', result);
53
+ } catch (error) {
54
+ console.error('Error:', error);
55
+ }
56
+ }
57
+
58
+ // Example 4: International number with libphonenumber-js
59
+ async function exampleInternationalNumber() {
60
+ try {
61
+ const result = await verifyPhone({
62
+ phoneNumber: '49 30 12345678', // German number
63
+ code: 'GHIJKL',
64
+ blockVoip: true,
65
+ voipDetectionMethod: 'libphonenumber',
66
+ useLibPhoneNumber: true,
67
+ awsRegion: 'eu-west-1'
68
+ });
69
+
70
+ console.log('Result:', result);
71
+ } catch (error) {
72
+ console.error('Error:', error);
73
+ }
74
+ }
75
+
76
+ // Example 5: Comparing minimal vs full metadata
77
+ async function exampleMetadataComparison() {
78
+ try {
79
+ console.log('=== Testing with minimal metadata (75KB) ===');
80
+ const resultMinimal = await verifyPhone({
81
+ phoneNumber: '+1-800-555-0123',
82
+ code: 'MIN123',
83
+ blockVoip: true,
84
+ voipDetectionMethod: 'libphonenumber',
85
+ useLibPhoneNumber: true,
86
+ metadataType: 'minimal' // Uses pattern-based heuristics
87
+ });
88
+ console.log('Minimal metadata result:', resultMinimal);
89
+
90
+ console.log('\n=== Testing with full metadata (140KB) ===');
91
+ const resultFull = await verifyPhone({
92
+ phoneNumber: '+1-800-555-0123',
93
+ code: 'FULL456',
94
+ blockVoip: true,
95
+ voipDetectionMethod: 'libphonenumber',
96
+ useLibPhoneNumber: true,
97
+ metadataType: 'full' // Uses phone number type detection
98
+ });
99
+ console.log('Full metadata result:', resultFull);
100
+
101
+ } catch (error) {
102
+ console.error('Error:', error);
103
+ }
104
+ }
105
+
106
+ // Run examples
107
+ console.log('=== Example 1: VoIP Detection with libphonenumber-js ===');
108
+ await exampleWithLibPhoneNumberVoipDetection();
109
+
110
+ console.log('\n=== Example 2: Formatting with libphonenumber-js ===');
111
+ await exampleWithLibPhoneNumberFormatting();
112
+
113
+ console.log('\n=== Example 3: Traditional External API ===');
114
+ await exampleWithExternalApi();
115
+
116
+ console.log('\n=== Example 4: International Number ===');
117
+ await exampleInternationalNumber();
118
+
119
+ console.log('\n=== Example 5: Metadata Comparison ===');
120
+ await exampleMetadataComparison();