UNPKG

totem-otp-delivery-webhook

Version:
246 lines (200 loc) 5.41 kB
# totem-otp-delivery-webhook HTTP webhook delivery agent for TotemOTP framework. ## Installation ```bash npm install totem-otp-delivery-webhook ``` ## Usage ### Basic Usage ```typescript import { WebhookDeliveryAgent } from 'totem-otp-delivery-webhook' import { TotemOTP } from 'totem-otp' // Create webhook delivery agent const webhookAgent = new WebhookDeliveryAgent({ webhookUrl: 'https://your-webhook-endpoint.com/otp' }) // Use with TotemOTP const totem = new TotemOTP({ storage: () => yourStorageInstance, schemas: [ { match: (target) => target.type === 'email', otp: { charset: ['0123456789'], length: 6 }, reference: { charset: ['ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'], length: 8 }, aging: { successValidateCount: 1, purgeFromDbIn: 1800000, // 30 minutes canResendIn: 120000, // 2 minutes expiresIn: 300000 // 5 minutes } } ], deliveryAgents: [ { match: (target) => target.type === 'email', agent: () => webhookAgent } ] }) ``` ### Custom Body Builder ```typescript const webhookAgent = new WebhookDeliveryAgent({ webhookUrl: 'https://your-webhook-endpoint.com/otp', bodyBuilder: (otp) => ({ // Custom webhook payload recipient: otp.target.value, code: otp.value, expires: new Date(otp.expiresAtMs).toISOString(), reference: otp.reference, type: otp.target.type }) }) ``` ### Custom Headers and Method ```typescript const webhookAgent = new WebhookDeliveryAgent({ webhookUrl: 'https://your-webhook-endpoint.com/otp', method: 'PUT', headers: { 'Authorization': 'Bearer your-token', 'X-Custom-Header': 'custom-value' }, timeout: 10000 // 10 seconds }) ``` ## Configuration Options ```typescript interface WebhookDeliveryAgentOptions { /** * Webhook destination URL */ webhookUrl: string /** * Optional callback function to compute the request body * If not provided, a default body structure will be used */ bodyBuilder?: (otp: IOTPValue) => Record<string, any> /** * Optional HTTP headers to include in the request * @default { 'Content-Type': 'application/json' } */ headers?: Record<string, string> /** * Optional HTTP method * @default 'POST' */ method?: 'POST' | 'PUT' | 'PATCH' /** * Optional timeout in milliseconds * @default 30000 (30 seconds) */ timeout?: number } ``` ## Default Webhook Payload When no custom `bodyBuilder` is provided, the webhook will receive: ```json { "event": "otp_requested", "timestamp": "2025-07-16T17:00:00.000Z", "data": { "target": { "type": "email", "value": "user@example.com", "uniqueIdentifier": "user-123" }, "otp": { "value": "123456", "reference": "REF12345", "expiresAt": "2025-07-16T17:05:00.000Z", "resendAllowedAt": "2025-07-16T17:02:00.000Z" } } } ``` ## Receipt ID Handling The delivery agent attempts to extract a receipt ID from the webhook response: ### JSON Response ```json { "receiptId": "receipt-123", // or "receipt_id", "id", "messageId", "message_id" } ``` ### Text Response ``` receipt-123 ``` If no receipt ID is found, a fallback ID is generated in the format: ``` webhook_{timestamp}_{hash}_{otpReference} ``` ## Custom Body Builders ### Email-Style Delivery Agent ```typescript const emailAgent = new WebhookDeliveryAgent({ webhookUrl: 'https://email-service.com/send', headers: { 'Authorization': 'Bearer token' }, bodyBuilder: (otp) => ({ to: otp.target.value, subject: 'Your OTP Code', body: `Your OTP code is: ${otp.value}. This code will expire at ${new Date(otp.expiresAtMs).toLocaleString()}.`, reference: otp.reference, expiresAt: new Date(otp.expiresAtMs).toISOString() }) }) ``` ### SMS-Style Delivery Agent ```typescript const smsAgent = new WebhookDeliveryAgent({ webhookUrl: 'https://sms-service.com/send', bodyBuilder: (otp) => ({ to: otp.target.value, message: `Your OTP code is: ${otp.value}. Expires in ${Math.ceil((otp.expiresAtMs - Date.now()) / 60000)} minutes.`, reference: otp.reference, expiresAt: new Date(otp.expiresAtMs).toISOString() }) }) ``` ### Custom Delivery Agent ```typescript const customAgent = new WebhookDeliveryAgent({ webhookUrl: 'https://custom-service.com/notify', method: 'PUT', bodyBuilder: (otp) => ({ customField: otp.value, customTarget: otp.target.value }) }) ``` ## Error Handling The delivery agent will throw an error if: - The webhook responds with HTTP status code outside 200-299 range - Network/connection errors occur - Request timeout is exceeded ```typescript try { const receiptId = await webhookAgent.sendMessageToAudience(otp) console.log('OTP sent successfully:', receiptId) } catch (error) { console.error('Webhook delivery failed:', error.message) } ``` ## Testing For testing purposes, you can use tools like [nock](https://github.com/nock/nock) to mock HTTP requests: ```typescript import nock from 'nock' // Mock webhook endpoint nock('https://your-webhook-endpoint.com') .post('/otp') .reply(200, { receiptId: 'test-receipt-123' }) // Test your delivery agent const result = await webhookAgent.sendMessageToAudience(testOTPValue) expect(result).toBe('test-receipt-123') ``` ## Requirements - Node.js 16 or higher - TypeScript 4.5 or higher ## License ISC