kaneo (minimalist kanban) fork to experiment adding a tangled integration
github.com/usekaneo/kaneo
1import { and, eq } from "drizzle-orm";
2import db from "../../../database";
3import { externalLinkTable, taskTable } from "../../../database/schema";
4import { updateExternalLink } from "../services/link-manager";
5import {
6 findAllIntegrationsByRepo,
7 updateTaskStatus,
8} from "../services/task-service";
9import { resolveTargetStatus } from "../utils/resolve-column";
10
11type IssueClosedPayload = {
12 action: string;
13 issue: {
14 number: number;
15 title: string;
16 html_url: string;
17 state: string;
18 };
19 repository: {
20 owner: { login: string };
21 name: string;
22 full_name: string;
23 };
24};
25
26export async function handleIssueClosed(payload: IssueClosedPayload) {
27 const { issue, repository } = payload;
28
29 const integrations = await findAllIntegrationsByRepo(
30 repository.owner.login,
31 repository.name,
32 );
33
34 for (const integration of integrations) {
35 const externalLink = await db.query.externalLinkTable.findFirst({
36 where: and(
37 eq(externalLinkTable.integrationId, integration.id),
38 eq(externalLinkTable.resourceType, "issue"),
39 eq(externalLinkTable.externalId, issue.number.toString()),
40 ),
41 });
42
43 if (!externalLink) {
44 continue;
45 }
46
47 const task = await db.query.taskTable.findFirst({
48 where: eq(taskTable.id, externalLink.taskId),
49 });
50
51 if (!task) {
52 continue;
53 }
54
55 const existingMetadata = externalLink.metadata
56 ? JSON.parse(externalLink.metadata)
57 : {};
58
59 if (existingMetadata.createdFrom === "kaneo") {
60 continue;
61 }
62
63 const targetStatus = await resolveTargetStatus(
64 task.projectId,
65 "issue_closed",
66 "done",
67 );
68
69 await updateTaskStatus(task.id, targetStatus);
70
71 await updateExternalLink(externalLink.id, {
72 metadata: {
73 ...existingMetadata,
74 state: "closed",
75 },
76 });
77
78 return;
79 }
80}