Merge branch 'dev-1' into dev

This commit is contained in:
Wuesteon 2025-12-05 17:57:26 +01:00
commit d41d060bb3
1770 changed files with 168028 additions and 31031 deletions

View file

@ -0,0 +1,41 @@
import { Controller, Get, Post, Put, Delete, Body, Param, UseGuards } from '@nestjs/common';
import { DeckService } from './deck.service';
import { CreateDeckDto } from './deck.dto';
import type { UpdateDeckDto } from './deck.dto';
import { JwtAuthGuard, CurrentUser } from '@manacore/shared-nestjs-auth';
import type { CurrentUserData } from '@manacore/shared-nestjs-auth';
@Controller('decks')
@UseGuards(JwtAuthGuard)
export class DeckController {
constructor(private readonly deckService: DeckService) {}
@Get()
async findAll(@CurrentUser() user: CurrentUserData) {
return this.deckService.findByUser(user.userId);
}
@Get(':id')
async findOne(@Param('id') id: string, @CurrentUser() user: CurrentUserData) {
return this.deckService.findOneWithSlides(id, user.userId);
}
@Post()
async create(@Body() createDeckDto: CreateDeckDto, @CurrentUser() user: CurrentUserData) {
return this.deckService.create(user.userId, createDeckDto);
}
@Put(':id')
async update(
@Param('id') id: string,
@Body() updateDeckDto: UpdateDeckDto,
@CurrentUser() user: CurrentUserData
) {
return this.deckService.update(id, user.userId, updateDeckDto);
}
@Delete(':id')
async remove(@Param('id') id: string, @CurrentUser() user: CurrentUserData) {
return this.deckService.remove(id, user.userId);
}
}

View file

@ -0,0 +1,32 @@
import { IsString, IsOptional, IsBoolean, IsUUID } from 'class-validator';
export class CreateDeckDto {
@IsString()
title: string;
@IsString()
@IsOptional()
description?: string;
@IsUUID()
@IsOptional()
themeId?: string;
}
export class UpdateDeckDto {
@IsString()
@IsOptional()
title?: string;
@IsString()
@IsOptional()
description?: string;
@IsUUID()
@IsOptional()
themeId?: string;
@IsBoolean()
@IsOptional()
isPublic?: boolean;
}

View file

@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { DeckController } from './deck.controller';
import { DeckService } from './deck.service';
@Module({
controllers: [DeckController],
providers: [DeckService],
exports: [DeckService],
})
export class DeckModule {}

View file

@ -0,0 +1,113 @@
import { Injectable, Inject, NotFoundException } from '@nestjs/common';
import { eq, and, desc } from 'drizzle-orm';
import { DATABASE_CONNECTION } from '../db/database.module';
import { Database } from '../db/connection';
import { decks, slides } from '../db/schema';
import { CreateDeckDto } from './deck.dto';
import type { UpdateDeckDto } from './deck.dto';
@Injectable()
export class DeckService {
constructor(
@Inject(DATABASE_CONNECTION)
private readonly db: Database
) {}
async findByUser(userId: string) {
return this.db.query.decks.findMany({
where: eq(decks.userId, userId),
orderBy: [desc(decks.updatedAt)],
with: {
theme: true,
},
});
}
async findOneWithSlides(id: string, userId: string) {
const deck = await this.db.query.decks.findFirst({
where: and(eq(decks.id, id), eq(decks.userId, userId)),
with: {
slides: {
orderBy: [slides.order],
},
theme: true,
},
});
if (!deck) {
throw new NotFoundException('Deck not found');
}
return deck;
}
async findOne(id: string) {
return this.db.query.decks.findFirst({
where: eq(decks.id, id),
with: {
slides: {
orderBy: [slides.order],
},
theme: true,
},
});
}
async create(userId: string, dto: CreateDeckDto) {
const [deck] = await this.db
.insert(decks)
.values({
userId,
title: dto.title,
description: dto.description,
themeId: dto.themeId,
})
.returning();
return deck;
}
async update(id: string, userId: string, dto: UpdateDeckDto) {
// Verify ownership
const existing = await this.db.query.decks.findFirst({
where: and(eq(decks.id, id), eq(decks.userId, userId)),
});
if (!existing) {
throw new NotFoundException('Deck not found');
}
const [updated] = await this.db
.update(decks)
.set({
...dto,
updatedAt: new Date(),
})
.where(eq(decks.id, id))
.returning();
return updated;
}
async remove(id: string, userId: string) {
// Verify ownership
const existing = await this.db.query.decks.findFirst({
where: and(eq(decks.id, id), eq(decks.userId, userId)),
});
if (!existing) {
throw new NotFoundException('Deck not found');
}
await this.db.delete(decks).where(eq(decks.id, id));
return { success: true };
}
async verifyOwnership(id: string, userId: string): Promise<boolean> {
const deck = await this.db.query.decks.findFirst({
where: and(eq(decks.id, id), eq(decks.userId, userId)),
});
return !!deck;
}
}