Skip to content

Work / DwarSeva Societies / Wiki / Decisions

2026-10-04-field-resolvers-live-with-their-service

Decisioncanonicalverified 2026-10-04

DECISION.2026-10-04.FIELD-RESOLVERS-LIVE-WITH-THEIR-SERVICE

Decision

By required service. Ask which service resolves the relation, find the domain that owns it, and put the file there: {parentType}.{relation}.fields.resolver.ts, class {Parent}{Relation}FieldsResolver, one relation per file. If both placements need a new import, choose the side that already imports the dependency transitively.

Why

A GraphQL field resolver joins two domains: User.billsCreated is a field of User and needs BillService. Wherever the file goes, one module must import the other, and the wrong choice creates a circular import between NestJS modules. The rule existed long before this page; it is recorded here on the day the wiki was created, and its original date is unknown. The rules file said it had been broken more than twenty times.

Options weighed:

  • By parent type — User.* resolvers in users/. The obvious reading, and the one that kept being chosen. users/ would then import every domain that has a relation to a user.
  • By required service — the resolver sits beside the service that resolves the relation.

Impact

  • User.billsCreated lives in finance/bill/; Society.units in society/society/; Payment.user in finance/payment/.
  • A reader looking for every field of User cannot find them in one folder; they must search by filename.
  • No module is imported only to satisfy a field resolver.
  • The full checklist, decision tree and examples stay in AGENTS.md, because an agent has to act on them.

Status

Active

Sources

  • AGENTS.md — "Field resolver placement rule"
  • apps/server/src/api