9636242b42
- replace Database with db instance - use schema imports for tables - use db.select, db.insert, onConflictDoUpdate - remove manual connection handling and console logs - improve type safety and maintainability refactor(students): migrate to Drizzle ORM and async queries Replace raw sqlite queries with Drizzle ORM. Remove the connect helper and use the shared db instance and schema definitions. Convert getItself, getAll and addStudents to async functions, use eq and lt helpers, and simplify promotion handling. This improves type safety, maintainability, and allows non‑blocking database access.
123 lines
3.2 KiB
TypeScript
123 lines
3.2 KiB
TypeScript
import { FreshContext, Handlers } from "$fresh/server.ts";
|
|
import { db } from "$root/databases/db.ts";
|
|
import { promotions, students } from "$root/databases/schema.ts";
|
|
import { AuthenticatedState } from "$root/defaults/interfaces.ts";
|
|
import { eq, lt } from "npm:drizzle-orm";
|
|
|
|
async function getItself(
|
|
userId: string,
|
|
): Promise<{ student: Student | null; promo: Promotion | null }> {
|
|
const student = await db
|
|
.select()
|
|
.from(students)
|
|
.where(eq(students.userId, userId))
|
|
.limit(1)
|
|
.then((rows) => rows[0] ?? null);
|
|
|
|
if (!student) {
|
|
return { student: null, promo: null };
|
|
}
|
|
|
|
const promo = await db
|
|
.select()
|
|
.from(promotions)
|
|
.where(eq(promotions.id, student.promotionId!))
|
|
.limit(1)
|
|
.then((rows) => rows[0] ?? null);
|
|
|
|
return { student, promo };
|
|
}
|
|
|
|
async function getAll(): Promise<
|
|
{ students: Student[]; promos: Promotion[] }
|
|
> {
|
|
const rows = await db
|
|
.select({
|
|
userId: students.userId,
|
|
firstName: students.firstName,
|
|
lastName: students.lastName,
|
|
mail: students.mail,
|
|
promotionId: students.promotionId,
|
|
})
|
|
.from(students)
|
|
.innerJoin(promotions, eq(students.promotionId, promotions.id))
|
|
.where(lt(promotions.current, 6));
|
|
|
|
const promos = await db
|
|
.select()
|
|
.from(promotions)
|
|
.where(lt(promotions.current, 6));
|
|
|
|
return { students: rows as Student[], promos };
|
|
}
|
|
|
|
async function addStudents(
|
|
studentList: Student[],
|
|
promoId: number,
|
|
): Promise<void> {
|
|
for (const student of studentList) {
|
|
await db
|
|
.insert(students)
|
|
.values({
|
|
userId: student.userId,
|
|
firstName: student.firstName,
|
|
lastName: student.lastName,
|
|
mail: student.mail,
|
|
promotionId: promoId,
|
|
})
|
|
.onConflictDoNothing();
|
|
}
|
|
}
|
|
|
|
export const handler: Handlers<null, AuthenticatedState> = {
|
|
async GET(
|
|
_request: Request,
|
|
context: FreshContext<AuthenticatedState>,
|
|
): Promise<Response> {
|
|
if (context.state.session.eduPersonPrimaryAffiliation == "student") {
|
|
return new Response(
|
|
JSON.stringify(await getItself(context.state.session.uid)),
|
|
{ headers: { "content-type": "application/json" } },
|
|
);
|
|
}
|
|
|
|
return new Response(
|
|
JSON.stringify(await getAll()),
|
|
{ headers: { "content-type": "application/json" } },
|
|
);
|
|
},
|
|
|
|
async POST(
|
|
request: Request,
|
|
_context: FreshContext<AuthenticatedState>,
|
|
): Promise<Response> {
|
|
const { students: studentList, promo }: {
|
|
students: Student[];
|
|
promo: string;
|
|
} = await request.json();
|
|
|
|
if (!promo || !promo.match(/^\d{4}-\dA$/) || !Array.isArray(studentList)) {
|
|
return new Response(null, { status: 400 });
|
|
}
|
|
|
|
const { endyear, current } = promo.match(
|
|
/^(?<endyear>\d{4})-(?<current>\d)A$/,
|
|
)?.groups!;
|
|
|
|
await db
|
|
.insert(promotions)
|
|
.values({ endyear: Number(endyear), current: Number(current) })
|
|
.onConflictDoNothing();
|
|
|
|
const promo_row = await db
|
|
.select()
|
|
.from(promotions)
|
|
.where(eq(promotions.endyear, Number(endyear)))
|
|
.then((rows) => rows.find((r) => r.current === Number(current))!);
|
|
|
|
await addStudents(studentList, promo_row.id);
|
|
|
|
return new Response(null, { status: 201 });
|
|
},
|
|
};
|