/** * InMemoryTasksClient — deterministic in-memory TasksClient for local dev. * * Holds tasks in memory partitioned by `sub` so a user only ever sees and * mutates their own tasks (mirroring the real ABAC LeadingKeys boundary). * Seeded with a couple of FAKE tasks. No AWS, no network. * * This is for build-plan §4 "in-memory dev clients (tools return real data * locally)". */ import type { CompleteTaskInput, CreateTaskInput, DeleteTaskInput, ListTasksInput, Task, TasksClient, } from './client.js'; function seedTasks(): Map { return new Map([ [ 'lauren@seahavenind.com', [ { taskId: 'task-0001', sub: 'lauren@seahavenind.com', title: 'Order replacement dock breakers', description: 'Confirm 30A marine-grade rating before ordering.', completed: false, createdAt: '2026-06-20T08:00:00Z', }, { taskId: 'task-0002', sub: 'lauren@seahavenind.com', title: 'Send insurance cert to new vendor', completed: true, createdAt: '2026-06-18T09:30:00Z', completedAt: '2026-06-19T10:15:00Z', }, ], ], [ 'adam@seahavenind.com', [ { taskId: 'task-0003', sub: 'adam@seahavenind.com', title: 'Review Q2 vendor balances in QBO', completed: false, createdAt: '2026-06-22T13:00:00Z', }, ], ], ]); } /** In-memory TasksClient partitioned by sub. */ export class InMemoryTasksClient implements TasksClient { private readonly tasksBySub: Map; private counter = 1000; constructor() { this.tasksBySub = seedTasks(); } async createTask(input: CreateTaskInput): Promise { const task: Task = { taskId: `task-${(++this.counter).toString().padStart(4, '0')}`, sub: input.sub, title: input.title, completed: false, createdAt: new Date().toISOString(), }; if (input.description !== undefined) { task.description = input.description; } const list = this.tasksBySub.get(input.sub) ?? []; list.push(task); this.tasksBySub.set(input.sub, list); return task; } async listTasks(input: ListTasksInput): Promise { const list = this.tasksBySub.get(input.sub) ?? []; if (input.includeCompleted === true) { return [...list]; } return list.filter((t) => !t.completed); } async completeTask(input: CompleteTaskInput): Promise { const list = this.tasksBySub.get(input.sub) ?? []; const task = list.find((t) => t.taskId === input.taskId); if (!task) { throw new Error(`Task ${input.taskId} not found for user ${input.sub}`); } task.completed = true; task.completedAt = new Date().toISOString(); return task; } async deleteTask(input: DeleteTaskInput): Promise { const list = this.tasksBySub.get(input.sub) ?? []; const idx = list.findIndex((t) => t.taskId === input.taskId); if (idx !== -1) { list.splice(idx, 1); } } }