import { randomUUID } from "node:crypto"; import type { FolderCreateInput, FolderNotFoundError, FolderUpdateInput, ProjectCreateInput, ProjectNotFoundError, ProjectStore, ProjectUpdateInput, } from "./project-store.js"; import { failure, type Result, success } from "./result.js"; import type { Folder, Project } from "./types.js"; function generateId(): string { return randomUUID(); } function projectNotFoundError(projectId: string): ProjectNotFoundError { return { type: "PROJECT_NOT_FOUND", projectId }; } function folderNotFoundError(folderId: string): FolderNotFoundError { return { type: "FOLDER_NOT_FOUND", folderId }; } export class InMemoryProjectStore implements ProjectStore { private projects: Map = new Map(); async create(input: ProjectCreateInput): Promise> { const now = new Date(); const project: Project = { id: generateId(), name: input.name, description: input.description ?? null, isGlobal: input.isGlobal ?? false, folders: [], createdAt: now, updatedAt: now, }; this.projects.set(project.id, project); return success(project); } async get(id: string): Promise> { const project = this.projects.get(id); if (!project) { return failure(projectNotFoundError(id)); } return success(project); } async update( id: string, input: ProjectUpdateInput, ): Promise> { const existing = this.projects.get(id); if (!existing) { return failure(projectNotFoundError(id)); } const updated: Project = { ...existing, name: input.name ?? existing.name, description: input.description !== undefined ? input.description : existing.description, isGlobal: input.isGlobal ?? existing.isGlobal, updatedAt: new Date(), }; this.projects.set(id, updated); return success(updated); } async delete(id: string): Promise> { if (!this.projects.has(id)) { return failure(projectNotFoundError(id)); } this.projects.delete(id); return success(undefined); } async list(): Promise> { return success(Array.from(this.projects.values())); } async addFolder( projectId: string, input: FolderCreateInput, ): Promise> { const project = this.projects.get(projectId); if (!project) { return failure(projectNotFoundError(projectId)); } const now = new Date(); const folder: Folder = { id: generateId(), name: input.name, description: input.description ?? null, projectId, createdAt: now, updatedAt: now, }; const updatedProject: Project = { ...project, folders: [...project.folders, folder], updatedAt: now, }; this.projects.set(projectId, updatedProject); return success(folder); } async updateFolder( projectId: string, folderId: string, input: FolderUpdateInput, ): Promise> { const project = this.projects.get(projectId); if (!project) { return failure(projectNotFoundError(projectId)); } const existingFolder = project.folders.find( (folder) => folder.id === folderId, ); if (!existingFolder) { return failure(folderNotFoundError(folderId)); } const updatedFolder: Folder = { ...existingFolder, name: input.name ?? existingFolder.name, description: input.description !== undefined ? input.description : existingFolder.description, updatedAt: new Date(), }; const updatedFolders = project.folders.map((folder) => folder.id === folderId ? updatedFolder : folder, ); const updatedProject: Project = { ...project, folders: updatedFolders, updatedAt: new Date(), }; this.projects.set(projectId, updatedProject); return success(updatedFolder); } async removeFolder( projectId: string, folderId: string, ): Promise> { const project = this.projects.get(projectId); if (!project) { return failure(projectNotFoundError(projectId)); } const folderExists = project.folders.some( (folder) => folder.id === folderId, ); if (!folderExists) { return failure(folderNotFoundError(folderId)); } const updatedProject: Project = { ...project, folders: project.folders.filter((folder) => folder.id !== folderId), updatedAt: new Date(), }; this.projects.set(projectId, updatedProject); return success(undefined); } async listFolders( projectId: string, ): Promise> { const project = this.projects.get(projectId); if (!project) { return failure(projectNotFoundError(projectId)); } return success(project.folders); } }