// drizzle.service.ts import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { and, eq, isNull } from 'drizzle-orm'; import { drizzle } from 'drizzle-orm/libsql'; import { Deck, User } from '../db/schema'; @Injectable() export class DrizzleService { private db = drizzle('file:local.db'); async getDecks(user: User) { return this.db.select().from(Deck).where(eq(Deck.user, user.email)); } async createDeck(deckname: string, user: User) { const result = await this.db.insert(Deck).values({ deckname, user: user.email }).returning(); return { status: 'success', deck: result }; } async getDeckByName(deckname: string, user: User) { return this.db .select() .from(Deck) .where(and(eq(Deck.deckname, deckname), eq(Deck.user, user.email))); } async deleteDeck(deckname: string, user: User) { const existingDeck = await this.getDeckByName(deckname, user); if (existingDeck.length === 0) { throw new HttpException('Deck not found', HttpStatus.NOT_FOUND); } await this.db.delete(Deck).where(and(eq(Deck.deckname, deckname), eq(Deck.user, user.email))); return { status: 'success' }; } async renameDeck(oldDeckname: string, newDeckname: string, user: User) { const existingDeck = await this.getDeckByName(oldDeckname, user); if (existingDeck.length === 0) { throw new HttpException('Deck not found', HttpStatus.NOT_FOUND); } const existingNewDeck = await this.getDeckByName(newDeckname, user); if (existingNewDeck.length > 0) { throw new HttpException('Deck with the new name already exists', HttpStatus.CONFLICT); } await this.db.update(Deck).set({ deckname: newDeckname }).where(eq(Deck.deckname, oldDeckname)); return { status: 'success', message: 'Deck renamed successfully' }; } async updateImage(data: { deckname: string; bildname: string; bildid: string; boxes: Array<{ x1: number; x2: number; y1: number; y2: number }> }, user: User) { const existingDeck = await this.getDeckByName(data.deckname, user); if (existingDeck.length === 0) { throw new HttpException('Deck not found', HttpStatus.NOT_FOUND); } await this.db.delete(Deck).where(and(eq(Deck.deckname, data.deckname), eq(Deck.bildid, data.bildid))); const insertedImages: any = []; for (let index = 0; index < data.boxes.length; index++) { const box = data.boxes[index]; const result = await this.db .insert(Deck) .values({ deckname: data.deckname, bildname: data.bildname, bildid: data.bildid, iconindex: index, x1: box.x1, x2: box.x2, y1: box.y1, y2: box.y2, user: 'andreas.knuth@gmail.com', }) .returning(); insertedImages.push(result); } return { status: 'success', inserted_images: insertedImages }; } async deleteImagesByBildId(bildid: string) { const affectedDecks = await this.db.select({ deckname: Deck.deckname }).from(Deck).where(eq(Deck.bildid, bildid)).all(); if (affectedDecks.length === 0) { throw new HttpException('No entries found for the given image ID', HttpStatus.NOT_FOUND); } await this.db.delete(Deck).where(eq(Deck.bildid, bildid)); for (const deck of affectedDecks) { const remainingImages = await this.db .select() .from(Deck) .where(and(eq(Deck.deckname, deck.deckname), eq(Deck.bildid, bildid))) .all(); if (remainingImages.length === 0) { const emptyDeckEntry = await this.db .select() .from(Deck) .where(and(eq(Deck.deckname, deck.deckname), isNull(Deck.bildid))) .all(); if (emptyDeckEntry.length === 0) { await this.db.insert(Deck).values({ deckname: deck.deckname, user: 'andreas.knuth@gmail.com' }); } } } return { status: 'success', message: `All entries for image ID "${bildid}" have been deleted.`, }; } async moveImage(bildid: string, targetDeckId: string) { const existingImages = await this.db.select().from(Deck).where(eq(Deck.bildid, bildid)).all(); if (existingImages.length === 0) { throw new HttpException('No entries found for the given image ID', HttpStatus.NOT_FOUND); } await this.db.update(Deck).set({ deckname: targetDeckId }).where(eq(Deck.bildid, bildid)); return { status: 'success', moved_entries: existingImages.length }; } async updateBox( boxId: number, data: { due?: number; ivl?: number; factor?: number; reps?: number; lapses?: number; isGraduated?: boolean; }, ) { const updateData: any = { ...data }; if (typeof data.isGraduated === 'boolean') { updateData.isGraduated = Number(data.isGraduated); } const result = await this.db.update(Deck).set(updateData).where(eq(Deck.id, boxId)); if (result.rowsAffected === 0) { throw new HttpException('Box not found', HttpStatus.NOT_FOUND); } return { status: 'success' }; } }