Skip to main content
Glama

Activepieces MCP Server

by eldoonreval
todo.service.tsβ€’7.59 kB
import { ActivepiecesError, apId, assertNotNullOrUndefined, Cursor, ErrorCode, FlowId, isNil, PlatformId, ProjectId, SeekPage, spreadIfDefined, StatusOption, Todo, TodoWithAssignee, UNRESOLVED_STATUS, UserId } from '@activepieces/shared' import { FastifyBaseLogger } from 'fastify' import { IsNull, Like, Not } from 'typeorm' import { repoFactory } from '../core/db/repo-factory' import { buildPaginator } from '../helper/pagination/build-paginator' import { paginationHelper } from '../helper/pagination/pagination-utils' import { Order } from '../helper/pagination/paginator' import { userService } from '../user/user-service' import { TodoEntity } from './todo.entity' const repo = repoFactory(TodoEntity) export const todoService = (_log: FastifyBaseLogger) => ({ async create(params: CreateParams): Promise<Todo> { return repo().save({ id: apId(), status: UNRESOLVED_STATUS, ...params, }) }, async getOne(params: GetParams): Promise<Todo | null> { return repo().findOneBy({ id: params.id, ...spreadIfDefined('platformId', params.platformId), ...spreadIfDefined('projectId', params.projectId) }) }, async getOneOrThrow(params: GetParams): Promise<Todo> { const todo = await this.getOne(params) if (isNil(todo)) { throw new ActivepiecesError({ code: ErrorCode.ENTITY_NOT_FOUND, params: { entityType: 'todo', entityId: params.id, message: 'Todo by id not found' }, }) } return todo }, async getOnePopulatedOrThrow(params: GetParams): Promise<TodoWithAssignee> { const todo = await this.getOne(params) if (!todo) { throw new ActivepiecesError({ code: ErrorCode.ENTITY_NOT_FOUND, params: { entityType: 'todo', entityId: params.id, message: 'Todo by id not found' }, }) } const enrichedTask = await enrichTodoWithAssignee(todo) return enrichedTask }, async update(params: UpdateParams): Promise<Todo | null> { const todo = await this.getOneOrThrow(params) if (params.status && todo.resolveUrl && params.status.continueFlow !== false) { await sendResolveRequest(todo.resolveUrl, params.status) } await repo().update({ id: params.id, platformId: params.platformId, projectId: params.projectId, }, { ...spreadIfDefined('title', params.title), ...spreadIfDefined('description', params.description), ...spreadIfDefined('status', params.status), ...spreadIfDefined('statusOptions', params.statusOptions), ...spreadIfDefined('assigneeId', params.assigneeId), ...(params.status && params.status.continueFlow !== false && !params.isTest ? { resolveUrl: null } : {}), }) return this.getOneOrThrow(params) }, async resolve(params: ResolveParams) { const todo = await this.getOneOrThrow({ id: params.id }) assertNotNullOrUndefined(todo.resolveUrl, 'Todo does not have an resolve url') const status = todo.statusOptions.find((option) => option.name === params.status) if (isNil(status)) { throw new ActivepiecesError({ code: ErrorCode.VALIDATION, params: { message: 'Status not found' }, }) } if (status.continueFlow === false) { throw new ActivepiecesError({ code: ErrorCode.VALIDATION, params: { message: `Todo cannot be resolved because the continueFlow is set to false for the status: ${status.name}` }, }) } await sendResolveRequest(todo.resolveUrl, status) await this.update({ id: params.id, platformId: todo.platformId, projectId: todo.projectId, status, isTest: params.isTest, }) return { status: params.status, } }, async list(params: ListParams): Promise<SeekPage<TodoWithAssignee>> { const decodedCursor = paginationHelper.decodeCursor(params.cursor) const paginator = buildPaginator<Todo>({ entity: TodoEntity, query: { limit: params.limit, order: Order.DESC, orderBy: 'created', afterCursor: decodedCursor.nextCursor, beforeCursor: decodedCursor.previousCursor, }, }) let query = repo().createQueryBuilder('todo').where({ platformId: params.platformId, projectId: params.projectId, ...spreadIfDefined('flowId', params.flowId), }) if (params.assigneeId) { query = query.andWhere({ assigneeId: params.assigneeId, }) } if (params.statusOptions) { if (params.statusOptions[0] === UNRESOLVED_STATUS.name) { query = query.andWhere('(status->>\'name\' = :statusName OR status->>\'continueFlow\' = :continueFlow)', { statusName: UNRESOLVED_STATUS.name, continueFlow: 'false', }) } else { query = query.andWhere('status->>\'name\' != :statusName AND (status->>\'continueFlow\' IS NULL OR status->>\'continueFlow\' != :continueFlow)', { statusName: UNRESOLVED_STATUS.name, continueFlow: 'false', }) } } if (params.title) { query = query.andWhere({ title: Like(`%${params.title}%`), }) } // To avoid fetching tasks for testing purposes query = query.andWhere({ runId: Not(IsNull()), }) const { data, cursor: newCursor } = await paginator.paginate(query) const enrichedData = await Promise.all(data.map((task) => enrichTodoWithAssignee(task))) return paginationHelper.createPage<TodoWithAssignee>(enrichedData, newCursor) }, }) async function sendResolveRequest(resolveUrl: string, status: StatusOption) { const url = new URL(resolveUrl) url.searchParams.append('status', status.name) await fetch(url.toString(), { method: 'POST', }) } async function enrichTodoWithAssignee( todo: Todo, ): Promise<TodoWithAssignee> { if (isNil(todo.assigneeId)) { return { ...todo, assignee: null, } } const assignee = await userService.getMetaInformation({ id: todo.assigneeId, }) return { ...todo, assignee, } } type ResolveParams = { id: string status: string isTest?: boolean } type GetParams = { id: string platformId?: PlatformId projectId?: ProjectId } type ListParams = { platformId: PlatformId projectId: ProjectId flowId?: FlowId assigneeId?: UserId limit: number cursor: Cursor | null statusOptions?: string[] title?: string } type CreateParams = { title: string description?: string statusOptions: StatusOption[] platformId: string projectId: string flowId: string runId?: string assigneeId?: string resolveUrl?: string } type UpdateParams = { id: string platformId: string projectId: string title?: string description?: string status?: StatusOption statusOptions?: StatusOption[] assigneeId?: string isTest?: boolean }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/eldoonreval/activepieces'

If you have feedback or need assistance with the MCP directory API, please join our Discord server