@hasna/connectors 0.3.16 → 0.4.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.
Files changed (127) hide show
  1. package/bin/index.js +71 -1
  2. package/bin/mcp.js +71 -1
  3. package/bin/serve.js +70 -0
  4. package/connectors/connect-asana/.env.example +11 -0
  5. package/connectors/connect-asana/CLAUDE.md +128 -0
  6. package/connectors/connect-asana/README.md +193 -0
  7. package/connectors/connect-asana/package.json +52 -0
  8. package/connectors/connect-asana/src/api/client.ts +119 -0
  9. package/connectors/connect-asana/src/api/index.ts +319 -0
  10. package/connectors/connect-asana/src/cli/index.ts +731 -0
  11. package/connectors/connect-asana/src/index.ts +19 -0
  12. package/connectors/connect-asana/src/types/index.ts +270 -0
  13. package/connectors/connect-asana/src/utils/config.ts +171 -0
  14. package/connectors/connect-asana/src/utils/output.ts +119 -0
  15. package/connectors/connect-asana/tsconfig.json +16 -0
  16. package/connectors/connect-clickup/.env.example +11 -0
  17. package/connectors/connect-clickup/CLAUDE.md +128 -0
  18. package/connectors/connect-clickup/README.md +193 -0
  19. package/connectors/connect-clickup/package.json +52 -0
  20. package/connectors/connect-clickup/src/api/client.ts +116 -0
  21. package/connectors/connect-clickup/src/api/index.ts +400 -0
  22. package/connectors/connect-clickup/src/cli/index.ts +625 -0
  23. package/connectors/connect-clickup/src/index.ts +19 -0
  24. package/connectors/connect-clickup/src/types/index.ts +591 -0
  25. package/connectors/connect-clickup/src/utils/config.ts +157 -0
  26. package/connectors/connect-clickup/src/utils/output.ts +119 -0
  27. package/connectors/connect-clickup/tsconfig.json +16 -0
  28. package/connectors/connect-confluence/.env.example +11 -0
  29. package/connectors/connect-confluence/CLAUDE.md +272 -0
  30. package/connectors/connect-confluence/README.md +193 -0
  31. package/connectors/connect-confluence/package.json +53 -0
  32. package/connectors/connect-confluence/scripts/release.ts +179 -0
  33. package/connectors/connect-confluence/src/api/client.ts +213 -0
  34. package/connectors/connect-confluence/src/api/example.ts +48 -0
  35. package/connectors/connect-confluence/src/api/index.ts +51 -0
  36. package/connectors/connect-confluence/src/cli/index.ts +254 -0
  37. package/connectors/connect-confluence/src/index.ts +103 -0
  38. package/connectors/connect-confluence/src/types/index.ts +237 -0
  39. package/connectors/connect-confluence/src/utils/auth.ts +274 -0
  40. package/connectors/connect-confluence/src/utils/bulk.ts +212 -0
  41. package/connectors/connect-confluence/src/utils/config.ts +326 -0
  42. package/connectors/connect-confluence/src/utils/output.ts +175 -0
  43. package/connectors/connect-confluence/src/utils/settings.ts +114 -0
  44. package/connectors/connect-confluence/src/utils/storage.ts +198 -0
  45. package/connectors/connect-confluence/tsconfig.json +16 -0
  46. package/connectors/connect-jira/.env.example +11 -0
  47. package/connectors/connect-jira/CLAUDE.md +128 -0
  48. package/connectors/connect-jira/README.md +193 -0
  49. package/connectors/connect-jira/package.json +53 -0
  50. package/connectors/connect-jira/src/api/client.ts +131 -0
  51. package/connectors/connect-jira/src/api/index.ts +266 -0
  52. package/connectors/connect-jira/src/cli/index.ts +653 -0
  53. package/connectors/connect-jira/src/index.ts +23 -0
  54. package/connectors/connect-jira/src/types/index.ts +448 -0
  55. package/connectors/connect-jira/src/utils/config.ts +179 -0
  56. package/connectors/connect-jira/src/utils/output.ts +119 -0
  57. package/connectors/connect-jira/tsconfig.json +16 -0
  58. package/connectors/connect-linear/CLAUDE.md +88 -0
  59. package/connectors/connect-linear/README.md +201 -0
  60. package/connectors/connect-linear/package.json +45 -0
  61. package/connectors/connect-linear/src/api/client.ts +62 -0
  62. package/connectors/connect-linear/src/api/index.ts +46 -0
  63. package/connectors/connect-linear/src/api/issues.ts +247 -0
  64. package/connectors/connect-linear/src/api/projects.ts +179 -0
  65. package/connectors/connect-linear/src/api/teams.ts +125 -0
  66. package/connectors/connect-linear/src/api/users.ts +112 -0
  67. package/connectors/connect-linear/src/cli/index.ts +560 -0
  68. package/connectors/connect-linear/src/index.ts +27 -0
  69. package/connectors/connect-linear/src/types/index.ts +275 -0
  70. package/connectors/connect-linear/src/utils/config.ts +249 -0
  71. package/connectors/connect-linear/src/utils/output.ts +119 -0
  72. package/connectors/connect-linear/tsconfig.json +16 -0
  73. package/connectors/connect-slack/.env.example +7 -0
  74. package/connectors/connect-slack/CLAUDE.md +69 -0
  75. package/connectors/connect-slack/README.md +150 -0
  76. package/connectors/connect-slack/package.json +44 -0
  77. package/connectors/connect-slack/src/api/channels.ts +112 -0
  78. package/connectors/connect-slack/src/api/client.ts +97 -0
  79. package/connectors/connect-slack/src/api/index.ts +42 -0
  80. package/connectors/connect-slack/src/api/messages.ts +127 -0
  81. package/connectors/connect-slack/src/api/users.ts +110 -0
  82. package/connectors/connect-slack/src/cli/index.ts +494 -0
  83. package/connectors/connect-slack/src/index.ts +21 -0
  84. package/connectors/connect-slack/src/types/index.ts +263 -0
  85. package/connectors/connect-slack/src/utils/config.ts +297 -0
  86. package/connectors/connect-slack/src/utils/output.ts +119 -0
  87. package/connectors/connect-slack/tsconfig.json +16 -0
  88. package/connectors/connect-telegram/.env.example +2 -0
  89. package/connectors/connect-telegram/package.json +49 -0
  90. package/connectors/connect-todoist/.env.example +11 -0
  91. package/connectors/connect-todoist/CLAUDE.md +104 -0
  92. package/connectors/connect-todoist/README.md +193 -0
  93. package/connectors/connect-todoist/package.json +52 -0
  94. package/connectors/connect-todoist/src/api/client.ts +117 -0
  95. package/connectors/connect-todoist/src/api/index.ts +188 -0
  96. package/connectors/connect-todoist/src/cli/index.ts +990 -0
  97. package/connectors/connect-todoist/src/index.ts +21 -0
  98. package/connectors/connect-todoist/src/types/index.ts +240 -0
  99. package/connectors/connect-todoist/src/utils/config.ts +157 -0
  100. package/connectors/connect-todoist/src/utils/output.ts +119 -0
  101. package/connectors/connect-todoist/tsconfig.json +16 -0
  102. package/connectors/connect-trello/.env.example +11 -0
  103. package/connectors/connect-trello/CLAUDE.md +128 -0
  104. package/connectors/connect-trello/README.md +193 -0
  105. package/connectors/connect-trello/package.json +53 -0
  106. package/connectors/connect-trello/src/api/client.ts +128 -0
  107. package/connectors/connect-trello/src/api/index.ts +278 -0
  108. package/connectors/connect-trello/src/cli/index.ts +737 -0
  109. package/connectors/connect-trello/src/index.ts +21 -0
  110. package/connectors/connect-trello/src/types/index.ts +314 -0
  111. package/connectors/connect-trello/src/utils/config.ts +182 -0
  112. package/connectors/connect-trello/src/utils/output.ts +119 -0
  113. package/connectors/connect-trello/tsconfig.json +16 -0
  114. package/connectors/connect-whatsapp/.env.example +11 -0
  115. package/connectors/connect-whatsapp/CLAUDE.md +113 -0
  116. package/connectors/connect-whatsapp/README.md +193 -0
  117. package/connectors/connect-whatsapp/package.json +53 -0
  118. package/connectors/connect-whatsapp/src/api/client.ts +133 -0
  119. package/connectors/connect-whatsapp/src/api/index.ts +365 -0
  120. package/connectors/connect-whatsapp/src/cli/index.ts +686 -0
  121. package/connectors/connect-whatsapp/src/index.ts +25 -0
  122. package/connectors/connect-whatsapp/src/types/index.ts +502 -0
  123. package/connectors/connect-whatsapp/src/utils/config.ts +179 -0
  124. package/connectors/connect-whatsapp/src/utils/output.ts +119 -0
  125. package/connectors/connect-whatsapp/tsconfig.json +16 -0
  126. package/dist/index.js +70 -0
  127. package/package.json +1 -1
