Skip to content

feat: allow field resolvers on fields without arguments#2629

Merged
Noroth merged 9 commits intomainfrom
ludwig/eng-9161-add-support-in-protographic
Mar 13, 2026
Merged

feat: allow field resolvers on fields without arguments#2629
Noroth merged 9 commits intomainfrom
ludwig/eng-9161-add-support-in-protographic

Conversation

@Noroth
Copy link
Copy Markdown
Contributor

@Noroth Noroth commented Mar 11, 2026

This PR enables protographic to generate field resolvers for fields without arguments. This is useful when you have expensive fields that would otherwise be always resolved by the operation to be excluded and resolved separately.

Summary by CodeRabbit

  • New Features

    • Field resolvers now support no-argument resolvers.
  • Documentation

    • Expanded and clarified field-resolver behavior, context validation, naming/conversion rules, mapping guidance, and minor API-reference formatting fixes.
  • Tests

    • Added and expanded tests covering no-argument resolvers, multi-context fields, repeated/list argument handling, and proto output expectations.

Checklist

  • I have discussed my proposed changes in an issue and have received approval to proceed.
  • I have followed the coding standards of the project.
  • Tests or benchmarks have been added or updated.
  • Documentation has been updated on https://github.com/wundergraph/cosmo-docs.
  • I have read the Contributors Guide.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 11, 2026

Walkthrough

Adds support for field resolvers without arguments, updates visitor and validation logic to recognize a CONNECT_FIELD_RESOLVER directive, emits resolver RPCs/messages selectively, expands tests for no-arg resolvers and argument-list semantics, and applies documentation and formatting edits across protographic docs and tests.

Changes

Cohort / File(s) Summary
Docs / API
protographic/OPERATIONS_TO_PROTO.md, protographic/README.md, protographic/SDL_MAPPING_RULES.md, protographic/SDL_PROTO_RULES.md, protographic/plugin_development.md
Formatting and content updates: API reference signature formatting, expanded SDL→proto rules and field-resolver behavior (with/without args), enum/field mapping examples, and minor markdown fixes.
Visitor: SDL → Mapping
protographic/src/sdl-to-mapping-visitor.ts
Adjust field selection logic to treat fields as resolvers when they have arguments OR the CONNECT_FIELD_RESOLVER directive; import/update directive constant usage.
Visitor: SDL → Proto
protographic/src/sdl-to-proto-visitor.ts
Emit resolver RPCs/messages only when appropriate (args present or directive-driven), build args messages conditionally, handle repeated/wrapper arg types, update processed-types tracking and field filtering to exclude resolver fields from parent messages.
Validation
protographic/src/sdl-validation-visitor.ts
Refined guards and warning logic: early-return conditions changed, directive-specific warning messaging when context missing, and validation flow updated to consider directive presence vs. args.
Tests — Resolver Behavior
protographic/tests/sdl-to-mapping/04-field-resolvers.test.ts, protographic/tests/sdl-to-proto/13-field-arguments.test.ts, protographic/tests/sdl-validation/01-basic-validation.test.ts
Added tests for field resolvers without arguments, multiple context fields, repeated/list wrapper semantics, and updated validation/warning expectations.
Tests — Formatting / Minor Edits
protographic/tests/abstract-selection-rewriter/01-basics.test.ts, protographic/tests/abstract-selection-rewriter/02-advanced.test.ts, protographic/tests/operations/proto-text-generator.test.ts, protographic/tests/operations/request-builder.test.ts
Cosmetic reflowing, semicolon/trailing-comma fixes, import formatting, and constant repositioning without behavior changes.
Tooling / Config
protographic/vite.config.ts, package.json
Small whitespace/newline and manifest edits.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main feature: allowing field resolvers on fields without arguments, which is directly supported by the changes across multiple files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 11, 2026

Codecov Report

❌ Patch coverage is 95.91837% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.30%. Comparing base (e735694) to head (67a4ba4).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
protographic/src/sdl-validation-visitor.ts 88.23% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #2629       +/-   ##
===========================================
+ Coverage   64.58%   89.30%   +24.71%     
===========================================
  Files         301       21      -280     
  Lines       42900     4527    -38373     
  Branches     4601     1248     -3353     
