vibe coded v1
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import { DatabaseSync, type SQLOutputValue } from "node:sqlite";
|
||||
import { Dump, type User } from "./interfaces.ts";
|
||||
import { Dump, type RichContent, type User } from "./interfaces.ts";
|
||||
|
||||
export const db = new DatabaseSync("api/sql/gerbeur.db");
|
||||
db.exec("PRAGMA journal_mode = WAL;");
|
||||
db.exec("PRAGMA foreign_keys = ON;");
|
||||
|
||||
/**
|
||||
* Database Row Types
|
||||
@@ -9,10 +11,17 @@ export const db = new DatabaseSync("api/sql/gerbeur.db");
|
||||
|
||||
export interface DumpRow {
|
||||
id: string;
|
||||
kind: string;
|
||||
title: string;
|
||||
description: string | null;
|
||||
comment: string | null;
|
||||
user_id: string;
|
||||
created_at: string;
|
||||
url: string | null;
|
||||
rich_content: string | null;
|
||||
file_name: string | null;
|
||||
file_mime: string | null;
|
||||
file_size: number | null;
|
||||
vote_count: number;
|
||||
[key: string]: SQLOutputValue; // Index signature
|
||||
}
|
||||
|
||||
@@ -22,6 +31,7 @@ export interface UserRow {
|
||||
password_hash: string;
|
||||
is_admin: number;
|
||||
created_at: string;
|
||||
avatar_mime: string | null;
|
||||
[key: string]: SQLOutputValue; // Index signature
|
||||
}
|
||||
|
||||
@@ -33,11 +43,22 @@ export function isDumpRow(obj: Record<string, SQLOutputValue>): obj is DumpRow {
|
||||
return !!obj &&
|
||||
typeof obj === "object" &&
|
||||
"id" in obj && typeof obj.id === "string" &&
|
||||
"kind" in obj && typeof obj.kind === "string" &&
|
||||
"title" in obj && typeof obj.title === "string" &&
|
||||
"description" in obj &&
|
||||
(typeof obj.description === "string" || obj.description === null) &&
|
||||
"comment" in obj &&
|
||||
(typeof obj.comment === "string" || obj.comment === null) &&
|
||||
"user_id" in obj && typeof obj.user_id === "string" &&
|
||||
"created_at" in obj && typeof obj.created_at === "string";
|
||||
"created_at" in obj && typeof obj.created_at === "string" &&
|
||||
"url" in obj && (typeof obj.url === "string" || obj.url === null) &&
|
||||
"rich_content" in obj &&
|
||||
(typeof obj.rich_content === "string" || obj.rich_content === null) &&
|
||||
"file_name" in obj &&
|
||||
(typeof obj.file_name === "string" || obj.file_name === null) &&
|
||||
"file_mime" in obj &&
|
||||
(typeof obj.file_mime === "string" || obj.file_mime === null) &&
|
||||
"file_size" in obj &&
|
||||
(typeof obj.file_size === "number" || obj.file_size === null) &&
|
||||
"vote_count" in obj && typeof obj.vote_count === "number";
|
||||
}
|
||||
|
||||
export function isUserRow(obj: Record<string, SQLOutputValue>): obj is UserRow {
|
||||
@@ -47,32 +68,48 @@ export function isUserRow(obj: Record<string, SQLOutputValue>): obj is UserRow {
|
||||
"username" in obj && typeof obj.username === "string" &&
|
||||
"password_hash" in obj && typeof obj.password_hash === "string" &&
|
||||
"is_admin" in obj && typeof obj.is_admin === "number" &&
|
||||
"created_at" in obj && typeof obj.created_at === "string";
|
||||
"created_at" in obj && typeof obj.created_at === "string" &&
|
||||
"avatar_mime" in obj &&
|
||||
(typeof obj.avatar_mime === "string" || obj.avatar_mime === null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Conversion Helpers
|
||||
*/
|
||||
|
||||
export function dumpRowToApi(
|
||||
row: DumpRow,
|
||||
): Dump {
|
||||
export function dumpRowToApi(row: DumpRow): Dump {
|
||||
return {
|
||||
id: row.id,
|
||||
kind: row.kind as "url" | "file",
|
||||
title: row.title,
|
||||
description: row.description ?? undefined,
|
||||
comment: row.comment ?? undefined,
|
||||
userId: row.user_id,
|
||||
createdAt: new Date(row.created_at),
|
||||
url: row.url ?? undefined,
|
||||
richContent: row.rich_content
|
||||
? (JSON.parse(row.rich_content) as RichContent)
|
||||
: undefined,
|
||||
fileName: row.file_name ?? undefined,
|
||||
fileMime: row.file_mime ?? undefined,
|
||||
fileSize: row.file_size ?? undefined,
|
||||
voteCount: row.vote_count,
|
||||
};
|
||||
}
|
||||
|
||||
export function dumpApiToRow(dump: Dump): DumpRow {
|
||||
return {
|
||||
id: dump.id,
|
||||
kind: dump.kind,
|
||||
title: dump.title,
|
||||
description: dump.description ?? null,
|
||||
comment: dump.comment ?? null,
|
||||
user_id: dump.userId,
|
||||
created_at: dump.createdAt.toISOString(),
|
||||
url: dump.url ?? null,
|
||||
rich_content: dump.richContent ? JSON.stringify(dump.richContent) : null,
|
||||
file_name: dump.fileName ?? null,
|
||||
file_mime: dump.fileMime ?? null,
|
||||
file_size: dump.fileSize ?? null,
|
||||
vote_count: dump.voteCount,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -83,6 +120,7 @@ export function userRowToApi(row: UserRow): User {
|
||||
passwordHash: row.password_hash,
|
||||
isAdmin: Boolean(row.is_admin),
|
||||
createdAt: new Date(row.created_at),
|
||||
avatarMime: row.avatar_mime ?? undefined,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -93,5 +131,6 @@ export function userApiToRow(user: User): UserRow {
|
||||
password_hash: user.passwordHash,
|
||||
is_admin: user.isAdmin ? 1 : 0,
|
||||
created_at: user.createdAt.toISOString(),
|
||||
avatar_mime: user.avatarMime ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user