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.

fix(CVG-45): centralize duplicate mappers in @cv/core, route api modules through local wrappers

DI runtime fix: NestJS uses class identity for injection. SkillService et al expected core's SkillMapper class but api was registering its own duplicate, causing UnknownDependenciesException at boot. Solution: delete api duplicate mapper files (skill/level/role/company/application/cv-template/cv/education/institution/employment/organization/vacancies + sub-entities), export from core barrels, route api Module imports through api-local wrappers (which add resolvers/dataloaders) instead of core's bare modules.

+46 -696
+8 -8
apps/api/src/modules/admin/admin.module.ts
··· 1 1 import { AIModule } from "@cv/ai-provider"; 2 2 import { BaseModule } from "@cv/core"; 3 3 import { Module } from "@nestjs/common"; 4 - import { ApplicationStatusModule } from "@cv/core"; 5 - import { EducationModule } from "@cv/core"; 6 - import { CompanyModule } from "@cv/core"; 7 - import { LevelModule } from "@cv/core"; 8 - import { RoleModule } from "@cv/core"; 9 - import { SkillModule } from "@cv/core"; 10 - import { OrganizationModule } from "@cv/core"; 11 - import { JobTypeModule } from "@cv/core"; 4 + import { ApplicationStatusModule } from "@/modules/application/application-status/application-status.module"; 5 + import { EducationModule } from "@/modules/education/education.module"; 6 + import { CompanyModule } from "@/modules/job-experience/company/company.module"; 7 + import { LevelModule } from "@/modules/job-experience/level/level.module"; 8 + import { RoleModule } from "@/modules/job-experience/role/role.module"; 9 + import { SkillModule } from "@/modules/job-experience/skill/skill.module"; 10 + import { OrganizationModule } from "@/modules/organization/organization.module"; 11 + import { JobTypeModule } from "@/modules/vacancies/job-type/job-type.module"; 12 12 import { DatabaseModule } from "@/modules/database/database.module"; 13 13 import { AdminResolver } from "./admin.resolver"; 14 14 import { AdminLookupResolver } from "./graphql/admin-lookup.resolver";
-29
apps/api/src/modules/application/application-status/application-status.mapper.ts
··· 1 - import { createNamedEntityMapper } from "@cv/core"; 2 - import { Injectable } from "@nestjs/common"; 3 - import type { ApplicationStatus as PrismaApplicationStatus } from "@prisma/client"; 4 - import { ApplicationStatus } from "@cv/core"; 5 - 6 - @Injectable() 7 - export class ApplicationStatusMapper { 8 - private mapper = createNamedEntityMapper< 9 - PrismaApplicationStatus, 10 - ApplicationStatus 11 - >(ApplicationStatus); 12 - 13 - toDomain(prismaEntity: null): null; 14 - toDomain(prismaEntity: PrismaApplicationStatus): ApplicationStatus; 15 - toDomain( 16 - prismaEntity: PrismaApplicationStatus | null, 17 - ): ApplicationStatus | null; 18 - toDomain( 19 - prismaEntity: PrismaApplicationStatus | null, 20 - ): ApplicationStatus | null { 21 - return this.mapper.toDomain(prismaEntity); 22 - } 23 - 24 - mapToDomain( 25 - prismaEntities: PrismaApplicationStatus[], 26 - ): ApplicationStatus[] { 27 - return this.mapper.mapToDomain(prismaEntities); 28 - } 29 - }
-83
apps/api/src/modules/application/application.mapper.ts
··· 1 - import { Injectable } from "@nestjs/common"; 2 - import type { Prisma } from "@prisma/client"; 3 - import { cvMapper } from "@cv/core"; 4 - import { VacancyMapper } from "@cv/core"; 5 - import { 6 - Application, 7 - type ApplicationStatusRelation, 8 - } from "@cv/core"; 9 - 10 - type PrismaApplicationWithRelations = Prisma.ApplicationGetPayload<{ 11 - include: { 12 - user: true; 13 - status: true; 14 - vacancy: { 15 - include: { 16 - company: true; 17 - role: true; 18 - level: true; 19 - jobType: true; 20 - skills: true; 21 - }; 22 - }; 23 - cv: { 24 - include: { 25 - template: true; 26 - }; 27 - }; 28 - }; 29 - }>; 30 - 31 - @Injectable() 32 - export class ApplicationMapper { 33 - constructor(private readonly vacancyMapper: VacancyMapper) {} 34 - 35 - toDomain( 36 - prismaApplication: PrismaApplicationWithRelations | null, 37 - ): Application | null { 38 - if (!prismaApplication) { 39 - return null; 40 - } 41 - 42 - const status: ApplicationStatusRelation = { 43 - id: prismaApplication.status.id, 44 - name: prismaApplication.status.name, 45 - description: prismaApplication.status.description, 46 - createdAt: prismaApplication.status.createdAt, 47 - updatedAt: prismaApplication.status.updatedAt, 48 - }; 49 - 50 - const vacancy = this.vacancyMapper.toDomain(prismaApplication.vacancy); 51 - if (!vacancy) { 52 - throw new Error("Vacancy is required for Application"); 53 - } 54 - 55 - const cv = prismaApplication.cv 56 - ? cvMapper.toDomain(prismaApplication.cv) 57 - : null; 58 - 59 - return new Application( 60 - prismaApplication.id, 61 - prismaApplication.userId, 62 - prismaApplication.profileId, 63 - vacancy, 64 - prismaApplication.statusId, 65 - status, 66 - prismaApplication.appliedAt, 67 - prismaApplication.createdAt, 68 - prismaApplication.updatedAt, 69 - cv, 70 - prismaApplication.coverLetter ?? undefined, 71 - ); 72 - } 73 - 74 - mapToDomainWithRelations( 75 - prismaApplications: PrismaApplicationWithRelations[], 76 - ): Application[] { 77 - return prismaApplications 78 - .map((application) => this.toDomain(application)) 79 - .filter( 80 - (application): application is Application => application !== null, 81 - ); 82 - } 83 - }
+3 -3
apps/api/src/modules/application/application.module.ts
··· 2 2 import { AuthModule } from "@cv/auth"; 3 3 import { DatabaseModule } from "@cv/core"; 4 4 import { Module } from "@nestjs/common"; 5 - import { AuthenticationModule } from "@cv/core"; 6 - import { CVTemplateModule } from "@cv/core"; 7 - import { VacancyModule } from "@cv/core"; 5 + import { AuthenticationModule } from "@/modules/authentication/authentication.module"; 6 + import { CVTemplateModule } from "@/modules/cv-template/cv-template.module"; 7 + import { VacancyModule } from "@/modules/vacancies/vacancy.module"; 8 8 import { ApplicationMapper } from "@cv/core"; 9 9 import { ApplicationPolicy } from "@cv/core"; 10 10 import { ApplicationService } from "@cv/core";
+1 -1
apps/api/src/modules/current-user/current-user.module.ts
··· 1 1 import { UserModule } from "@cv/core"; 2 2 import { forwardRef, Module } from "@nestjs/common"; 3 - import { AuthenticationModule } from "@cv/core"; 3 + import { AuthenticationModule } from "@/modules/authentication/authentication.module"; 4 4 import { MeResolver } from "./me.resolver"; 5 5 6 6 @Module({
+3 -3
apps/api/src/modules/cv-parser/cv-parser.module.ts
··· 10 10 import { diskStorage } from "multer"; 11 11 import { DataImportModule } from "@/modules/data-import/data-import.module"; 12 12 import { FileImportSource } from "@/modules/data-import/sources/file-import-source"; 13 - import { EducationModule } from "@cv/core"; 14 - import { EmploymentModule } from "@cv/core"; 15 - import { ProfileModule } from "@cv/core"; 13 + import { EducationModule } from "@/modules/education/education.module"; 14 + import { EmploymentModule } from "@/modules/job-experience/employment/employment.module"; 15 + import { ProfileModule } from "@/modules/profile/profile.module"; 16 16 import { UserAiSettingsModule } from "@/modules/user-settings/user-ai-settings.module"; 17 17 import { AIProviderResolverService } from "./ai-provider-resolver.service"; 18 18 import { CVParserResolver } from "./cv-parser.resolver";
-19
apps/api/src/modules/cv-template/cv-template.mapper.ts
··· 1 - import type { CVTemplate as PrismaCVTemplate } from "@prisma/client"; 2 - import { CVTemplate } from "./graphql/cv-template.type"; 3 - 4 - export const cvTemplateMapper = { 5 - toDomain: (template: PrismaCVTemplate): CVTemplate => 6 - new CVTemplate( 7 - template.id, 8 - template.name, 9 - template.createdAt, 10 - template.updatedAt, 11 - template.description, 12 - template.body, 13 - template.css, 14 - template.engine, 15 - ), 16 - 17 - mapToDomain: (templates: PrismaCVTemplate[]): CVTemplate[] => 18 - templates.map((template) => cvTemplateMapper.toDomain(template)), 19 - };
+2 -2
apps/api/src/modules/cv-template/cv-template.module.ts
··· 1 1 import { AuthorizationModule } from "@cv/core"; 2 2 import { BaseModule, DatabaseModule } from "@cv/core"; 3 3 import { Module, forwardRef } from "@nestjs/common"; 4 - import { AuthenticationModule } from "@cv/core"; 5 - import { ProfileModule } from "@cv/core"; 4 + import { AuthenticationModule } from "@/modules/authentication/authentication.module"; 5 + import { ProfileModule } from "@/modules/profile/profile.module"; 6 6 import { CVDataAssemblerService } from "@cv/core"; 7 7 import { CVRendererService } from "@cv/core"; 8 8 import { CVDataLoaderService } from "./cv.dataloader";
-28
apps/api/src/modules/cv-template/cv.mapper.ts
··· 1 - import type { 2 - CV as PrismaCV, 3 - CVTemplate as PrismaCVTemplate, 4 - } from "@prisma/client"; 5 - import { cvTemplateMapper } from "@cv/core"; 6 - import { CV } from "./graphql/cv.type"; 7 - 8 - export type PrismaCVWithTemplate = PrismaCV & { 9 - template: PrismaCVTemplate; 10 - }; 11 - 12 - export const cvMapper = { 13 - toDomain: (cv: PrismaCVWithTemplate): CV => { 14 - return new CV( 15 - cv.id, 16 - cv.profileId, 17 - cv.title, 18 - cv.createdAt, 19 - cv.updatedAt, 20 - cvTemplateMapper.toDomain(cv.template), 21 - cv.introduction ?? null, 22 - ); 23 - }, 24 - 25 - mapToDomain: (cvs: PrismaCVWithTemplate[]): CV[] => { 26 - return cvs.map((cv) => cvMapper.toDomain(cv)); 27 - }, 28 - };
+1 -1
apps/api/src/modules/data-import/data-import.module.ts
··· 2 2 import { DatabaseModule } from "@cv/core"; 3 3 import { Module } from "@nestjs/common"; 4 4 import { EntityResolverService } from "@/modules/cv-parser/entity-resolver.service"; 5 - import { ProfileModule } from "@cv/core"; 5 + import { ProfileModule } from "@/modules/profile/profile.module"; 6 6 import { UserFileResolver } from "./graphql/user-file.resolver"; 7 7 import { ImportService } from "./import.service"; 8 8 import { ImportJobMapper } from "./import-job.mapper";
-64
apps/api/src/modules/education/education.mapper.ts
··· 1 - import type { BaseMapper } from "@cv/core"; 2 - import { Injectable } from "@nestjs/common"; 3 - import type { Prisma } from "@prisma/client"; 4 - import { SkillMapper } from "@/modules/job-experience/skill/skill.mapper"; 5 - import { Education } from "@cv/core"; 6 - import { InstitutionMapper } from "@cv/core"; 7 - 8 - type PrismaEducation = Prisma.EducationGetPayload<{ 9 - include: { 10 - institution: true; 11 - profile: true; 12 - skills: true; 13 - }; 14 - }>; 15 - 16 - @Injectable() 17 - export class EducationMapper implements BaseMapper<PrismaEducation, Education> { 18 - constructor( 19 - private readonly institutionMapper: InstitutionMapper, 20 - private readonly skillMapper: SkillMapper, 21 - ) {} 22 - 23 - /** 24 - * Maps a Prisma Education entity to a domain Education entity 25 - * Uses overloads to return the correct type based on input 26 - */ 27 - toDomain(prismaEducation: null): null; 28 - toDomain(prismaEducation: PrismaEducation): Education; 29 - toDomain(prismaEducation: PrismaEducation | null): Education | null; 30 - toDomain(prismaEducation: PrismaEducation | null): Education | null { 31 - if (!prismaEducation) { 32 - return null; 33 - } 34 - 35 - const institution = this.institutionMapper.toDomain( 36 - prismaEducation.institution, 37 - ); 38 - if (!institution) { 39 - throw new Error("Institution is required for Education"); 40 - } 41 - 42 - return new Education( 43 - prismaEducation.id, 44 - prismaEducation.profileId, 45 - institution, 46 - prismaEducation.degree, 47 - prismaEducation.fieldOfStudy, 48 - prismaEducation.startDate, 49 - prismaEducation.endDate, 50 - prismaEducation.description, 51 - prismaEducation.createdAt, 52 - prismaEducation.updatedAt, 53 - prismaEducation.skills 54 - ? this.skillMapper.mapToDomain(prismaEducation.skills) 55 - : undefined, 56 - ); 57 - } 58 - 59 - mapToDomain(prismaEducations: PrismaEducation[]): Education[] { 60 - return prismaEducations 61 - .map((education) => this.toDomain(education)) 62 - .filter((education): education is Education => education !== null); 63 - } 64 - }
+2 -2
apps/api/src/modules/education/education.module.ts
··· 1 1 import { AuthorizationModule } from "@cv/core"; 2 2 import { BaseModule, DatabaseModule } from "@cv/core"; 3 3 import { Module } from "@nestjs/common"; 4 - import { AuthenticationModule } from "@cv/core"; 5 - import { SkillModule } from "@cv/core"; 4 + import { AuthenticationModule } from "@/modules/authentication/authentication.module"; 5 + import { SkillModule } from "@/modules/job-experience/skill/skill.module"; 6 6 import { EducationMapper } from "@cv/core"; 7 7 import { EducationPolicy } from "@cv/core"; 8 8 import { EducationService } from "@cv/core";
-22
apps/api/src/modules/education/institution.mapper.ts
··· 1 - import { createNamedEntityMapper } from "@cv/core"; 2 - import { Injectable } from "@nestjs/common"; 3 - import type { Institution as PrismaInstitution } from "@prisma/client"; 4 - import { Institution } from "@cv/core"; 5 - 6 - @Injectable() 7 - export class InstitutionMapper { 8 - private mapper = createNamedEntityMapper<PrismaInstitution, Institution>( 9 - Institution, 10 - ); 11 - 12 - toDomain(prismaInstitution: null): null; 13 - toDomain(prismaInstitution: PrismaInstitution): Institution; 14 - toDomain(prismaInstitution: PrismaInstitution | null): Institution | null; 15 - toDomain(prismaInstitution: PrismaInstitution | null): Institution | null { 16 - return this.mapper.toDomain(prismaInstitution); 17 - } 18 - 19 - mapToDomain(prismaInstitutions: PrismaInstitution[]): Institution[] { 20 - return this.mapper.mapToDomain(prismaInstitutions); 21 - } 22 - }
-27
apps/api/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 { Company } from "@cv/core"; 4 - 5 - @Injectable() 6 - export class CompanyMapper { 7 - toDomain(prismaCompany: null): null; 8 - toDomain(prismaCompany: PrismaCompany): Company; 9 - toDomain(prismaCompany: PrismaCompany | null): Company | null; 10 - toDomain(prismaCompany: PrismaCompany | null): Company | null { 11 - if (prismaCompany === null) { 12 - return null; 13 - } 14 - return new Company( 15 - prismaCompany.id, 16 - prismaCompany.name, 17 - prismaCompany.createdAt, 18 - prismaCompany.updatedAt, 19 - prismaCompany.description ?? undefined, 20 - prismaCompany.website ?? undefined, 21 - ); 22 - } 23 - 24 - mapToDomain(prismaCompanies: PrismaCompany[]): Company[] { 25 - return prismaCompanies.map((company) => this.toDomain(company)); 26 - } 27 - }
+2 -2
apps/api/src/modules/job-experience/company/company.module.ts
··· 1 1 import { AuthorizationModule } from "@cv/core"; 2 2 import { BaseModule, DatabaseModule } from "@cv/core"; 3 3 import { Module } from "@nestjs/common"; 4 - import { AuthenticationModule } from "@cv/core"; 4 + import { AuthenticationModule } from "@/modules/authentication/authentication.module"; 5 5 import { CompanyService } from "@cv/core"; 6 6 import { CompanyDataLoaderService } from "./company.dataloader"; 7 7 import { CompanyFactory } from "@cv/core"; 8 - import { CompanyMapper } from "./company.mapper"; 8 + import { CompanyMapper } from "@cv/core"; 9 9 import { CompanyPolicy } from "@cv/core"; 10 10 import { CompanyResolver } from "./graphql/company.resolver"; 11 11
+5 -5
apps/api/src/modules/job-experience/employment/employment.module.ts
··· 1 1 import { AuthorizationModule } from "@cv/core"; 2 2 import { BaseModule, DatabaseModule } from "@cv/core"; 3 3 import { Module } from "@nestjs/common"; 4 - import { AuthenticationModule } from "@cv/core"; 5 - import { CompanyModule } from "@cv/core"; 6 - import { LevelModule } from "@cv/core"; 7 - import { RoleModule } from "@cv/core"; 8 - import { SkillModule } from "@cv/core"; 4 + import { AuthenticationModule } from "@/modules/authentication/authentication.module"; 5 + import { CompanyModule } from "@/modules/job-experience/company/company.module"; 6 + import { LevelModule } from "@/modules/job-experience/level/level.module"; 7 + import { RoleModule } from "@/modules/job-experience/role/role.module"; 8 + import { SkillModule } from "@/modules/job-experience/skill/skill.module"; 9 9 import { EmploymentResolver } from "./graphql/employment.resolver"; 10 10 import { UserFieldResolver } from "./graphql/user-field.resolver"; 11 11 import { CareerHistoryOnboardingStep } from "./onboarding/career-history.step";
-84
apps/api/src/modules/job-experience/employment/user-job-experience.mapper.ts
··· 1 - import type { BaseMapper } from "@cv/core"; 2 - import { Injectable } from "@nestjs/common"; 3 - import type { 4 - Company as PrismaCompany, 5 - Level as PrismaLevel, 6 - Profile as PrismaProfile, 7 - Role as PrismaRole, 8 - Skill as PrismaSkill, 9 - UserJobExperience as PrismaUserJobExperience, 10 - } from "@prisma/client"; 11 - import { CompanyMapper } from "@/modules/job-experience/company/company.mapper"; 12 - import { LevelMapper } from "@/modules/job-experience/level/level.mapper"; 13 - import { RoleMapper } from "@/modules/job-experience/role/role.mapper"; 14 - import { SkillMapper } from "@/modules/job-experience/skill/skill.mapper"; 15 - import { UserJobExperience } from "@cv/core"; 16 - 17 - /** 18 - * Extended Prisma entity type that includes relations 19 - */ 20 - type PrismaUserJobExperienceWithRelations = PrismaUserJobExperience & { 21 - company: PrismaCompany; 22 - role: PrismaRole; 23 - level: PrismaLevel; 24 - skills?: PrismaSkill[]; 25 - profile?: PrismaProfile | null; 26 - }; 27 - 28 - /** 29 - * Mapper service for converting between Prisma UserJobExperience entities and domain UserJobExperience entities 30 - */ 31 - @Injectable() 32 - export class UserJobExperienceMapper 33 - implements BaseMapper<PrismaUserJobExperienceWithRelations, UserJobExperience> 34 - { 35 - constructor( 36 - private companyMapper: CompanyMapper, 37 - private roleMapper: RoleMapper, 38 - private levelMapper: LevelMapper, 39 - private skillMapper: SkillMapper, 40 - ) {} 41 - /** 42 - * Maps a Prisma UserJobExperience entity to a domain UserJobExperience entity 43 - * Uses overloads to return the correct type based on input 44 - */ 45 - toDomain(prismaExperience: null): null; 46 - toDomain( 47 - prismaExperience: PrismaUserJobExperienceWithRelations, 48 - ): UserJobExperience; 49 - toDomain( 50 - prismaExperience: PrismaUserJobExperienceWithRelations | null, 51 - ): UserJobExperience | null; 52 - toDomain( 53 - prismaExperience: PrismaUserJobExperienceWithRelations | null, 54 - ): UserJobExperience | null { 55 - if (prismaExperience === null) { 56 - return null; 57 - } 58 - 59 - return new UserJobExperience( 60 - prismaExperience.id, 61 - prismaExperience.profileId, 62 - prismaExperience.startDate, 63 - prismaExperience.createdAt, 64 - prismaExperience.updatedAt, 65 - this.companyMapper.toDomain(prismaExperience.company), 66 - this.roleMapper.toDomain(prismaExperience.role), 67 - this.levelMapper.toDomain(prismaExperience.level), 68 - prismaExperience.endDate ?? undefined, 69 - prismaExperience.description ?? undefined, 70 - prismaExperience.skills 71 - ? this.skillMapper.mapToDomain(prismaExperience.skills) 72 - : undefined, 73 - ); 74 - } 75 - 76 - /** 77 - * Maps an array of Prisma UserJobExperience entities to domain UserJobExperience entities 78 - */ 79 - mapToDomain( 80 - prismaExperiences: PrismaUserJobExperienceWithRelations[], 81 - ): UserJobExperience[] { 82 - return prismaExperiences.map((experience) => this.toDomain(experience)); 83 - } 84 - }
-23
apps/api/src/modules/job-experience/level/level.mapper.ts
··· 1 - import { createNamedEntityMapper } from "@cv/core"; 2 - import { Injectable } from "@nestjs/common"; 3 - import type { Level as PrismaLevel } from "@prisma/client"; 4 - import { Level } from "@cv/core"; 5 - 6 - /** 7 - * Mapper service for converting between Prisma Level entities and domain Level entities 8 - */ 9 - @Injectable() 10 - export class LevelMapper { 11 - private mapper = createNamedEntityMapper<PrismaLevel, Level>(Level); 12 - 13 - toDomain(prismaLevel: null): null; 14 - toDomain(prismaLevel: PrismaLevel): Level; 15 - toDomain(prismaLevel: PrismaLevel | null): Level | null; 16 - toDomain(prismaLevel: PrismaLevel | null): Level | null { 17 - return this.mapper.toDomain(prismaLevel); 18 - } 19 - 20 - mapToDomain(prismaLevels: PrismaLevel[]): Level[] { 21 - return this.mapper.mapToDomain(prismaLevels); 22 - } 23 - }
+2 -2
apps/api/src/modules/job-experience/level/level.module.ts
··· 1 1 import { AuthorizationModule } from "@cv/core"; 2 2 import { BaseModule, DatabaseModule } from "@cv/core"; 3 3 import { Module } from "@nestjs/common"; 4 - import { AuthenticationModule } from "@cv/core"; 4 + import { AuthenticationModule } from "@/modules/authentication/authentication.module"; 5 5 import { LevelService } from "@cv/core"; 6 6 import { LevelResolver } from "./graphql/level.resolver"; 7 7 import { LevelDataLoaderService } from "./level.dataloader"; 8 8 import { LevelFactory } from "@cv/core"; 9 - import { LevelMapper } from "./level.mapper"; 9 + import { LevelMapper } from "@cv/core"; 10 10 import { LevelPolicy } from "@cv/core"; 11 11 12 12 @Module({
-23
apps/api/src/modules/job-experience/role/role.mapper.ts
··· 1 - import { createNamedEntityMapper } from "@cv/core"; 2 - import { Injectable } from "@nestjs/common"; 3 - import type { Role as PrismaRole } from "@prisma/client"; 4 - import { Role } from "@cv/core"; 5 - 6 - /** 7 - * Mapper service for converting between Prisma Role entities and domain Role entities 8 - */ 9 - @Injectable() 10 - export class RoleMapper { 11 - private mapper = createNamedEntityMapper<PrismaRole, Role>(Role); 12 - 13 - toDomain(prismaRole: null): null; 14 - toDomain(prismaRole: PrismaRole): Role; 15 - toDomain(prismaRole: PrismaRole | null): Role | null; 16 - toDomain(prismaRole: PrismaRole | null): Role | null { 17 - return this.mapper.toDomain(prismaRole); 18 - } 19 - 20 - mapToDomain(prismaRoles: PrismaRole[]): Role[] { 21 - return this.mapper.mapToDomain(prismaRoles); 22 - } 23 - }
+2 -2
apps/api/src/modules/job-experience/role/role.module.ts
··· 1 1 import { AuthorizationModule } from "@cv/core"; 2 2 import { BaseModule, DatabaseModule } from "@cv/core"; 3 3 import { Module } from "@nestjs/common"; 4 - import { AuthenticationModule } from "@cv/core"; 4 + import { AuthenticationModule } from "@/modules/authentication/authentication.module"; 5 5 import { RoleService } from "@cv/core"; 6 6 import { RoleResolver } from "./graphql/role.resolver"; 7 7 import { RoleDataLoaderService } from "./role.dataloader"; 8 8 import { RoleFactory } from "@cv/core"; 9 - import { RoleMapper } from "./role.mapper"; 9 + import { RoleMapper } from "@cv/core"; 10 10 import { RolePolicy } from "@cv/core"; 11 11 12 12 @Module({
-23
apps/api/src/modules/job-experience/skill/skill.mapper.ts
··· 1 - import { createNamedEntityMapper } from "@cv/core"; 2 - import { Injectable } from "@nestjs/common"; 3 - import type { Skill as PrismaSkill } from "@prisma/client"; 4 - import { Skill } from "@cv/core"; 5 - 6 - /** 7 - * Mapper service for converting between Prisma Skill entities and domain Skill entities 8 - */ 9 - @Injectable() 10 - export class SkillMapper { 11 - private mapper = createNamedEntityMapper<PrismaSkill, Skill>(Skill); 12 - 13 - toDomain(prismaSkill: null): null; 14 - toDomain(prismaSkill: PrismaSkill): Skill; 15 - toDomain(prismaSkill: PrismaSkill | null): Skill | null; 16 - toDomain(prismaSkill: PrismaSkill | null): Skill | null { 17 - return this.mapper.toDomain(prismaSkill); 18 - } 19 - 20 - mapToDomain(prismaSkills: PrismaSkill[]): Skill[] { 21 - return this.mapper.mapToDomain(prismaSkills); 22 - } 23 - }
+2 -2
apps/api/src/modules/job-experience/skill/skill.module.ts
··· 1 1 import { AuthorizationModule } from "@cv/core"; 2 2 import { BaseModule, DatabaseModule } from "@cv/core"; 3 3 import { Module } from "@nestjs/common"; 4 - import { AuthenticationModule } from "@cv/core"; 4 + import { AuthenticationModule } from "@/modules/authentication/authentication.module"; 5 5 import { SkillService } from "@cv/core"; 6 6 import { JobExperienceSeedService } from "../seed/job-experience.seed"; 7 7 import { ReferenceDataSeedService } from "../seed/reference-data.seed"; 8 8 import { SkillResolver } from "./graphql/skill.resolver"; 9 9 import { SkillFactory } from "@cv/core"; 10 - import { SkillMapper } from "./skill.mapper"; 10 + import { SkillMapper } from "@cv/core"; 11 11 import { SkillPolicy } from "@cv/core"; 12 12 13 13 @Module({
-30
apps/api/src/modules/organization/organization-role.mapper.ts
··· 1 - import type { BaseMapper } from "@cv/core"; 2 - import { Injectable } from "@nestjs/common"; 3 - import type { OrganizationRole as PrismaOrganizationRole } from "@prisma/client"; 4 - import { OrganizationRole } from "@cv/core"; 5 - 6 - @Injectable() 7 - export class OrganizationRoleMapper 8 - implements BaseMapper<PrismaOrganizationRole, OrganizationRole> 9 - { 10 - toDomain(prismaRole: null): null; 11 - toDomain(prismaRole: PrismaOrganizationRole): OrganizationRole; 12 - toDomain(prismaRole: PrismaOrganizationRole | null): OrganizationRole | null; 13 - toDomain(prismaRole: PrismaOrganizationRole | null): OrganizationRole | null { 14 - if (prismaRole === null) { 15 - return null; 16 - } 17 - return new OrganizationRole( 18 - prismaRole.id, 19 - prismaRole.name, 20 - prismaRole.createdAt, 21 - prismaRole.updatedAt, 22 - prismaRole.description, 23 - prismaRole.color, 24 - ); 25 - } 26 - 27 - mapToDomain(prismaRoles: PrismaOrganizationRole[]): OrganizationRole[] { 28 - return prismaRoles.map((r) => this.toDomain(r)); 29 - } 30 - }
-29
apps/api/src/modules/organization/organization.mapper.ts
··· 1 - import type { BaseMapper } from "@cv/core"; 2 - import { Injectable } from "@nestjs/common"; 3 - import type { Organization as PrismaOrganization } from "@prisma/client"; 4 - import { Organization } from "@cv/core"; 5 - 6 - @Injectable() 7 - export class OrganizationMapper 8 - implements BaseMapper<PrismaOrganization, Organization> 9 - { 10 - toDomain(prismaOrganization: null): null; 11 - toDomain(prismaOrganization: PrismaOrganization): Organization; 12 - toDomain(prismaOrganization: PrismaOrganization | null): Organization | null; 13 - toDomain(prismaOrganization: PrismaOrganization | null): Organization | null { 14 - if (prismaOrganization === null) { 15 - return null; 16 - } 17 - return new Organization( 18 - prismaOrganization.id, 19 - prismaOrganization.name, 20 - prismaOrganization.createdAt, 21 - prismaOrganization.updatedAt, 22 - prismaOrganization.description, 23 - ); 24 - } 25 - 26 - mapToDomain(prismaOrganizations: PrismaOrganization[]): Organization[] { 27 - return prismaOrganizations.map((o) => this.toDomain(o)); 28 - } 29 - }
+1 -1
apps/api/src/modules/organization/organization.module.ts
··· 1 1 import { AuthorizationModule } from "@cv/core"; 2 2 import { BaseModule, DatabaseModule } from "@cv/core"; 3 3 import { Module } from "@nestjs/common"; 4 - import { AuthenticationModule } from "@cv/core"; 4 + import { AuthenticationModule } from "@/modules/authentication/authentication.module"; 5 5 import { OrganizationResolver } from "./graphql/organization.resolver"; 6 6 import { UserFieldResolver } from "./graphql/user-field.resolver"; 7 7 import { OrganizationFactory } from "@cv/core";
+3 -3
apps/api/src/modules/profile/profile.module.ts
··· 6 6 ProfileService, 7 7 } from "@cv/core"; 8 8 import { Module, forwardRef } from "@nestjs/common"; 9 - import { CVTemplateModule } from "@cv/core"; 10 - import { EducationModule } from "@cv/core"; 11 - import { EmploymentModule } from "@cv/core"; 9 + import { CVTemplateModule } from "@/modules/cv-template/cv-template.module"; 10 + import { EducationModule } from "@/modules/education/education.module"; 11 + import { EmploymentModule } from "@/modules/job-experience/employment/employment.module"; 12 12 import { ProfileFieldResolver } from "./graphql/profile-field.resolver"; 13 13 import { ProfileResolver } from "./graphql/profile.resolver"; 14 14 import { ProfileOnboardingStep } from "./onboarding/profile.step";
-20
apps/api/src/modules/vacancies/contract-type/contract-type.mapper.ts
··· 1 - import { createNamedEntityMapper } from "@cv/core"; 2 - import { Injectable } from "@nestjs/common"; 3 - import type { ContractType as PrismaContractType } from "@prisma/client"; 4 - import { ContractType } from "@cv/core"; 5 - 6 - @Injectable() 7 - export class ContractTypeMapper { 8 - private mapper = createNamedEntityMapper<PrismaContractType, ContractType>(ContractType); 9 - 10 - toDomain(prisma: null): null; 11 - toDomain(prisma: PrismaContractType): ContractType; 12 - toDomain(prisma: PrismaContractType | null): ContractType | null; 13 - toDomain(prisma: PrismaContractType | null): ContractType | null { 14 - return this.mapper.toDomain(prisma); 15 - } 16 - 17 - mapToDomain(prisma: PrismaContractType[]): ContractType[] { 18 - return this.mapper.mapToDomain(prisma); 19 - } 20 - }
-20
apps/api/src/modules/vacancies/job-type/job-type.mapper.ts
··· 1 - import { createNamedEntityMapper } from "@cv/core"; 2 - import { Injectable } from "@nestjs/common"; 3 - import type { JobType as PrismaJobType } from "@prisma/client"; 4 - import { JobType } from "@cv/core"; 5 - 6 - @Injectable() 7 - export class JobTypeMapper { 8 - private mapper = createNamedEntityMapper<PrismaJobType, JobType>(JobType); 9 - 10 - toDomain(prismaEntity: null): null; 11 - toDomain(prismaEntity: PrismaJobType): JobType; 12 - toDomain(prismaEntity: PrismaJobType | null): JobType | null; 13 - toDomain(prismaEntity: PrismaJobType | null): JobType | null { 14 - return this.mapper.toDomain(prismaEntity); 15 - } 16 - 17 - mapToDomain(prismaEntities: PrismaJobType[]): JobType[] { 18 - return this.mapper.mapToDomain(prismaEntities); 19 - } 20 - }
-26
apps/api/src/modules/vacancies/location/location.mapper.ts
··· 1 - import { Injectable } from "@nestjs/common"; 2 - import type { Location as PrismaLocation } from "@prisma/client"; 3 - import { Location } from "@cv/core"; 4 - 5 - @Injectable() 6 - export class LocationMapper { 7 - toDomain(prisma: null): null; 8 - toDomain(prisma: PrismaLocation): Location; 9 - toDomain(prisma: PrismaLocation | null): Location | null; 10 - toDomain(prisma: PrismaLocation | null): Location | null { 11 - if (!prisma) return null; 12 - return new Location( 13 - prisma.id, 14 - prisma.name, 15 - prisma.type, 16 - prisma.createdAt, 17 - prisma.updatedAt, 18 - prisma.code ?? undefined, 19 - prisma.parentId ?? undefined, 20 - ); 21 - } 22 - 23 - mapToDomain(items: PrismaLocation[]): Location[] { 24 - return items.map((item) => this.toDomain(item)).filter((item): item is Location => item !== null); 25 - } 26 - }
-20
apps/api/src/modules/vacancies/rate-type/rate-type.mapper.ts
··· 1 - import { createNamedEntityMapper } from "@cv/core"; 2 - import { Injectable } from "@nestjs/common"; 3 - import type { RateType as PrismaRateType } from "@prisma/client"; 4 - import { RateType } from "@cv/core"; 5 - 6 - @Injectable() 7 - export class RateTypeMapper { 8 - private mapper = createNamedEntityMapper<PrismaRateType, RateType>(RateType); 9 - 10 - toDomain(prisma: null): null; 11 - toDomain(prisma: PrismaRateType): RateType; 12 - toDomain(prisma: PrismaRateType | null): RateType | null; 13 - toDomain(prisma: PrismaRateType | null): RateType | null { 14 - return this.mapper.toDomain(prisma); 15 - } 16 - 17 - mapToDomain(prisma: PrismaRateType[]): RateType[] { 18 - return this.mapper.mapToDomain(prisma); 19 - } 20 - }
-84
apps/api/src/modules/vacancies/vacancy.mapper.ts
··· 1 - import { Injectable } from "@nestjs/common"; 2 - import type { Prisma } from "@prisma/client"; 3 - import { CompanyMapper } from "@/modules/job-experience/company/company.mapper"; 4 - import { LevelMapper } from "@/modules/job-experience/level/level.mapper"; 5 - import { RoleMapper } from "@/modules/job-experience/role/role.mapper"; 6 - import { Vacancy } from "@cv/core"; 7 - 8 - type PrismaVacancyWithRelations = Prisma.VacancyGetPayload<{ 9 - include: { 10 - company: true; 11 - role: true; 12 - level: true; 13 - jobType: true; 14 - skills: true; 15 - }; 16 - }>; 17 - 18 - @Injectable() 19 - export class VacancyMapper { 20 - constructor( 21 - private readonly companyMapper: CompanyMapper, 22 - private readonly roleMapper: RoleMapper, 23 - private readonly levelMapper: LevelMapper, 24 - ) {} 25 - 26 - toDomain(prismaVacancy: PrismaVacancyWithRelations | null): Vacancy | null { 27 - if (!prismaVacancy) { 28 - return null; 29 - } 30 - 31 - const company = this.companyMapper.toDomain(prismaVacancy.company); 32 - if (!company) { 33 - throw new Error("Company is required for Vacancy"); 34 - } 35 - 36 - const role = this.roleMapper.toDomain(prismaVacancy.role); 37 - if (!role) { 38 - throw new Error("Role is required for Vacancy"); 39 - } 40 - 41 - const level = prismaVacancy.level 42 - ? this.levelMapper.toDomain(prismaVacancy.level) 43 - : null; 44 - 45 - const vacancy = new Vacancy( 46 - prismaVacancy.id, 47 - prismaVacancy.title, 48 - prismaVacancy.ownerId, 49 - company, 50 - role, 51 - prismaVacancy.createdAt, 52 - prismaVacancy.updatedAt, 53 - level, 54 - prismaVacancy.jobTypeId ?? undefined, 55 - prismaVacancy.description ?? undefined, 56 - prismaVacancy.requirements ?? undefined, 57 - undefined, 58 - prismaVacancy.minSalary ?? undefined, 59 - prismaVacancy.maxSalary ?? undefined, 60 - prismaVacancy.applicationUrl ?? undefined, 61 - prismaVacancy.deadline ?? undefined, 62 - prismaVacancy.isActive, 63 - prismaVacancy.isPublic, 64 - ); 65 - 66 - vacancy.hoursFrom = prismaVacancy.hoursFrom ?? undefined; 67 - vacancy.hoursTo = prismaVacancy.hoursTo ?? undefined; 68 - vacancy.rateTypeId = prismaVacancy.rateTypeId ?? undefined; 69 - vacancy.contractTypeId = prismaVacancy.contractTypeId ?? undefined; 70 - vacancy.locationId = prismaVacancy.locationId ?? undefined; 71 - vacancy.externalId = prismaVacancy.externalId ?? undefined; 72 - vacancy.source = prismaVacancy.source ?? undefined; 73 - vacancy.externalApplyUrl = prismaVacancy.externalApplyUrl ?? undefined; 74 - vacancy.publishedAt = prismaVacancy.publishedAt ?? undefined; 75 - 76 - return vacancy; 77 - } 78 - 79 - mapToDomain(prismaVacancies: PrismaVacancyWithRelations[]): Vacancy[] { 80 - return prismaVacancies 81 - .map((v) => this.toDomain(v)) 82 - .filter((v): v is Vacancy => v !== null); 83 - } 84 - }
+5 -5
apps/api/src/modules/vacancies/vacancy.module.ts
··· 1 1 import { AuthorizationModule } from "@cv/core"; 2 2 import { BaseModule, DatabaseModule } from "@cv/core"; 3 3 import { Module } from "@nestjs/common"; 4 - import { AuthenticationModule } from "@cv/core"; 5 - import { CompanyModule } from "@cv/core"; 6 - import { LevelModule } from "@cv/core"; 7 - import { RoleModule } from "@cv/core"; 8 - import { SkillModule } from "@cv/core"; 4 + import { AuthenticationModule } from "@/modules/authentication/authentication.module"; 5 + import { CompanyModule } from "@/modules/job-experience/company/company.module"; 6 + import { LevelModule } from "@/modules/job-experience/level/level.module"; 7 + import { RoleModule } from "@/modules/job-experience/role/role.module"; 8 + import { SkillModule } from "@/modules/job-experience/skill/skill.module"; 9 9 import { ContractTypeModule } from "./contract-type/contract-type.module"; 10 10 import { VacancyUserFieldResolver } from "./graphql/user-field.resolver"; 11 11 import { VacancyResolver } from "./graphql/vacancy.resolver";
+1
packages/core/src/modules/job-experience/company/index.ts
··· 1 1 export { Company } from "./company.entity"; 2 2 export { CompanyFactory } from "./company.factory"; 3 + export { CompanyMapper } from "./company.mapper"; 3 4 export { CompanyModule } from "./company.module"; 4 5 export { CompanyPolicy } from "./company.policy"; 5 6 export { CompanyService } from "./company.service";
+1
packages/core/src/modules/job-experience/level/index.ts
··· 1 1 export { Level } from "./level.entity"; 2 2 export { LevelFactory } from "./level.factory"; 3 + export { LevelMapper } from "./level.mapper"; 3 4 export { LevelModule } from "./level.module"; 4 5 export { LevelPolicy } from "./level.policy"; 5 6 export { LevelService } from "./level.service";
+1
packages/core/src/modules/job-experience/role/index.ts
··· 1 1 export { Role } from "./role.entity"; 2 2 export { RoleFactory } from "./role.factory"; 3 + export { RoleMapper } from "./role.mapper"; 3 4 export { RoleModule } from "./role.module"; 4 5 export { RolePolicy } from "./role.policy"; 5 6 export { RoleService } from "./role.service";
+1
packages/core/src/modules/job-experience/skill/index.ts
··· 1 1 export { Skill } from "./skill.entity"; 2 2 export { SkillFactory } from "./skill.factory"; 3 + export { SkillMapper } from "./skill.mapper"; 3 4 export { SkillModule } from "./skill.module"; 4 5 export { SkillPolicy } from "./skill.policy"; 5 6 export { SkillService } from "./skill.service";