@elizaos/plugin-whatsapp 0.1.7-alpha.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.
package/Readme.md ADDED
@@ -0,0 +1,154 @@
1
+ # WhatsApp Cloud API Plugin
2
+
3
+ A plugin for integrating WhatsApp Cloud API with your application.
4
+
5
+ ## Installation
6
+
7
+ </file>
8
+
9
+ npm install @eliza/plugin-whatsapp
10
+
11
+ ## Configuration
12
+
13
+ typescript
14
+ import { WhatsAppPlugin } from '@eliza/plugin-whatsapp';
15
+ const whatsappPlugin = new WhatsAppPlugin({
16
+ accessToken: 'your_access_token',
17
+ phoneNumberId: 'your_phone_number_id',
18
+ webhookVerifyToken: 'your_webhook_verify_token',
19
+ businessAccountId: 'your_business_account_id'
20
+ });
21
+
22
+ ## Usage
23
+
24
+ ### Sending Messages
25
+
26
+ typescript
27
+ // Send a text message
28
+ await whatsappPlugin.sendMessage({
29
+ type: 'text',
30
+ to: '1234567890',
31
+ content: 'Hello from WhatsApp!'
32
+ });
33
+ // Send a template message
34
+ await whatsappPlugin.sendMessage({
35
+ type: 'template',
36
+ to: '1234567890',
37
+ content: {
38
+ name: 'hello_world',
39
+ language: {
40
+ code: 'en'
41
+ }
42
+ }
43
+ });
44
+
45
+ ### Handling Webhooks
46
+
47
+ typescript
48
+ // Verify webhook
49
+ app.get('/webhook', (req, res) => {
50
+ const verified = await whatsappPlugin.verifyWebhook(req.query['hub.verify_token']);
51
+ if (verified) {
52
+ res.send(req.query['hub.challenge']);
53
+ } else {
54
+ res.sendStatus(403);
55
+ }
56
+ });
57
+ // Handle webhook events
58
+ app.post('/webhook', (req, res) => {
59
+ await whatsappPlugin.handleWebhook(req.body);
60
+ res.sendStatus(200);
61
+ });
62
+
63
+ ## Features
64
+
65
+ - Send text messages
66
+ - Send template messages
67
+ - Webhook verification
68
+ - Webhook event handling
69
+ - Message status updates
70
+
71
+ ## API Reference
72
+
73
+ ### WhatsAppPlugin
74
+
75
+ #### Constructor
76
+
77
+ - `config: WhatsAppConfig` - Configuration object for the plugin
78
+
79
+ #### Methods
80
+
81
+ - `sendMessage(message: WhatsAppMessage): Promise<any>` - Send a WhatsApp message
82
+ - `handleWebhook(event: WhatsAppWebhookEvent): Promise<void>` - Process incoming webhook events
83
+ - `verifyWebhook(token: string): Promise<boolean>` - Verify webhook token
84
+
85
+ ### Types
86
+
87
+ typescript
88
+ interface WhatsAppConfig {
89
+ accessToken: string;
90
+ phoneNumberId: string;
91
+ webhookVerifyToken?: string;
92
+ businessAccountId?: string;
93
+ }
94
+ interface WhatsAppMessage {
95
+ type: 'text' | 'template';
96
+ to: string;
97
+ content: string | WhatsAppTemplate;
98
+ }
99
+ interface WhatsAppTemplate {
100
+ name: string;
101
+ language: {
102
+ code: string;
103
+ };
104
+ components?: Array<{
105
+ type: string;
106
+ parameters: Array<{
107
+ type: string;
108
+ text?: string;
109
+ }>;
110
+ }>;
111
+ }
112
+
113
+ ## Error Handling
114
+
115
+ The plugin throws errors in the following cases:
116
+
117
+ - Invalid configuration
118
+ - Failed message sending
119
+ - Webhook verification failure
120
+ - Invalid webhook payload
121
+
122
+ Example error handling:
123
+
124
+ typescript
125
+ try {
126
+ await whatsappPlugin.sendMessage({
127
+ type: 'text',
128
+ to: '1234567890',
129
+ content: 'Hello!'
130
+ });
131
+ } catch (error) {
132
+ console.error('Failed to send message:', error.message);
133
+ }
134
+
135
+ ## Best Practices
136
+
137
+ 1. Always validate phone numbers before sending messages
138
+ 2. Use template messages for first-time messages to users
139
+ 3. Store message IDs for tracking delivery status
140
+ 4. Implement proper error handling
141
+ 5. Set up webhook retry mechanisms
142
+ 6. Keep your access tokens secure
143
+
144
+ ## Contributing
145
+
146
+ 1. Fork the repository
147
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
148
+ 3. Commit your changes (`git commit -m 'Add some amazing feature'`)
149
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
150
+ 5. Open a Pull Request
151
+
152
+ ## License
153
+
154
+ MIT
@@ -0,0 +1,72 @@
1
+ import { Plugin } from '@elizaos/core';
2
+
3
+ interface WhatsAppConfig {
4
+ accessToken: string;
5
+ phoneNumberId: string;
6
+ webhookVerifyToken?: string;
7
+ businessAccountId?: string;
8
+ }
9
+ interface WhatsAppMessage {
10
+ type: "text" | "template";
11
+ to: string;
12
+ content: string | WhatsAppTemplate;
13
+ }
14
+ interface WhatsAppTemplate {
15
+ name: string;
16
+ language: {
17
+ code: string;
18
+ };
19
+ components?: Array<{
20
+ type: string;
21
+ parameters: Array<{
22
+ type: string;
23
+ text?: string;
24
+ }>;
25
+ }>;
26
+ }
27
+ interface WhatsAppWebhookEvent {
28
+ object: string;
29
+ entry: Array<{
30
+ id: string;
31
+ changes: Array<{
32
+ value: {
33
+ messaging_product: string;
34
+ metadata: {
35
+ display_phone_number: string;
36
+ phone_number_id: string;
37
+ };
38
+ statuses?: Array<{
39
+ id: string;
40
+ status: string;
41
+ timestamp: string;
42
+ recipient_id: string;
43
+ }>;
44
+ messages?: Array<{
45
+ from: string;
46
+ id: string;
47
+ timestamp: string;
48
+ text?: {
49
+ body: string;
50
+ };
51
+ type: string;
52
+ }>;
53
+ };
54
+ field: string;
55
+ }>;
56
+ }>;
57
+ }
58
+
59
+ declare class WhatsAppPlugin implements Plugin {
60
+ private config;
61
+ private client;
62
+ private messageHandler;
63
+ private webhookHandler;
64
+ name: string;
65
+ description: string;
66
+ constructor(config: WhatsAppConfig);
67
+ sendMessage(message: WhatsAppMessage): Promise<any>;
68
+ handleWebhook(event: WhatsAppWebhookEvent): Promise<void>;
69
+ verifyWebhook(token: string): Promise<boolean>;
70
+ }
71
+
72
+ export { type WhatsAppConfig, type WhatsAppMessage, WhatsAppPlugin, type WhatsAppTemplate, type WhatsAppWebhookEvent };
package/dist/index.mjs ADDED
@@ -0,0 +1,116 @@
1
+ // src/client.ts
2
+ import axios from "axios";
3
+ var WhatsAppClient = class {
4
+ client;
5
+ config;
6
+ constructor(config) {
7
+ this.config = config;
8
+ this.client = axios.create({
9
+ baseURL: "https://graph.facebook.com/v17.0",
10
+ headers: {
11
+ Authorization: `Bearer ${config.accessToken}`,
12
+ "Content-Type": "application/json"
13
+ }
14
+ });
15
+ }
16
+ async sendMessage(message) {
17
+ const endpoint = `/${this.config.phoneNumberId}/messages`;
18
+ const payload = {
19
+ messaging_product: "whatsapp",
20
+ recipient_type: "individual",
21
+ to: message.to,
22
+ type: message.type,
23
+ ...message.type === "text" ? { text: { body: message.content } } : { template: message.content }
24
+ };
25
+ return this.client.post(endpoint, payload);
26
+ }
27
+ async verifyWebhook(token) {
28
+ return token === this.config.webhookVerifyToken;
29
+ }
30
+ };
31
+
32
+ // src/handlers/message.handler.ts
33
+ var MessageHandler = class {
34
+ constructor(client) {
35
+ this.client = client;
36
+ }
37
+ async send(message) {
38
+ try {
39
+ const response = await this.client.sendMessage(message);
40
+ return response.data;
41
+ } catch (error) {
42
+ if (error instanceof Error) {
43
+ throw new Error(
44
+ `Failed to send WhatsApp message: ${error.message}`
45
+ );
46
+ }
47
+ throw new Error("Failed to send WhatsApp message");
48
+ }
49
+ }
50
+ };
51
+
52
+ // src/handlers/webhook.handler.ts
53
+ var WebhookHandler = class {
54
+ constructor(client) {
55
+ this.client = client;
56
+ }
57
+ async handle(event) {
58
+ try {
59
+ if (event.entry?.[0]?.changes?.[0]?.value?.messages) {
60
+ const messages = event.entry[0].changes[0].value.messages;
61
+ for (const message of messages) {
62
+ await this.handleMessage(message);
63
+ }
64
+ }
65
+ if (event.entry?.[0]?.changes?.[0]?.value?.statuses) {
66
+ const statuses = event.entry[0].changes[0].value.statuses;
67
+ for (const status of statuses) {
68
+ await this.handleStatus(status);
69
+ }
70
+ }
71
+ } catch (error) {
72
+ if (error instanceof Error) {
73
+ throw new Error(
74
+ `Failed to send WhatsApp message: ${error.message}`
75
+ );
76
+ }
77
+ throw new Error("Failed to send WhatsApp message");
78
+ }
79
+ }
80
+ async handleMessage(message) {
81
+ console.log("Received message:", message);
82
+ }
83
+ async handleStatus(status) {
84
+ console.log("Received status update:", status);
85
+ }
86
+ };
87
+
88
+ // src/index.ts
89
+ var WhatsAppPlugin = class {
90
+ constructor(config) {
91
+ this.config = config;
92
+ this.name = "WhatsApp Cloud API Plugin";
93
+ this.description = "A plugin for integrating WhatsApp Cloud API with your application.";
94
+ this.client = new WhatsAppClient(config);
95
+ this.messageHandler = new MessageHandler(this.client);
96
+ this.webhookHandler = new WebhookHandler(this.client);
97
+ }
98
+ client;
99
+ messageHandler;
100
+ webhookHandler;
101
+ name;
102
+ description;
103
+ async sendMessage(message) {
104
+ return this.messageHandler.send(message);
105
+ }
106
+ async handleWebhook(event) {
107
+ return this.webhookHandler.handle(event);
108
+ }
109
+ async verifyWebhook(token) {
110
+ return this.client.verifyWebhook(token);
111
+ }
112
+ };
113
+ export {
114
+ WhatsAppPlugin
115
+ };
116
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts","../src/handlers/message.handler.ts","../src/handlers/webhook.handler.ts","../src/index.ts"],"sourcesContent":["import axios, { AxiosInstance } from \"axios\";\nimport { WhatsAppConfig, WhatsAppMessage } from \"./types\";\n\nexport class WhatsAppClient {\n private client: AxiosInstance;\n private config: WhatsAppConfig;\n\n constructor(config: WhatsAppConfig) {\n this.config = config;\n this.client = axios.create({\n baseURL: \"https://graph.facebook.com/v17.0\",\n headers: {\n Authorization: `Bearer ${config.accessToken}`,\n \"Content-Type\": \"application/json\",\n },\n });\n }\n\n async sendMessage(message: WhatsAppMessage): Promise<any> {\n const endpoint = `/${this.config.phoneNumberId}/messages`;\n\n const payload = {\n messaging_product: \"whatsapp\",\n recipient_type: \"individual\",\n to: message.to,\n type: message.type,\n ...(message.type === \"text\"\n ? { text: { body: message.content } }\n : { template: message.content }),\n };\n\n return this.client.post(endpoint, payload);\n }\n\n async verifyWebhook(token: string): Promise<boolean> {\n return token === this.config.webhookVerifyToken;\n }\n}\n","import { WhatsAppClient } from \"../client\";\nimport { WhatsAppMessage } from \"../types\";\n\nexport class MessageHandler {\n constructor(private client: WhatsAppClient) {}\n\n async send(message: WhatsAppMessage): Promise<any> {\n try {\n const response = await this.client.sendMessage(message);\n return response.data;\n } catch (error: unknown) {\n if (error instanceof Error) {\n throw new Error(\n `Failed to send WhatsApp message: ${error.message}`\n );\n }\n throw new Error('Failed to send WhatsApp message');\n }\n }\n}\n","import { WhatsAppClient } from \"../client\";\nimport { WhatsAppWebhookEvent } from \"../types\";\n\nexport class WebhookHandler {\n constructor(private client: WhatsAppClient) {}\n\n async handle(event: WhatsAppWebhookEvent): Promise<void> {\n try {\n // Process messages\n if (event.entry?.[0]?.changes?.[0]?.value?.messages) {\n const messages = event.entry[0].changes[0].value.messages;\n for (const message of messages) {\n await this.handleMessage(message);\n }\n }\n\n // Process status updates\n if (event.entry?.[0]?.changes?.[0]?.value?.statuses) {\n const statuses = event.entry[0].changes[0].value.statuses;\n for (const status of statuses) {\n await this.handleStatus(status);\n }\n }\n } catch (error: unknown) {\n if (error instanceof Error) {\n throw new Error(\n `Failed to send WhatsApp message: ${error.message}`\n );\n }\n throw new Error(\"Failed to send WhatsApp message\");\n }\n }\n\n private async handleMessage(message: any): Promise<void> {\n // Implement message handling logic\n // This could emit events or trigger callbacks based on your framework's needs\n console.log(\"Received message:\", message);\n }\n\n private async handleStatus(status: any): Promise<void> {\n // Implement status update handling logic\n // This could emit events or trigger callbacks based on your framework's needs\n console.log(\"Received status update:\", status);\n }\n}\n","import { Plugin } from \"@elizaos/core\";\nimport { WhatsAppClient } from \"./client\";\nimport { WhatsAppConfig, WhatsAppMessage, WhatsAppWebhookEvent } from \"./types\";\nimport { MessageHandler, WebhookHandler } from \"./handlers\";\n\nexport class WhatsAppPlugin implements Plugin {\n private client: WhatsAppClient;\n private messageHandler: MessageHandler;\n private webhookHandler: WebhookHandler;\n\n name: string;\n description: string;\n\n constructor(private config: WhatsAppConfig) {\n this.name = \"WhatsApp Cloud API Plugin\";\n this.description =\n \"A plugin for integrating WhatsApp Cloud API with your application.\";\n this.client = new WhatsAppClient(config);\n this.messageHandler = new MessageHandler(this.client);\n this.webhookHandler = new WebhookHandler(this.client);\n }\n\n async sendMessage(message: WhatsAppMessage): Promise<any> {\n return this.messageHandler.send(message);\n }\n\n async handleWebhook(event: WhatsAppWebhookEvent): Promise<void> {\n return this.webhookHandler.handle(event);\n }\n\n async verifyWebhook(token: string): Promise<boolean> {\n return this.client.verifyWebhook(token);\n }\n}\n\nexport * from \"./types\";\n"],"mappings":"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","names":[]}
@@ -0,0 +1,9 @@
1
+ import eslintGlobalConfig from "../../eslint.config.mjs";
2
+
3
+ export default [
4
+ ...eslintGlobalConfig,
5
+ {
6
+ files: ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"],
7
+ ignores: ["**/node_modules/**", "**/dist/**"],
8
+ },
9
+ ];
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@elizaos/plugin-whatsapp",
3
+ "version": "0.1.7-alpha.1",
4
+ "description": "WhatsApp Cloud API plugin",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsup --format esm --dts",
9
+ "dev": "tsup --format esm --dts --watch",
10
+ "test": "jest",
11
+ "lint": "eslint --fix --cache ."
12
+ },
13
+ "dependencies": {
14
+ "@elizaos/core": "workspace:*",
15
+ "axios": "1.7.8"
16
+ },
17
+ "devDependencies": {
18
+ "@types/jest": "29.5.14",
19
+ "@types/node": "20.17.9",
20
+ "@typescript-eslint/eslint-plugin": "8.16.0",
21
+ "@typescript-eslint/parser": "8.16.0",
22
+ "jest": "29.7.0",
23
+ "ts-jest": "29.2.5",
24
+ "typescript": "5.6.3"
25
+ }
26
+ }
package/src/client.ts ADDED
@@ -0,0 +1,38 @@
1
+ import axios, { AxiosInstance } from "axios";
2
+ import { WhatsAppConfig, WhatsAppMessage } from "./types";
3
+
4
+ export class WhatsAppClient {
5
+ private client: AxiosInstance;
6
+ private config: WhatsAppConfig;
7
+
8
+ constructor(config: WhatsAppConfig) {
9
+ this.config = config;
10
+ this.client = axios.create({
11
+ baseURL: "https://graph.facebook.com/v17.0",
12
+ headers: {
13
+ Authorization: `Bearer ${config.accessToken}`,
14
+ "Content-Type": "application/json",
15
+ },
16
+ });
17
+ }
18
+
19
+ async sendMessage(message: WhatsAppMessage): Promise<any> {
20
+ const endpoint = `/${this.config.phoneNumberId}/messages`;
21
+
22
+ const payload = {
23
+ messaging_product: "whatsapp",
24
+ recipient_type: "individual",
25
+ to: message.to,
26
+ type: message.type,
27
+ ...(message.type === "text"
28
+ ? { text: { body: message.content } }
29
+ : { template: message.content }),
30
+ };
31
+
32
+ return this.client.post(endpoint, payload);
33
+ }
34
+
35
+ async verifyWebhook(token: string): Promise<boolean> {
36
+ return token === this.config.webhookVerifyToken;
37
+ }
38
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./message.handler";
2
+ export * from "./webhook.handler";
@@ -0,0 +1,20 @@
1
+ import { WhatsAppClient } from "../client";
2
+ import { WhatsAppMessage } from "../types";
3
+
4
+ export class MessageHandler {
5
+ constructor(private client: WhatsAppClient) {}
6
+
7
+ async send(message: WhatsAppMessage): Promise<any> {
8
+ try {
9
+ const response = await this.client.sendMessage(message);
10
+ return response.data;
11
+ } catch (error: unknown) {
12
+ if (error instanceof Error) {
13
+ throw new Error(
14
+ `Failed to send WhatsApp message: ${error.message}`
15
+ );
16
+ }
17
+ throw new Error('Failed to send WhatsApp message');
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,45 @@
1
+ import { WhatsAppClient } from "../client";
2
+ import { WhatsAppWebhookEvent } from "../types";
3
+
4
+ export class WebhookHandler {
5
+ constructor(private client: WhatsAppClient) {}
6
+
7
+ async handle(event: WhatsAppWebhookEvent): Promise<void> {
8
+ try {
9
+ // Process messages
10
+ if (event.entry?.[0]?.changes?.[0]?.value?.messages) {
11
+ const messages = event.entry[0].changes[0].value.messages;
12
+ for (const message of messages) {
13
+ await this.handleMessage(message);
14
+ }
15
+ }
16
+
17
+ // Process status updates
18
+ if (event.entry?.[0]?.changes?.[0]?.value?.statuses) {
19
+ const statuses = event.entry[0].changes[0].value.statuses;
20
+ for (const status of statuses) {
21
+ await this.handleStatus(status);
22
+ }
23
+ }
24
+ } catch (error: unknown) {
25
+ if (error instanceof Error) {
26
+ throw new Error(
27
+ `Failed to send WhatsApp message: ${error.message}`
28
+ );
29
+ }
30
+ throw new Error("Failed to send WhatsApp message");
31
+ }
32
+ }
33
+
34
+ private async handleMessage(message: any): Promise<void> {
35
+ // Implement message handling logic
36
+ // This could emit events or trigger callbacks based on your framework's needs
37
+ console.log("Received message:", message);
38
+ }
39
+
40
+ private async handleStatus(status: any): Promise<void> {
41
+ // Implement status update handling logic
42
+ // This could emit events or trigger callbacks based on your framework's needs
43
+ console.log("Received status update:", status);
44
+ }
45
+ }
package/src/index.ts ADDED
@@ -0,0 +1,36 @@
1
+ import { Plugin } from "@elizaos/core";
2
+ import { WhatsAppClient } from "./client";
3
+ import { WhatsAppConfig, WhatsAppMessage, WhatsAppWebhookEvent } from "./types";
4
+ import { MessageHandler, WebhookHandler } from "./handlers";
5
+
6
+ export class WhatsAppPlugin implements Plugin {
7
+ private client: WhatsAppClient;
8
+ private messageHandler: MessageHandler;
9
+ private webhookHandler: WebhookHandler;
10
+
11
+ name: string;
12
+ description: string;
13
+
14
+ constructor(private config: WhatsAppConfig) {
15
+ this.name = "WhatsApp Cloud API Plugin";
16
+ this.description =
17
+ "A plugin for integrating WhatsApp Cloud API with your application.";
18
+ this.client = new WhatsAppClient(config);
19
+ this.messageHandler = new MessageHandler(this.client);
20
+ this.webhookHandler = new WebhookHandler(this.client);
21
+ }
22
+
23
+ async sendMessage(message: WhatsAppMessage): Promise<any> {
24
+ return this.messageHandler.send(message);
25
+ }
26
+
27
+ async handleWebhook(event: WhatsAppWebhookEvent): Promise<void> {
28
+ return this.webhookHandler.handle(event);
29
+ }
30
+
31
+ async verifyWebhook(token: string): Promise<boolean> {
32
+ return this.client.verifyWebhook(token);
33
+ }
34
+ }
35
+
36
+ export * from "./types";
package/src/types.ts ADDED
@@ -0,0 +1,58 @@
1
+ export interface WhatsAppConfig {
2
+ accessToken: string;
3
+ phoneNumberId: string;
4
+ webhookVerifyToken?: string;
5
+ businessAccountId?: string;
6
+ }
7
+
8
+ export interface WhatsAppMessage {
9
+ type: "text" | "template";
10
+ to: string;
11
+ content: string | WhatsAppTemplate;
12
+ }
13
+
14
+ export interface WhatsAppTemplate {
15
+ name: string;
16
+ language: {
17
+ code: string;
18
+ };
19
+ components?: Array<{
20
+ type: string;
21
+ parameters: Array<{
22
+ type: string;
23
+ text?: string;
24
+ }>;
25
+ }>;
26
+ }
27
+
28
+ export interface WhatsAppWebhookEvent {
29
+ object: string;
30
+ entry: Array<{
31
+ id: string;
32
+ changes: Array<{
33
+ value: {
34
+ messaging_product: string;
35
+ metadata: {
36
+ display_phone_number: string;
37
+ phone_number_id: string;
38
+ };
39
+ statuses?: Array<{
40
+ id: string;
41
+ status: string;
42
+ timestamp: string;
43
+ recipient_id: string;
44
+ }>;
45
+ messages?: Array<{
46
+ from: string;
47
+ id: string;
48
+ timestamp: string;
49
+ text?: {
50
+ body: string;
51
+ };
52
+ type: string;
53
+ }>;
54
+ };
55
+ field: string;
56
+ }>;
57
+ }>;
58
+ }
@@ -0,0 +1 @@
1
+ export * from "./validators";
@@ -0,0 +1,44 @@
1
+ import { WhatsAppMessage, WhatsAppTemplate, WhatsAppConfig } from "../types";
2
+
3
+ export function validateConfig(config: WhatsAppConfig): void {
4
+ if (!config.accessToken) {
5
+ throw new Error("WhatsApp access token is required");
6
+ }
7
+ if (!config.phoneNumberId) {
8
+ throw new Error("WhatsApp phone number ID is required");
9
+ }
10
+ }
11
+
12
+ export function validateMessage(message: WhatsAppMessage): void {
13
+ if (!message.to) {
14
+ throw new Error("Recipient phone number is required");
15
+ }
16
+
17
+ if (!message.type) {
18
+ throw new Error("Message type is required");
19
+ }
20
+
21
+ if (!message.content) {
22
+ throw new Error("Message content is required");
23
+ }
24
+
25
+ if (message.type === "template") {
26
+ validateTemplate(message.content as WhatsAppTemplate);
27
+ }
28
+ }
29
+
30
+ export function validateTemplate(template: WhatsAppTemplate): void {
31
+ if (!template.name) {
32
+ throw new Error("Template name is required");
33
+ }
34
+
35
+ if (!template.language || !template.language.code) {
36
+ throw new Error("Template language code is required");
37
+ }
38
+ }
39
+
40
+ export function validatePhoneNumber(phoneNumber: string): boolean {
41
+ // Basic phone number validation - can be enhanced based on requirements
42
+ const phoneRegex = /^\d{1,15}$/;
43
+ return phoneRegex.test(phoneNumber);
44
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "extends": "../core/tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "src",
6
+ "baseUrl": ".",
7
+ "types": [
8
+ "node",
9
+ "jest"
10
+ ]
11
+ },
12
+ "include": [
13
+ "src/**/*.ts"
14
+ ],
15
+ "exclude": [
16
+ "node_modules",
17
+ "dist",
18
+ "**/*.test.ts"
19
+ ]
20
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,19 @@
1
+ import { defineConfig } from "tsup";
2
+
3
+ export default defineConfig({
4
+ entry: ["src/index.ts"],
5
+ outDir: "dist",
6
+ sourcemap: true,
7
+ clean: true,
8
+ format: ["esm"], // Ensure you're targeting CommonJS
9
+ external: [
10
+ "dotenv", // Externalize dotenv to prevent bundling
11
+ "fs", // Externalize fs to use Node.js built-in module
12
+ "path", // Externalize other built-ins if necessary
13
+ "@reflink/reflink",
14
+ "@node-llama-cpp",
15
+ "https",
16
+ "http",
17
+ "agentkeepalive",
18
+ ],
19
+ });