/
DME
/
NotesApp
Обзор
Документация
Войти
/
DME
/
NotesApp
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/server/api/routers/note.ts
216 строк
7 KB
Karasique333
Commit
19 июн 2025, 15:09
19 июн 2025, 15:09
d96c829
Код
Авторство
О чём код?
// server/api/routers/note.ts import { and, eq, ilike, sql } from 'drizzle-orm' import { z } from 'zod' import { authProcedure, createTRPCRouter } from '@/server/api/trpc' import { note, checklistItem, noteImage } from '@/server/db/schema' export const noteRouter = createTRPCRouter({ create: authProcedure .input( z.object({ title: z.string().min(1), tags: z.array(z.string()).default([]), status: z.enum(['archived', 'active']).default('active'), content: z.string().optional(), checklist: z .array( z.object({ content: z.string(), completed: z.boolean(), }) ) .default([]), images: z.array(z.string()).default([]), }) ) .mutation(async ({ ctx, input }) => { const noteId = crypto.randomUUID() const noteData = await ctx.db .insert(note) .values({ id: noteId, userId: ctx.session.userId, title: input.title, tags: input.tags, status: input.status, content: input.content ?? '', }) .returning() if (input.checklist.length > 0) { await ctx.db.insert(checklistItem).values( input.checklist.map((item) => ({ noteId, content: item.content, completed: item.completed, })) ) } if (input.images.length > 0) { await ctx.db.insert(noteImage).values( input.images.map((url) => ({ noteId, url, })) ) } return noteData[0] }), update: authProcedure .input( z.object({ id: z.string(), title: z.string().optional(), tags: z.array(z.string()).optional(), status: z.enum(['archived', 'active']).optional(), content: z.string().optional(), checklist: z .array( z.object({ content: z.string(), completed: z.boolean(), }) ) .optional(), images: z.array(z.string()).optional(), }) ) .mutation(async ({ ctx, input }) => { const { id, checklist, images } = input // Обновление основной заметки await ctx.db .update(note) .set({ ...(input.title && { title: input.title }), ...(input.tags && { tags: input.tags }), ...(input.status && { status: input.status }), ...(input.content && { content: input.content }), updatedAt: new Date(), }) .where(and(eq(note.id, id), eq(note.userId, ctx.session.userId))) // Обновление чек-листа (удаление старого и вставка нового) if (checklist) { await ctx.db.delete(checklistItem).where(eq(checklistItem.noteId, id)) if (checklist.length > 0) { await ctx.db.insert(checklistItem).values( checklist.map((item) => ({ noteId: id, content: item.content, completed: item.completed, })) ) } } // Обновление изображений if (images) { await ctx.db.delete(noteImage).where(eq(noteImage.noteId, id)) if (images.length > 0) { await ctx.db.insert(noteImage).values( images.map((url) => ({ noteId: id, url, })) ) } } return { success: true } }), delete: authProcedure .input(z.object({ id: z.string() })) .mutation(async ({ ctx, input }) => { await ctx.db .delete(note) .where(and(eq(note.id, input.id), eq(note.userId, ctx.session.userId))) return { success: true } }), get: authProcedure .input( z.object({ id: z.string(), }) ) .query(async ({ ctx, input }) => { const noteData = await ctx.db .select() .from(note) .where(and(eq(note.id, input.id), eq(note.userId, ctx.session.userId))) if (!noteData[0]) return null const checklistItems = await ctx.db .select() .from(checklistItem) .where(eq(checklistItem.noteId, input.id)) const images = await ctx.db .select() .from(noteImage) .where(eq(noteImage.noteId, input.id)) return { ...noteData[0], checklistItems, images, } }), getAll: authProcedure .input( z.object({ title: z.string().optional(), tags: z.array(z.string()).optional(), content: z.string().optional(), }) ) .query(async ({ ctx, input }) => { const conditions = [ eq(note.userId, ctx.session.userId), eq(note.status, 'active'), ] if (input.title) { conditions.push(ilike(note.title, `%${input.title}%`)) } if (input.content) { conditions.push(ilike(note.content, `%${input.content}%`)) } if (input.tags && input.tags.length > 0) { conditions.push( sql`${note.tags} && ARRAY[${sql.join(input.tags.map((tag) => sql`${tag}`))}]::text[]` ) } return ctx.db.select().from(note).where(and(...conditions)) }), getTags: authProcedure.query(async ({ ctx }) => { const tags = await ctx.db .select({ tag: sql<string>`unnest(${note.tags})`.as('tag') }) .from(note) .where(eq(note.userId, ctx.session.userId)) return [...new Set(tags.map((row) => row.tag))] }), getArchived: authProcedure.query(async ({ ctx }) => { return await ctx.db .select() .from(note) .where(and(eq(note.userId, ctx.session.userId), eq(note.status, 'archived'))) }), })