Added redoc and skills endpoints
This commit is contained in:
parent
9fa7224303
commit
4263dc70da
6 changed files with 169 additions and 2 deletions
|
|
@ -1,13 +1,30 @@
|
||||||
import { Controller, Get } from '@nestjs/common';
|
import { Controller, Get } from '@nestjs/common';
|
||||||
import { AppService } from './app.service';
|
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()
|
@Controller()
|
||||||
|
@ApiExtraModels(SkillDto)
|
||||||
export class AppController {
|
export class AppController {
|
||||||
constructor(private readonly appService: AppService) {}
|
constructor(private readonly appService: AppService, private readonly skillsService: SkillsService) {}
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
sayHello(): string {
|
sayHello(): string {
|
||||||
return this.appService.getHello();
|
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({ })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { AppController } from './app.controller';
|
import { AppController } from './app.controller';
|
||||||
import { AppService } from './app.service';
|
import { AppService } from './app.service';
|
||||||
|
import { SkillsService } from './skills/skills.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [],
|
imports: [],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [AppService],
|
providers: [AppService, SkillsService],
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { NestFactory } from "@nestjs/core";
|
import { NestFactory } from "@nestjs/core";
|
||||||
import { AppModule } from "./app.module";
|
import { AppModule } from "./app.module";
|
||||||
import { SwaggerModule, DocumentBuilder } from "@nestjs/swagger";
|
import { SwaggerModule, DocumentBuilder } from "@nestjs/swagger";
|
||||||
|
import { RedocModule, RedocOptions } from "@juicyllama/nestjs-redoc";
|
||||||
|
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
const app = await NestFactory.create(AppModule);
|
const app = await NestFactory.create(AppModule);
|
||||||
|
|
@ -19,6 +20,29 @@ async function bootstrap() {
|
||||||
operationIdFactory: (controllerKey: string, methodKey: string) => (`${methodKey[0].toUpperCase()}${methodKey.substring(1)}`)
|
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);
|
SwaggerModule.setup("/api", app, document);
|
||||||
|
|
||||||
await app.listen(3000);
|
await app.listen(3000);
|
||||||
|
|
|
||||||
18
cv/src/skills/skills.service.spec.ts
Normal file
18
cv/src/skills/skills.service.spec.ts
Normal 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();
|
||||||
|
});
|
||||||
|
});
|
||||||
72
cv/src/skills/skills.service.ts
Normal file
72
cv/src/skills/skills.service.ts
Normal 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])));
|
||||||
|
}
|
||||||
|
}
|
||||||
35
cv/src/skills/skills.types.ts
Normal file
35
cv/src/skills/skills.types.ts
Normal 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue