|
1 | | -import { BaseService } from '../base'; |
2 | | -import { |
3 | | - TaskCreateOptions, |
| 1 | +import { ValidationError } from '../../core/errors'; |
| 2 | +import { track } from '../../core/telemetry'; |
| 3 | +import { DEFAULT_TASK_EXPAND, TaskMap, TaskStatusMap } from '../../models/action-center/tasks.constants'; |
| 4 | +import { TASK_TYPE_ENDPOINTS, TaskAssignmentResponseCollection, TaskGetFormOptions, TasksAssignOptions } from '../../models/action-center/tasks.internal-types'; |
| 5 | +import { |
| 6 | + TaskCreateResponse, |
| 7 | + TaskGetResponse, |
| 8 | + TaskServiceModel, |
| 9 | + createTaskWithMethods |
| 10 | +} from '../../models/action-center/tasks.models'; |
| 11 | +import { |
4 | 12 | TaskAssignmentOptions, |
5 | 13 | TaskAssignmentResponse, |
6 | | - TasksUnassignOptions, |
7 | 14 | TaskCompletionOptions, |
8 | | - TaskType, |
| 15 | + TaskCreateOptions, |
9 | 16 | TaskGetAllOptions, |
10 | 17 | TaskGetByIdOptions, |
11 | | - UserLoginInfo, |
12 | 18 | TaskGetUsersOptions, |
| 19 | + TaskType, |
| 20 | + TasksUnassignOptions, |
| 21 | + UserLoginInfo, |
13 | 22 | } from '../../models/action-center/tasks.types'; |
14 | | -import { |
15 | | - TaskServiceModel, |
16 | | - TaskGetResponse, |
17 | | - TaskCreateResponse, |
18 | | - createTaskWithMethods |
19 | | -} from '../../models/action-center/tasks.models'; |
20 | | -import { OperationResponse } from '../../models/common/types'; |
21 | | -import { pascalToCamelCaseKeys, camelToPascalCaseKeys, transformData, applyDataTransforms, addPrefixToKeys } from '../../utils/transform'; |
22 | | -import { TaskStatusMap, TaskMap, DEFAULT_TASK_EXPAND } from '../../models/action-center/tasks.constants'; |
23 | | -import { createHeaders } from '../../utils/http/headers'; |
24 | | -import { FOLDER_ID } from '../../utils/constants/headers'; |
| 23 | +import { BaseOptions, OperationResponse } from '../../models/common/types'; |
| 24 | +import { ODATA_OFFSET_PARAMS, ODATA_PAGINATION, ODATA_PREFIX } from '../../utils/constants/common'; |
25 | 25 | import { TASK_ENDPOINTS } from '../../utils/constants/endpoints'; |
26 | | -import { ODATA_PREFIX, ODATA_PAGINATION, ODATA_OFFSET_PARAMS } from '../../utils/constants/common'; |
27 | | -import { PaginatedResponse, NonPaginatedResponse, HasPaginationOptions } from '../../utils/pagination'; |
| 26 | +import { FOLDER_ID } from '../../utils/constants/headers'; |
| 27 | +import { createHeaders } from '../../utils/http/headers'; |
| 28 | +import { processODataArrayResponse } from '../../utils/object'; |
| 29 | +import { HasPaginationOptions, NonPaginatedResponse, PaginatedResponse } from '../../utils/pagination'; |
28 | 30 | import { PaginationHelpers } from '../../utils/pagination/helpers'; |
29 | 31 | import { PaginationType } from '../../utils/pagination/internal-types'; |
30 | | -import { TaskAssignmentResponseCollection, TaskGetFormOptions, TasksAssignOptions } from '../../models/action-center/tasks.internal-types'; |
31 | | -import { track } from '../../core/telemetry'; |
32 | | -import { processODataArrayResponse } from '../../utils/object'; |
| 32 | +import { addPrefixToKeys, applyDataTransforms, camelToPascalCaseKeys, pascalToCamelCaseKeys, transformData } from '../../utils/transform'; |
| 33 | +import { BaseService } from '../base'; |
33 | 34 |
|
34 | 35 | /** |
35 | 36 | * Service for interacting with UiPath Tasks API |
@@ -234,52 +235,63 @@ export class TaskService extends BaseService implements TaskServiceModel { |
234 | 235 |
|
235 | 236 | /** |
236 | 237 | * Gets a task by ID |
237 | | - * IMPORTANT: For form tasks, folderId must be provided. |
238 | | - * |
239 | 238 | * @param id - The ID of the task to retrieve |
240 | | - * @param options - Optional query parameters |
241 | | - * @param folderId - Optional folder ID (REQUIRED for form tasks) |
242 | | - * @returns Promise resolving to the task (form tasks will return form-specific data) |
243 | | - * |
| 239 | + * @param options - Optional query parameters including taskType for faster retrieval {@link TaskGetByIdOptions} |
| 240 | + * @param folderId - Optional folder ID (REQUIRED when options.taskType is provided) |
| 241 | + * @returns Promise resolving to the task |
| 242 | + * {@link TaskGetResponse} |
244 | 243 | * @example |
245 | 244 | * ```typescript |
246 | | - * import { Tasks } from '@uipath/uipath-typescript/tasks'; |
| 245 | + * // Get a task by ID |
| 246 | + * const task = await tasks.getById(<taskId>); |
247 | 247 | * |
248 | | - * const tasks = new Tasks(sdk); |
| 248 | + * // Get a form task by ID |
| 249 | + * const formTask = await tasks.getById(<taskId>, {}, <folderId>); |
249 | 250 | * |
250 | | - * // Get task by ID |
251 | | - * const task = await tasks.getById(123); |
| 251 | + * // Access form task properties |
| 252 | + * console.log(formTask.formLayout); |
252 | 253 | * |
253 | | - * // If the task is a form task, it will automatically return form-specific data |
| 254 | + * // Get a document validation task by ID (faster with taskType provided in the options) |
| 255 | + * const dvTask = await tasks.getById(<taskId>, { taskType: TaskType.DocumentValidation }, <folderId>); |
254 | 256 | * ``` |
255 | 257 | */ |
256 | 258 | @track('Tasks.GetById') |
257 | 259 | async getById(id: number, options: TaskGetByIdOptions = {}, folderId?: number): Promise<TaskGetResponse> { |
| 260 | + const { taskType, ...restOptions } = options; |
| 261 | + |
| 262 | + // If taskType is provided, skip the generic GET_BY_ID call and go directly to the type-specific endpoint |
| 263 | + if (taskType && taskType in TASK_TYPE_ENDPOINTS) { |
| 264 | + if (!folderId) { |
| 265 | + throw new ValidationError({ message: 'folderId is required when taskType is provided' }); |
| 266 | + } |
| 267 | + return this.getByTaskType(id, folderId, taskType, restOptions); |
| 268 | + } |
| 269 | + |
258 | 270 | const headers = createHeaders({ [FOLDER_ID]: folderId }); |
259 | | - |
| 271 | + |
260 | 272 | // Add default expand parameters |
261 | | - const modifiedOptions = this.addDefaultExpand(options); |
262 | | - |
| 273 | + const modifiedOptions = this.addDefaultExpand(restOptions); |
| 274 | + |
263 | 275 | // prefix all keys in options |
264 | 276 | const keysToPrefix = Object.keys(modifiedOptions); |
265 | 277 | const apiOptions = addPrefixToKeys(modifiedOptions, ODATA_PREFIX, keysToPrefix); |
266 | 278 | const response = await this.get<TaskGetResponse>( |
267 | 279 | TASK_ENDPOINTS.GET_BY_ID(id), |
268 | | - { |
| 280 | + { |
269 | 281 | params: apiOptions, |
270 | 282 | headers |
271 | 283 | } |
272 | 284 | ); |
273 | | - |
| 285 | + |
274 | 286 | // Transform response from PascalCase to camelCase and normalize time fields |
275 | 287 | const transformedTask = transformData(pascalToCamelCaseKeys(response.data) as TaskGetResponse, TaskMap); |
276 | | - |
277 | | - // Check if this is a form task and get form-specific data if it is |
278 | | - if (transformedTask.type === TaskType.Form) { |
279 | | - const formOptions: TaskGetFormOptions = { expandOnFormLayout: true }; |
280 | | - return this.getFormTaskById(id, folderId || transformedTask.folderId, formOptions); |
| 288 | + |
| 289 | + // Get task type from response and fetch type-specific data |
| 290 | + const resolvedFolderId = folderId || transformedTask.folderId; |
| 291 | + if (transformedTask.type in TASK_TYPE_ENDPOINTS) { |
| 292 | + return this.getByTaskType(id, resolvedFolderId, transformedTask.type, restOptions); |
281 | 293 | } |
282 | | - |
| 294 | + |
283 | 295 | return createTaskWithMethods( |
284 | 296 | applyDataTransforms(transformedTask, { field: 'status', valueMap: TaskStatusMap }), |
285 | 297 | this |
@@ -506,29 +518,39 @@ export class TaskService extends BaseService implements TaskServiceModel { |
506 | 518 | } |
507 | 519 |
|
508 | 520 | /** |
509 | | - * Gets a form task by ID (private method) |
510 | | - * |
511 | | - * @param id - The ID of the form task to retrieve |
| 521 | + * Routes to the type-specific endpoint based on task type. |
| 522 | + */ |
| 523 | + private getByTaskType(id: number, folderId: number, taskType: TaskType, options: BaseOptions = {}): Promise<TaskGetResponse> { |
| 524 | + const endpoint = TASK_TYPE_ENDPOINTS[taskType]; |
| 525 | + const extraParams: TaskGetFormOptions = taskType === TaskType.Form ? { expandOnFormLayout: true, ...options } : options; |
| 526 | + return this.getTaskByTypeEndpoint(id, folderId, endpoint, extraParams); |
| 527 | + } |
| 528 | + |
| 529 | + /** |
| 530 | + * Fetches a task from a type-specific endpoint. |
| 531 | + * |
| 532 | + * @param id - The task ID |
512 | 533 | * @param folderId - Required folder ID |
513 | | - * @param options - Optional query parameters |
514 | | - * @returns Promise resolving to the form task |
| 534 | + * @param endpoint - The type-specific endpoint to call |
| 535 | + * @param extraParams - Additional query parameters (e.g. form options) |
| 536 | + * @returns Promise resolving to the task |
515 | 537 | */ |
516 | | - private async getFormTaskById(id: number, folderId: number, options: TaskGetFormOptions = {}): Promise<TaskGetResponse> { |
| 538 | + private async getTaskByTypeEndpoint(id: number, folderId: number, endpoint: string, extraParams: TaskGetFormOptions = {}): Promise<TaskGetResponse> { |
517 | 539 | const headers = createHeaders({ [FOLDER_ID]: folderId }); |
518 | | - |
| 540 | + |
519 | 541 | const response = await this.get<TaskGetResponse>( |
520 | | - TASK_ENDPOINTS.GET_TASK_FORM_BY_ID, |
521 | | - { |
| 542 | + endpoint, |
| 543 | + { |
522 | 544 | params: { |
523 | 545 | taskId: id, |
524 | | - ...options |
| 546 | + ...extraParams |
525 | 547 | }, |
526 | 548 | headers |
527 | 549 | } |
528 | 550 | ); |
529 | | - const transformedFormTask = transformData(response.data, TaskMap); |
| 551 | + const transformedTask = transformData(response.data, TaskMap); |
530 | 552 | return createTaskWithMethods( |
531 | | - applyDataTransforms(transformedFormTask, { field: 'status', valueMap: TaskStatusMap }), |
| 553 | + applyDataTransforms(transformedTask, { field: 'status', valueMap: TaskStatusMap }), |
532 | 554 | this |
533 | 555 | ) as TaskGetResponse; |
534 | 556 | } |
|
0 commit comments