Moved doc generation to separate functions in separate files

This commit is contained in:
Thom Werring 2023-10-22 08:17:11 +02:00
parent b6255cacc0
commit c7d358a352
4 changed files with 156 additions and 88 deletions

147
src/common/openApi.ts Normal file
View file

@ -0,0 +1,147 @@
import { RedocModule, RedocOptions } from "@juicyllama/nestjs-redoc";
import { INestApplication } from "@nestjs/common";
import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger";
import { skills } from "@/skills/skills";
import { experiences } from "@/experiences/experiences";
import { ExperienceType } from "@/experiences/experiences.types";
const apiDocument = (
options: {
title: string;
description: string;
version: `${number}.${number}.${number}${string}` | `${number}.${number}${string}` | `${number}${string}`;
contact: {
name: string;
email: string;
};
},
redocOptions: RedocOptions
) => {
redocOptions.title = options.title;
return new DocumentBuilder()
.setTitle(options.title)
.setDescription(options.description)
.setVersion(options.version)
.setContact(options.contact.name, null, options.contact.email)
.addServer("http://localhost:3000/");
};
const addIntro = (document: DocumentBuilder, redocOptions: RedocOptions): DocumentBuilder => {
const intro = [
"I'm a software lead with 5+ years of experience in cloud-native development and Agile/Scrum methodologies. I'm passionate about building and leading high-performing teams to deliver scalable and reliable cloud-based applications. I have a proven track record of success in using Node.js, TypeScript, JavaScript, Docker, Kubernetes, AWS, DevOps, Git, microservices, and HAProxy to create and deploy innovative solutions.",
"I'm also a strong communicator and collaborator, and I'm always looking for ways to improve my skills and knowledge. I'm excited about the future of cloud computing, and I'm eager to use my skills and experience to help others achieve their goals.",
];
const introTagGroup = redocOptions.tagGroups.find((tagGroup) => tagGroup.name === "Intro");
if (!introTagGroup) {
redocOptions.tagGroups.push({
name: "Intro",
tags: ["Intro"],
});
} else {
introTagGroup.tags.push("Intro");
}
return document.addTag("Intro", intro.join("<br/>"));
};
const addSkills = (document: DocumentBuilder, count: number = 5, redocOptions: RedocOptions): DocumentBuilder => {
const introTagGroup = redocOptions.tagGroups.find((tagGroup) => tagGroup.name === "Intro");
if (!introTagGroup) {
redocOptions.tagGroups.push({
name: "Intro",
tags: ["Skills"],
});
} else {
introTagGroup.tags.push("Skills");
}
const intro = "A short excerpt of my skills are";
const skillList = skills
.slice(0, count)
.reduce((list, skill) => list.concat(`<li><strong>${skill.name}</strong> ${skill.description}</li>`), "");
return document.addTag("Skills", `${intro}<br/><ul>${skillList}</ul>`);
};
const formatExperience = (experience: ExperienceType) => {
return `${experience.startDate.toLocaleDateString("en-GB")}`;
};
const addExperiences = (document: DocumentBuilder, count: number = 5, redocOptions: RedocOptions): DocumentBuilder => {
let experienceTagGroup = redocOptions.tagGroups.find((tagGroup) => tagGroup.name === "Experience");
if (!experienceTagGroup) {
experienceTagGroup = {
name: "Experience",
tags: ["Experience"],
};
redocOptions.tagGroups.push(experienceTagGroup);
}
experiences.slice(0, count).forEach((experience) => {
experienceTagGroup.tags.push(experience.name);
document.addTag(experience.name, formatExperience(experience));
});
return document;
};
const initDocs = async ({
app,
config,
redocOptions,
swaggerUIPath,
redocPath,
}: {
app: INestApplication;
config: DocumentBuilder;
redocOptions: RedocOptions;
swaggerUIPath: string;
redocPath: string;
}): Promise<void> => {
const document = SwaggerModule.createDocument(app, config.build(), {
operationIdFactory: (controllerKey: string, methodKey: string) =>
`${methodKey[0].toUpperCase()}${methodKey.substring(1)}`,
});
SwaggerModule.setup(swaggerUIPath, app, document);
await RedocModule.setup(redocPath, app, document, redocOptions);
};
export default async (app: INestApplication) => {
const redocOptions: RedocOptions = {
logo: {
url: "https://picsum.photos/256/128",
altText: "Thom Werring",
},
sortPropsAlphabetically: true,
hideDownloadButton: false,
tagGroups: [],
};
const config = apiDocument(
{
title: "Thom Werring - CV",
description: "Westerstraat 83<br/>1521ZB, Wormerveer<br/><a href='tel:+31637650849'>+31 6 37 65 08 49</a>",
version: "1.0.0a",
contact: {
name: "Thom Werring",
email: "cv@t-werring.nl",
},
},
redocOptions
);
addIntro(config, redocOptions);
addSkills(config, 5, redocOptions);
addExperiences(config, 3, redocOptions);
await initDocs({
app,
config,
redocOptions,
swaggerUIPath: "/api",
redocPath: "/docs",
});
};

