diff --git a/db.ts b/db.ts index 58b2f3b..a012630 100644 --- a/db.ts +++ b/db.ts @@ -2,7 +2,7 @@ import { createPentagon, TableDefinition, } from 'https://deno.land/x/pentagon@v0.1.5/mod.ts' -import { TaskModel, TodoModel, UserModel } from '@homeman/models.ts' +import { TodoModel, UserModel } from '@homeman/models.ts' export const kv = await Deno.openKv('homeman.db') @@ -19,9 +19,6 @@ export const schema: Record = { assignee: ['users', UserModel, 'assigneeUserId', 'id'], }, }, - tasks: { - schema: TaskModel, - }, } export const db = createPentagon(kv, schema) diff --git a/islands/Routine.tsx b/islands/Routine.tsx index 1f465f2..e3985b1 100644 --- a/islands/Routine.tsx +++ b/islands/Routine.tsx @@ -1,16 +1,9 @@ -import { - DailyPhase, - DailyPhaseModel, - DoneTask, - Task, - toPhase, -} from '@homeman/models.ts' +import { DailyPhase, DailyPhaseModel, Task, toPhase } from '@homeman/models.ts' import { useSignal } from '@preact/signals' import { excitement } from '@homeman/common.ts' export interface Props { tasks: Task[] - done: DoneTask[] } interface TaskWithIndex extends Task { @@ -62,38 +55,37 @@ export function Routine(
diff --git a/main.ts b/main.ts index 11ebba6..bf7b415 100644 --- a/main.ts +++ b/main.ts @@ -10,5 +10,18 @@ import '$std/dotenv/load.ts' import { start } from '$fresh/server.ts' import manifest from './fresh.gen.ts' import config from './fresh.config.ts' +import { kv } from '@homeman/db.ts' +import { Task } from '@homeman/models.ts' + +Deno.cron('Reset daily tasks', '0 4 * * *', async () => { + console.log('4am daily tasks reset') + const tasks = await Array.fromAsync(kv.list({ prefix: ['task'] })) + tasks.forEach( + async (t) => { + const nv = { ...t.value, doneAt: null } + await kv.set(t.key, nv) + }, + ) +}) await start(manifest, config) diff --git a/playground.ts b/playground.ts index 0d386a1..6877363 100644 --- a/playground.ts +++ b/playground.ts @@ -1,5 +1,5 @@ import { DailyPhase, TaskModel } from '@homeman/models.ts' -import { db } from '@homeman/db.ts' +import { kv } from '@homeman/db.ts' import { ulid } from 'https://deno.land/x/ulid@v0.3.0/mod.ts' const hardcoded: Record = { @@ -41,6 +41,7 @@ const hardcoded: Record = { ['👨‍⚖️', 'Sleep!'], ], } +console.log({ kv }) Object.entries(hardcoded).forEach(async ([tphase, phaseTasks]) => { const phase = tphase as DailyPhase for (const [emoji, description] of phaseTasks) { @@ -52,9 +53,10 @@ Object.entries(hardcoded).forEach(async ([tphase, phaseTasks]) => { doneAt: null, }) console.log(task) - const result = await db.tasks.create({ - data: task, - }) - console.log('after create:', result) + try { + await kv.set(['task', task.id], task) + } catch (e) { + console.error('error creating:', e) + } } }) diff --git a/routes/api/tasks.ts b/routes/api/tasks.ts index 69fa4c7..b7e73c0 100644 --- a/routes/api/tasks.ts +++ b/routes/api/tasks.ts @@ -1,64 +1,40 @@ import { Handlers } from '$fresh/server.ts' import { Task, TaskModel } from '@homeman/models.ts' -import { db, kv } from '@homeman/db.ts' +import { kv } from '@homeman/db.ts' import { ulid } from 'https://deno.land/x/ulid@v0.3.0/mod.ts' import { z } from 'https://deno.land/x/zod@v3.21.4/mod.ts' -const TaskPayload = TaskModel.partial({ id: true }) +const TaskPayload = TaskModel.omit({ doneAt: true }).partial({ + id: true, +}).extend({ + done: z.boolean().optional(), +}) type TaskPayload = z.infer async function createOrUpdate(task: TaskPayload) { - if (!task.id || task.id === '') { - const newTask: Task = { - ...task, - id: ulid(), - } - const result = await db.tasks.create({ data: newTask }) - await kv.set(['last_task_updated'], newTask.id) - return result - } else { - const result = await db.tasks.update({ where: { id: task.id }, data: task }) - await kv.set(['last_task_updated'], task.id) - return result + const newTask: Task = TaskModel.parse({ + ...task, + doneAt: task.done ? new Date() : null, + }) + if (!newTask.id || newTask.id === '') { + newTask.id = ulid() } + const result = await kv.set(['task', newTask.id], newTask) + await kv.set(['last_task_updated'], newTask.id) + return result } export const handler: Handlers = { async POST(req, _ctx) { - if (req.headers.get('content-type')?.includes('json')) { - const result = await createOrUpdate( - TaskPayload.parse(await req.json()), - ) - return new Response(JSON.stringify(result)) - } else { - const form = await req.formData() - const id = form.get('id')?.toString() || undefined - - const doneAt = form.get('doneAt') - console.log('task POST doneAt:', doneAt) - - const task = TaskPayload.parse({ - id: id, - emoji: form.get('emoji')?.toString() || null, - doneAt: form.get('doneAt')?.toString() || null, - description: form.get('description')?.toString(), - assigneeUserId: form.get('assigneeUserId')?.toString() || null, - }) - - if (!id) { - delete task.id - } - - if (!task.assigneeUserId) { - delete task.id - } - - await createOrUpdate(task) - - const url = new URL(req.url) - url.pathname = '/' - return Response.redirect(url, 303) - } + const result = await createOrUpdate( + TaskPayload.parse(await req.json()), + ) + return new Response(JSON.stringify(result)) + }, + async PUT(req, _ctx) { + const t = TaskPayload.parse(await req.json()) + const result = await createOrUpdate(t) + return new Response(JSON.stringify(result)) }, async DELETE(req, _ctx) { // task: form or query params or json @@ -70,7 +46,7 @@ export const handler: Handlers = { } console.log('delete task data:', data) const taskData = TaskModel.pick({ id: true }).parse(data) - const result = await db.tasks.delete({ where: taskData }) + const result = await kv.delete(['task', taskData.id]) await kv.set(['last_task_updated'], taskData.id) return new Response(JSON.stringify(result)) }, @@ -98,9 +74,7 @@ export const handler: Handlers = { continue } - const task = await db.tasks.findFirst({ - where: { id: entry.value }, - }) + const task = (await kv.get(['task', entry.value])).value const chunk = `data: ${ JSON.stringify({ id: entry.value, @@ -136,10 +110,12 @@ export const handler: Handlers = { const taskData = TaskModel.pick({ id: true }).safeParse(data) if (taskData.success) { return new Response( - JSON.stringify(await db.tasks.findFirst({ where: taskData.data })), + JSON.stringify((await kv.get(['task', taskData.data.id])).value), ) } else { - return new Response(JSON.stringify(await db.tasks.findMany({}))) + return new Response( + JSON.stringify(Array.fromAsync(kv.list({ prefix: ['task'] }))), + ) } }, } diff --git a/routes/routine.tsx b/routes/routine.tsx index be87cc5..4437056 100644 --- a/routes/routine.tsx +++ b/routes/routine.tsx @@ -1,7 +1,7 @@ import { Handlers, PageProps } from '$fresh/server.ts' import { Task } from '@homeman/models.ts' import { Routine } from '@homeman/islands/Routine.tsx' -import { db } from '@homeman/db.ts' +import { kv } from '@homeman/db.ts' // import { db, kv, Todo, UserWithTodos } from '@homeman/models.ts' interface Data { @@ -10,7 +10,10 @@ interface Data { export const handler: Handlers = { async GET(_req, ctx) { - const tasks = await db.tasks.findMany({}) + const tasks = (await Array.fromAsync(kv.list({ prefix: ['task'] }))).map( + (r) => r.value + ) + console.log({ tasks }) return ctx.render({ tasks }) }, }