Added redoc and skills endpoints

This commit is contained in:
Thom Werring 2023-10-21 10:29:20 +02:00
parent 9fa7224303
commit 4263dc70da
6 changed files with 169 additions and 2 deletions

View file

@ -1,13 +1,30 @@
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
import { ApiExtraModels, ApiOkResponse, ApiResponse, ApiTags, getSchemaPath } from "@nestjs/swagger";
import { SkillsService } from "src/skills/skills.service";
import { SkillDto } from "src/skills/skills.types";
@Controller()
@ApiExtraModels(SkillDto)
export class AppController {
constructor(private readonly appService: AppService) {}
constructor(private readonly appService: AppService, private readonly skillsService: SkillsService) {}
@Get()
sayHello(): string {
return this.appService.getHello();
}
@Get("skills")
@ApiTags("Skills")
@ApiOkResponse({
description: "Returns a list of all skills",
schema: {
items: {
$ref: getSchemaPath(SkillDto)
}
}
})
getSkills(): ReadonlyArray<SkillDto> {
return this.skillsService.getSkills({ })
}
}

View file

@ -1,10 +1,11 @@
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { SkillsService } from './skills/skills.service';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
providers: [AppService, SkillsService],
})
export class AppModule {}

View file

@ -1,6 +1,7 @@
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
import { SwaggerModule, DocumentBuilder } from "@nestjs/swagger";
import { RedocModule, RedocOptions } from "@juicyllama/nestjs-redoc";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
@ -19,6 +20,29 @@ async function bootstrap() {
operationIdFactory: (controllerKey: string, methodKey: string) => (`${methodKey[0].toUpperCase()}${methodKey.substring(1)}`)
});
const redocOptions: RedocOptions = {
title: 'CV - Thom Werring',
logo: {
url: 'https://picsum.photos/256/128',
altText: 'Thom Werring'
},
sortPropsAlphabetically: true,
hideDownloadButton: false,
hideHostname: true,
tagGroups: [
{
name: 'Skills',
tags: ['Skills', ],
},
{
name: 'Experience',
tags: ['Saysimple', 'Blackorange', 'Werring webdevelopment'],
},
],
};
await RedocModule.setup('/docs', app, document, redocOptions);
SwaggerModule.setup("/api", app, document);
await app.listen(3000);

View file

@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { SkillsService } from './skills.service';
describe('SkillsService', () => {
let service: SkillsService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [SkillsService],
}).compile();
service = module.get<SkillsService>(SkillsService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View file

@ -0,0 +1,72 @@
import { Injectable } from "@nestjs/common";
import { SkillDto, SkillType } from "src/skills/skills.types";
@Injectable()
export class SkillsService {
private readonly skills: ReadonlyArray<SkillDto>;
constructor() {
this.skills = SkillDto.asDto([
{
name: "Git",
description: "Working with git, maintaining repositories, managing pull/merge requests.",
category: "Version control systems",
},
{
name: "NodeJs, TypeScript, and Javascript",
description: "Building efficient and scalable microservices.",
category: "Programming languages",
},
{
name: "Docker",
description: "Containerizing and running microservices in a local development environment.",
category: "Containerization",
},
{
name: "Kubernetes",
description: "Deploying microservices to AWS (EKS).",
category: "Containerization",
},
{
name: "EKS",
description: "Managing Elastic Kubernetes Service on AWS.",
category: "AWS",
},
{
name: "API Gateway",
description: "Building and deploying cloud based applications.",
category: "AWS",
},
{
name: "Lambda",
description: "Building and deploying cloud based applications.",
category: "AWS",
},
{
name: "CloudWatch",
description: "Monitoring cloud based applications.",
category: "AWS",
},
{
name: "CI/CD pipelines",
description: "Automating testing, building and deployments.",
category: "DevOps",
},
{
name: "PHP",
description: "Building Websites and applications in PHP Laravel.",
category: "Programming languages",
},
])
.sort((skillA, skillB) => skillA.category > skillB.category ? 1 : -1);
}
getSkills(filter?: Partial<SkillType>) {
const filtersValues = Object.entries(filter).map(([key, filterValue]) => ([key, new RegExp(filterValue, "i")])) as [keyof SkillType, RegExp][];
if (!filter || filtersValues.length === 0) {
return this.skills;
}
return this.skills.filter((skill) => filtersValues.some(([key, filterValue]) => filterValue.test(skill[key])));
}
}

View file

@ -0,0 +1,35 @@
import { ApiProperty } from "@nestjs/swagger";
export type SkillType = {
name: string;
category: string;
description: string;
}
type Test<T extends SkillType | SkillType[]> = T extends SkillType ? SkillDto : SkillDto[];
export class SkillDto implements SkillType {
@ApiProperty()
readonly name: string;
@ApiProperty()
readonly category: string;
@ApiProperty()
readonly description: string;
constructor(skill: SkillType) {
Object.assign(this, {
name: skill.name,
category: skill.category,
descriptions: skill.description
});
}
public static asDto<T extends SkillType>(skills: T): SkillDto
public static asDto<T extends SkillType[]>(skills: T): SkillDto[]
public static asDto<T extends SkillType | SkillType[]>(skills: T): SkillDto | SkillDto[] {
if (!Array.isArray(skills)) {
return new SkillDto(skills);
}
return skills.map((skill) => new SkillDto(skill));
}
}