vokabeltraining/api/src/app/drizzle.service.ts

155 lines
5.0 KiB
TypeScript

// 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' };
}
}