@bubblelab/bubble-core 0.1.254 → 0.1.261

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 (54) hide show
  1. package/dist/bubble-bundle.d.ts +148 -31
  2. package/dist/bubble-factory.d.ts.map +1 -1
  3. package/dist/bubble-factory.js +9 -0
  4. package/dist/bubble-factory.js.map +1 -1
  5. package/dist/bubbles/service-bubble/ai-agent.d.ts.map +1 -1
  6. package/dist/bubbles/service-bubble/ai-agent.js +9 -2
  7. package/dist/bubbles/service-bubble/ai-agent.js.map +1 -1
  8. package/dist/bubbles/service-bubble/asana/asana.d.ts +1232 -0
  9. package/dist/bubbles/service-bubble/asana/asana.d.ts.map +1 -0
  10. package/dist/bubbles/service-bubble/asana/asana.js +809 -0
  11. package/dist/bubbles/service-bubble/asana/asana.js.map +1 -0
  12. package/dist/bubbles/service-bubble/asana/asana.schema.d.ts +1169 -0
  13. package/dist/bubbles/service-bubble/asana/asana.schema.d.ts.map +1 -0
  14. package/dist/bubbles/service-bubble/asana/asana.schema.js +740 -0
  15. package/dist/bubbles/service-bubble/asana/asana.schema.js.map +1 -0
  16. package/dist/bubbles/service-bubble/asana/index.d.ts +3 -0
  17. package/dist/bubbles/service-bubble/asana/index.d.ts.map +1 -0
  18. package/dist/bubbles/service-bubble/asana/index.js +3 -0
  19. package/dist/bubbles/service-bubble/asana/index.js.map +1 -0
  20. package/dist/bubbles/service-bubble/confluence/confluence.d.ts +2 -2
  21. package/dist/bubbles/service-bubble/confluence/confluence.schema.d.ts +2 -2
  22. package/dist/bubbles/service-bubble/discord/discord.d.ts +778 -0
  23. package/dist/bubbles/service-bubble/discord/discord.d.ts.map +1 -0
  24. package/dist/bubbles/service-bubble/discord/discord.js +370 -0
  25. package/dist/bubbles/service-bubble/discord/discord.js.map +1 -0
  26. package/dist/bubbles/service-bubble/discord/discord.schema.d.ts +739 -0
  27. package/dist/bubbles/service-bubble/discord/discord.schema.d.ts.map +1 -0
  28. package/dist/bubbles/service-bubble/discord/discord.schema.js +352 -0
  29. package/dist/bubbles/service-bubble/discord/discord.schema.js.map +1 -0
  30. package/dist/bubbles/service-bubble/discord/index.d.ts +3 -0
  31. package/dist/bubbles/service-bubble/discord/index.d.ts.map +1 -0
  32. package/dist/bubbles/service-bubble/discord/index.js +3 -0
  33. package/dist/bubbles/service-bubble/discord/index.js.map +1 -0
  34. package/dist/bubbles/service-bubble/salesforce/index.d.ts +3 -0
  35. package/dist/bubbles/service-bubble/salesforce/index.d.ts.map +1 -0
  36. package/dist/bubbles/service-bubble/salesforce/index.js +3 -0
  37. package/dist/bubbles/service-bubble/salesforce/index.js.map +1 -0
  38. package/dist/bubbles/service-bubble/salesforce/salesforce.d.ts +209 -0
  39. package/dist/bubbles/service-bubble/salesforce/salesforce.d.ts.map +1 -0
  40. package/dist/bubbles/service-bubble/salesforce/salesforce.js +221 -0
  41. package/dist/bubbles/service-bubble/salesforce/salesforce.js.map +1 -0
  42. package/dist/bubbles/service-bubble/salesforce/salesforce.schema.d.ts +179 -0
  43. package/dist/bubbles/service-bubble/salesforce/salesforce.schema.d.ts.map +1 -0
  44. package/dist/bubbles/service-bubble/salesforce/salesforce.schema.js +127 -0
  45. package/dist/bubbles/service-bubble/salesforce/salesforce.schema.js.map +1 -0
  46. package/dist/bubbles/service-bubble/snowflake/snowflake.d.ts.map +1 -1
  47. package/dist/bubbles/service-bubble/snowflake/snowflake.js +1 -1
  48. package/dist/bubbles/service-bubble/snowflake/snowflake.js.map +1 -1
  49. package/dist/bubbles.json +3945 -4
  50. package/dist/index.d.ts +6 -0
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +3 -0
  53. package/dist/index.js.map +1 -1
  54. package/package.json +2 -2
