From 11bb625a979abf9977e25edcc0a9a06dce11b647 Mon Sep 17 00:00:00 2001 From: June Date: Fri, 30 Jan 2026 14:10:48 +1300 Subject: [PATCH] Port Entry api routes --- compose.yaml | 6 +-- src/lib/server/http.ts | 12 +++++ src/routes/api/entry/+server.ts | 71 +++++++++++++++++++++++++++++ src/routes/api/entry/all/+server.ts | 8 ++++ src/routes/api/entry/new/+server.ts | 23 ++++++++++ 5 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 src/lib/server/http.ts create mode 100644 src/routes/api/entry/+server.ts create mode 100644 src/routes/api/entry/all/+server.ts create mode 100644 src/routes/api/entry/new/+server.ts diff --git a/compose.yaml b/compose.yaml index e685673..d65b7c4 100644 --- a/compose.yaml +++ b/compose.yaml @@ -7,8 +7,6 @@ services: environment: POSTGRES_USER: root POSTGRES_PASSWORD: mysecretpassword - POSTGRES_DB: local + POSTGRES_DB: memento volumes: - - pgdata:/var/lib/postgresql -volumes: - pgdata: + - ~/tmp/pgdata:/var/lib/postgresql diff --git a/src/lib/server/http.ts b/src/lib/server/http.ts new file mode 100644 index 0000000..133752d --- /dev/null +++ b/src/lib/server/http.ts @@ -0,0 +1,12 @@ +export function httpResponse(data: object | null, code: number) { + return new Response(JSON.stringify(data), { + status: code + }) +} + +export function getParams(request: Request) { + const params = request.url.split("?")[1] + const searchParams = new URLSearchParams(params); + const paramsDict = Object.fromEntries(searchParams.entries()); + return paramsDict +} \ No newline at end of file diff --git a/src/routes/api/entry/+server.ts b/src/routes/api/entry/+server.ts new file mode 100644 index 0000000..da28694 --- /dev/null +++ b/src/routes/api/entry/+server.ts @@ -0,0 +1,71 @@ +import { db } from "$lib/server/db"; +import { entryTable } from "$lib/server/db/schema"; +import { httpResponse } from "$lib/server/http"; +import { getParams } from "$lib/server/http"; +import { eq, like, sql } from 'drizzle-orm'; + +export async function GET({ request }) { + const { id, date, month } = getParams(request) + + if (id && !isNaN(Number(id))) { + return getEntryByID(Number(id)) + } + + if (date) { + return getEntryByDate(date) + } + + if (month) { + return getEntryByMonth(month) + } + + return httpResponse({ error: 'Failed to retrieve entry' }, 500); +} + +async function getEntryByID(id: number) { + try { + const entry = await db.select().from(entryTable).where(eq(entryTable.id, id)) + if (entry.length == 0) { + return httpResponse({'error': 'entry not found'}, 404) + } + return httpResponse(entry[0], 200) + } catch { + return httpResponse({'error': 'bad request'}, 400) + } +} + +async function getEntryByDate(dateString: string) { + try { + // timezones suck + const startDate = new Date(dateString) + startDate.setHours(0, 0, 0, 0) + + const endDate = new Date(dateString) + endDate.setHours(23, 59, 59, 999) + + const entry = await db.select().from(entryTable).where( + sql`${entryTable.date} >= ${startDate.toISOString()}::timestamp AND ${entryTable.date} <= ${endDate.toISOString()}::timestamp` + ) + + return httpResponse(entry, 200) + } catch(error) { + return httpResponse({'error': error}, 400) + } +} + +async function getEntryByMonth(monthString: string) { + try { + const [year, month] = monthString.split('-').map(Number) + + const startDate = new Date(year, month - 1, 1, 0, 0, 0, 0) + const endDate = new Date(year, month, 1, 0, 0, 0, 0) + + const entries = await db.select().from(entryTable).where( + sql`${entryTable.date} >= ${startDate.toISOString()}::timestamp AND ${entryTable.date} < ${endDate.toISOString()}::timestamp` + ) + + return httpResponse(entries, 200) + } catch(error) { + return httpResponse({'error': error}, 400) + } +} \ No newline at end of file diff --git a/src/routes/api/entry/all/+server.ts b/src/routes/api/entry/all/+server.ts new file mode 100644 index 0000000..c708fa5 --- /dev/null +++ b/src/routes/api/entry/all/+server.ts @@ -0,0 +1,8 @@ +import { db } from "$lib/server/db"; +import { entryTable } from "$lib/server/db/schema"; + +export async function GET() { + const entries = await db.select().from(entryTable) + + return new Response(JSON.stringify(entries)) +} \ No newline at end of file diff --git a/src/routes/api/entry/new/+server.ts b/src/routes/api/entry/new/+server.ts new file mode 100644 index 0000000..d422e9c --- /dev/null +++ b/src/routes/api/entry/new/+server.ts @@ -0,0 +1,23 @@ +import { db } from "$lib/server/db"; +import { entryTable } from "$lib/server/db/schema"; +import { httpResponse } from "$lib/server/http"; + +export async function POST({ request }) { + + if (request.headers.get("Content-Type") === "application/json") { + + try { + const body = await request.json(); + const entry: typeof entryTable.$inferInsert = body + entry.date = new Date(body.date) + + await db.insert(entryTable).values(entry) + + return httpResponse({ "success": entry }, 200); + } catch(e) { + return httpResponse({ "error": `Malformed JSON (${e})` }, 400) + } + } + + return httpResponse(null, 400); +} \ No newline at end of file