View file

@ -10,7 +10,7 @@ export class ExperiencesService {
constructor(private readonly skillsService: SkillsService) {
this.experiences = ExperienceDto.asDto(this.linkSkills(experiences)).sort((experienceA, experienceB) =>
experienceA.startDate > experienceB.startDate ? 1 : -1
experienceA.startDate < experienceB.startDate ? 1 : -1
);
}

View file

@ -26,15 +26,12 @@ During my time
city: "Amsterdam",
url: "http://blackorange.nl/",
jobTitle: "Junior Developer / System Administrator",
startDate: new Date(2018, 9, 1),
startDate: new Date(2014, 9, 1),
endDate: new Date(2018, 8, 30),
description: "",
description: "Blorp",
skills: [
{
category: "AWS|Containerization|DevOps",
},
{
name: "NodeJs|Git|Server",
name: "PHP|Git|Server",
},
],
},
@ -42,9 +39,9 @@ During my time
name: "Werring Webdevelopment",
city: "Middenbeemster",
jobTitle: "ZZP",
startDate: new Date(2018, 9, 1),
startDate: new Date(2012, 9, 1),
endDate: new Date(2018, 8, 30),
description: "",
description: "Blorp2",
skills: [
{
name: "PHP|Webhosting",
@ -56,7 +53,7 @@ During my time
city: "Utrecht",
url: "http://ingeniumcabobianci.nl/",
jobTitle: "Penningmeester",
startDate: new Date(2018, 9, 1),
startDate: new Date(2011, 9, 1),
endDate: new Date(2018, 8, 30),
description: "",
skills: [

View file

@ -1,87 +1,11 @@
import { NestFactory } from "@nestjs/core";
import { AppModule } from "@/app.module";
import { SwaggerModule, DocumentBuilder } from "@nestjs/swagger";
import { RedocModule, RedocOptions } from "@juicyllama/nestjs-redoc";
import openApi from "@/common/openApi";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const config = new DocumentBuilder()
.setTitle("Thom Werring - CV")
.setDescription("Westerstraat 83<br/>1521ZB, Wormerveer<br/><a href='tel:+31637650849'>+31 6 37 65 08 49</a>")
// .addApiKey({
// type: "apiKey",
// name: "Authorization",
// bearerFormat: "bearer",
// }, "Credentials")
.setVersion("1.0.0a")
.setContact("Thom Werring", null, "cv@t-werring.nl")
.addTag(
"Skills",
`<p>I'm a software lead with 5+ years of experience in cloud-native development and Agile/Scrum methodologies. I'm passionate about building and leading high-performing teams to deliver scalable and reliable cloud-based applications. I have a proven track record of success in using Node.js, TypeScript, JavaScript, Docker, Kubernetes, AWS, DevOps, Git, microservices, and HAProxy to create and deploy innovative solutions.<br/>
I'm also a strong communicator and collaborator, and I'm always looking for ways to improve my skills and knowledge. I'm excited about the future of cloud computing, and I'm eager to use my skills and experience to help others achieve their goals.
</p>
`
)
.addTag(
"Saysimple",
`<p>Senior Developer - Haarlem<br/> October 2018 - PRESENT</p><p>
<ul>
<li><strong>NodeJs, TypeScript, Javascript</strong> Building scalable microservices</li>
<li><strong>Docker and Kubernetes</strong> Containerizing and deploying microservices to AWS EKS</li>
<li><strong>AWS</strong> Building, deploying, and monitoring cloud-based applications (EKS, Lambda, API Gateway, CloudWatch, etc.).</li>
<li><strong>DevOps</strong> Automating deployments and CI/CD pipelines.</li>
<li><strong>On call</strong> Handling outages and maintenance during nights & weekends</li>
</ul>
</p>`
)
.addTag(
"Blackorange",
`<p>Junior Developer - Amsterdam<br/> October 2014 - September 2018</p><p>
<ul>
<li><strong>PHP, Laravel</strong> Building websites and -applications in PHP Laravel</li>
<li><strong>Linux System Administrator</strong> Setup & maintenance of our application hosting</li>
</ul>
</p>`
)
.addTag(
"Werring webdevelopment",
`<p>ZZP - Middenbeemster<br/> Januari 2012 - December 2016</p><p>
<ul>
<li><strong>PHP, Wordpress</strong> Building websites in PHP & Wordpress</li>
<li><strong>Webhosting & Email</strong> managing webhosting for companies. </li>
</ul>
</p>`
)
.build();
const document = SwaggerModule.createDocument(app, config, {
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,
tagGroups: [
{
name: "Skills",
tags: ["Skills"],
},
{
name: "Experience",
tags: ["Experience", "Saysimple", "Blackorange", "Werring webdevelopment"],
},
],
};
await RedocModule.setup("/docs", app, document, redocOptions);
SwaggerModule.setup("/api", app, document);
await openApi(app);
await app.listen(3000);
}