This commit is contained in:
Bastian Wagner
2025-12-19 11:18:53 +01:00
commit 5a08e2319f
48 changed files with 23098 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
import { Test, TestingModule } from '@nestjs/testing';
import { AppController } from './app.controller';
import { AppService } from './app.service';
describe('AppController', () => {
let appController: AppController;
beforeEach(async () => {
const app: TestingModule = await Test.createTestingModule({
controllers: [AppController],
providers: [AppService],
}).compile();
appController = app.get<AppController>(AppController);
});
describe('root', () => {
it('should return "Hello World!"', () => {
expect(appController.getHello()).toBe('Hello World!');
});
});
});

View File

@@ -0,0 +1,12 @@
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
}

View File

@@ -0,0 +1,23 @@
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { DatabaseModule } from './database/database.module';
import { GroupsModule } from './groups/groups.module';
@Module({
imports: [ConfigModule.forRoot({
envFilePath: '.env',
isGlobal: true
}),
DatabaseModule,
GroupsModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {
constructor(private config: ConfigService) {
console.log(config.get('DATABASE_USER'))
}
}

View File

@@ -0,0 +1,8 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}

View File

@@ -0,0 +1,30 @@
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { GroupEntity } from '../groups/persistence/group.entity';
const ENTITY = [GroupEntity]
@Module({
imports: [
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: (configService: ConfigService) => ({
type: 'mysql',
host: configService.get('DATABASE_HOST') || 'localhost',
port: parseInt(configService.get('DATABASE_PORT') || '0'),
username: configService.get('DATABASE_USER'),
password: configService.get('DATABASE_PASSWORD'),
database: configService.get('DATABASE_NAME'),
entities: ENTITY,
synchronize: true,
})
})
],
providers: [ConfigService,],
exports: [TypeOrmModule]
})
export class DatabaseModule {}

View File

@@ -0,0 +1,15 @@
import { Body, Controller, Post } from "@nestjs/common";
import { CreateGroupDto } from "../dto/create-group.dto";
import { GroupsService } from "../application/groups.service";
@Controller({path: 'groups'})
export class GroupsController {
constructor(private groupsService: GroupsService) {}
@Post()
createGroup(@Body() dto: CreateGroupDto) {
return this.groupsService.create(dto);
}
}

View File

@@ -0,0 +1,18 @@
import { Injectable, NotFoundException } from "@nestjs/common";
import { GroupsRepository } from "../persistence/group.repository";
import { CreateGroupDto } from "../dto/create-group.dto";
@Injectable()
export class GroupsService {
constructor(private readonly groups: GroupsRepository) {}
async join(id: string) {
const group = await this.groups.findById(id);
if (!group) throw new NotFoundException();
return group;
}
async create(dto: CreateGroupDto) {
return this.groups.create(dto);
}
}

View File

@@ -0,0 +1,8 @@
import { IsString, IsNotEmpty, Length } from 'class-validator';
export class CreateGroupDto {
@IsString()
@IsNotEmpty()
@Length(1, 100)
name: string;
}

View File

@@ -0,0 +1,13 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { GroupEntity } from './persistence/group.entity';
import { GroupsController } from './api/groups.controller';
import { GroupsService } from './application/groups.service';
import { GroupsRepository } from './persistence/group.repository';
@Module({
imports: [TypeOrmModule.forFeature([GroupEntity])],
controllers: [GroupsController],
providers: [GroupsService, GroupsRepository]
})
export class GroupsModule {}

View File

@@ -0,0 +1,12 @@
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
@Entity('groups')
export class GroupEntity {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({nullable: false})
name: string;
}

View File

@@ -0,0 +1,25 @@
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { GroupEntity } from "./group.entity";
import { CreateGroupDto } from "../dto/create-group.dto";
@Injectable()
export class GroupsRepository {
constructor(
@InjectRepository(GroupEntity)
private readonly repo: Repository<GroupEntity>,
) {}
save(group: GroupEntity) {
return this.repo.save(group);
}
findById(id: string) {
return this.repo.findOne({ where: { id } });
}
create(dto: CreateGroupDto) {
return this.repo.save(this.repo.create(dto))
}
}

19
costly-api/src/main.ts Normal file
View File

@@ -0,0 +1,19 @@
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(
new ValidationPipe({
whitelist: true, // entfernt unbekannte Felder
forbidNonWhitelisted: true, // wirft Fehler bei unbekannten Feldern
transform: true, // DTOs werden automatisch instanziiert
transformOptions: {
enableImplicitConversion: true,
},
}),
);
await app.listen(process.env.PORT ?? 3000);
}
bootstrap();