kaneo (minimalist kanban) fork to experiment adding a tangled integration
github.com/usekaneo/kaneo
1import { and, eq, or } from "drizzle-orm";
2import { HTTPException } from "hono/http-exception";
3import db from "../../database";
4import { taskRelationTable, taskTable } from "../../database/schema";
5
6async function createTaskRelation({
7 sourceTaskId,
8 targetTaskId,
9 relationType,
10}: {
11 sourceTaskId: string;
12 targetTaskId: string;
13 relationType: string;
14}) {
15 if (sourceTaskId === targetTaskId) {
16 throw new HTTPException(400, {
17 message: "Cannot create a relation between a task and itself",
18 });
19 }
20
21 const [sourceTask] = await db
22 .select({ id: taskTable.id })
23 .from(taskTable)
24 .where(eq(taskTable.id, sourceTaskId))
25 .limit(1);
26
27 if (!sourceTask) {
28 throw new HTTPException(404, { message: "Source task not found" });
29 }
30
31 const [targetTask] = await db
32 .select({ id: taskTable.id })
33 .from(taskTable)
34 .where(eq(taskTable.id, targetTaskId))
35 .limit(1);
36
37 if (!targetTask) {
38 throw new HTTPException(404, { message: "Target task not found" });
39 }
40
41 const existing = await db
42 .select({ id: taskRelationTable.id })
43 .from(taskRelationTable)
44 .where(
45 and(
46 eq(taskRelationTable.relationType, relationType),
47 or(
48 and(
49 eq(taskRelationTable.sourceTaskId, sourceTaskId),
50 eq(taskRelationTable.targetTaskId, targetTaskId),
51 ),
52 and(
53 eq(taskRelationTable.sourceTaskId, targetTaskId),
54 eq(taskRelationTable.targetTaskId, sourceTaskId),
55 ),
56 ),
57 ),
58 )
59 .limit(1);
60
61 if (existing.length > 0) {
62 throw new HTTPException(409, {
63 message: "This relation already exists",
64 });
65 }
66
67 const [relation] = await db
68 .insert(taskRelationTable)
69 .values({
70 sourceTaskId,
71 targetTaskId,
72 relationType,
73 })
74 .returning();
75
76 if (!relation) {
77 throw new HTTPException(500, {
78 message: "Failed to create task relation",
79 });
80 }
81
82 return relation;
83}
84
85export default createTaskRelation;