mirror of
https://github.com/hex248/sprint.git
synced 2026-02-08 10:33:01 +00:00
/project/* routes
This commit is contained in:
@@ -1,22 +1,34 @@
|
|||||||
import { eq } from "drizzle-orm";
|
import { eq } from "drizzle-orm";
|
||||||
import { db } from "../client";
|
import { db } from "../client";
|
||||||
import { Project, User } from "../schema";
|
import { Issue, Project, User } from "../schema";
|
||||||
|
|
||||||
export async function createProject(blob: string, name: string, owner: typeof User.$inferSelect) {
|
export async function createProject(blob: string, name: string, ownerId: number) {
|
||||||
const [project] = await db
|
const [project] = await db
|
||||||
.insert(Project)
|
.insert(Project)
|
||||||
.values({
|
.values({
|
||||||
blob,
|
blob,
|
||||||
name,
|
name,
|
||||||
ownerId: owner.id,
|
ownerId,
|
||||||
})
|
})
|
||||||
.returning();
|
.returning();
|
||||||
if (!project) {
|
|
||||||
throw new Error(`failed to create project ${name} with blob ${blob} for owner ${owner.username}`);
|
|
||||||
}
|
|
||||||
return project;
|
return project;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function updateProject(
|
||||||
|
projectId: number,
|
||||||
|
updates: { blob?: string; name?: string; ownerId?: number },
|
||||||
|
) {
|
||||||
|
const [project] = await db.update(Project).set(updates).where(eq(Project.id, projectId)).returning();
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteProject(projectId: number) {
|
||||||
|
// delete all of the project's issues first
|
||||||
|
await db.delete(Issue).where(eq(Issue.projectId, projectId));
|
||||||
|
// delete actual project
|
||||||
|
await db.delete(Project).where(eq(Project.id, projectId));
|
||||||
|
}
|
||||||
|
|
||||||
export async function getProjectByID(projectId: number) {
|
export async function getProjectByID(projectId: number) {
|
||||||
const [project] = await db.select().from(Project).where(eq(Project.id, projectId));
|
const [project] = await db.select().from(Project).where(eq(Project.id, projectId));
|
||||||
return project;
|
return project;
|
||||||
|
|||||||
@@ -7,6 +7,11 @@ export async function createUser(name: string, username: string) {
|
|||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getUserById(id: number) {
|
||||||
|
const [user] = await db.select().from(User).where(eq(User.id, id));
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
export async function getUserByUsername(username: string) {
|
export async function getUserByUsername(username: string) {
|
||||||
const [user] = await db.select().from(User).where(eq(User.username, username));
|
const [user] = await db.select().from(User).where(eq(User.username, username));
|
||||||
return user;
|
return user;
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ const main = async () => {
|
|||||||
"/issue/delete": routes.issueDelete,
|
"/issue/delete": routes.issueDelete,
|
||||||
"/issues/:projectBlob": routes.issuesInProject,
|
"/issues/:projectBlob": routes.issuesInProject,
|
||||||
"/issues/all": routes.issues,
|
"/issues/all": routes.issues,
|
||||||
|
|
||||||
|
"/project/create": routes.projectCreate,
|
||||||
|
"/project/update": routes.projectUpdate,
|
||||||
|
"/project/delete": routes.projectDelete,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,19 @@ import issueUpdate from "./issue/update";
|
|||||||
import issuesInProject from "./issues/[projectBlob]";
|
import issuesInProject from "./issues/[projectBlob]";
|
||||||
import issues from "./issues/all";
|
import issues from "./issues/all";
|
||||||
|
|
||||||
|
import projectCreate from "./project/create";
|
||||||
|
import projectUpdate from "./project/update";
|
||||||
|
import projectDelete from "./project/delete";
|
||||||
|
|
||||||
export const routes = {
|
export const routes = {
|
||||||
issueCreate,
|
issueCreate,
|
||||||
issueDelete,
|
issueDelete,
|
||||||
issueUpdate,
|
issueUpdate,
|
||||||
|
|
||||||
issuesInProject,
|
issuesInProject,
|
||||||
issues,
|
issues,
|
||||||
|
|
||||||
|
projectCreate,
|
||||||
|
projectUpdate,
|
||||||
|
projectDelete,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { BunRequest } from "bun";
|
import type { BunRequest } from "bun";
|
||||||
import { getIssues } from "../../db/queries";
|
import { getIssues } from "../../db/queries";
|
||||||
|
|
||||||
export default async function issues(req: BunRequest) {
|
export default async function issuesAll(req: BunRequest) {
|
||||||
const issues = await getIssues();
|
const issues = await getIssues();
|
||||||
|
|
||||||
return Response.json(issues);
|
return Response.json(issues);
|
||||||
|
|||||||
32
src/routes/project/create.ts
Normal file
32
src/routes/project/create.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import type { BunRequest } from "bun";
|
||||||
|
import { createProject, getUserById, getProjectByBlob } from "../../db/queries";
|
||||||
|
|
||||||
|
// /project/create?blob=BLOB&name=Testing&ownerId=1
|
||||||
|
export default async function projectCreate(req: BunRequest) {
|
||||||
|
const url = new URL(req.url);
|
||||||
|
const blob = url.searchParams.get("blob");
|
||||||
|
const name = url.searchParams.get("name");
|
||||||
|
const ownerId = url.searchParams.get("ownerId");
|
||||||
|
|
||||||
|
if (!blob || !name || !ownerId) {
|
||||||
|
return new Response(
|
||||||
|
`missing parameters: ${!blob ? "blob " : ""}${!name ? "name " : ""}${!ownerId ? "ownerId" : ""}`,
|
||||||
|
{ status: 400 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if project with blob already exists
|
||||||
|
const existingProject = await getProjectByBlob(blob);
|
||||||
|
if (existingProject) {
|
||||||
|
return new Response(`project with blob ${blob} already exists`, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const owner = await getUserById(parseInt(ownerId, 10));
|
||||||
|
if (!owner) {
|
||||||
|
return new Response(`owner with id ${ownerId} not found`, { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const project = await createProject(blob, name, owner.id);
|
||||||
|
|
||||||
|
return Response.json(project);
|
||||||
|
}
|
||||||
21
src/routes/project/delete.ts
Normal file
21
src/routes/project/delete.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import type { BunRequest } from "bun";
|
||||||
|
import { getProjectByID, deleteProject } from "../../db/queries";
|
||||||
|
|
||||||
|
// /project/delete?id=1
|
||||||
|
export default async function projectDelete(req: BunRequest) {
|
||||||
|
const url = new URL(req.url);
|
||||||
|
const id = url.searchParams.get("id");
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return new Response(`project id is required`, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingProject = await getProjectByID(Number(id));
|
||||||
|
if (!existingProject) {
|
||||||
|
return new Response(`project with id ${id} does not exist`, { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
await deleteProject(Number(id));
|
||||||
|
|
||||||
|
return new Response(`project with id ${id} deleted successfully`, { status: 200 });
|
||||||
|
}
|
||||||
44
src/routes/project/update.ts
Normal file
44
src/routes/project/update.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import type { BunRequest } from "bun";
|
||||||
|
import { getProjectByBlob, getProjectByID, getUserById, updateProject } from "../../db/queries";
|
||||||
|
|
||||||
|
// /project/update?id=1&blob=NEW&name=new%20name&ownerId=1
|
||||||
|
export default async function projectUpdate(req: BunRequest) {
|
||||||
|
const url = new URL(req.url);
|
||||||
|
const id = url.searchParams.get("id");
|
||||||
|
const blob = url.searchParams.get("blob") || undefined;
|
||||||
|
const name = url.searchParams.get("name") || undefined;
|
||||||
|
const ownerId = url.searchParams.get("ownerId") || undefined;
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
return new Response(`project id is required`, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingProject = await getProjectByID(Number(id));
|
||||||
|
if (!existingProject) {
|
||||||
|
return new Response(`project with id ${id} does not exist`, { status: 404 });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!blob && !name && !ownerId) {
|
||||||
|
return new Response(`at least one of blob, name, or ownerId must be provided`, {
|
||||||
|
status: 400,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const projectWithBlob = blob ? await getProjectByBlob(blob) : null;
|
||||||
|
if (projectWithBlob && projectWithBlob.id !== Number(id)) {
|
||||||
|
return new Response(`a project with blob "${blob}" already exists`, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const newOwner = ownerId ? await getUserById(Number(ownerId)) : null;
|
||||||
|
if (ownerId && !newOwner) {
|
||||||
|
return new Response(`user with id ${ownerId} does not exist`, { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const project = await updateProject(Number(id), {
|
||||||
|
blob: blob,
|
||||||
|
name: name,
|
||||||
|
ownerId: newOwner?.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
return Response.json(project);
|
||||||
|
}
|
||||||
@@ -8,7 +8,10 @@ export const createDemoData = async () => {
|
|||||||
|
|
||||||
const projectNames = ["PROJ", "TEST", "SAMPLE"];
|
const projectNames = ["PROJ", "TEST", "SAMPLE"];
|
||||||
for (const name of projectNames) {
|
for (const name of projectNames) {
|
||||||
const project = await createProject(name.slice(0, 4), name, user);
|
const project = await createProject(name.slice(0, 4), name, user.id);
|
||||||
|
if (!project) {
|
||||||
|
throw new Error(`failed to create demo project: ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 1; i <= 5; i++) {
|
for (let i = 1; i <= 5; i++) {
|
||||||
await createIssue(
|
await createIssue(
|
||||||
|
|||||||
Reference in New Issue
Block a user