initial commit, boilerplate stuff

This commit is contained in:
khannurien
2026-03-15 17:15:46 +00:00
commit 6207a7549f
52 changed files with 4400 additions and 0 deletions

View File

@@ -0,0 +1,99 @@
import {
APIErrorCode,
APIException,
type CreateDumpRequest,
type Dump,
type UpdateDumpRequest,
} from "../model/interfaces.ts";
import { db, dumpApiToRow, dumpRowToApi, isDumpRow } from "../model/db.ts";
export function createDump(
request: CreateDumpRequest,
userId: string,
): Dump {
const dumpId = crypto.randomUUID();
const createdAt = new Date();
db.prepare(
`INSERT INTO dumps (id, title, description, user_id, created_at)
VALUES (?, ?, ?, ?, ?);`,
).run(
dumpId,
request.title,
request.description ?? null,
userId,
createdAt.toISOString(),
);
return {
id: dumpId,
title: request.title,
description: request.description ?? undefined,
userId: userId,
createdAt,
};
}
export function getDump(dumpId: string): Dump {
const dumpRow = db.prepare(
`SELECT id, title, description, user_id, created_at
FROM dumps WHERE id = ?;`,
).get(dumpId);
if (!dumpRow || !isDumpRow(dumpRow)) {
throw new APIException(APIErrorCode.NOT_FOUND, 404, "Dump not found");
}
return dumpRowToApi(dumpRow);
}
export function listDumps(): Dump[] {
const dumpRows = db.prepare(
`SELECT id, title, description, user_id, created_at FROM dumps;`,
).all();
if (!dumpRows || !dumpRows.every(isDumpRow)) {
throw new APIException(APIErrorCode.NOT_FOUND, 404, "No dump found");
}
const dumps: Dump[] = dumpRows.map(dumpRowToApi);
return dumps;
}
export function updateDump(
dumpId: string,
request: UpdateDumpRequest,
): Dump {
const dump = getDump(dumpId);
const updatedDump = {
...dump,
...request,
};
const updatedDumpRow = dumpApiToRow(updatedDump);
const dumpResult = db.prepare(
`UPDATE dumps SET title = ?, description = ? WHERE id = ?;`,
).run(
updatedDumpRow.title,
updatedDumpRow.description,
updatedDumpRow.id,
);
if (dumpResult.changes === 0) {
throw new APIException(APIErrorCode.NOT_FOUND, 404, "Dump not found");
}
return updatedDump;
}
export function deleteDump(dumpId: string): void {
const result = db.prepare(
`DELETE FROM dumps WHERE id = ?;`,
).run(dumpId);
if (result.changes === 0) {
throw new APIException(APIErrorCode.NOT_FOUND, 404, "Dump not found");
}
}

View File

@@ -0,0 +1,130 @@
import {
APIErrorCode,
APIException,
type RegisterUserRequest,
type UpdateUserRequest,
type User,
} from "../model/interfaces.ts";
import { db, isUserRow, userApiToRow, userRowToApi } from "../model/db.ts";
import { hashPassword } from "../lib/jwt.ts";
export async function createUser(
request: RegisterUserRequest,
): Promise<User> {
const userId = crypto.randomUUID();
const createdAt = new Date();
const existingUser = db.prepare(
"SELECT id FROM users WHERE username = ?;",
).get(request.username);
if (existingUser) {
throw new APIException(
APIErrorCode.VALIDATION_ERROR,
400,
"Username already exists",
);
}
const passwordHash = await hashPassword(request.password);
db.prepare(
`INSERT INTO users (id, username, password_hash, is_admin, created_at)
VALUES (?, ?, ?, ?, ?);`,
).run(
userId,
request.username,
passwordHash,
0,
createdAt.toISOString(),
);
return {
id: userId,
username: request.username,
passwordHash,
isAdmin: false,
createdAt,
};
}
export function getUserById(userId: string): User {
const userRow = db.prepare(
`SELECT id, username, password_hash, is_admin, created_at
FROM users WHERE id = ?`,
).get(userId);
if (!userRow || !isUserRow(userRow)) {
throw new APIException(APIErrorCode.NOT_FOUND, 404, "User not found");
}
return userRowToApi(userRow);
}
export function getUserByUsername(username: string): User {
const userRow = db.prepare(
`SELECT id, username, password_hash, is_admin, created_at
FROM users WHERE username = ?`,
).get(username);
if (!userRow || !isUserRow(userRow)) {
throw new APIException(APIErrorCode.NOT_FOUND, 404, "User not found");
}
return userRowToApi(userRow);
}
export function listUsers(): User[] {
const userRows = db.prepare(
`SELECT id, username, password_hash, is_admin, created_at FROM users`,
).all();
if (!userRows || !userRows.every(isUserRow)) {
throw new APIException(APIErrorCode.NOT_FOUND, 404, "No user found");
}
return userRows.map(userRowToApi);
}
export async function updateUser(
userId: string,
request: UpdateUserRequest,
): Promise<User> {
const user = getUserById(userId);
const { password, ...requestFields } = request;
const updatedUser: User = {
...user,
passwordHash: password ? await hashPassword(password) : user.passwordHash,
...requestFields,
};
const updatedUserRow = userApiToRow(updatedUser);
const userResult = db.prepare(
`UPDATE users SET username = ?, password_hash = ?, is_admin = ? WHERE id = ?`,
).run(
updatedUserRow.username,
updatedUserRow.password_hash,
updatedUserRow.is_admin,
updatedUserRow.id,
);
if (userResult.changes === 0) {
throw new APIException(APIErrorCode.NOT_FOUND, 404, "Dump not found");
}
return updatedUser;
}
export function deleteUser(userId: string): void {
const result = db.prepare(
`DELETE FROM users WHERE id = ?;`,
).run(userId);
if (result.changes === 0) {
throw new APIException(APIErrorCode.NOT_FOUND, 404, "User not found");
}
}