Pushing errors back to frontend
Some checks failed
Music Collection CI Workflow / test (./backend) (push) Failing after 26s
Music Collection CI Workflow / test (./frontend) (push) Successful in 38s
Music Collection CI Workflow / build-and-push-images (./backend/Dockerfile, git.anatid.net/tabris/music-collection-backend, ./backend) (push) Has been skipped
Music Collection CI Workflow / build-and-push-images (./frontend/Dockerfile, git.anatid.net/tabris/music-collection-frontend, ./frontend) (push) Has been skipped
Music Collection CI Workflow / deploy (push) Has been skipped
Some checks failed
Music Collection CI Workflow / test (./backend) (push) Failing after 26s
Music Collection CI Workflow / test (./frontend) (push) Successful in 38s
Music Collection CI Workflow / build-and-push-images (./backend/Dockerfile, git.anatid.net/tabris/music-collection-backend, ./backend) (push) Has been skipped
Music Collection CI Workflow / build-and-push-images (./frontend/Dockerfile, git.anatid.net/tabris/music-collection-frontend, ./frontend) (push) Has been skipped
Music Collection CI Workflow / deploy (push) Has been skipped
This commit is contained in:
parent
040675bb5d
commit
2214fa32f5
@ -31,7 +31,9 @@ export class AlbumController {
|
||||
|
||||
@Post()
|
||||
@UsePipes(new ValidationPipe({ transform: true }))
|
||||
async create(@Body() createAlbumDto: CreateAlbumDto): Promise<Album | string | null> {
|
||||
async create(
|
||||
@Body() createAlbumDto: CreateAlbumDto,
|
||||
): Promise<Album | string | null> {
|
||||
return this.albumService.create(createAlbumDto);
|
||||
}
|
||||
|
||||
|
@ -13,40 +13,45 @@ export class AlbumService {
|
||||
) {}
|
||||
|
||||
findAll(): Promise<Album[] | string | null> {
|
||||
return this.albumRepository.find({
|
||||
order: {
|
||||
artist: 'ASC',
|
||||
title: 'ASC',
|
||||
},
|
||||
}).then((albums) => {
|
||||
return albums;
|
||||
})
|
||||
.catch((error) => {
|
||||
return `There was a problem getting the list of albums: ${error}`
|
||||
});
|
||||
return this.albumRepository
|
||||
.find({
|
||||
order: {
|
||||
artist: 'ASC',
|
||||
title: 'ASC',
|
||||
},
|
||||
})
|
||||
.then((albums) => {
|
||||
return albums;
|
||||
})
|
||||
.catch((error) => {
|
||||
return `There was a problem getting the list of albums: ${error}`;
|
||||
});
|
||||
}
|
||||
|
||||
findOneById(id: number): Promise<Album | string | null> {
|
||||
return this.albumRepository.findOne({
|
||||
where: {
|
||||
id: id,
|
||||
},
|
||||
relations: {
|
||||
songs: true,
|
||||
},
|
||||
order: {
|
||||
songs: {
|
||||
trackNumber: 'ASC',
|
||||
return this.albumRepository
|
||||
.findOne({
|
||||
where: {
|
||||
id: id,
|
||||
},
|
||||
},
|
||||
}).then((album) => {
|
||||
return album;
|
||||
})
|
||||
.catch((error) => {
|
||||
return `There was a problem creating the Album identified by ID ${id}: ${error}`
|
||||
}).finally(() => {
|
||||
return `There was a problem creating the Album identified by ID ${id}`
|
||||
});
|
||||
relations: {
|
||||
songs: true,
|
||||
},
|
||||
order: {
|
||||
songs: {
|
||||
trackNumber: 'ASC',
|
||||
},
|
||||
},
|
||||
})
|
||||
.then((album) => {
|
||||
return album;
|
||||
})
|
||||
.catch((error) => {
|
||||
return `There was a problem creating the Album identified by ID ${id}: ${error}`;
|
||||
})
|
||||
.finally(() => {
|
||||
return `There was a problem creating the Album identified by ID ${id}`;
|
||||
});
|
||||
}
|
||||
|
||||
async create(createAlbumDto: CreateAlbumDto): Promise<Album | string | null> {
|
||||
@ -55,12 +60,13 @@ export class AlbumService {
|
||||
artist: createAlbumDto.artist,
|
||||
genre: createAlbumDto.genre,
|
||||
});
|
||||
return await this.albumRepository.save(album)
|
||||
return await this.albumRepository
|
||||
.save(album)
|
||||
.then((savedAlbum) => {
|
||||
return savedAlbum;
|
||||
})
|
||||
.catch((error) => {
|
||||
return `There was a problem creating the Album (${createAlbumDto.title} by ${createAlbumDto.artist} (${createAlbumDto.genre})): ${error}`
|
||||
return `There was a problem creating the Album (${createAlbumDto.title} by ${createAlbumDto.artist} (${createAlbumDto.genre})): ${error}`;
|
||||
});
|
||||
}
|
||||
|
||||
@ -100,12 +106,13 @@ export class AlbumService {
|
||||
}
|
||||
|
||||
async remove(id: number): Promise<DeleteResult | string | null> {
|
||||
return await this.albumRepository.delete(id)
|
||||
.then((deleteResult) => {
|
||||
return deleteResult;
|
||||
})
|
||||
.catch((error) => {
|
||||
return `There was a problem deleting the Album identified by ID ${id}: ${error}`
|
||||
});
|
||||
return await this.albumRepository
|
||||
.delete(id)
|
||||
.then((deleteResult) => {
|
||||
return deleteResult;
|
||||
})
|
||||
.catch((error) => {
|
||||
return `There was a problem deleting the Album identified by ID ${id}: ${error}`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { IsNotEmpty, IsString } from 'class-validator';
|
||||
|
||||
export class CreateAlbumDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { IsNotEmpty, IsNumber, IsString } from 'class-validator';
|
||||
|
||||
export class UpdateAlbumDto {
|
||||
@Column()
|
||||
@IsNumber()
|
||||
id: number;
|
||||
|
||||
@ -13,7 +14,6 @@ export class UpdateAlbumDto {
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
genre: string;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { ValidationPipe } from '@nestjs/common';
|
||||
import { UnprocessableEntityException, ValidationError, ValidationPipe } from '@nestjs/common';
|
||||
import { AppModule } from './app.module';
|
||||
|
||||
async function bootstrap() {
|
||||
@ -13,16 +13,53 @@ async function bootstrap() {
|
||||
allowedHeaders:
|
||||
'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept, Observe',
|
||||
});
|
||||
app.useGlobalPipes(new ValidationPipe({
|
||||
transform: true,
|
||||
exceptionFactory: (errors) => {
|
||||
const result = errors.map((error) => ({
|
||||
property: error.property,
|
||||
message: error.constraints[Object.keys(error.constraints)[0]],
|
||||
}));
|
||||
return new UnprocessableEntityException(result);
|
||||
app.useGlobalPipes(
|
||||
new ValidationPipe({
|
||||
transform: true,
|
||||
whitelist: true,
|
||||
exceptionFactory: (validationErrors: ValidationError[] = []) => {
|
||||
const getPrettyClassValidatorErrors = (
|
||||
validationErrors: ValidationError[],
|
||||
parentProperty = '',
|
||||
): Array<{ property: string; errors: string[] }> => {
|
||||
const errors : any[] = [];
|
||||
|
||||
const getValidationErrorsRecursively = (
|
||||
validationErrors: ValidationError[],
|
||||
parentProperty = '',
|
||||
) => {
|
||||
for (const error of validationErrors) {
|
||||
const propertyPath = parentProperty
|
||||
? `${parentProperty}.${error.property}`
|
||||
: error.property;
|
||||
|
||||
if (error.constraints) {
|
||||
errors.push({
|
||||
property: propertyPath,
|
||||
errors: Object.values(error.constraints),
|
||||
});
|
||||
}
|
||||
|
||||
if (error.children?.length) {
|
||||
getValidationErrorsRecursively(error.children, propertyPath);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
getValidationErrorsRecursively(validationErrors, parentProperty);
|
||||
|
||||
return errors;
|
||||
};
|
||||
|
||||
const errors = getPrettyClassValidatorErrors(validationErrors);
|
||||
|
||||
return new UnprocessableEntityException({
|
||||
message: 'validation error',
|
||||
errors: errors,
|
||||
});
|
||||
},
|
||||
}));
|
||||
}),
|
||||
);
|
||||
await app.listen(process.env.PORT ?? 3000);
|
||||
}
|
||||
bootstrap();
|
||||
|
@ -1,21 +1,16 @@
|
||||
import { Entity, Column, ManyToOne, PrimaryGeneratedColumn } from 'typeorm';
|
||||
import { IsNotEmpty, IsNumber, IsString } from 'class-validator';
|
||||
|
||||
export class CreateSongDto {
|
||||
@Column({ unique: true })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
title: string;
|
||||
|
||||
@Column()
|
||||
@IsNumber()
|
||||
duration: number;
|
||||
|
||||
@Column()
|
||||
@IsNumber()
|
||||
trackNumber: number;
|
||||
|
||||
@Column()
|
||||
@IsNumber()
|
||||
albumId: number;
|
||||
}
|
||||
|
@ -1,22 +1,19 @@
|
||||
import { IsNotEmpty, IsNumber, IsString } from 'class-validator';
|
||||
|
||||
export class UpdateSongDto {
|
||||
@Column()
|
||||
@IsNumber()
|
||||
id: number;
|
||||
|
||||
@Column({ unique: true })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
title: string;
|
||||
|
||||
@Column()
|
||||
@IsNumber()
|
||||
duration: number;
|
||||
|
||||
@Column()
|
||||
@IsNumber()
|
||||
trackNumber: number;
|
||||
|
||||
@Column()
|
||||
@IsNumber()
|
||||
albumId: number;
|
||||
}
|
||||
|
@ -31,7 +31,9 @@ export class SongController {
|
||||
|
||||
@Post()
|
||||
@UsePipes(new ValidationPipe({ transform: true }))
|
||||
async create(@Body() createSongDto: CreateSongDto): Promise<Song | string | null> {
|
||||
async create(
|
||||
@Body() createSongDto: CreateSongDto,
|
||||
): Promise<Song | string | null> {
|
||||
return this.songService.create(createSongDto);
|
||||
}
|
||||
|
||||
|
@ -16,25 +16,29 @@ export class SongService {
|
||||
) {}
|
||||
|
||||
findAll(): Promise<Song[] | string | null> {
|
||||
return this.songRepository.find({
|
||||
order: {
|
||||
trackNumber: 'ASC',
|
||||
},
|
||||
}).then((songs) => {
|
||||
return songs;
|
||||
})
|
||||
.catch((error) => {
|
||||
return `There was a problem getting the list of songs: ${error}`
|
||||
});
|
||||
return this.songRepository
|
||||
.find({
|
||||
order: {
|
||||
trackNumber: 'ASC',
|
||||
},
|
||||
})
|
||||
.then((songs) => {
|
||||
return songs;
|
||||
})
|
||||
.catch((error) => {
|
||||
return `There was a problem getting the list of songs: ${error}`;
|
||||
});
|
||||
}
|
||||
|
||||
findOneById(id: number): Promise<Song | string | null> {
|
||||
return this.songRepository.findOneBy({ id: id }).then((albums) => {
|
||||
return albums;
|
||||
})
|
||||
.catch((error) => {
|
||||
return `There was a problem getting the song identified by ID ${id}: ${error}`
|
||||
});
|
||||
return this.songRepository
|
||||
.findOneBy({ id: id })
|
||||
.then((albums) => {
|
||||
return albums;
|
||||
})
|
||||
.catch((error) => {
|
||||
return `There was a problem getting the song identified by ID ${id}: ${error}`;
|
||||
});
|
||||
}
|
||||
|
||||
async create(createSongDto: CreateSongDto): Promise<Song | string | null> {
|
||||
@ -47,18 +51,23 @@ export class SongService {
|
||||
song.duration = createSongDto.duration;
|
||||
song.trackNumber = createSongDto.trackNumber;
|
||||
song.album = album;
|
||||
return this.songRepository.save(song).then((albums) => {
|
||||
return albums;
|
||||
})
|
||||
.catch((error) => {
|
||||
return `There was a problem creating the song (${createSongDto.trackNumber} ${createSongDto.title} (${createSongDto.duration}s) on the Album ${album.title} by ${album.artist}): ${error}`
|
||||
});
|
||||
return this.songRepository
|
||||
.save(song)
|
||||
.then((albums) => {
|
||||
return albums;
|
||||
})
|
||||
.catch((error) => {
|
||||
return `There was a problem creating the song (${createSongDto.trackNumber} ${createSongDto.title} (${createSongDto.duration}s) on the Album ${album.title} by ${album.artist}): ${error}`;
|
||||
});
|
||||
} else {
|
||||
throw new Error(`Unable to find Album with ID ${createSongDto.albumId}`);
|
||||
}
|
||||
}
|
||||
|
||||
async update(id: number, updateSongDto: UpdateSongDto): Promise<Song | string | null> {
|
||||
async update(
|
||||
id: number,
|
||||
updateSongDto: UpdateSongDto,
|
||||
): Promise<Song | string | null> {
|
||||
if (id == updateSongDto.id) {
|
||||
const album = await this.albumRepository.findOneBy({
|
||||
id: updateSongDto.albumId,
|
||||
@ -91,12 +100,13 @@ export class SongService {
|
||||
}
|
||||
|
||||
async remove(id: number): Promise<DeleteResult | string | null> {
|
||||
return await this.songRepository.delete(id)
|
||||
.then((deleteResult) => {
|
||||
return deleteResult;
|
||||
})
|
||||
.catch((error) => {
|
||||
return `There was a problem deleting the Song identified by ID ${id}: ${error}`
|
||||
});
|
||||
return await this.songRepository
|
||||
.delete(id)
|
||||
.then((deleteResult) => {
|
||||
return deleteResult;
|
||||
})
|
||||
.catch((error) => {
|
||||
return `There was a problem deleting the Song identified by ID ${id}: ${error}`;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user