@@ -0,0 +1,809 @@
1
+ import { ServiceBubble } from '../../../types/service-bubble-class.js';
2
+ import { CredentialType, decodeCredentialPayload, } from '@bubblelab/shared-schemas';
3
+ import { AsanaParamsSchema, AsanaResultSchema, } from './asana.schema.js';
4
+ const ASANA_API_BASE = 'https://app.asana.com/api/1.0';
5
+ /**
6
+ * Asana Service Bubble
7
+ *
8
+ * Comprehensive Asana integration for managing tasks, projects, sections,
9
+ * comments, users, teams, tags, and more via the Asana REST API.
10
+ */
11
+ export class AsanaBubble extends ServiceBubble {
12
+ static type = 'service';
13
+ static service = 'asana';
14
+ static authType = 'oauth';
15
+ static bubbleName = 'asana';
16
+ static schema = AsanaParamsSchema;
17
+ static resultSchema = AsanaResultSchema;
18
+ static shortDescription = 'Asana integration for tasks, projects, and team collaboration';
19
+ static longDescription = `
20
+ Comprehensive Asana project management integration.
21
+
22
+ Features:
23
+ - Create, read, update, delete, and search tasks
24
+ - Manage projects, sections, and project memberships
25
+ - Add comments and view task activity stories
26
+ - List users, teams, and team members
27
+ - Manage tags and custom fields
28
+ - View attachments and workspaces
29
+ - Filter tasks by project, section, assignee, dates, and completion status
30
+
31
+ Security Features:
32
+ - OAuth 2.0 authentication with Asana
33
+ - Workspace-scoped access
34
+ - Secure credential handling with base64-encoded payloads
35
+ `;
36
+ static alias = '';
37
+ constructor(params = {
38
+ operation: 'list_tasks',
39
+ project: '',
40
+ }, context) {
41
+ super(params, context);
42
+ }
43
+ async testCredential() {
44
+ const creds = this.parseCredentials();
45
+ if (!creds) {
46
+ throw new Error('Asana credentials are required');
47
+ }
48
+ const response = await fetch(`${ASANA_API_BASE}/users/me`, {
49
+ headers: {
50
+ Authorization: `Bearer ${creds.accessToken}`,
51
+ Accept: 'application/json',
52
+ },
53
+ });
54
+ if (!response.ok) {
55
+ const text = await response.text();
56
+ throw new Error(`Asana API error (${response.status}): ${text}`);
57
+ }
58
+ return true;
59
+ }
60
+ parseCredentials() {
61
+ const { credentials } = this.params;
62
+ if (!credentials || typeof credentials !== 'object') {
63
+ return null;
64
+ }
65
+ const raw = credentials[CredentialType.ASANA_CRED];
66
+ if (!raw) {
67
+ return null;
68
+ }
69
+ try {
70
+ const parsed = decodeCredentialPayload(raw);
71
+ if (parsed.accessToken) {
72
+ return {
73
+ accessToken: parsed.accessToken,
74
+ workspaceId: parsed.workspaceId || '',
75
+ };
76
+ }
77
+ }
78
+ catch {
79
+ // If decoding fails, treat the raw value as an access token (validator path)
80
+ }
81
+ return { accessToken: raw, workspaceId: '' };
82
+ }
83
+ chooseCredential() {
84
+ const creds = this.parseCredentials();
85
+ return creds?.accessToken;
86
+ }
87
+ /** Resolve workspace GID from params or credential metadata. */
88
+ getWorkspaceId(paramsWorkspace) {
89
+ if (paramsWorkspace)
90
+ return paramsWorkspace;
91
+ const creds = this.parseCredentials();
92
+ if (creds?.workspaceId)
93
+ return creds.workspaceId;
94
+ throw new Error('Workspace GID is required. Provide it in the workspace parameter or ensure your Asana credential has workspace metadata.');
95
+ }
96
+ // ─── API Request Helper ─────────────────────────────────────────────
97
+ async asanaRequest(endpoint, method = 'GET', body) {
98
+ const creds = this.parseCredentials();
99
+ if (!creds) {
100
+ throw new Error('Asana credentials are required');
101
+ }
102
+ const url = `${ASANA_API_BASE}${endpoint}`;
103
+ const init = {
104
+ method,
105
+ headers: {
106
+ Authorization: `Bearer ${creds.accessToken}`,
107
+ 'Content-Type': 'application/json',
108
+ Accept: 'application/json',
109
+ },
110
+ };
111
+ if (body && method !== 'GET') {
112
+ init.body = JSON.stringify(body);
113
+ }
114
+ const response = await fetch(url, init);
115
+ if (!response.ok) {
116
+ const errorText = await response.text();
117
+ let message = `Asana API error (${response.status})`;
118
+ try {
119
+ const errorJson = JSON.parse(errorText);
120
+ if (errorJson.errors?.[0]?.message) {
121
+ message += `: ${errorJson.errors[0].message}`;
122
+ }
123
+ else {
124
+ message += `: ${errorText}`;
125
+ }
126
+ }
127
+ catch {
128
+ message += `: ${errorText}`;
129
+ }
130
+ throw new Error(message);
131
+ }
132
+ if (response.status === 204) {
133
+ return undefined;
134
+ }
135
+ return await response.json();
136
+ }
137
+ /** Build opt_fields query param string. */
138
+ buildOptFields(opt_fields) {
139
+ if (!opt_fields || opt_fields.length === 0)
140
+ return '';
141
+ return `opt_fields=${opt_fields.join(',')}`;
142
+ }
143
+ /** Build query string from params object, omitting undefined/empty values. */
144
+ buildQuery(params) {
145
+ const parts = [];
146
+ for (const [key, value] of Object.entries(params)) {
147
+ if (value !== undefined && value !== '') {
148
+ parts.push(`${key}=${encodeURIComponent(String(value))}`);
149
+ }
150
+ }
151
+ return parts.length > 0 ? `?${parts.join('&')}` : '';
152
+ }
153
+ // ─── Action Dispatcher ──────────────────────────────────────────────
154
+ async performAction(context) {
155
+ void context;
156
+ const { operation } = this.params;
157
+ try {
158
+ const result = await (async () => {
159
+ const p = this.params;
160
+ switch (operation) {
161
+ // Tasks
162
+ case 'list_tasks':
163
+ return await this.listTasks(p);
164
+ case 'get_task':
165
+ return await this.getTask(p);
166
+ case 'create_task':
167
+ return await this.createTask(p);
168
+ case 'update_task':
169
+ return await this.updateTask(p);
170
+ case 'delete_task':
171
+ return await this.deleteTask(p);
172
+ case 'search_tasks':
173
+ return await this.searchTasks(p);
174
+ case 'add_task_to_section':
175
+ return await this.addTaskToSection(p);
176
+ case 'set_dependencies':
177
+ return await this.setDependencies(p);
178
+ // Projects
179
+ case 'list_projects':
180
+ return await this.listProjects(p);
181
+ case 'get_project':
182
+ return await this.getProject(p);
183
+ case 'create_project':
184
+ return await this.createProject(p);
185
+ case 'update_project':
186
+ return await this.updateProject(p);
187
+ case 'list_sections':
188
+ return await this.listSections(p);
189
+ case 'create_section':
190
+ return await this.createSection(p);
191
+ // Comments / Stories
192
+ case 'add_comment':
193
+ return await this.addComment(p);
194
+ case 'get_task_stories':
195
+ return await this.getTaskStories(p);
196
+ // Users & Teams
197
+ case 'list_users':
198
+ return await this.listUsers(p);
199
+ case 'get_user':
200
+ return await this.getUser(p);
201
+ case 'list_teams':
202
+ return await this.listTeams(p);
203
+ case 'list_team_members':
204
+ return await this.listTeamMembers(p);
205
+ // Tags
206
+ case 'list_tags':
207
+ return await this.listTags(p);
208
+ case 'create_tag':
209
+ return await this.createTag(p);
210
+ case 'add_tag_to_task':
211
+ return await this.addTagToTask(p);
212
+ case 'remove_tag_from_task':
213
+ return await this.removeTagFromTask(p);
214
+ // Workspaces
215
+ case 'list_workspaces':
216
+ return await this.listWorkspaces(p);
217
+ // Custom Fields
218
+ case 'list_custom_fields':
219
+ return await this.listCustomFields(p);
220
+ // Attachments
221
+ case 'list_attachments':
222
+ return await this.listAttachments(p);
223
+ // Subtasks
224
+ case 'list_subtasks':
225
+ return await this.listSubtasks(p);
226
+ // Task-Project Membership
227
+ case 'add_task_to_project':
228
+ return await this.addTaskToProject(p);
229
+ case 'remove_task_from_project':
230
+ return await this.removeTaskFromProject(p);
231
+ // Section Management
232
+ case 'update_section':
233
+ return await this.updateSection(p);
234
+ case 'delete_section':
235
+ return await this.deleteSection(p);
236
+ // Project Deletion
237
+ case 'delete_project':
238
+ return await this.deleteProject(p);
239
+ default:
240
+ throw new Error(`Unsupported operation: ${operation}`);
241
+ }
242
+ })();
243
+ return result;
244
+ }
245
+ catch (error) {
246
+ return {
247
+ operation,
248
+ success: false,
249
+ error: error instanceof Error ? error.message : 'Unknown error occurred',
250
+ };
251
+ }
252
+ }
253
+ // ─── Task Operations ────────────────────────────────────────────────
254
+ async listTasks(params) {
255
+ const queryParams = {
256
+ limit: params.limit,
257
+ completed_since: params.completed_since,
258
+ modified_since: params.modified_since,
259
+ };
260
+ if (params.opt_fields?.length) {
261
+ queryParams.opt_fields = params.opt_fields.join(',');
262
+ }
263
+ if (params.section) {
264
+ queryParams.section = params.section;
265
+ }
266
+ else if (params.project) {
267
+ queryParams.project = params.project;
268
+ }
269
+ else if (params.assignee) {
270
+ queryParams.assignee = params.assignee;
271
+ queryParams.workspace = this.getWorkspaceId(params.workspace);
272
+ }
273
+ else {
274
+ throw new Error('At least one of project, section, or assignee must be provided');
275
+ }
276
+ const qs = this.buildQuery(queryParams);
277
+ const data = (await this.asanaRequest(`/tasks${qs}`));
278
+ return {
279
+ operation: 'list_tasks',
280
+ success: true,
281
+ tasks: data.data,
282
+ error: '',
283
+ };
284
+ }
285
+ async getTask(params) {
286
+ const optFields = this.buildOptFields(params.opt_fields);
287
+ const qs = optFields ? `?${optFields}` : '';
288
+ const data = (await this.asanaRequest(`/tasks/${params.task_gid}${qs}`));
289
+ return {
290
+ operation: 'get_task',
291
+ success: true,
292
+ task: data.data,
293
+ error: '',
294
+ };
295
+ }
296
+ async createTask(params) {
297
+ const body = { name: params.name };
298
+ if (params.notes)
299
+ body.notes = params.notes;
300
+ if (params.html_notes)
301
+ body.html_notes = params.html_notes;
302
+ if (params.assignee)
303
+ body.assignee = params.assignee;
304
+ if (params.due_on)
305
+ body.due_on = params.due_on;
306
+ if (params.due_at)
307
+ body.due_at = params.due_at;
308
+ if (params.start_on)
309
+ body.start_on = params.start_on;
310
+ if (params.projects)
311
+ body.projects = params.projects;
312
+ if (params.memberships)
313
+ body.memberships = params.memberships;
314
+ if (params.tags)
315
+ body.tags = params.tags;
316
+ if (params.parent)
317
+ body.parent = params.parent;
318
+ if (params.custom_fields)
319
+ body.custom_fields = params.custom_fields;
320
+ // If no project or parent specified, workspace is required
321
+ if (!params.projects?.length &&
322
+ !params.parent &&
323
+ !params.memberships?.length) {
324
+ body.workspace = this.getWorkspaceId(params.workspace);
325
+ }
326
+ const data = (await this.asanaRequest('/tasks', 'POST', {
327
+ data: body,
328
+ }));
329
+ return {
330
+ operation: 'create_task',
331
+ success: true,
332
+ task: data.data,
333
+ error: '',
334
+ };
335
+ }
336
+ async updateTask(params) {
337
+ const body = {};
338
+ if (params.name !== undefined)
339
+ body.name = params.name;
340
+ if (params.notes !== undefined)
341
+ body.notes = params.notes;
342
+ if (params.html_notes !== undefined)
343
+ body.html_notes = params.html_notes;
344
+ if (params.assignee !== undefined)
345
+ body.assignee = params.assignee;
346
+ if (params.due_on !== undefined)
347
+ body.due_on = params.due_on;
348
+ if (params.due_at !== undefined)
349
+ body.due_at = params.due_at;
350
+ if (params.start_on !== undefined)
351
+ body.start_on = params.start_on;
352
+ if (params.completed !== undefined)
353
+ body.completed = params.completed;
354
+ if (params.custom_fields !== undefined)
355
+ body.custom_fields = params.custom_fields;
356
+ const data = (await this.asanaRequest(`/tasks/${params.task_gid}`, 'PUT', {
357
+ data: body,
358
+ }));
359
+ return {
360
+ operation: 'update_task',
361
+ success: true,
362
+ task: data.data,
363
+ error: '',
364
+ };
365
+ }
366
+ async deleteTask(params) {
367
+ await this.asanaRequest(`/tasks/${params.task_gid}`, 'DELETE');
368
+ return {
369
+ operation: 'delete_task',
370
+ success: true,
371
+ error: '',
372
+ };
373
+ }
374
+ async searchTasks(params) {
375
+ const workspaceId = this.getWorkspaceId(params.workspace);
376
+ const queryParams = {
377
+ limit: params.limit,
378
+ sort_by: params.sort_by,
379
+ sort_ascending: params.sort_ascending,
380
+ };
381
+ if (params.text)
382
+ queryParams['text'] = params.text;
383
+ if (params.assignee)
384
+ queryParams['assignee.any'] = params.assignee;
385
+ if (params.projects?.length)
386
+ queryParams['projects.any'] = params.projects.join(',');
387
+ if (params.completed !== undefined)
388
+ queryParams['completed'] = params.completed;
389
+ if (params.is_subtask !== undefined)
390
+ queryParams['is_subtask'] = params.is_subtask;
391
+ if (params.opt_fields?.length)
392
+ queryParams['opt_fields'] = params.opt_fields.join(',');
393
+ const qs = this.buildQuery(queryParams);
394
+ const data = (await this.asanaRequest(`/workspaces/${workspaceId}/tasks/search${qs}`));
395
+ return {
396
+ operation: 'search_tasks',
397
+ success: true,
398
+ tasks: data.data,
399
+ error: '',
400
+ };
401
+ }
402
+ async addTaskToSection(params) {
403
+ const body = { task: params.task_gid };
404
+ if (params.insert_before)
405
+ body.insert_before = params.insert_before;
406
+ if (params.insert_after)
407
+ body.insert_after = params.insert_after;
408
+ await this.asanaRequest(`/sections/${params.section_gid}/addTask`, 'POST', {
409
+ data: body,
410
+ });
411
+ return {
412
+ operation: 'add_task_to_section',
413
+ success: true,
414
+ error: '',
415
+ };
416
+ }
417
+ async setDependencies(params) {
418
+ await this.asanaRequest(`/tasks/${params.task_gid}/addDependencies`, 'POST', { data: { dependencies: params.dependencies } });
419
+ return {
420
+ operation: 'set_dependencies',
421
+ success: true,
422
+ error: '',
423
+ };
424
+ }
425
+ // ─── Project Operations ─────────────────────────────────────────────
426
+ async listProjects(params) {
427
+ const queryParams = {
428
+ limit: params.limit,
429
+ archived: params.archived,
430
+ };
431
+ if (params.team) {
432
+ queryParams.team = params.team;
433
+ }
434
+ else {
435
+ queryParams.workspace = this.getWorkspaceId(params.workspace);
436
+ }
437
+ if (params.opt_fields?.length)
438
+ queryParams.opt_fields = params.opt_fields.join(',');
439
+ const qs = this.buildQuery(queryParams);
440
+ const data = (await this.asanaRequest(`/projects${qs}`));
441
+ return {
442
+ operation: 'list_projects',
443
+ success: true,
444
+ projects: data.data,
445
+ error: '',
446
+ };
447
+ }
448
+ async getProject(params) {
449
+ const optFields = this.buildOptFields(params.opt_fields);
450
+ const qs = optFields ? `?${optFields}` : '';
451
+ const data = (await this.asanaRequest(`/projects/${params.project_gid}${qs}`));
452
+ return {
453
+ operation: 'get_project',
454
+ success: true,
455
+ project: data.data,
456
+ error: '',
457
+ };
458
+ }
459
+ async createProject(params) {
460
+ const body = {
461
+ name: params.name,
462
+ workspace: this.getWorkspaceId(params.workspace),
463
+ };
464
+ if (params.notes)
465
+ body.notes = params.notes;
466
+ if (params.team)
467
+ body.team = params.team;
468
+ if (params.color)
469
+ body.color = params.color;
470
+ if (params.layout)
471
+ body.default_view = params.layout;
472
+ if (params.is_template !== undefined)
473
+ body.is_template = params.is_template;
474
+ if (params.public !== undefined)
475
+ body.public = params.public;
476
+ const data = (await this.asanaRequest('/projects', 'POST', {
477
+ data: body,
478
+ }));
479
+ return {
480
+ operation: 'create_project',
481
+ success: true,
482
+ project: data.data,
483
+ error: '',
484
+ };
485
+ }
486
+ async updateProject(params) {
487
+ const body = {};
488
+ if (params.name !== undefined)
489
+ body.name = params.name;
490
+ if (params.notes !== undefined)
491
+ body.notes = params.notes;
492
+ if (params.color !== undefined)
493
+ body.color = params.color;
494
+ if (params.archived !== undefined)
495
+ body.archived = params.archived;
496
+ if (params.public !== undefined)
497
+ body.public = params.public;
498
+ if (params.due_on !== undefined)
499
+ body.due_on = params.due_on;
500
+ if (params.start_on !== undefined)
501
+ body.start_on = params.start_on;
502
+ const data = (await this.asanaRequest(`/projects/${params.project_gid}`, 'PUT', { data: body }));
503
+ return {
504
+ operation: 'update_project',
505
+ success: true,
506
+ project: data.data,
507
+ error: '',
508
+ };
509
+ }
510
+ async listSections(params) {
511
+ const queryParams = {
512
+ limit: params.limit,
513
+ };
514
+ if (params.opt_fields?.length)
515
+ queryParams.opt_fields = params.opt_fields.join(',');
516
+ const qs = this.buildQuery(queryParams);
517
+ const data = (await this.asanaRequest(`/projects/${params.project_gid}/sections${qs}`));
518
+ return {
519
+ operation: 'list_sections',
520
+ success: true,
521
+ sections: data.data,
522
+ error: '',
523
+ };
524
+ }
525
+ async createSection(params) {
526
+ const body = { name: params.name };
527
+ if (params.insert_before)
528
+ body.insert_before = params.insert_before;
529
+ if (params.insert_after)
530
+ body.insert_after = params.insert_after;
531
+ const data = (await this.asanaRequest(`/projects/${params.project_gid}/sections`, 'POST', { data: body }));
532
+ return {
533
+ operation: 'create_section',
534
+ success: true,
535
+ section: data.data,
536
+ error: '',
537
+ };
538
+ }
539
+ // ─── Comment / Story Operations ─────────────────────────────────────
540
+ async addComment(params) {
541
+ const body = {};
542
+ if (params.html_text) {
543
+ body.html_text = params.html_text;
544
+ }
545
+ else if (params.text) {
546
+ body.text = params.text;
547
+ }
548
+ else {
549
+ throw new Error('Either text or html_text must be provided');
550
+ }
551
+ const data = (await this.asanaRequest(`/tasks/${params.task_gid}/stories`, 'POST', { data: body }));
552
+ return {
553
+ operation: 'add_comment',
554
+ success: true,
555
+ story: data.data,
556
+ error: '',
557
+ };
558
+ }
559
+ async getTaskStories(params) {
560
+ const queryParams = {
561
+ limit: params.limit,
562
+ };
563
+ if (params.opt_fields?.length)
564
+ queryParams.opt_fields = params.opt_fields.join(',');
565
+ const qs = this.buildQuery(queryParams);
566
+ const data = (await this.asanaRequest(`/tasks/${params.task_gid}/stories${qs}`));
567
+ return {
568
+ operation: 'get_task_stories',
569
+ success: true,
570
+ stories: data.data,
571
+ error: '',
572
+ };
573
+ }
574
+ // ─── User & Team Operations ─────────────────────────────────────────
575
+ async listUsers(params) {
576
+ const workspaceId = this.getWorkspaceId(params.workspace);
577
+ const queryParams = {
578
+ workspace: workspaceId,
579
+ limit: params.limit,
580
+ };
581
+ if (params.opt_fields?.length)
582
+ queryParams.opt_fields = params.opt_fields.join(',');
583
+ const qs = this.buildQuery(queryParams);
584
+ const data = (await this.asanaRequest(`/users${qs}`));
585
+ return {
586
+ operation: 'list_users',
587
+ success: true,
588
+ users: data.data,
589
+ error: '',
590
+ };
591
+ }
592
+ async getUser(params) {
593
+ const optFields = this.buildOptFields(params.opt_fields);
594
+ const qs = optFields ? `?${optFields}` : '';
595
+ const data = (await this.asanaRequest(`/users/${params.user_gid}${qs}`));
596
+ return {
597
+ operation: 'get_user',
598
+ success: true,
599
+ user: data.data,
600
+ error: '',
601
+ };
602
+ }
603
+ async listTeams(params) {
604
+ const workspaceId = this.getWorkspaceId(params.workspace);
605
+ const queryParams = {
606
+ limit: params.limit,
607
+ };
608
+ if (params.opt_fields?.length)
609
+ queryParams.opt_fields = params.opt_fields.join(',');
610
+ const qs = this.buildQuery(queryParams);
611
+ const data = (await this.asanaRequest(`/organizations/${workspaceId}/teams${qs}`));
612
+ return {
613
+ operation: 'list_teams',
614
+ success: true,
615
+ teams: data.data,
616
+ error: '',
617
+ };
618
+ }
619
+ async listTeamMembers(params) {
620
+ const queryParams = {
621
+ limit: params.limit,
622
+ };
623
+ if (params.opt_fields?.length)
624
+ queryParams.opt_fields = params.opt_fields.join(',');
625
+ const qs = this.buildQuery(queryParams);
626
+ const data = (await this.asanaRequest(`/teams/${params.team_gid}/users${qs}`));
627
+ return {
628
+ operation: 'list_team_members',
629
+ success: true,
630
+ users: data.data,
631
+ error: '',
632
+ };
633
+ }
634
+ // ─── Tag Operations ─────────────────────────────────────────────────
635
+ async listTags(params) {
636
+ const workspaceId = this.getWorkspaceId(params.workspace);
637
+ const queryParams = {
638
+ workspace: workspaceId,
639
+ limit: params.limit,
640
+ };
641
+ if (params.opt_fields?.length)
642
+ queryParams.opt_fields = params.opt_fields.join(',');
643
+ const qs = this.buildQuery(queryParams);
644
+ const data = (await this.asanaRequest(`/tags${qs}`));
645
+ return {
646
+ operation: 'list_tags',
647
+ success: true,
648
+ tags: data.data,
649
+ error: '',
650
+ };
651
+ }
652
+ async createTag(params) {
653
+ const body = {
654
+ name: params.name,
655
+ workspace: this.getWorkspaceId(params.workspace),
656
+ };
657
+ if (params.color)
658
+ body.color = params.color;
659
+ const data = (await this.asanaRequest('/tags', 'POST', {
660
+ data: body,
661
+ }));
662
+ return {
663
+ operation: 'create_tag',
664
+ success: true,
665
+ tag: data.data,
666
+ error: '',
667
+ };
668
+ }
669
+ async addTagToTask(params) {
670
+ await this.asanaRequest(`/tasks/${params.task_gid}/addTag`, 'POST', {
671
+ data: { tag: params.tag_gid },
672
+ });
673
+ return {
674
+ operation: 'add_tag_to_task',
675
+ success: true,
676
+ error: '',
677
+ };
678
+ }
679
+ async removeTagFromTask(params) {
680
+ await this.asanaRequest(`/tasks/${params.task_gid}/removeTag`, 'POST', {
681
+ data: { tag: params.tag_gid },
682
+ });
683
+ return {
684
+ operation: 'remove_tag_from_task',
685
+ success: true,
686
+ error: '',
687
+ };
688
+ }
689
+ // ─── Workspace Operations ──────────────────────────────────────────
690
+ async listWorkspaces(params) {
691
+ const queryParams = {
692
+ limit: params.limit,
693
+ };
694
+ if (params.opt_fields?.length)
695
+ queryParams.opt_fields = params.opt_fields.join(',');
696
+ const qs = this.buildQuery(queryParams);
697
+ const data = (await this.asanaRequest(`/workspaces${qs}`));
698
+ return {
699
+ operation: 'list_workspaces',
700
+ success: true,
701
+ workspaces: data.data,
702
+ error: '',
703
+ };
704
+ }
705
+ // ─── Custom Fields Operations ───────────────────────────────────────
706
+ async listCustomFields(params) {
707
+ const queryParams = {
708
+ limit: params.limit,
709
+ };
710
+ if (params.opt_fields?.length)
711
+ queryParams.opt_fields = params.opt_fields.join(',');
712
+ const qs = this.buildQuery(queryParams);
713
+ const data = (await this.asanaRequest(`/projects/${params.project_gid}/custom_field_settings${qs}`));
714
+ return {
715
+ operation: 'list_custom_fields',
716
+ success: true,
717
+ custom_fields: data.data,
718
+ error: '',
719
+ };
720
+ }
721
+ // ─── Attachment Operations ──────────────────────────────────────────
722
+ async listAttachments(params) {
723
+ const queryParams = {
724
+ parent: params.task_gid,
725
+ limit: params.limit,
726
+ };
727
+ if (params.opt_fields?.length)
728
+ queryParams.opt_fields = params.opt_fields.join(',');
729
+ const qs = this.buildQuery(queryParams);
730
+ const data = (await this.asanaRequest(`/attachments${qs}`));
731
+ return {
732
+ operation: 'list_attachments',
733
+ success: true,
734
+ attachments: data.data,
735
+ error: '',
736
+ };
737
+ }
738
+ // ─── Subtask Operations ─────────────────────────────────────────────
739
+ async listSubtasks(params) {
740
+ const queryParams = {
741
+ limit: params.limit,
742
+ };
743
+ if (params.opt_fields?.length)
744
+ queryParams.opt_fields = params.opt_fields.join(',');
745
+ const qs = this.buildQuery(queryParams);
746
+ const data = (await this.asanaRequest(`/tasks/${params.task_gid}/subtasks${qs}`));
747
+ return {
748
+ operation: 'list_subtasks',
749
+ success: true,
750
+ tasks: data.data,
751
+ error: '',
752
+ };
753
+ }
754
+ // ─── Task-Project Membership Operations ─────────────────────────────
755
+ async addTaskToProject(params) {
756
+ const body = { project: params.project_gid };
757
+ if (params.section_gid)
758
+ body.section = params.section_gid;
759
+ await this.asanaRequest(`/tasks/${params.task_gid}/addProject`, 'POST', {
760
+ data: body,
761
+ });
762
+ return {
763
+ operation: 'add_task_to_project',
764
+ success: true,
765
+ error: '',
766
+ };
767
+ }
768
+ async removeTaskFromProject(params) {
769
+ await this.asanaRequest(`/tasks/${params.task_gid}/removeProject`, 'POST', {
770
+ data: { project: params.project_gid },
771
+ });
772
+ return {
773
+ operation: 'remove_task_from_project',
774
+ success: true,
775
+ error: '',
776
+ };
777
+ }
778
+ // ─── Section Management Operations ──────────────────────────────────
779
+ async updateSection(params) {
780
+ const body = {};
781
+ if (params.name !== undefined)
782
+ body.name = params.name;
783
+ const data = (await this.asanaRequest(`/sections/${params.section_gid}`, 'PUT', { data: body }));
784
+ return {
785
+ operation: 'update_section',
786
+ success: true,
787
+ section: data.data,
788
+ error: '',
789
+ };
790
+ }
791
+ async deleteSection(params) {
792
+ await this.asanaRequest(`/sections/${params.section_gid}`, 'DELETE');
793
+ return {
794
+ operation: 'delete_section',
795
+ success: true,
796
+ error: '',
797
+ };
798
+ }
799
+ // ─── Project Deletion ───────────────────────────────────────────────
800
+ async deleteProject(params) {
801
+ await this.asanaRequest(`/projects/${params.project_gid}`, 'DELETE');
802
+ return {
803
+ operation: 'delete_project',
804
+ success: true,
805
+ error: '',
806
+ };
807
+ }
808
+ }
809
+ //# sourceMappingURL=asana.js.map