===========================================
- Hits        27709     4043    -23666     
+ Misses      15170      484    -14686     
+ Partials       21        0       -21     
Files with missing lines Coverage Δ
protographic/src/sdl-to-mapping-visitor.ts 96.92% <100.00%> (ø)
protographic/src/sdl-to-proto-visitor.ts 94.02% <100.00%> (ø)
protographic/src/sdl-validation-visitor.ts 86.28% <88.23%> (ø)

... and 319 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@protographic/src/sdl-to-proto-visitor.ts`:
- Around line 1300-1313: The synthetic args message generation drops list-ness
because the mapping only forwards typeName; update the field mapping in the
hasArgs branch (the call that builds the message for argsMessageName inside
buildMessage) to include the isRepeated flag returned by getProtoTypeFromGraphQL
so repeated GraphQL argument types become "repeated" in the proto; i.e., when
iterating field.args use const protoType =
this.getProtoTypeFromGraphQL(arg.type) and pass protoType.typeName and
protoType.isRepeated (alongside fieldNumber and fieldName from
graphqlFieldToProtoField) into buildMessage so list-valued resolver args are
emitted correctly.

In `@protographic/src/sdl-validation-visitor.ts`:
- Around line 353-358: The validation reports "No `@connect__fieldResolver`
directive found..." even for zero-arg fields that rely on the implicit ID
fallback when only the directive's context is omitted; update the check that
emits that warning to only run when the directive is actually absent (use the
existing hasResolverDirective variable) and, if the directive exists but has an
empty/missing context, emit a different message that mentions a missing/empty
context rather than "directive not found"; locate and modify the warning
emission near where hasArgs and hasResolverDirective are computed (references:
hasArgs, hasResolverDirective, CONNECT_FIELD_RESOLVER) so the warning is gated
by !hasResolverDirective or replaced with a context-specific warning when the
directive is present but context is empty.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8188a894-5648-42bf-92f3-ac607d5c3574

📥 Commits

Reviewing files that changed from the base of the PR and between 2375cd8 and df3b195.

📒 Files selected for processing (15)
  • protographic/OPERATIONS_TO_PROTO.md
  • protographic/README.md
  • protographic/SDL_MAPPING_RULES.md
  • protographic/SDL_PROTO_RULES.md
  • protographic/plugin_development.md
  • protographic/src/sdl-to-mapping-visitor.ts
  • protographic/src/sdl-to-proto-visitor.ts
  • protographic/src/sdl-validation-visitor.ts
  • protographic/tests/abstract-selection-rewriter/01-basics.test.ts
  • protographic/tests/abstract-selection-rewriter/02-advanced.test.ts
  • protographic/tests/operations/proto-text-generator.test.ts
  • protographic/tests/operations/request-builder.test.ts
  • protographic/tests/sdl-to-mapping/04-field-resolvers.test.ts
  • protographic/tests/sdl-to-proto/13-field-arguments.test.ts
  • protographic/vite.config.ts

Comment thread protographic/src/sdl-to-proto-visitor.ts
Comment thread protographic/src/sdl-validation-visitor.ts
@Noroth Noroth marked this pull request as ready for review March 11, 2026 13:50
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
protographic/tests/sdl-to-proto/13-field-arguments.test.ts (1)

966-1262: Add one lock-data regression around the new resolver path.

The new snapshots validate emitted proto text, but they do not exercise the schema-evolution case where an existing object field becomes a @connect__fieldResolver. Since compileGraphQLToProto() already returns lockData, a round-trip with previous lock data would catch two easy-to-miss regressions: the removed field number should become reserved on the parent message, and the generated Resolve* resolver messages should stay out of lockData. Based on learnings, resolver-related messages (created by createResolverRequestMessage and createResolverResponseMessage) are special messages that should not be tracked in the proto lock file, unlike other message types.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@protographic/tests/sdl-to-proto/13-field-arguments.test.ts` around lines 966
- 1262, Add a lock-data regression test: call compileGraphQLToProto twice
simulating prior lockData and a new schema where a field becomes
`@connect__fieldResolver`, then verify lockData reserves the removed field number
on the parent message and that resolver messages created by
createResolverRequestMessage and createResolverResponseMessage are not written
into lockData; update the test to use the returned lockData from
compileGraphQLToProto for the first run and pass it back into the second run to
assert the reserved field behavior and absence of resolver-related messages in
lockData.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@protographic/tests/sdl-to-proto/13-field-arguments.test.ts`:
- Around line 966-1262: Add a lock-data regression test: call
compileGraphQLToProto twice simulating prior lockData and a new schema where a
field becomes `@connect__fieldResolver`, then verify lockData reserves the removed
field number on the parent message and that resolver messages created by
createResolverRequestMessage and createResolverResponseMessage are not written
into lockData; update the test to use the returned lockData from
compileGraphQLToProto for the first run and pass it back into the second run to
assert the reserved field behavior and absence of resolver-related messages in
lockData.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 622a4c7c-d73a-4405-b401-e9539fe57bc1

📥 Commits

Reviewing files that changed from the base of the PR and between df3b195 and 81d6027.

📒 Files selected for processing (2)
  • protographic/src/sdl-to-proto-visitor.ts
  • protographic/tests/sdl-to-proto/13-field-arguments.test.ts

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
protographic/tests/sdl-validation/01-basic-validation.test.ts (1)

241-262: Consider adding a test for field without arguments and without explicit context.

The new test covers the case where a field without arguments has @connect__fieldResolver with an explicit context. For completeness, consider adding a complementary test for the fallback behavior when no context is provided:

test('should fall back to ID field for field without arguments when no context is provided', () => {
  const sdl = `
    directive `@connect__fieldResolver`(context: openfed__FieldSet!) on FIELD_DEFINITION
    scalar openfed__FieldSet

    type Query {
        user(id: ID!): User!
    }

    type User {
        id: ID!
        name: String!
        avatar: String! `@connect__fieldResolver`
    }
  `;

  const visitor = new SDLValidationVisitor(sdl);
  const result = visitor.visit();

  expect(result.errors).toHaveLength(0);
  expect(result.warnings).toHaveLength(1);
  expect(result.warnings[0]).toContain(
    '@connect__fieldResolver directive on the field avatar has no context provided - falling back to ID field',
  );
});

This would ensure consistent behavior between fields with and without arguments when the context fallback is triggered.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@protographic/tests/sdl-validation/01-basic-validation.test.ts` around lines
241 - 262, Add a complementary test to cover the fallback behavior when a field
without arguments uses `@connect__fieldResolver` but no context is provided:
create a test (e.g., "should fall back to ID field for field without arguments
when no context is provided") in the same suite that builds an SDL where
User.avatar has `@connect__fieldResolver` (no context), instantiate
SDLValidationVisitor(sdl) and call visit(), then assert result.errors.length ===
0 and result.warnings.length === 1 and that the warning message contains text
indicating the directive on field "avatar" has no context and is falling back to
the ID field (so the test references SDLValidationVisitor, the avatar field, and
the `@connect__fieldResolver` directive).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@protographic/tests/sdl-validation/01-basic-validation.test.ts`:
- Around line 241-262: Add a complementary test to cover the fallback behavior
when a field without arguments uses `@connect__fieldResolver` but no context is
provided: create a test (e.g., "should fall back to ID field for field without
arguments when no context is provided") in the same suite that builds an SDL
where User.avatar has `@connect__fieldResolver` (no context), instantiate
SDLValidationVisitor(sdl) and call visit(), then assert result.errors.length ===
0 and result.warnings.length === 1 and that the warning message contains text
indicating the directive on field "avatar" has no context and is falling back to
the ID field (so the test references SDLValidationVisitor, the avatar field, and
the `@connect__fieldResolver` directive).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 155dd836-a6ad-41c2-bc72-3d173f266b0e

📥 Commits

Reviewing files that changed from the base of the PR and between 81d6027 and 2483ce3.

📒 Files selected for processing (2)
  • protographic/src/sdl-validation-visitor.ts
  • protographic/tests/sdl-validation/01-basic-validation.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • protographic/src/sdl-validation-visitor.ts

@Noroth Noroth enabled auto-merge (squash) March 13, 2026 09:32
Copy link
Copy Markdown
Contributor

@dkorittki dkorittki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@Noroth Noroth merged commit 56859f0 into main Mar 13, 2026
10 checks passed
@Noroth Noroth deleted the ludwig/eng-9161-add-support-in-protographic branch March 13, 2026 11:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants