Add includable fields for all ressources

This commit is contained in:
2023-10-08 19:15:25 +02:00
parent be58e932a9
commit 76d7e69d19
11 changed files with 149 additions and 27 deletions

View File

@@ -12,6 +12,7 @@ import {
Post,
Query,
Req,
UseGuards,
} from '@nestjs/common';
import { ApiOkResponsePlaginated, Plage } from 'src/models/plage';
import { CreateAlbumDto } from './dto/create-album.dto';
@@ -21,11 +22,18 @@ import { Prisma, Album } from '@prisma/client';
import { ApiOkResponse, ApiOperation, ApiTags } from '@nestjs/swagger';
import { FilterQuery } from 'src/utils/filter.pipe';
import { Album as _Album } from 'src/_gen/prisma-class/album';
import { IncludeMap, mapInclude } from 'src/utils/include';
import { JwtAuthGuard } from 'src/auth/jwt-auth.guard';
@Controller('album')
@ApiTags('album')
@UseGuards(JwtAuthGuard)
export class AlbumController {
static filterableFields: string[] = ['+id', 'name', '+artistId'];
static includableFields: IncludeMap<Prisma.AlbumInclude> = {
artist: true,
Song: true,
};
constructor(private readonly albumService: AlbumService) {}
@@ -65,6 +73,7 @@ export class AlbumController {
@Req() req: Request,
@FilterQuery(AlbumController.filterableFields)
where: Prisma.AlbumWhereInput,
@Query('include') include: string,
@Query('skip', new DefaultValuePipe(0), ParseIntPipe) skip: number,
@Query('take', new DefaultValuePipe(20), ParseIntPipe) take: number,
): Promise<Plage<Album>> {
@@ -72,6 +81,7 @@ export class AlbumController {
skip,
take,
where,
include: mapInclude(include, req, AlbumController.includableFields),
});
return new Plage(ret, req);
}
@@ -79,8 +89,15 @@ export class AlbumController {
@Get(':id')
@ApiOperation({ description: 'Get an album by id' })
@ApiOkResponse({ type: _Album })
async findOne(@Param('id', ParseIntPipe) id: number) {
const res = await this.albumService.album({ id });
async findOne(
@Req() req: Request,
@Query('include') include: string,
@Param('id', ParseIntPipe) id: number,
) {
const res = await this.albumService.album(
{ id },
mapInclude(include, req, AlbumController.includableFields),
);
if (res === null) throw new NotFoundException('Album not found');
return res;

View File

@@ -14,9 +14,11 @@ export class AlbumService {
async album(
albumWhereUniqueInput: Prisma.AlbumWhereUniqueInput,
include?: Prisma.AlbumInclude,
): Promise<Album | null> {
return this.prisma.album.findUnique({
where: albumWhereUniqueInput,
include,
});
}
@@ -26,14 +28,16 @@ export class AlbumService {
cursor?: Prisma.AlbumWhereUniqueInput;
where?: Prisma.AlbumWhereInput;
orderBy?: Prisma.AlbumOrderByWithRelationInput;
include?: Prisma.AlbumInclude;
}): Promise<Album[]> {
const { skip, take, cursor, where, orderBy } = params;
const { skip, take, cursor, where, orderBy, include } = params;
return this.prisma.album.findMany({
skip,
take,
cursor,
where,
orderBy,
include,
});
}

View File

@@ -14,6 +14,7 @@ import {
Query,
Req,
StreamableFile,
UseGuards,
} from '@nestjs/common';
import { ApiOkResponsePlaginated, Plage } from 'src/models/plage';
import { CreateArtistDto } from './dto/create-artist.dto';
@@ -29,11 +30,18 @@ import {
import { createReadStream, existsSync } from 'fs';
import { FilterQuery } from 'src/utils/filter.pipe';
import { Artist as _Artist } from 'src/_gen/prisma-class/artist';
import { IncludeMap, mapInclude } from 'src/utils/include';
import { JwtAuthGuard } from 'src/auth/jwt-auth.guard';
@Controller('artist')
@ApiTags('artist')
@UseGuards(JwtAuthGuard)
export class ArtistController {
static filterableFields = ['+id', 'name'];
static includableFields: IncludeMap<Prisma.ArtistInclude> = {
Song: true,
Album: true,
};
constructor(private readonly service: ArtistService) {}
@@ -84,6 +92,7 @@ export class ArtistController {
@Req() req: Request,
@FilterQuery(ArtistController.filterableFields)
where: Prisma.ArtistWhereInput,
@Query('include') include: string,
@Query('skip', new DefaultValuePipe(0), ParseIntPipe) skip: number,
@Query('take', new DefaultValuePipe(20), ParseIntPipe) take: number,
): Promise<Plage<Artist>> {
@@ -91,6 +100,7 @@ export class ArtistController {
skip,
take,
where,
include: mapInclude(include, req, ArtistController.includableFields),
});
return new Plage(ret, req);
}
@@ -98,8 +108,15 @@ export class ArtistController {
@Get(':id')
@ApiOperation({ description: 'Get an artist by id' })
@ApiOkResponse({ type: _Artist })
async findOne(@Param('id', ParseIntPipe) id: number) {
const res = await this.service.get({ id });
async findOne(
@Req() req: Request,
@Query('include') include: string,
@Param('id', ParseIntPipe) id: number,
) {
const res = await this.service.get(
{ id },
mapInclude(include, req, ArtistController.includableFields),
);
if (res === null) throw new NotFoundException('Artist not found');
return res;

View File

@@ -12,9 +12,13 @@ export class ArtistService {
});
}
async get(where: Prisma.ArtistWhereUniqueInput): Promise<Artist | null> {
async get(
where: Prisma.ArtistWhereUniqueInput,
include?: Prisma.ArtistInclude,
): Promise<Artist | null> {
return this.prisma.artist.findUnique({
where,
include,
});
}
@@ -24,14 +28,16 @@ export class ArtistService {
cursor?: Prisma.ArtistWhereUniqueInput;
where?: Prisma.ArtistWhereInput;
orderBy?: Prisma.ArtistOrderByWithRelationInput;
include?: Prisma.ArtistInclude;
}): Promise<Artist[]> {
const { skip, take, cursor, where, orderBy } = params;
const { skip, take, cursor, where, orderBy, include } = params;
return this.prisma.artist.findMany({
skip,
take,
cursor,
where,
orderBy,
include,
});
}

View File

@@ -13,6 +13,7 @@ import {
Query,
Req,
StreamableFile,
UseGuards,
} from '@nestjs/common';
import { ApiOkResponsePlaginated, Plage } from 'src/models/plage';
import { CreateGenreDto } from './dto/create-genre.dto';
@@ -23,11 +24,17 @@ import { ApiTags } from '@nestjs/swagger';
import { createReadStream, existsSync } from 'fs';
import { FilterQuery } from 'src/utils/filter.pipe';
import { Genre as _Genre } from 'src/_gen/prisma-class/genre';
import { IncludeMap, mapInclude } from 'src/utils/include';
import { JwtAuthGuard } from 'src/auth/jwt-auth.guard';
@Controller('genre')
@ApiTags('genre')
@UseGuards(JwtAuthGuard)
export class GenreController {
static filterableFields: string[] = ['+id', 'name'];
static includableFields: IncludeMap<Prisma.GenreInclude> = {
Song: true,
};
constructor(private readonly service: GenreService) {}
@@ -71,6 +78,7 @@ export class GenreController {
@Req() req: Request,
@FilterQuery(GenreController.filterableFields)
where: Prisma.GenreWhereInput,
@Query('include') include: string,
@Query('skip', new DefaultValuePipe(0), ParseIntPipe) skip: number,
@Query('take', new DefaultValuePipe(20), ParseIntPipe) take: number,
): Promise<Plage<Genre>> {
@@ -78,13 +86,21 @@ export class GenreController {
skip,
take,
where,
include: mapInclude(include, req, GenreController.includableFields),
});
return new Plage(ret, req);
}
@Get(':id')
async findOne(@Param('id', ParseIntPipe) id: number) {
const res = await this.service.get({ id });
async findOne(
@Req() req: Request,
@Query('include') include: string,
@Param('id', ParseIntPipe) id: number,
) {
const res = await this.service.get(
{ id },
mapInclude(include, req, GenreController.includableFields),
);
if (res === null) throw new NotFoundException('Genre not found');
return res;

View File

@@ -12,9 +12,13 @@ export class GenreService {
});
}
async get(where: Prisma.GenreWhereUniqueInput): Promise<Genre | null> {
async get(
where: Prisma.GenreWhereUniqueInput,
include?: Prisma.GenreInclude,
): Promise<Genre | null> {
return this.prisma.genre.findUnique({
where,
include,
});
}
@@ -24,14 +28,16 @@ export class GenreService {
cursor?: Prisma.GenreWhereUniqueInput;
where?: Prisma.GenreWhereInput;
orderBy?: Prisma.GenreOrderByWithRelationInput;
include?: Prisma.GenreInclude;
}): Promise<Genre[]> {
const { skip, take, cursor, where, orderBy } = params;
const { skip, take, cursor, where, orderBy, include } = params;
return this.prisma.genre.findMany({
skip,
take,
cursor,
where,
orderBy,
include,
});
}

View File

@@ -3,7 +3,6 @@ import {
Get,
Query,
Req,
Request,
Param,
ParseIntPipe,
DefaultValuePipe,
@@ -12,6 +11,7 @@ import {
Body,
Delete,
NotFoundException,
UseGuards,
} from '@nestjs/common';
import { ApiOkResponsePlaginated, Plage } from 'src/models/plage';
import { LessonService } from './lesson.service';
@@ -19,6 +19,9 @@ import { ApiOperation, ApiProperty, ApiTags } from '@nestjs/swagger';
import { Prisma, Skill } from '@prisma/client';
import { FilterQuery } from 'src/utils/filter.pipe';
import { Lesson as _Lesson } from 'src/_gen/prisma-class/lesson';
import { JwtAuthGuard } from 'src/auth/jwt-auth.guard';
import { IncludeMap, mapInclude } from 'src/utils/include';
import { Request } from 'express';
export class Lesson {
@ApiProperty()
@@ -35,6 +38,7 @@ export class Lesson {
@ApiTags('lessons')
@Controller('lesson')
@UseGuards(JwtAuthGuard)
export class LessonController {
static filterableFields: string[] = [
'+id',
@@ -42,6 +46,9 @@ export class LessonController {
'+requiredLevel',
'mainSkill',
];
static includableFields: IncludeMap<Prisma.LessonInclude> = {
LessonHistory: true,
};
constructor(private lessonService: LessonService) {}
@@ -54,6 +61,7 @@ export class LessonController {
@Req() request: Request,
@FilterQuery(LessonController.filterableFields)
where: Prisma.LessonWhereInput,
@Query('include') include: string,
@Query('skip', new DefaultValuePipe(0), ParseIntPipe) skip: number,
@Query('take', new DefaultValuePipe(20), ParseIntPipe) take: number,
): Promise<Plage<Lesson>> {
@@ -61,6 +69,7 @@ export class LessonController {
skip,
take,
where,
include: mapInclude(include, request, LessonController.includableFields),
});
return new Plage(ret, request);
}
@@ -69,8 +78,15 @@ export class LessonController {
summary: 'Get a particular lessons',
})
@Get(':id')
async get(@Param('id', ParseIntPipe) id: number): Promise<Lesson> {
const ret = await this.lessonService.get(id);
async get(
@Req() req: Request,
@Query('include') include: string,
@Param('id', ParseIntPipe) id: number,
): Promise<Lesson> {
const ret = await this.lessonService.get(
id,
mapInclude(include, req, LessonController.includableFields),
);
if (!ret) throw new NotFoundException();
return ret;
}

View File

@@ -12,22 +12,28 @@ export class LessonService {
cursor?: Prisma.LessonWhereUniqueInput;
where?: Prisma.LessonWhereInput;
orderBy?: Prisma.LessonOrderByWithRelationInput;
include?: Prisma.LessonInclude;
}): Promise<Lesson[]> {
const { skip, take, cursor, where, orderBy } = params;
const { skip, take, cursor, where, orderBy, include } = params;
return this.prisma.lesson.findMany({
skip,
take,
cursor,
where,
orderBy,
include,
});
}
async get(id: number): Promise<Lesson | null> {
async get(
id: number,
include?: Prisma.LessonInclude,
): Promise<Lesson | null> {
return this.prisma.lesson.findFirst({
where: {
id: id,
},
include,
});
}

View File

@@ -9,6 +9,7 @@ import {
Param,
ParseIntPipe,
Post,
Query,
Request,
UseGuards,
} from '@nestjs/common';
@@ -26,6 +27,10 @@ import { SearchService } from './search.service';
import { Song as _Song } from 'src/_gen/prisma-class/song';
import { Genre as _Genre } from 'src/_gen/prisma-class/genre';
import { Artist as _Artist } from 'src/_gen/prisma-class/artist';
import { mapInclude } from 'src/utils/include';
import { SongController } from 'src/song/song.controller';
import { GenreController } from 'src/genre/genre.controller';
import { ArtistController } from 'src/artist/artist.controller';
@ApiTags('search')
@Controller('search')
@@ -39,10 +44,15 @@ export class SearchController {
@UseGuards(JwtAuthGuard)
async searchSong(
@Request() req: any,
@Query('include') include: string,
@Param('query') query: string,
): Promise<Song[] | null> {
try {
const ret = await this.searchService.songByGuess(query, req.user?.id);
const ret = await this.searchService.songByGuess(
query,
req.user?.id,
mapInclude(include, req, SongController.includableFields),
);
if (!ret.length) throw new NotFoundException();
else return ret;
} catch (error) {
@@ -57,10 +67,15 @@ export class SearchController {
@ApiOperation({ description: 'Search a genre' })
async searchGenre(
@Request() req: any,
@Query('include') include: string,
@Param('query') query: string,
): Promise<Genre[] | null> {
try {
const ret = await this.searchService.genreByGuess(query, req.user?.id);
const ret = await this.searchService.genreByGuess(
query,
req.user?.id,
mapInclude(include, req, GenreController.includableFields),
);
if (!ret.length) throw new NotFoundException();
else return ret;
} catch (error) {
@@ -75,10 +90,15 @@ export class SearchController {
@ApiOperation({ description: 'Search an artist' })
async searchArtists(
@Request() req: any,
@Query('include') include: string,
@Param('query') query: string,
): Promise<Artist[] | null> {
try {
const ret = await this.searchService.artistByGuess(query, req.user?.id);
const ret = await this.searchService.artistByGuess(
query,
req.user?.id,
mapInclude(include, req, ArtistController.includableFields),
);
if (!ret.length) throw new NotFoundException();
else return ret;
} catch (error) {

View File

@@ -10,27 +10,42 @@ export class SearchService {
private history: HistoryService,
) {}
async songByGuess(query: string, userID: number): Promise<Song[]> {
async songByGuess(
query: string,
userID: number,
include?: Prisma.SongInclude,
): Promise<Song[]> {
return this.prisma.song.findMany({
where: {
name: { contains: query, mode: 'insensitive' },
},
include,
});
}
async genreByGuess(query: string, userID: number): Promise<Genre[]> {
async genreByGuess(
query: string,
userID: number,
include?: Prisma.GenreInclude,
): Promise<Genre[]> {
return this.prisma.genre.findMany({
where: {
name: { contains: query, mode: 'insensitive' },
},
include,
});
}
async artistByGuess(query: string, userID: number): Promise<Artist[]> {
async artistByGuess(
query: string,
userID: number,
include?: Prisma.ArtistInclude,
): Promise<Artist[]> {
return this.prisma.artist.findMany({
where: {
name: { contains: query, mode: 'insensitive' },
},
include,
});
}
}

View File

@@ -46,6 +46,7 @@ class SongHistoryResult {
@Controller('song')
@ApiTags('song')
@UseGuards(JwtAuthGuard)
export class SongController {
static filterableFields: string[] = [
'+id',
@@ -54,7 +55,7 @@ export class SongController {
'+albumId',
'+genreId',
];
static includableFileds: IncludeMap<Prisma.SongInclude> = {
static includableFields: IncludeMap<Prisma.SongInclude> = {
artist: true,
album: true,
genre: true,
@@ -168,13 +169,12 @@ export class SongController {
skip,
take,
where,
include: mapInclude(include, req, SongController.includableFileds),
include: mapInclude(include, req, SongController.includableFields),
});
return new Plage(ret, req);
}
@Get(':id')
@UseGuards(JwtAuthGuard)
@ApiOperation({ description: 'Get a specific song data' })
@ApiNotFoundResponse({ description: 'Song not found' })
@ApiOkResponse({ type: _Song, description: 'Requested song' })
@@ -187,7 +187,7 @@ export class SongController {
{
id,
},
mapInclude(include, req, SongController.includableFileds),
mapInclude(include, req, SongController.includableFields),
);
if (res === null) throw new NotFoundException('Song not found');
@@ -196,7 +196,6 @@ export class SongController {
@Get(':id/history')
@HttpCode(200)
@UseGuards(JwtAuthGuard)
@ApiOperation({
description: 'get the history of the connected user on a specific song',
})