/** * Backend */ export interface Dump { id: string; title: string; description?: string; userId: string; createdAt: Date; } /** * Authentication */ export interface User { id: string; username: string; passwordHash: string; isAdmin: boolean; createdAt: Date; } export interface LoginUserRequest { username: string; password: string; } export interface RegisterUserRequest { username: string; password: string; } export interface UpdateUserRequest { username?: string; password?: string; isAdmin?: boolean; } export function isLoginUserRequest(obj: unknown): obj is LoginUserRequest { return !!obj && typeof obj === "object" && "username" in obj && typeof obj.username === "string" && "password" in obj && typeof obj.password === "string"; } export function isRegisterUserRequest( obj: unknown, ): obj is RegisterUserRequest { return !!obj && typeof obj === "object" && "username" in obj && typeof obj.username === "string" && "password" in obj && typeof obj.password === "string"; } export function isUpdateUserRequest(obj: unknown): obj is UpdateUserRequest { return !!obj && typeof obj === "object" && (!("username" in obj) || typeof obj.username === "string") && (!("password" in obj) || typeof obj.password === "string") && (!("isAdmin" in obj) || typeof obj.isAdmin === "boolean"); } export interface AuthResponse { token: string; user: User; } export interface AuthPayload { userId: string; username: string; isAdmin: boolean; exp: number; } export function isAuthPayload(obj: unknown): obj is AuthPayload { return !!obj && typeof obj === "object" && "userId" in obj && typeof obj.userId === "string" && "username" in obj && typeof obj.username === "string" && "isAdmin" in obj && typeof obj.isAdmin === "boolean" && "exp" in obj && typeof obj.exp === "number"; } /** * API */ export enum APIErrorCode { BAD_REQUEST = "BAD_REQUEST", NOT_FOUND = "NOT_FOUND", SERVER_ERROR = "SERVER_ERROR", TIMEOUT = "TIMEOUT", UNAUTHORIZED = "UNAUTHORIZED", VALIDATION_ERROR = "VALIDATION_ERROR", } export interface APIError { code: APIErrorCode; message: string; } export interface APISuccess { success: true; data: T; error?: never; } export interface APIFailure { success: false; data?: never; error: APIError; } export type APIResponse = APISuccess | APIFailure; export class APIException extends Error { readonly code: APIErrorCode; readonly status: number; constructor(code: APIErrorCode, status: number, message: string) { super(message); this.code = code; this.status = status; } } /** * Request DTOs */ export interface CreateDumpRequest { title: string; description?: string; } export function isCreateDumpRequest(obj: unknown): obj is CreateDumpRequest { return !!obj && typeof obj === "object" && "title" in obj && typeof obj.title === "string" && (!("description" in obj) || (typeof obj.description === "string" || obj.description === null)); } export interface UpdateDumpRequest { title?: string; description?: string; } export function isUpdateDumpRequest(obj: unknown): obj is UpdateDumpRequest { return !!obj && typeof obj === "object" && (!("title" in obj) || typeof obj.title === "string") && (!("description" in obj) || (typeof obj.description === "string" || obj.description === null)); }