because I got bored of customising my CV for every job
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(mappers): implement entity mappers for job experience

- Create SkillMapper with toDomain overloads and mapToDomain
- Create RoleMapper with toDomain overloads and mapToDomain
- Create LevelMapper with toDomain overloads and mapToDomain
- Create CompanyMapper with toDomain overloads and mapToDomain
- Create UserJobExperienceMapper with complex entity mapping
- Inject dependent mappers for proper entity relationships
- Implement proper TypeScript overloads for null handling

+221
+38
apps/server/src/modules/job-experience/company/company.mapper.ts
··· 1 + import { Injectable } from "@nestjs/common"; 2 + import type { Company as PrismaCompany } from "@prisma/client"; 3 + import type { BaseMapper } from "../../base/mapper.interface"; 4 + import { Company } from "./company.entity"; 5 + 6 + /** 7 + * Mapper service for converting between Prisma Company entities and domain Company entities 8 + */ 9 + @Injectable() 10 + export class CompanyMapper implements BaseMapper<PrismaCompany, Company> { 11 + /** 12 + * Maps a Prisma Company entity to a domain Company entity 13 + * Uses overloads to return the correct type based on input 14 + */ 15 + toDomain(prismaCompany: null): null; 16 + toDomain(prismaCompany: PrismaCompany): Company; 17 + toDomain(prismaCompany: PrismaCompany | null): Company | null; 18 + toDomain(prismaCompany: PrismaCompany | null): Company | null { 19 + if (prismaCompany === null) { 20 + return null; 21 + } 22 + return new Company( 23 + prismaCompany.id, 24 + prismaCompany.name, 25 + prismaCompany.createdAt, 26 + prismaCompany.updatedAt, 27 + prismaCompany.description ?? undefined, 28 + prismaCompany.website ?? undefined, 29 + ); 30 + } 31 + 32 + /** 33 + * Maps an array of Prisma Company entities to domain Company entities 34 + */ 35 + mapToDomain(prismaCompanies: PrismaCompany[]): Company[] { 36 + return prismaCompanies.map((company) => this.toDomain(company)); 37 + } 38 + }
+72
apps/server/src/modules/job-experience/employment/user-job-experience.mapper.ts
··· 1 + import { Injectable } from "@nestjs/common"; 2 + import type { 3 + UserJobExperience as PrismaUserJobExperience, 4 + Company as PrismaCompany, 5 + Role as PrismaRole, 6 + Level as PrismaLevel, 7 + Skill as PrismaSkill, 8 + } from "@prisma/client"; 9 + import type { BaseMapper } from "../../base/mapper.interface"; 10 + import { CompanyMapper } from "../company/company.mapper"; 11 + import { LevelMapper } from "../level/level.mapper"; 12 + import { RoleMapper } from "../role/role.mapper"; 13 + import { SkillMapper } from "../skill/skill.mapper"; 14 + import { UserJobExperience } from "./user-job-experience.entity"; 15 + 16 + /** 17 + * Extended Prisma entity type that includes relations 18 + */ 19 + type PrismaUserJobExperienceWithRelations = PrismaUserJobExperience & { 20 + company: PrismaCompany; 21 + role: PrismaRole; 22 + level: PrismaLevel; 23 + skills?: PrismaSkill[]; 24 + }; 25 + 26 + /** 27 + * Mapper service for converting between Prisma UserJobExperience entities and domain UserJobExperience entities 28 + */ 29 + @Injectable() 30 + export class UserJobExperienceMapper implements BaseMapper< 31 + PrismaUserJobExperienceWithRelations, 32 + UserJobExperience 33 + > { 34 + constructor( 35 + private companyMapper: CompanyMapper, 36 + private roleMapper: RoleMapper, 37 + private levelMapper: LevelMapper, 38 + private skillMapper: SkillMapper, 39 + ) {} 40 + /** 41 + * Maps a Prisma UserJobExperience entity to a domain UserJobExperience entity 42 + * Uses overloads to return the correct type based on input 43 + */ 44 + toDomain(prismaExperience: null): null; 45 + toDomain(prismaExperience: PrismaUserJobExperienceWithRelations): UserJobExperience; 46 + toDomain(prismaExperience: PrismaUserJobExperienceWithRelations | null): UserJobExperience | null; 47 + toDomain(prismaExperience: PrismaUserJobExperienceWithRelations | null): UserJobExperience | null { 48 + if (prismaExperience === null) { 49 + return null; 50 + } 51 + 52 + return new UserJobExperience( 53 + prismaExperience.id, 54 + prismaExperience.startDate, 55 + prismaExperience.createdAt, 56 + prismaExperience.updatedAt, 57 + this.companyMapper.toDomain(prismaExperience.company), 58 + this.roleMapper.toDomain(prismaExperience.role), 59 + this.levelMapper.toDomain(prismaExperience.level), 60 + prismaExperience.endDate ?? undefined, 61 + prismaExperience.description ?? undefined, 62 + prismaExperience.skills ? this.skillMapper.mapToDomain(prismaExperience.skills) : undefined, 63 + ); 64 + } 65 + 66 + /** 67 + * Maps an array of Prisma UserJobExperience entities to domain UserJobExperience entities 68 + */ 69 + mapToDomain(prismaExperiences: PrismaUserJobExperienceWithRelations[]): UserJobExperience[] { 70 + return prismaExperiences.map((experience) => this.toDomain(experience)); 71 + } 72 + }
+37
apps/server/src/modules/job-experience/level/level.mapper.ts
··· 1 + import { Injectable } from "@nestjs/common"; 2 + import type { Level as PrismaLevel } from "@prisma/client"; 3 + import type { BaseMapper } from "../../base/mapper.interface"; 4 + import { Level } from "./level.entity"; 5 + 6 + /** 7 + * Mapper service for converting between Prisma Level entities and domain Level entities 8 + */ 9 + @Injectable() 10 + export class LevelMapper implements BaseMapper<PrismaLevel, Level> { 11 + /** 12 + * Maps a Prisma Level entity to a domain Level entity 13 + * Uses overloads to return the correct type based on input 14 + */ 15 + toDomain(prismaLevel: null): null; 16 + toDomain(prismaLevel: PrismaLevel): Level; 17 + toDomain(prismaLevel: PrismaLevel | null): Level | null; 18 + toDomain(prismaLevel: PrismaLevel | null): Level | null { 19 + if (prismaLevel === null) { 20 + return null; 21 + } 22 + return new Level( 23 + prismaLevel.id, 24 + prismaLevel.name, 25 + prismaLevel.createdAt, 26 + prismaLevel.updatedAt, 27 + prismaLevel.description ?? undefined, 28 + ); 29 + } 30 + 31 + /** 32 + * Maps an array of Prisma Level entities to domain Level entities 33 + */ 34 + mapToDomain(prismaLevels: PrismaLevel[]): Level[] { 35 + return prismaLevels.map((level) => this.toDomain(level)); 36 + } 37 + }
+37
apps/server/src/modules/job-experience/role/role.mapper.ts
··· 1 + import { Injectable } from "@nestjs/common"; 2 + import type { Role as PrismaRole } from "@prisma/client"; 3 + import type { BaseMapper } from "../../base/mapper.interface"; 4 + import { Role } from "./role.entity"; 5 + 6 + /** 7 + * Mapper service for converting between Prisma Role entities and domain Role entities 8 + */ 9 + @Injectable() 10 + export class RoleMapper implements BaseMapper<PrismaRole, Role> { 11 + /** 12 + * Maps a Prisma Role entity to a domain Role entity 13 + * Uses overloads to return the correct type based on input 14 + */ 15 + toDomain(prismaRole: null): null; 16 + toDomain(prismaRole: PrismaRole): Role; 17 + toDomain(prismaRole: PrismaRole | null): Role | null; 18 + toDomain(prismaRole: PrismaRole | null): Role | null { 19 + if (prismaRole === null) { 20 + return null; 21 + } 22 + return new Role( 23 + prismaRole.id, 24 + prismaRole.name, 25 + prismaRole.createdAt, 26 + prismaRole.updatedAt, 27 + prismaRole.description ?? undefined, 28 + ); 29 + } 30 + 31 + /** 32 + * Maps an array of Prisma Role entities to domain Role entities 33 + */ 34 + mapToDomain(prismaRoles: PrismaRole[]): Role[] { 35 + return prismaRoles.map((role) => this.toDomain(role)); 36 + } 37 + }
+37
apps/server/src/modules/job-experience/skill/skill.mapper.ts
··· 1 + import { Injectable } from "@nestjs/common"; 2 + import type { Skill as PrismaSkill } from "@prisma/client"; 3 + import type { BaseMapper } from "../../base/mapper.interface"; 4 + import { Skill } from "./skill.entity"; 5 + 6 + /** 7 + * Mapper service for converting between Prisma Skill entities and domain Skill entities 8 + */ 9 + @Injectable() 10 + export class SkillMapper implements BaseMapper<PrismaSkill, Skill> { 11 + /** 12 + * Maps a Prisma Skill entity to a domain Skill entity 13 + * Uses overloads to return the correct type based on input 14 + */ 15 + toDomain(prismaSkill: null): null; 16 + toDomain(prismaSkill: PrismaSkill): Skill; 17 + toDomain(prismaSkill: PrismaSkill | null): Skill | null; 18 + toDomain(prismaSkill: PrismaSkill | null): Skill | null { 19 + if (prismaSkill === null) { 20 + return null; 21 + } 22 + return new Skill( 23 + prismaSkill.id, 24 + prismaSkill.name, 25 + prismaSkill.createdAt, 26 + prismaSkill.updatedAt, 27 + prismaSkill.description ?? undefined, 28 + ); 29 + } 30 + 31 + /** 32 + * Maps an array of Prisma Skill entities to domain Skill entities 33 + */ 34 + mapToDomain(prismaSkills: PrismaSkill[]): Skill[] { 35 + return prismaSkills.map((skill) => this.toDomain(skill)); 36 + } 37 + }