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.

docs(architecture): document Service → Mapper → Domain → GraphQL.fromDomain

+57
+57
ARCHITECTURE.md
··· 1 + # Architecture Overview 2 + 3 + This project follows a three-layer architecture with clear separation of concerns and strong typing across boundaries. 4 + 5 + ## Layers 6 + 7 + 1. GraphQL (API Layer) 8 + - Location: `apps/server/src/modules/**` 9 + - Implements resolvers and GraphQL object types (classes) 10 + - GraphQL classes expose `fromDomain()` static factories to convert domain entities to API types 11 + - No database access; no business logic 12 + 13 + 2. Domain (Core Model Layer) 14 + - Location: `apps/server/src/modules/**/*.entity.ts` 15 + - Plain classes representing core business entities 16 + - Encapsulate business rules where appropriate 17 + - No framework-specific decorators except GraphQL field metadata on API classes 18 + 19 + 3. Persistence (Prisma Layer) 20 + - Location: Prisma client via `PrismaService` 21 + - No domain logic; pure data access 22 + 23 + ## Mapping Pattern 24 + 25 + - Each entity has a dedicated Mapper service implementing `BaseMapper<PrismaModel, DomainEntity>` 26 + - Mappers are `@Injectable()` Nest providers 27 + - Services inject mappers and use them to convert from Prisma models to domain entities 28 + - GraphQL classes convert domain entities via `fromDomain()` when returning data 29 + 30 + Example flow: Resolver -> Service -> Prisma -> Mapper.toDomain -> Domain -> GraphQLType.fromDomain 31 + 32 + ## Conventions 33 + 34 + - Services accept and return domain entities (never Prisma models) 35 + - Mappers live alongside their entity modules, e.g. `organization.mapper.ts`, `vacancy.mapper.ts` 36 + - Modules must register mapper providers and export them if shared 37 + - Prefer constructor-based instantiation; avoid non-null assertions 38 + - Use bracket notation for `process.env["VAR"]` and `prisma["model"]` 39 + - Linting and formatting are enforced via Biome with `$schema` validation 40 + 41 + ## Current Mapper Implementations 42 + 43 + - Auth: `user.mapper.ts` (already injectable) 44 + - Organization: `organization.mapper.ts` (injectable and used by `organization.service.ts`) 45 + - Organization Roles: `organization-role.mapper.ts` (injectable and used by `organization-role.service.ts`) 46 + - Vacancies: `vacancy.mapper.ts` (injectable and used by `vacancy.service.ts`) 47 + - Job Experience submodules (company/level/role/skill) include injectable mappers 48 + 49 + ## Docker & Tooling 50 + 51 + - Node 22 for all images (client, server, compose client service) 52 + - Biome 2.2.6 with `$schema` and `files.includes` exclusions for `node_modules`, `dist`, `build` 53 + 54 + ## Testing 55 + 56 + - E2E tests under `apps/server/test` exercise GraphQL endpoints against a test app 57 + - Tests expect services to return proper domain entities; GraphQL types handle API shaping