import { prisma } from '@/services/core/database'; export interface Note { id: string; title: string; content: string; userId: string; createdAt: Date; updatedAt: Date; tags?: string[]; } export interface CreateNoteData { title: string; content: string; userId: string; tags?: string[]; } export interface UpdateNoteData { title?: string; content?: string; tags?: string[]; } /** * Service pour la gestion des notes markdown */ export class NotesService { /** * Récupère toutes les notes d'un utilisateur */ async getNotes(userId: string): Promise { const notes = await prisma.note.findMany({ where: { userId }, include: { noteTags: { include: { tag: true, }, }, }, orderBy: { updatedAt: 'desc' }, }); return notes.map((note) => ({ ...note, tags: note.noteTags.map((nt) => nt.tag.name), })); } /** * Récupère une note par son ID */ async getNoteById(noteId: string, userId: string): Promise { const note = await prisma.note.findFirst({ where: { id: noteId, userId, }, include: { noteTags: { include: { tag: true, }, }, }, }); if (!note) return null; return { ...note, tags: note.noteTags.map((nt) => nt.tag.name), }; } /** * Crée une nouvelle note */ async createNote(data: CreateNoteData): Promise { const note = await prisma.note.create({ data: { title: data.title, content: data.content, userId: data.userId, noteTags: data.tags ? { create: data.tags.map((tagName) => ({ tag: { connectOrCreate: { where: { name: tagName }, create: { name: tagName }, }, }, })), } : undefined, }, include: { noteTags: { include: { tag: true, }, }, }, }); return { ...note, tags: note.noteTags.map((nt) => nt.tag.name), }; } /** * Met à jour une note existante */ async updateNote( noteId: string, userId: string, data: UpdateNoteData ): Promise { // Vérifier que la note appartient à l'utilisateur const existingNote = await prisma.note.findFirst({ where: { id: noteId, userId, }, }); if (!existingNote) { throw new Error('Note not found or access denied'); } // Préparer les données de mise à jour const updateData: { updatedAt: Date; title?: string; content?: string; noteTags?: { deleteMany: Record; create: Array<{ tag: { connectOrCreate: { where: { name: string }; create: { name: string }; }; }; }>; }; } = { updatedAt: new Date(), }; // Ajouter les champs de base s'ils sont fournis if (data.title !== undefined) { updateData.title = data.title; } if (data.content !== undefined) { updateData.content = data.content; } // Gérer les tags si fournis if (data.tags !== undefined) { updateData.noteTags = { deleteMany: {}, // Supprimer tous les tags existants create: data.tags.map((tagName) => ({ tag: { connectOrCreate: { where: { name: tagName }, create: { name: tagName }, }, }, })), }; } const note = await prisma.note.update({ where: { id: noteId }, data: updateData, include: { noteTags: { include: { tag: true, }, }, }, }); return { ...note, tags: note.noteTags.map((nt) => nt.tag.name), }; } /** * Supprime une note */ async deleteNote(noteId: string, userId: string): Promise { // Vérifier que la note appartient à l'utilisateur const existingNote = await prisma.note.findFirst({ where: { id: noteId, userId, }, }); if (!existingNote) { throw new Error('Note not found or access denied'); } await prisma.note.delete({ where: { id: noteId }, }); } /** * Recherche des notes par titre ou contenu */ async searchNotes(userId: string, query: string): Promise { const notes = await prisma.note.findMany({ where: { userId, OR: [{ title: { contains: query } }, { content: { contains: query } }], }, orderBy: { updatedAt: 'desc' }, }); return notes; } /** * Récupère les statistiques des notes d'un utilisateur */ async getNotesStats(userId: string): Promise<{ totalNotes: number; totalWords: number; lastUpdated: Date | null; }> { const notes = await prisma.note.findMany({ where: { userId }, select: { content: true, updatedAt: true, }, }); const totalNotes = notes.length; const totalWords = notes.reduce((acc, note) => { return ( acc + note.content.split(/\s+/).filter((word) => word.length > 0).length ); }, 0); const lastUpdated = notes.length > 0 ? notes.reduce( (latest, note) => note.updatedAt > latest ? note.updatedAt : latest, notes[0].updatedAt ) : null; return { totalNotes, totalWords, lastUpdated, }; } } // Instance singleton export const notesService = new NotesService();