Files
toir-light/prompts/backend-rules.md
2026-04-03 20:54:37 +03:00

5.5 KiB

Backend Rules

Use this document during the Backend stage defined in prompts/general-prompt.md.

Purpose

Generate NestJS CRUD artifacts that match the DSL contract exactly and remain compatible with a standard NestJS workspace.

Mandatory Inputs

  • prompts/general-prompt.md
  • the active api API.<Entity> block from domain/toir.api.dsl
  • referenced DTOs and enums from domain/toir.api.dsl
  • an intact or repaired official NestJS scaffold under server/

api-summary.json may be consulted only as an auxiliary inventory or validator-related artifact. It must never replace the DSL as the backend source of truth.

Expected Outputs

Per entity:

  • server/src/modules/<kebab>/<kebab>.module.ts
  • server/src/modules/<kebab>/<kebab>.controller.ts
  • server/src/modules/<kebab>/<kebab>.service.ts
  • server/src/modules/<kebab>/dto/create-<kebab>.dto.ts
  • server/src/modules/<kebab>/dto/update-<kebab>.dto.ts

Repository-wide:

  • server/src/app.module.ts registrations

Scaffold Baseline

  • Start backend initialization and repair from the official NestJS CLI workspace, not from hand-written files.
  • Preserve Nest workspace essentials:
    • server/tsconfig.json
    • server/tsconfig.build.json
    • server/nest-cli.json
    • server/src/main.ts
    • server/src/app.module.ts
  • If the workspace is degraded, repair it before generating domain code.

Forbidden patterns:

  • hand-written pseudo-Nest scaffolds
  • deleting required Nest config files after generation
  • replacing normal Nest build/start behavior with ad hoc scripts

Route And Resource Contract

  • Use the shared entity-to-resource naming convention from prompts/general-prompt.md.
  • Each entity becomes a NestJS module, controller, service, and create/update DTO pair.
  • CRUD routes use the real primary key name in the path.
  • Every API record returned to React Admin must include id.
  • For natural-key entities, map the real primary key to id in responses and sort translation.

DTO Contract

  • DTO.<Entity>Create defines Create<Entity>Dto.
  • DTO.<Entity>Update defines Update<Entity>Dto.
  • Do not invent fields or pull field lists from memory.
  • Never include id in Create/Update DTOs.

Type and decorator rules:

DSL type TS DTO type class-validator decorator Notes
uuid string @IsUUID()
string string @IsString()
text string @IsString()
integer number @IsInt()
number number @IsNumber()
decimal string @IsString() serialize with Prisma Decimal
date string @IsString() serialize as ISO string
boolean boolean @IsBoolean()
enum name string @IsEnum(EnumName)

Nullability rules:

  • every field that is not is required gets @IsOptional() before the type decorator
  • every generated DTO imports from 'class-validator'

Controller Contract

  • Apply @UseGuards(JwtAuthGuard, RolesGuard) at controller class level.
  • Roles per verb:
    • GET -> viewer | editor | admin
    • POST, PATCH, PUT -> editor | admin
    • DELETE -> admin
  • Reconcile DSL HTTP shapes for repository compatibility:
    • list endpoints declared as POST .../page generate as @Get() with React Admin query params
    • update endpoints declared as PUT generate as @Patch(':<pk>')
  • Path parameters are taken from the DSL endpoint contract, not invented from generic CRUD memory.

Service Contract

  • Never pass raw update DTOs directly into Prisma update data.
  • Strip id, the real primary key, and readonly fields before writes.
  • Keep PrismaService lightweight:
    • extend PrismaClient
    • implement OnModuleInit
    • call $connect()
    • do not add beforeExit

List endpoint requirements:

  • accept React Admin query params: _start, _end, _sort, _order, q
  • set Content-Range
  • set Access-Control-Expose-Headers: Content-Range

Filtering rules:

  • string/text filters may use case-insensitive contains
  • foreign-key scalar filters must use exact-match semantics
  • enum filters must support both single and repeated params
  • repeated enum params must map to Prisma { in: [...] }
  • _sort=id must map to the real primary key for natural-key entities

Decimal and date handling:

  • decimal writes: new Prisma.Decimal(value)
  • decimal reads: .toString()
  • date writes: new Date(value)
  • date reads: .toISOString()

Natural-Key Rules

For entities whose physical primary key is not id:

  • route params use the real primary key name
  • responses expose id mapped from that primary key
  • sort/update behavior never targets a fake physical id
  • update payload sanitization removes both id and the real primary key

Completion Expectations

Backend generation is incomplete if any of the following is true:

  • required Nest scaffold files are missing
  • DTO decorators are incomplete or type-incorrect
  • controllers are missing guards or role decorators
  • natural-key handling regresses to a fake physical id
  • list/filter behavior is incompatible with React Admin expectations