kaneo (minimalist kanban) fork to experiment adding a tangled integration
github.com/usekaneo/kaneo
1import { Hono } from "hono";
2import { describeRoute, resolver, validator } from "hono-openapi";
3import * as v from "valibot";
4import { workspaceAccess } from "../utils/workspace-access-middleware";
5import createColumn from "./controllers/create-column";
6import deleteColumn from "./controllers/delete-column";
7import getColumns from "./controllers/get-columns";
8import reorderColumns from "./controllers/reorder-columns";
9import updateColumn from "./controllers/update-column";
10
11const column = new Hono<{
12 Variables: {
13 userId: string;
14 };
15}>()
16 .get(
17 "/:projectId",
18 describeRoute({
19 operationId: "getColumns",
20 tags: ["Columns"],
21 description: "Get all columns for a project",
22 responses: {
23 200: {
24 description: "List of columns ordered by position",
25 content: {
26 "application/json": { schema: resolver(v.any()) },
27 },
28 },
29 },
30 }),
31 validator("param", v.object({ projectId: v.string() })),
32 workspaceAccess.fromProject("projectId"),
33 async (c) => {
34 const { projectId } = c.req.valid("param");
35 const columns = await getColumns(projectId);
36 return c.json(columns);
37 },
38 )
39 .post(
40 "/:projectId",
41 describeRoute({
42 operationId: "createColumn",
43 tags: ["Columns"],
44 description: "Create a new column in a project",
45 responses: {
46 200: {
47 description: "Column created successfully",
48 content: {
49 "application/json": { schema: resolver(v.any()) },
50 },
51 },
52 },
53 }),
54 validator("param", v.object({ projectId: v.string() })),
55 validator(
56 "json",
57 v.object({
58 name: v.string(),
59 icon: v.optional(v.string()),
60 color: v.optional(v.string()),
61 isFinal: v.optional(v.boolean()),
62 }),
63 ),
64 workspaceAccess.fromProject("projectId"),
65 async (c) => {
66 const { projectId } = c.req.valid("param");
67 const { name, icon, color, isFinal } = c.req.valid("json");
68 const result = await createColumn({
69 projectId,
70 name,
71 icon,
72 color,
73 isFinal,
74 });
75 return c.json(result);
76 },
77 )
78 .put(
79 "/reorder/:projectId",
80 describeRoute({
81 operationId: "reorderColumns",
82 tags: ["Columns"],
83 description: "Reorder columns in a project",
84 responses: {
85 200: {
86 description: "Columns reordered successfully",
87 content: {
88 "application/json": { schema: resolver(v.any()) },
89 },
90 },
91 },
92 }),
93 validator("param", v.object({ projectId: v.string() })),
94 validator(
95 "json",
96 v.object({
97 columns: v.array(
98 v.object({
99 id: v.string(),
100 position: v.number(),
101 }),
102 ),
103 }),
104 ),
105 workspaceAccess.fromProject("projectId"),
106 async (c) => {
107 const { projectId } = c.req.valid("param");
108 const { columns } = c.req.valid("json");
109 const result = await reorderColumns(projectId, columns);
110 return c.json(result);
111 },
112 )
113 .put(
114 "/:id",
115 describeRoute({
116 operationId: "updateColumn",
117 tags: ["Columns"],
118 description: "Update a column",
119 responses: {
120 200: {
121 description: "Column updated successfully",
122 content: {
123 "application/json": { schema: resolver(v.any()) },
124 },
125 },
126 },
127 }),
128 validator("param", v.object({ id: v.string() })),
129 validator(
130 "json",
131 v.object({
132 name: v.optional(v.string()),
133 icon: v.optional(v.nullable(v.string())),
134 color: v.optional(v.nullable(v.string())),
135 isFinal: v.optional(v.boolean()),
136 }),
137 ),
138 workspaceAccess.fromColumn("id"),
139 async (c) => {
140 const { id } = c.req.valid("param");
141 const data = c.req.valid("json");
142 const result = await updateColumn(id, data);
143 return c.json(result);
144 },
145 )
146 .delete(
147 "/:id",
148 describeRoute({
149 operationId: "deleteColumn",
150 tags: ["Columns"],
151 description: "Delete a column",
152 responses: {
153 200: {
154 description: "Column deleted successfully",
155 content: {
156 "application/json": { schema: resolver(v.any()) },
157 },
158 },
159 },
160 }),
161 validator("param", v.object({ id: v.string() })),
162 workspaceAccess.fromColumn("id"),
163 async (c) => {
164 const { id } = c.req.valid("param");
165 const result = await deleteColumn(id);
166 return c.json(result);
167 },
168 );
169
170export default column;