waba-toolkit 0.2.0 → 0.3.0
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 +366 -4
- package/dist/index.cli.js +863 -0
- package/dist/index.d.mts +180 -1
- package/dist/index.d.ts +180 -1
- package/dist/index.js +203 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +199 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -2
package/README.md
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
# waba-toolkit
|
|
2
2
|
|
|
3
|
-
Type-safe
|
|
3
|
+
Type-safe WhatsApp Business API toolkit with CLI for webhooks, media downloads, signature verification, and message sending.
|
|
4
4
|
|
|
5
5
|
> **Note:** This is not an official Meta/WhatsApp package, nor is it a full API wrapper. It is a utility toolkit derived from patterns across several production projects that interface directly with the WhatsApp Business API (Cloud API).
|
|
6
6
|
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **CLI Tool** - Send messages, manage phone numbers, and configure settings from the command line
|
|
10
|
+
- **Type-Safe** - Full TypeScript support with discriminated unions for webhook and message types
|
|
11
|
+
- **Media Downloads** - Stream or buffer media with automatic URL refresh handling
|
|
12
|
+
- **Webhook Processing** - Classify and verify webhooks with HMAC-SHA256 signature verification
|
|
13
|
+
- **Message Sending** - Send text, template, and custom messages programmatically
|
|
14
|
+
- **Phone Management** - Register, deregister, and list phone numbers
|
|
15
|
+
- **Zero Dependencies** - Core library has no runtime dependencies (CLI uses Commander + Inquirer)
|
|
16
|
+
- **Dual Format** - ESM and CommonJS support
|
|
17
|
+
|
|
7
18
|
---
|
|
8
19
|
|
|
9
20
|
## Table of Contents
|
|
@@ -11,8 +22,15 @@ Type-safe, zero-dependency WhatsApp Business API toolkit for webhooks, media dow
|
|
|
11
22
|
- [Installation](#installation)
|
|
12
23
|
- [Requirements](#requirements)
|
|
13
24
|
- [Quick Start](#quick-start)
|
|
25
|
+
- [CLI Usage](#cli-usage)
|
|
26
|
+
- [Library Usage](#library-usage)
|
|
27
|
+
- [CLI Reference](#cli-reference)
|
|
28
|
+
- [Configuration](#configuration)
|
|
29
|
+
- [Phone Management](#phone-management)
|
|
30
|
+
- [Sending Messages](#sending-messages)
|
|
14
31
|
- [API Reference](#api-reference)
|
|
15
32
|
- [WABAClient](#wabaclient)
|
|
33
|
+
- [WABAApiClient](#wabaapiclient)
|
|
16
34
|
- [Webhook Functions](#webhook-functions)
|
|
17
35
|
- [Helper Functions](#helper-functions)
|
|
18
36
|
- [Error Classes](#error-classes)
|
|
@@ -38,9 +56,31 @@ npm install waba-toolkit
|
|
|
38
56
|
|
|
39
57
|
## Quick Start
|
|
40
58
|
|
|
59
|
+
### CLI Usage
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Configure once (interactive)
|
|
63
|
+
waba-toolkit configure
|
|
64
|
+
|
|
65
|
+
# List phone numbers
|
|
66
|
+
waba-toolkit list-phones --waba-id YOUR_WABA_ID
|
|
67
|
+
|
|
68
|
+
# Send a text message
|
|
69
|
+
waba-toolkit send text --to 1234567890 --message "Hello World"
|
|
70
|
+
|
|
71
|
+
# Register a phone number
|
|
72
|
+
waba-toolkit register --pin 123456
|
|
73
|
+
|
|
74
|
+
# View all commands
|
|
75
|
+
waba-toolkit --help
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Library Usage
|
|
79
|
+
|
|
41
80
|
```typescript
|
|
42
81
|
import {
|
|
43
82
|
WABAClient,
|
|
83
|
+
WABAApiClient,
|
|
44
84
|
classifyWebhook,
|
|
45
85
|
classifyMessage,
|
|
46
86
|
getContactInfo,
|
|
@@ -109,6 +149,211 @@ app.post('/webhook', async (req, res) => {
|
|
|
109
149
|
|
|
110
150
|
---
|
|
111
151
|
|
|
152
|
+
## CLI Reference
|
|
153
|
+
|
|
154
|
+
The CLI provides a convenient way to interact with the WhatsApp Business API without writing code.
|
|
155
|
+
|
|
156
|
+
### Configuration
|
|
157
|
+
|
|
158
|
+
Config is stored at `~/.waba-toolkit` (encrypted, machine-locked).
|
|
159
|
+
|
|
160
|
+
**Priority:** CLI flags > environment variables > config file
|
|
161
|
+
|
|
162
|
+
#### Interactive Setup
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
waba-toolkit configure
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Prompts for:
|
|
169
|
+
- Access token (required)
|
|
170
|
+
- Default phone number ID (optional)
|
|
171
|
+
- API version (optional, default: v22.0)
|
|
172
|
+
- WABA ID (optional)
|
|
173
|
+
- Business ID (optional)
|
|
174
|
+
|
|
175
|
+
#### View Configuration
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
waba-toolkit config show
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Shows current configuration with sensitive values masked (e.g., `EAA...****...abc`).
|
|
182
|
+
|
|
183
|
+
#### Update Configuration
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# Set default phone number ID
|
|
187
|
+
waba-toolkit config set-default-phone 1234567890
|
|
188
|
+
|
|
189
|
+
# Update specific fields
|
|
190
|
+
waba-toolkit config set access-token EAABsbCS...
|
|
191
|
+
waba-toolkit config set waba-id 1234567890
|
|
192
|
+
waba-toolkit config set api-version v22.0
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Valid fields: `access-token`, `default-phone-number-id`, `api-version`, `waba-id`, `business-id`
|
|
196
|
+
|
|
197
|
+
#### Environment Variables
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
export WABA_TOOLKIT_ACCESS_TOKEN="your-token"
|
|
201
|
+
export WABA_TOOLKIT_PHONE_NUMBER_ID="your-phone-number-id"
|
|
202
|
+
export WABA_TOOLKIT_WABA_ID="your-waba-id"
|
|
203
|
+
export WABA_TOOLKIT_API_VERSION="v22.0"
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Phone Management
|
|
207
|
+
|
|
208
|
+
#### List Phone Numbers
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
# List all phone numbers for a WABA
|
|
212
|
+
waba-toolkit list-phones --waba-id 1234567890
|
|
213
|
+
|
|
214
|
+
# Using environment variable
|
|
215
|
+
WABA_TOOLKIT_WABA_ID=1234567890 waba-toolkit list-phones
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Returns JSON with phone numbers, quality ratings, and verified names:
|
|
219
|
+
|
|
220
|
+
```json
|
|
221
|
+
{
|
|
222
|
+
"data": [
|
|
223
|
+
{
|
|
224
|
+
"verified_name": "Your Business",
|
|
225
|
+
"display_phone_number": "+1 555-0100",
|
|
226
|
+
"id": "1234567890",
|
|
227
|
+
"quality_rating": "GREEN"
|
|
228
|
+
}
|
|
229
|
+
]
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
#### Register Phone Number
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# Register with default phone number ID from config
|
|
237
|
+
waba-toolkit register --pin 123456
|
|
238
|
+
|
|
239
|
+
# Register specific phone number
|
|
240
|
+
waba-toolkit register --bpid 1234567890 --pin 123456
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
#### Deregister Phone Number
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
# Deregister default phone number
|
|
247
|
+
waba-toolkit deregister
|
|
248
|
+
|
|
249
|
+
# Deregister specific phone number
|
|
250
|
+
waba-toolkit deregister --bpid 1234567890
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Sending Messages
|
|
254
|
+
|
|
255
|
+
#### Text Message
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
# Basic text message
|
|
259
|
+
waba-toolkit send text --to 1234567890 --message "Hello World"
|
|
260
|
+
|
|
261
|
+
# With URL preview
|
|
262
|
+
waba-toolkit send text --to 1234567890 --message "Check out https://example.com" --preview-url
|
|
263
|
+
|
|
264
|
+
# Reply to message
|
|
265
|
+
waba-toolkit send text --to 1234567890 --message "Got it!" --reply-to wamid.abc123
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
#### Template Message
|
|
269
|
+
|
|
270
|
+
```bash
|
|
271
|
+
waba-toolkit send template --to 1234567890 --file template.json
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Template JSON format:
|
|
275
|
+
|
|
276
|
+
```json
|
|
277
|
+
{
|
|
278
|
+
"name": "hello_world",
|
|
279
|
+
"language": {
|
|
280
|
+
"code": "en_US"
|
|
281
|
+
},
|
|
282
|
+
"components": [
|
|
283
|
+
{
|
|
284
|
+
"type": "body",
|
|
285
|
+
"parameters": [
|
|
286
|
+
{ "type": "text", "text": "John" }
|
|
287
|
+
]
|
|
288
|
+
}
|
|
289
|
+
]
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
#### Custom Message (from JSON)
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
waba-toolkit send file --payload message.json
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Example payloads:
|
|
300
|
+
|
|
301
|
+
**Text:**
|
|
302
|
+
```json
|
|
303
|
+
{
|
|
304
|
+
"messaging_product": "whatsapp",
|
|
305
|
+
"to": "1234567890",
|
|
306
|
+
"type": "text",
|
|
307
|
+
"text": {
|
|
308
|
+
"body": "Hello World"
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
**Image:**
|
|
314
|
+
```json
|
|
315
|
+
{
|
|
316
|
+
"messaging_product": "whatsapp",
|
|
317
|
+
"to": "1234567890",
|
|
318
|
+
"type": "image",
|
|
319
|
+
"image": {
|
|
320
|
+
"link": "https://example.com/image.jpg"
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
**Interactive (List):**
|
|
326
|
+
```json
|
|
327
|
+
{
|
|
328
|
+
"messaging_product": "whatsapp",
|
|
329
|
+
"to": "1234567890",
|
|
330
|
+
"type": "interactive",
|
|
331
|
+
"interactive": {
|
|
332
|
+
"type": "list",
|
|
333
|
+
"body": {
|
|
334
|
+
"text": "Choose an option"
|
|
335
|
+
},
|
|
336
|
+
"action": {
|
|
337
|
+
"button": "View Menu",
|
|
338
|
+
"sections": [
|
|
339
|
+
{
|
|
340
|
+
"title": "Options",
|
|
341
|
+
"rows": [
|
|
342
|
+
{
|
|
343
|
+
"id": "1",
|
|
344
|
+
"title": "Option 1",
|
|
345
|
+
"description": "First option"
|
|
346
|
+
}
|
|
347
|
+
]
|
|
348
|
+
}
|
|
349
|
+
]
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
112
357
|
## API Reference
|
|
113
358
|
|
|
114
359
|
### WABAClient
|
|
@@ -152,6 +397,89 @@ const { buffer, mimeType, sha256, fileSize, url } = await client.getMedia(mediaI
|
|
|
152
397
|
|
|
153
398
|
---
|
|
154
399
|
|
|
400
|
+
### WABAApiClient
|
|
401
|
+
|
|
402
|
+
Client for outbound WhatsApp Business API operations (sending messages, phone registration).
|
|
403
|
+
|
|
404
|
+
#### Constructor
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
const apiClient = new WABAApiClient({
|
|
408
|
+
accessToken: string, // Required: Meta access token
|
|
409
|
+
phoneNumberId: string, // Required: Your business phone number ID
|
|
410
|
+
apiVersion?: string, // Optional: API version (default: 'v22.0')
|
|
411
|
+
baseUrl?: string, // Optional: Base URL (default: 'https://graph.facebook.com')
|
|
412
|
+
});
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
#### Methods
|
|
416
|
+
|
|
417
|
+
| Method | Description |
|
|
418
|
+
|--------|-------------|
|
|
419
|
+
| `registerPhone(pin)` | Register phone number with 6-digit PIN |
|
|
420
|
+
| `deregisterPhone()` | Deregister phone number |
|
|
421
|
+
| `listPhoneNumbers(wabaId)` | List all phone numbers for a WABA |
|
|
422
|
+
| `sendTextMessage(to, text, options)` | Send text message |
|
|
423
|
+
| `sendTemplateMessage(to, template)` | Send approved template message |
|
|
424
|
+
| `sendMessage(payload)` | Send any message type with custom payload |
|
|
425
|
+
|
|
426
|
+
#### Examples
|
|
427
|
+
|
|
428
|
+
```typescript
|
|
429
|
+
import { WABAApiClient } from 'waba-toolkit';
|
|
430
|
+
|
|
431
|
+
const apiClient = new WABAApiClient({
|
|
432
|
+
accessToken: process.env.META_ACCESS_TOKEN,
|
|
433
|
+
phoneNumberId: '1234567890',
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
// List phone numbers
|
|
437
|
+
const phones = await apiClient.listPhoneNumbers('YOUR_WABA_ID');
|
|
438
|
+
console.log(phones.data);
|
|
439
|
+
|
|
440
|
+
// Register phone
|
|
441
|
+
await apiClient.registerPhone('123456');
|
|
442
|
+
|
|
443
|
+
// Send text message
|
|
444
|
+
const response = await apiClient.sendTextMessage(
|
|
445
|
+
'1234567890',
|
|
446
|
+
'Hello from waba-toolkit!',
|
|
447
|
+
{ previewUrl: true }
|
|
448
|
+
);
|
|
449
|
+
console.log('Message ID:', response.messages[0].id);
|
|
450
|
+
|
|
451
|
+
// Reply to a message
|
|
452
|
+
await apiClient.sendTextMessage(
|
|
453
|
+
'1234567890',
|
|
454
|
+
'This is a reply',
|
|
455
|
+
{ context: { message_id: 'wamid.abc123' } }
|
|
456
|
+
);
|
|
457
|
+
|
|
458
|
+
// Send template message
|
|
459
|
+
await apiClient.sendTemplateMessage('1234567890', {
|
|
460
|
+
name: 'hello_world',
|
|
461
|
+
language: { code: 'en_US' },
|
|
462
|
+
components: [
|
|
463
|
+
{
|
|
464
|
+
type: 'body',
|
|
465
|
+
parameters: [{ type: 'text', text: 'John' }],
|
|
466
|
+
},
|
|
467
|
+
],
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
// Send custom message (image)
|
|
471
|
+
await apiClient.sendMessage({
|
|
472
|
+
messaging_product: 'whatsapp',
|
|
473
|
+
to: '1234567890',
|
|
474
|
+
type: 'image',
|
|
475
|
+
image: {
|
|
476
|
+
link: 'https://example.com/image.jpg',
|
|
477
|
+
},
|
|
478
|
+
});
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
---
|
|
482
|
+
|
|
155
483
|
### Webhook Functions
|
|
156
484
|
|
|
157
485
|
| Function | Description |
|
|
@@ -324,10 +652,19 @@ console.log(sentAt.toISOString());
|
|
|
324
652
|
| `WABAMediaError` | Media download failures (includes `mediaId` and `code`) |
|
|
325
653
|
| `WABANetworkError` | Network/connection failures (includes `cause`) |
|
|
326
654
|
| `WABASignatureError` | Invalid webhook signature |
|
|
655
|
+
| `WABAConfigError` | Configuration issues (includes `field`) |
|
|
656
|
+
| `WABAAuthError` | Authentication failures (includes `statusCode`) |
|
|
657
|
+
| `WABASendError` | Message sending failures (includes `statusCode` and `errorPayload`) |
|
|
327
658
|
|
|
328
659
|
```typescript
|
|
329
|
-
import {
|
|
660
|
+
import {
|
|
661
|
+
WABAMediaError,
|
|
662
|
+
WABANetworkError,
|
|
663
|
+
WABASendError,
|
|
664
|
+
WABAAuthError,
|
|
665
|
+
} from 'waba-toolkit';
|
|
330
666
|
|
|
667
|
+
// Media download errors
|
|
331
668
|
try {
|
|
332
669
|
const media = await client.getMedia(mediaId);
|
|
333
670
|
} catch (error) {
|
|
@@ -337,6 +674,18 @@ try {
|
|
|
337
674
|
console.error('Network error:', error.cause);
|
|
338
675
|
}
|
|
339
676
|
}
|
|
677
|
+
|
|
678
|
+
// Message sending errors
|
|
679
|
+
try {
|
|
680
|
+
await apiClient.sendTextMessage('1234567890', 'Hello');
|
|
681
|
+
} catch (error) {
|
|
682
|
+
if (error instanceof WABAAuthError) {
|
|
683
|
+
console.error(`Auth failed: ${error.statusCode}`);
|
|
684
|
+
} else if (error instanceof WABASendError) {
|
|
685
|
+
console.error(`Send failed: ${error.statusCode}`);
|
|
686
|
+
console.error('Details:', error.errorPayload);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
340
689
|
```
|
|
341
690
|
|
|
342
691
|
---
|
|
@@ -347,8 +696,9 @@ All types are exported for use in your application:
|
|
|
347
696
|
|
|
348
697
|
```typescript
|
|
349
698
|
import type {
|
|
350
|
-
//
|
|
699
|
+
// Clients
|
|
351
700
|
WABAClientOptions,
|
|
701
|
+
WABAApiClientOptions,
|
|
352
702
|
GetMediaOptions,
|
|
353
703
|
|
|
354
704
|
// Media
|
|
@@ -356,7 +706,19 @@ import type {
|
|
|
356
706
|
MediaStreamResult,
|
|
357
707
|
MediaBufferResult,
|
|
358
708
|
|
|
359
|
-
//
|
|
709
|
+
// API (Outbound)
|
|
710
|
+
SendTextMessageRequest,
|
|
711
|
+
SendTemplateMessageRequest,
|
|
712
|
+
SendMessageResponse,
|
|
713
|
+
MessagePayload,
|
|
714
|
+
RegisterPhoneRequest,
|
|
715
|
+
DeregisterPhoneRequest,
|
|
716
|
+
TemplateParameter,
|
|
717
|
+
TemplateComponent,
|
|
718
|
+
PhoneNumber,
|
|
719
|
+
ListPhoneNumbersResponse,
|
|
720
|
+
|
|
721
|
+
// Webhooks (Inbound)
|
|
360
722
|
WebhookPayload,
|
|
361
723
|
WebhookClassification,
|
|
362
724
|
MessageWebhookValue,
|