@@ -0,0 +1,365 @@
1
+ // WhatsApp Business Cloud Connector
2
+ // Send messages, manage templates, and handle webhooks
3
+
4
+ import { WhatsAppClient } from './client';
5
+ import type {
6
+ WhatsAppConfig,
7
+ SendMessageInput,
8
+ SendMessageResponse,
9
+ BusinessProfile,
10
+ PhoneNumber,
11
+ PhoneNumbersResponse,
12
+ MessageTemplate,
13
+ MessageTemplatesResponse,
14
+ MediaObject,
15
+ TextMessage,
16
+ Media,
17
+ Location,
18
+ Contact,
19
+ Interactive,
20
+ Template,
21
+ Reaction,
22
+ } from '../types';
23
+
24
+ export { WhatsAppClient } from './client';
25
+
26
+ export class WhatsApp {
27
+ private client: WhatsAppClient;
28
+
29
+ constructor(config: WhatsAppConfig) {
30
+ this.client = new WhatsAppClient(config);
31
+ }
32
+
33
+ // ============================================
34
+ // Message Operations
35
+ // ============================================
36
+
37
+ async sendMessage(input: SendMessageInput): Promise<SendMessageResponse> {
38
+ const phoneNumberId = this.client.getPhoneNumberId();
39
+ return this.client.post<SendMessageResponse>(
40
+ `/${phoneNumberId}/messages`,
41
+ input as unknown as Record<string, unknown>
42
+ );
43
+ }
44
+
45
+ async sendText(to: string, text: string, options?: {
46
+ previewUrl?: boolean;
47
+ replyToMessageId?: string;
48
+ }): Promise<SendMessageResponse> {
49
+ const message: SendMessageInput = {
50
+ messaging_product: 'whatsapp',
51
+ to,
52
+ type: 'text',
53
+ text: {
54
+ body: text,
55
+ preview_url: options?.previewUrl,
56
+ },
57
+ };
58
+ if (options?.replyToMessageId) {
59
+ message.context = { message_id: options.replyToMessageId };
60
+ }
61
+ return this.sendMessage(message);
62
+ }
63
+
64
+ async sendImage(to: string, image: Media, options?: {
65
+ replyToMessageId?: string;
66
+ }): Promise<SendMessageResponse> {
67
+ const message: SendMessageInput = {
68
+ messaging_product: 'whatsapp',
69
+ to,
70
+ type: 'image',
71
+ image,
72
+ };
73
+ if (options?.replyToMessageId) {
74
+ message.context = { message_id: options.replyToMessageId };
75
+ }
76
+ return this.sendMessage(message);
77
+ }
78
+
79
+ async sendAudio(to: string, audio: Media, options?: {
80
+ replyToMessageId?: string;
81
+ }): Promise<SendMessageResponse> {
82
+ const message: SendMessageInput = {
83
+ messaging_product: 'whatsapp',
84
+ to,
85
+ type: 'audio',
86
+ audio,
87
+ };
88
+ if (options?.replyToMessageId) {
89
+ message.context = { message_id: options.replyToMessageId };
90
+ }
91
+ return this.sendMessage(message);
92
+ }
93
+
94
+ async sendVideo(to: string, video: Media, options?: {
95
+ replyToMessageId?: string;
96
+ }): Promise<SendMessageResponse> {
97
+ const message: SendMessageInput = {
98
+ messaging_product: 'whatsapp',
99
+ to,
100
+ type: 'video',
101
+ video,
102
+ };
103
+ if (options?.replyToMessageId) {
104
+ message.context = { message_id: options.replyToMessageId };
105
+ }
106
+ return this.sendMessage(message);
107
+ }
108
+
109
+ async sendDocument(to: string, document: Media, options?: {
110
+ replyToMessageId?: string;
111
+ }): Promise<SendMessageResponse> {
112
+ const message: SendMessageInput = {
113
+ messaging_product: 'whatsapp',
114
+ to,
115
+ type: 'document',
116
+ document,
117
+ };
118
+ if (options?.replyToMessageId) {
119
+ message.context = { message_id: options.replyToMessageId };
120
+ }
121
+ return this.sendMessage(message);
122
+ }
123
+
124
+ async sendSticker(to: string, sticker: Media, options?: {
125
+ replyToMessageId?: string;
126
+ }): Promise<SendMessageResponse> {
127
+ const message: SendMessageInput = {
128
+ messaging_product: 'whatsapp',
129
+ to,
130
+ type: 'sticker',
131
+ sticker,
132
+ };
133
+ if (options?.replyToMessageId) {
134
+ message.context = { message_id: options.replyToMessageId };
135
+ }
136
+ return this.sendMessage(message);
137
+ }
138
+
139
+ async sendLocation(to: string, location: Location, options?: {
140
+ replyToMessageId?: string;
141
+ }): Promise<SendMessageResponse> {
142
+ const message: SendMessageInput = {
143
+ messaging_product: 'whatsapp',
144
+ to,
145
+ type: 'location',
146
+ location,
147
+ };
148
+ if (options?.replyToMessageId) {
149
+ message.context = { message_id: options.replyToMessageId };
150
+ }
151
+ return this.sendMessage(message);
152
+ }
153
+
154
+ async sendContacts(to: string, contacts: Contact[], options?: {
155
+ replyToMessageId?: string;
156
+ }): Promise<SendMessageResponse> {
157
+ const message: SendMessageInput = {
158
+ messaging_product: 'whatsapp',
159
+ to,
160
+ type: 'contacts',
161
+ contacts,
162
+ };
163
+ if (options?.replyToMessageId) {
164
+ message.context = { message_id: options.replyToMessageId };
165
+ }
166
+ return this.sendMessage(message);
167
+ }
168
+
169
+ async sendInteractive(to: string, interactive: Interactive, options?: {
170
+ replyToMessageId?: string;
171
+ }): Promise<SendMessageResponse> {
172
+ const message: SendMessageInput = {
173
+ messaging_product: 'whatsapp',
174
+ to,
175
+ type: 'interactive',
176
+ interactive,
177
+ };
178
+ if (options?.replyToMessageId) {
179
+ message.context = { message_id: options.replyToMessageId };
180
+ }
181
+ return this.sendMessage(message);
182
+ }
183
+
184
+ async sendTemplate(to: string, template: Template, options?: {
185
+ replyToMessageId?: string;
186
+ }): Promise<SendMessageResponse> {
187
+ const message: SendMessageInput = {
188
+ messaging_product: 'whatsapp',
189
+ to,
190
+ type: 'template',
191
+ template,
192
+ };
193
+ if (options?.replyToMessageId) {
194
+ message.context = { message_id: options.replyToMessageId };
195
+ }
196
+ return this.sendMessage(message);
197
+ }
198
+
199
+ async sendReaction(to: string, reaction: Reaction): Promise<SendMessageResponse> {
200
+ const message: SendMessageInput = {
201
+ messaging_product: 'whatsapp',
202
+ to,
203
+ type: 'reaction',
204
+ reaction,
205
+ };
206
+ return this.sendMessage(message);
207
+ }
208
+
209
+ async markAsRead(messageId: string): Promise<{ success: boolean }> {
210
+ const phoneNumberId = this.client.getPhoneNumberId();
211
+ return this.client.post<{ success: boolean }>(
212
+ `/${phoneNumberId}/messages`,
213
+ {
214
+ messaging_product: 'whatsapp',
215
+ status: 'read',
216
+ message_id: messageId,
217
+ }
218
+ );
219
+ }
220
+
221
+ // ============================================
222
+ // Media Operations
223
+ // ============================================
224
+
225
+ async uploadMedia(file: Blob, mimeType: string, filename?: string): Promise<{ id: string }> {
226
+ const phoneNumberId = this.client.getPhoneNumberId();
227
+ const formData = new FormData();
228
+ formData.append('file', file, filename);
229
+ formData.append('messaging_product', 'whatsapp');
230
+ formData.append('type', mimeType);
231
+
232
+ // Note: This requires special handling for multipart/form-data
233
+ // For now, return the endpoint info
234
+ throw new Error('Media upload requires multipart/form-data. Use the API directly.');
235
+ }
236
+
237
+ async getMediaUrl(mediaId: string): Promise<MediaObject> {
238
+ return this.client.get<MediaObject>(`/${mediaId}`);
239
+ }
240
+
241
+ async deleteMedia(mediaId: string): Promise<{ success: boolean }> {
242
+ return this.client.delete<{ success: boolean }>(`/${mediaId}`);
243
+ }
244
+
245
+ // ============================================
246
+ // Business Profile Operations
247
+ // ============================================
248
+
249
+ async getBusinessProfile(fields?: string[]): Promise<{ data: BusinessProfile[] }> {
250
+ const phoneNumberId = this.client.getPhoneNumberId();
251
+ const params: Record<string, string> = {};
252
+ if (fields && fields.length > 0) {
253
+ params.fields = fields.join(',');
254
+ } else {
255
+ params.fields = 'about,address,description,email,profile_picture_url,websites,vertical';
256
+ }
257
+ return this.client.get<{ data: BusinessProfile[] }>(
258
+ `/${phoneNumberId}/whatsapp_business_profile`,
259
+ params
260
+ );
261
+ }
262
+
263
+ async updateBusinessProfile(profile: Partial<BusinessProfile>): Promise<{ success: boolean }> {
264
+ const phoneNumberId = this.client.getPhoneNumberId();
265
+ return this.client.post<{ success: boolean }>(
266
+ `/${phoneNumberId}/whatsapp_business_profile`,
267
+ {
268
+ messaging_product: 'whatsapp',
269
+ ...profile,
270
+ }
271
+ );
272
+ }
273
+
274
+ // ============================================
275
+ // Phone Number Operations
276
+ // ============================================
277
+
278
+ async getPhoneNumber(): Promise<PhoneNumber> {
279
+ const phoneNumberId = this.client.getPhoneNumberId();
280
+ return this.client.get<PhoneNumber>(`/${phoneNumberId}`);
281
+ }
282
+
283
+ async listPhoneNumbers(): Promise<PhoneNumbersResponse> {
284
+ const businessAccountId = this.client.getBusinessAccountId();
285
+ if (!businessAccountId) {
286
+ throw new Error('Business account ID is required to list phone numbers');
287
+ }
288
+ return this.client.get<PhoneNumbersResponse>(`/${businessAccountId}/phone_numbers`);
289
+ }
290
+
291
+ async requestVerificationCode(codeMethod: 'SMS' | 'VOICE', language: string): Promise<{ success: boolean }> {
292
+ const phoneNumberId = this.client.getPhoneNumberId();
293
+ return this.client.post<{ success: boolean }>(
294
+ `/${phoneNumberId}/request_code`,
295
+ {
296
+ code_method: codeMethod,
297
+ language,
298
+ }
299
+ );
300
+ }
301
+
302
+ async verifyCode(code: string): Promise<{ success: boolean }> {
303
+ const phoneNumberId = this.client.getPhoneNumberId();
304
+ return this.client.post<{ success: boolean }>(
305
+ `/${phoneNumberId}/verify_code`,
306
+ { code }
307
+ );
308
+ }
309
+
310
+ // ============================================
311
+ // Template Operations
312
+ // ============================================
313
+
314
+ async listTemplates(options?: {
315
+ limit?: number;
316
+ after?: string;
317
+ }): Promise<MessageTemplatesResponse> {
318
+ const businessAccountId = this.client.getBusinessAccountId();
319
+ if (!businessAccountId) {
320
+ throw new Error('Business account ID is required to list templates');
321
+ }
322
+ const params: Record<string, string | number> = {};
323
+ if (options?.limit) {
324
+ params.limit = options.limit;
325
+ }
326
+ if (options?.after) {
327
+ params.after = options.after;
328
+ }
329
+ return this.client.get<MessageTemplatesResponse>(
330
+ `/${businessAccountId}/message_templates`,
331
+ params
332
+ );
333
+ }
334
+
335
+ async getTemplate(templateId: string): Promise<MessageTemplate> {
336
+ return this.client.get<MessageTemplate>(`/${templateId}`);
337
+ }
338
+
339
+ async deleteTemplate(templateName: string): Promise<{ success: boolean }> {
340
+ const businessAccountId = this.client.getBusinessAccountId();
341
+ if (!businessAccountId) {
342
+ throw new Error('Business account ID is required to delete templates');
343
+ }
344
+ return this.client.delete<{ success: boolean }>(
345
+ `/${businessAccountId}/message_templates`,
346
+ { name: templateName }
347
+ );
348
+ }
349
+
350
+ // ============================================
351
+ // Utility Methods
352
+ // ============================================
353
+
354
+ getClient(): WhatsAppClient {
355
+ return this.client;
356
+ }
357
+
358
+ getPhoneNumberId(): string {
359
+ return this.client.getPhoneNumberId();
360
+ }
361
+
362
+ getBusinessAccountId(): string | undefined {
363
+ return this.client.getBusinessAccountId();
364
+ }
365
+ }