Skip to content

Work / DwarSeva / Wiki / Concepts

field-resolver-standards

Conceptverified 2026-10-30

field-resolver-standards

A field resolver goes in the domain folder that owns the service required to resolve the relation. Never place it by parent type. Why: field-resolver-placement. This rule has been violated 20+ times; a resolver in the wrong domain is rejected. Before creating one, ask: "What service do I need? Which domain has that service?"

Placement

  1. Identify the service needed. Find the domain folder that contains it. Create the file in that feature folder.
  2. Does the target domain already import the required service's module? Yes: place it there. No: if the service's domain already imports the target domain's module, place it in the service's domain. Otherwise choose the domain with fewer new imports.
  3. Never add a module import solely to satisfy a relation if placing the resolver in the other domain resolves it.
  4. If both sides need new imports, choose the side already importing the dependency transitively.
Service Folder (under apps/server/src/api/)
BillService finance/bill/
PaymentService finance/payment/
SocietyService society/society/
UnitService society/unit/
UserService users/user/, or a domain that already imports UserModule

Real files: finance/bill/user.billsCreated, society/unit/society.units, society/society/announcement.society, users/user/payment.user, users/user/announcement.createdBy, society/society-member/user.societyMemberships (each .fields.resolver.ts).

Known exception in the code: society/unit/unit.society.fields.resolver.ts uses SocietyService.

Standards

  • File {parentType}.{relation}.fields.resolver.ts; class {Parent}{Relation}FieldsResolver with @Resolver("Parent").
  • One relation per file. Never group unrelated relations.
  • @UseGuards(AuthGuard, ScopeGuard) at method level, plus @RequireScope({ requireSociety: true }) when needed. Class level is acceptable only if every field shares identical requirements; be consistent.
  • Try/catch with logger.warn; return null or [] on failure.
  • Services only, no direct database calls. Do not inject unused services. Import types from gql/server.

Common violations

  1. User.* resolvers in users/ when they need other services.
  2. Society.* resolvers in society/unit/ when they need SocietyService.
  3. New module imports just to satisfy a placement.
  4. Several unrelated relations in one resolver file.
  5. Placing by parent type instead of required service.

Checklist before creating one

  • Which service, and which domain folder holds it?
  • Does that domain already import the service's module?
  • If not, would adding the import create a circular dependency?
  • Is there a placement that avoids new imports?

If you cannot answer these, do not create the resolver. Template: server-patterns.