@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.
- package/dist/bubble-bundle.d.ts +148 -31
- package/dist/bubble-factory.d.ts.map +1 -1
- package/dist/bubble-factory.js +9 -0
- package/dist/bubble-factory.js.map +1 -1
- package/dist/bubbles/service-bubble/ai-agent.d.ts.map +1 -1
- package/dist/bubbles/service-bubble/ai-agent.js +9 -2
- package/dist/bubbles/service-bubble/ai-agent.js.map +1 -1
- package/dist/bubbles/service-bubble/asana/asana.d.ts +1232 -0
- package/dist/bubbles/service-bubble/asana/asana.d.ts.map +1 -0
- package/dist/bubbles/service-bubble/asana/asana.js +809 -0
- package/dist/bubbles/service-bubble/asana/asana.js.map +1 -0
- package/dist/bubbles/service-bubble/asana/asana.schema.d.ts +1169 -0
- package/dist/bubbles/service-bubble/asana/asana.schema.d.ts.map +1 -0
- package/dist/bubbles/service-bubble/asana/asana.schema.js +740 -0
- package/dist/bubbles/service-bubble/asana/asana.schema.js.map +1 -0
- package/dist/bubbles/service-bubble/asana/index.d.ts +3 -0
- package/dist/bubbles/service-bubble/asana/index.d.ts.map +1 -0
- package/dist/bubbles/service-bubble/asana/index.js +3 -0
- package/dist/bubbles/service-bubble/asana/index.js.map +1 -0
- package/dist/bubbles/service-bubble/confluence/confluence.d.ts +2 -2
- package/dist/bubbles/service-bubble/confluence/confluence.schema.d.ts +2 -2
- package/dist/bubbles/service-bubble/discord/discord.d.ts +778 -0
- package/dist/bubbles/service-bubble/discord/discord.d.ts.map +1 -0
- package/dist/bubbles/service-bubble/discord/discord.js +370 -0
- package/dist/bubbles/service-bubble/discord/discord.js.map +1 -0
- package/dist/bubbles/service-bubble/discord/discord.schema.d.ts +739 -0
- package/dist/bubbles/service-bubble/discord/discord.schema.d.ts.map +1 -0
- package/dist/bubbles/service-bubble/discord/discord.schema.js +352 -0
- package/dist/bubbles/service-bubble/discord/discord.schema.js.map +1 -0
- package/dist/bubbles/service-bubble/discord/index.d.ts +3 -0
- package/dist/bubbles/service-bubble/discord/index.d.ts.map +1 -0
- package/dist/bubbles/service-bubble/discord/index.js +3 -0
- package/dist/bubbles/service-bubble/discord/index.js.map +1 -0
- package/dist/bubbles/service-bubble/salesforce/index.d.ts +3 -0
- package/dist/bubbles/service-bubble/salesforce/index.d.ts.map +1 -0
- package/dist/bubbles/service-bubble/salesforce/index.js +3 -0
- package/dist/bubbles/service-bubble/salesforce/index.js.map +1 -0
- package/dist/bubbles/service-bubble/salesforce/salesforce.d.ts +209 -0
- package/dist/bubbles/service-bubble/salesforce/salesforce.d.ts.map +1 -0
- package/dist/bubbles/service-bubble/salesforce/salesforce.js +221 -0
- package/dist/bubbles/service-bubble/salesforce/salesforce.js.map +1 -0
- package/dist/bubbles/service-bubble/salesforce/salesforce.schema.d.ts +179 -0
- package/dist/bubbles/service-bubble/salesforce/salesforce.schema.d.ts.map +1 -0
- package/dist/bubbles/service-bubble/salesforce/salesforce.schema.js +127 -0
- package/dist/bubbles/service-bubble/salesforce/salesforce.schema.js.map +1 -0
- package/dist/bubbles/service-bubble/snowflake/snowflake.d.ts.map +1 -1
- package/dist/bubbles/service-bubble/snowflake/snowflake.js +1 -1
- package/dist/bubbles/service-bubble/snowflake/snowflake.js.map +1 -1
- package/dist/bubbles.json +3945 -4
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- 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
|