kaneo (minimalist kanban) fork to experiment adding a tangled integration github.com/usekaneo/kaneo
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 39e2dfae265f26c8d6d888a560f50ab2d5d58b3f 225 lines 6.3 kB view raw
1import { Hono } from "hono"; 2import { describeRoute, resolver, validator } from "hono-openapi"; 3import * as v from "valibot"; 4import { projectSchema } from "../schemas"; 5import { workspaceAccess } from "../utils/workspace-access-middleware"; 6import archiveProjectCtrl from "./controllers/archive-project"; 7import createProjectCtrl from "./controllers/create-project"; 8import deleteProjectCtrl from "./controllers/delete-project"; 9import getProjectCtrl from "./controllers/get-project"; 10import getProjectsCtrl from "./controllers/get-projects"; 11import unarchiveProjectCtrl from "./controllers/unarchive-project"; 12import updateProjectCtrl from "./controllers/update-project"; 13 14const project = new Hono<{ 15 Variables: { 16 userId: string; 17 workspaceId: string; 18 }; 19}>() 20 .get( 21 "/", 22 describeRoute({ 23 operationId: "listProjects", 24 tags: ["Projects"], 25 description: "Get all projects in a workspace", 26 responses: { 27 200: { 28 description: "List of projects with statistics", 29 content: { 30 "application/json": { schema: resolver(v.array(projectSchema)) }, 31 }, 32 }, 33 }, 34 }), 35 validator( 36 "query", 37 v.object({ 38 workspaceId: v.string(), 39 includeArchived: v.optional(v.string()), 40 }), 41 ), 42 workspaceAccess.fromQuery(), 43 async (c) => { 44 const workspaceId = c.get("workspaceId"); 45 const { includeArchived } = c.req.valid("query"); 46 const projects = await getProjectsCtrl( 47 workspaceId, 48 includeArchived === "true", 49 ); 50 return c.json(projects); 51 }, 52 ) 53 .post( 54 "/", 55 describeRoute({ 56 operationId: "createProject", 57 tags: ["Projects"], 58 description: "Create a new project in a workspace", 59 responses: { 60 200: { 61 description: "Project created successfully", 62 content: { 63 "application/json": { schema: resolver(projectSchema) }, 64 }, 65 }, 66 }, 67 }), 68 validator( 69 "json", 70 v.object({ 71 name: v.string(), 72 workspaceId: v.string(), 73 icon: v.string(), 74 slug: v.string(), 75 }), 76 ), 77 workspaceAccess.fromBody(), 78 async (c) => { 79 const { name, icon, slug } = c.req.valid("json"); 80 const workspaceId = c.get("workspaceId"); 81 const newProject = await createProjectCtrl(workspaceId, name, icon, slug); 82 return c.json(newProject); 83 }, 84 ) 85 .get( 86 "/:id", 87 describeRoute({ 88 operationId: "getProject", 89 tags: ["Projects"], 90 description: "Get a specific project by ID", 91 responses: { 92 200: { 93 description: "Project details", 94 content: { 95 "application/json": { schema: resolver(projectSchema) }, 96 }, 97 }, 98 }, 99 }), 100 validator("param", v.object({ id: v.string() })), 101 workspaceAccess.fromProject(), 102 async (c) => { 103 const { id } = c.req.valid("param"); 104 const workspaceId = c.get("workspaceId"); 105 const projectData = await getProjectCtrl(id, workspaceId); 106 return c.json(projectData); 107 }, 108 ) 109 .put( 110 "/:id", 111 describeRoute({ 112 operationId: "updateProject", 113 tags: ["Projects"], 114 description: "Update an existing project", 115 responses: { 116 200: { 117 description: "Project updated successfully", 118 content: { 119 "application/json": { schema: resolver(projectSchema) }, 120 }, 121 }, 122 }, 123 }), 124 validator("param", v.object({ id: v.string() })), 125 validator( 126 "json", 127 v.object({ 128 name: v.string(), 129 icon: v.string(), 130 slug: v.string(), 131 description: v.string(), 132 isPublic: v.boolean(), 133 }), 134 ), 135 workspaceAccess.fromProject(), 136 async (c) => { 137 const { id } = c.req.valid("param"); 138 const { name, icon, slug, description, isPublic } = c.req.valid("json"); 139 const workspaceId = c.get("workspaceId"); 140 const updatedProject = await updateProjectCtrl( 141 id, 142 name, 143 icon, 144 slug, 145 description, 146 isPublic, 147 workspaceId, 148 ); 149 return c.json(updatedProject); 150 }, 151 ) 152 .delete( 153 "/:id", 154 describeRoute({ 155 operationId: "deleteProject", 156 tags: ["Projects"], 157 description: "Delete a project by ID", 158 responses: { 159 200: { 160 description: "Project deleted successfully", 161 content: { 162 "application/json": { schema: resolver(projectSchema) }, 163 }, 164 }, 165 }, 166 }), 167 validator("param", v.object({ id: v.string() })), 168 workspaceAccess.fromProject(), 169 async (c) => { 170 const { id } = c.req.valid("param"); 171 const workspaceId = c.get("workspaceId"); 172 const deletedProject = await deleteProjectCtrl(id, workspaceId); 173 return c.json(deletedProject); 174 }, 175 ) 176 .put( 177 "/:id/archive", 178 describeRoute({ 179 operationId: "archiveProject", 180 tags: ["Projects"], 181 description: "Archive a project by ID", 182 responses: { 183 200: { 184 description: "Project archived successfully", 185 content: { 186 "application/json": { schema: resolver(projectSchema) }, 187 }, 188 }, 189 }, 190 }), 191 validator("param", v.object({ id: v.string() })), 192 workspaceAccess.fromProject(), 193 async (c) => { 194 const { id } = c.req.valid("param"); 195 const workspaceId = c.get("workspaceId"); 196 const archivedProject = await archiveProjectCtrl(id, workspaceId); 197 return c.json(archivedProject); 198 }, 199 ) 200 .put( 201 "/:id/unarchive", 202 describeRoute({ 203 operationId: "unarchiveProject", 204 tags: ["Projects"], 205 description: "Unarchive a project by ID", 206 responses: { 207 200: { 208 description: "Project unarchived successfully", 209 content: { 210 "application/json": { schema: resolver(projectSchema) }, 211 }, 212 }, 213 }, 214 }), 215 validator("param", v.object({ id: v.string() })), 216 workspaceAccess.fromProject(), 217 async (c) => { 218 const { id } = c.req.valid("param"); 219 const workspaceId = c.get("workspaceId"); 220 const unarchivedProject = await unarchiveProjectCtrl(id, workspaceId); 221 return c.json(unarchivedProject); 222 }, 223 ); 224 225export default project;