UNPKG

@pipedream/linear_app

Version:

Pipedream Linear_app Components

445 lines (440 loc) 11.3 kB
import { LinearClient } from "@linear/sdk"; import constants from "./common/constants.mjs"; import utils from "./common/utils.mjs"; import { axios } from "@pipedream/platform"; import queries from "./common/queries.mjs"; export default { type: "app", app: "linear_app", propDefinitions: { teamId: { type: "string", label: "Team", description: "The identifier or key of the team associated with the issue", async options({ prevContext }) { return this.listResourcesOptions({ prevContext, resourcesFn: this.listTeams, resouceMapper: ({ id, name, }) => ({ label: name, value: id, }), }); }, }, issueId: { type: "string", label: "Issue", description: "The issue to update", async options({ teamId, prevContext, }) { return this.listResourcesOptions({ prevContext, resourcesFn: this.listIssues, resourcesArgs: teamId && { filter: { team: { id: { eq: teamId, }, }, }, }, resouceMapper: ({ id, title, }) => ({ label: title, value: id, }), }); }, }, projectId: { type: "string", label: "Project", description: "The identifier or key of the project associated with the issue", optional: true, async options({ teamId, prevContext, }) { return this.listResourcesOptions({ prevContext, resourcesFn: this.listProjects, resouceMapper: ({ id, name, }) => ({ label: name, value: id, }), resourcesArgs: teamId && { filter: { accessibleTeams: { id: { eq: teamId, }, }, }, }, }); }, }, issueTitle: { type: "string", label: "Title", description: "The title of the issue.", }, assigneeId: { type: "string", label: "Assignee", description: "The user to assign to the issue", optional: true, async options({ prevContext }) { return this.listResourcesOptions({ prevContext, resourcesFn: this.listUsers, resouceMapper: ({ id, name, }) => ({ label: name, value: id, }), }); }, }, stateId: { type: "string", label: "State (Status)", description: "The state (status) to assign to the issue", optional: true, async options({ teamId, prevContext, }) { return this.listResourcesOptions({ prevContext, resourcesFn: this.listStates, resourcesArgs: teamId && { filter: { team: { id: { eq: teamId, }, }, }, }, resouceMapper: ({ id: value, name: label, }) => ({ label, value, }), }); }, }, boardOrder: { type: "string", label: "Board order", description: "The position of the issue in its column on the board view", optional: true, }, issueDescription: { type: "string", label: "Description", description: "The issue description in markdown format", optional: true, }, issueLabels: { type: "string[]", label: "Issue Labels", description: "The labels in the issue", optional: true, async options({ prevContext, byId = false, }) { return this.listResourcesOptions({ prevContext, resourcesFn: this.listIssueLabels, resouceMapper: ({ id, name, }) => byId ? ({ label: name, value: id, }) : name, }); }, }, projectStatusId: { type: "string", label: "Status ID", description: "The ID of the status of the project", optional: true, async options({ prevContext }) { return this.listResourcesOptions({ prevContext, resourcesFn: this.listProjectStatuses, resouceMapper: ({ id, name, }) => ({ label: name, value: id, }), }); }, }, projectLabelIds: { type: "string[]", label: "Label IDs", description: "The IDs of the labels for the project", optional: true, async options({ prevContext }) { return this.listResourcesOptions({ prevContext, resourcesFn: this.listProjectLabels, resouceMapper: ({ id, name, }) => ({ label: name, value: id, }), }); }, }, projectPriority: { type: "integer", label: "Priority", description: "The priority of the project", optional: true, options: constants.PRIORITY_OPTIONS, }, issuePriority: { type: "integer", label: "Priority", description: "The priority of the issue", optional: true, options: constants.PRIORITY_OPTIONS, }, query: { type: "string", label: "Query", description: "Search string to look for in issue titles. The query is used to filter issues where the title contains the query text (case insensitive).", optional: true, }, orderBy: { type: "string", label: "Order By", description: "By which field should the pagination order by. Available options are `createdAt` (default) and `updatedAt`.", optional: true, options: constants.ORDER_BY_OPTIONS, }, includeArchived: { type: "boolean", label: "Include archived", description: "Should archived resources be included? (default: `false`)", optional: true, }, limit: { type: "integer", label: "Limit", description: "Maximum number of issues to return. If no query is provided, this defaults to 20 to avoid returning too many results.", optional: true, }, }, methods: { getAxiosHeaders() { return { Authorization: `${this.$auth.api_key}`, }; }, makeAxiosRequest({ $ = this, ...args }) { return axios($, { url: "https://api.linear.app/graphql", headers: this.getAxiosHeaders(), ...args, }); }, post(args = {}) { return this.makeAxiosRequest({ method: "POST", ...args, }); }, getClientOptions(options = {}) { return { apiKey: this.$auth.api_key, ...options, }; }, client(options = {}) { return new LinearClient(this.getClientOptions(options)); }, async createWebhook(input) { return this.client().createWebhook(input); }, async deleteWebhook(id) { return this.client().deleteWebhook(id); }, async createIssue(input) { return this.client().createIssue(input); }, async updateIssue({ issueId, input, }) { return this.client().updateIssue(issueId, input); }, async listIssues(variables) { const { data: { issues } } = await this.post({ data: { query: queries.listIssues, variables, }, }); return issues; }, async getIssue(variables) { const { data: { issue } } = await this.post({ data: { query: queries.getIssue, variables, }, }); return issue; }, async getUser(id) { return this.client().user(id); }, async getProject(id) { return this.client().project(id); }, async getProjectUpdate(id) { return this.client().projectUpdate(id); }, async getProjectUpdateGraphQL(id) { const { data: { projectUpdate } } = await this.post({ data: { query: queries.getProjectUpdate, variables: { projectUpdateId: id, }, }, }); return projectUpdate; }, async getState(id) { return this.client().workflowState(id); }, async getTeam(id) { return this.client().team(id); }, async listTeams(variables = {}) { return this.client().teams(variables); }, async listProjects(variables) { const { data: { projects } } = await this.post({ data: { query: queries.listProjects, variables, }, }); return projects; }, async listProjectUpdates(variables) { const { data: { projectUpdates } } = await this.post({ data: { query: queries.listProjectUpdates, variables, }, }); return projectUpdates; }, async listUsers(variables = {}) { return this.client().users(variables); }, async listStates(variables = {}) { return this.client().workflowStates(variables); }, async listIssueLabels(variables = {}) { return this.client().issueLabels(variables); }, async listComments(variables = {}) { return this.client().comments(variables); }, async getComment(variables) { const { data: { comment } } = await this.post({ data: { query: queries.getComment, variables, }, }); return comment; }, async listProjectStatuses(variables = {}) { return this.client().projectStatuses(variables); }, async listProjectLabels(variables = {}) { return this.client().projectLabels(variables); }, async listResourcesOptions({ prevContext, resourcesFn, resourcesArgs, resouceMapper, } = {}) { const { after, hasNextPage, } = prevContext; if (hasNextPage === false) { return []; } const { nodes, pageInfo, } = await resourcesFn({ after, first: constants.DEFAULT_LIMIT, ...resourcesArgs, }); return { options: nodes.map(resouceMapper), context: { after: pageInfo?.endCursor, hasNextPage: pageInfo?.hasNextPage, }, }; }, async *paginateResources({ resourcesFn, resourcesFnArgs, max = constants.DEFAULT_MAX_RECORDS, useGraphQl = true, }) { let counter = 0; let hasNextPage; let endCursor; do { const variables = useGraphQl ? utils.buildVariables(endCursor, resourcesFnArgs) : { after: endCursor, first: constants.DEFAULT_LIMIT, ...resourcesFnArgs, }; const { nodes, pageInfo, } = await resourcesFn(variables); for (const node of nodes) { counter += 1; yield node; } ({ hasNextPage, endCursor, } = pageInfo); } while (hasNextPage && counter < max); }, }, };