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-SERVICEDecision
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 inusers/. 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.billsCreatedlives infinance/bill/;Society.unitsinsociety/society/;Payment.userinfinance/payment/.- A reader looking for every field of
Usercannot 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