kaneo (minimalist kanban) fork to experiment adding a tangled integration
github.com/usekaneo/kaneo
1import { eq, sql } from "drizzle-orm";
2import { HTTPException } from "hono/http-exception";
3import db from "../../database";
4import { columnTable } from "../../database/schema";
5
6function toSlug(name: string): string {
7 return name
8 .toLowerCase()
9 .trim()
10 .replace(/[^a-z0-9]+/g, "-")
11 .replace(/^-+|-+$/g, "");
12}
13
14async function createColumn({
15 projectId,
16 name,
17 icon,
18 color,
19 isFinal,
20}: {
21 projectId: string;
22 name: string;
23 icon?: string;
24 color?: string;
25 isFinal?: boolean;
26}) {
27 const slug = toSlug(name);
28
29 const existing = await db
30 .select({ id: columnTable.id })
31 .from(columnTable)
32 .where(
33 sql`${columnTable.projectId} = ${projectId} AND ${columnTable.slug} = ${slug}`,
34 );
35
36 if (existing.length > 0) {
37 throw new HTTPException(409, {
38 message: `Column with slug "${slug}" already exists in this project`,
39 });
40 }
41
42 const [maxPos] = await db
43 .select({
44 maxPosition: sql<number>`COALESCE(MAX(${columnTable.position}), -1)`,
45 })
46 .from(columnTable)
47 .where(eq(columnTable.projectId, projectId));
48
49 const position = (maxPos?.maxPosition ?? -1) + 1;
50
51 const [created] = await db
52 .insert(columnTable)
53 .values({
54 projectId,
55 name,
56 slug,
57 position,
58 icon: icon || null,
59 color: color || null,
60 isFinal: isFinal ?? false,
61 })
62 .returning();
63
64 if (!created) {
65 throw new HTTPException(500, { message: "Failed to create column" });
66 }
67
68 return created;
69}
70
71export default createColumn;