Skip to content

fix(protographic): enforce using __typename in composite types for requires#2680

Merged
Noroth merged 13 commits intomainfrom
ludwig/eng-9277-include-__typename-for-composite-types-in-protographic
Mar 24, 2026
Merged

fix(protographic): enforce using __typename in composite types for requires#2680
Noroth merged 13 commits intomainfrom
ludwig/eng-9277-include-__typename-for-composite-types-in-protographic

Conversation

@Noroth
Copy link
Copy Markdown
Contributor

@Noroth Noroth commented Mar 23, 2026

When using composite types in @requires in protobuf, we need to determine the type from the subgraph to properly set the proto message data. To ensure this is defined in the schema we add a new linting rule for field sets in @requires directives.

Summary by CodeRabbit

  • New Features

    • Added selection-set validation for @requires with an optional auto-fix that inserts missing __typename into inline fragments.
  • Bug Fixes

    • Ensure __typename is propagated into inline fragments for validation and omitted from generated proto outputs.
  • Tests

    • Added extensive tests covering __typename behavior, inline-fragment propagation, @requires validation, unions, nesting, and visitor behavior.
  • Chores

    • Test coverage config added and .gitignore updated.
  • Documentation

    • Updated rules describing @requires normalization and proto mapping for interfaces/unions.

Checklist

Open Source AI Manifesto

This project follows the principles of the Open Source AI Manifesto. Please ensure your contribution aligns with its principles.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 23, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Propagates __typename into inline fragments during selection rewriting, skips __typename when mapping required-field protos, and adds SDL validation (with optional auto-fix) that enforces __typename in @requires(fields: "...") via a new SelectionSetValidationVisitor.

Changes

Cohort / File(s) Summary
Selection rewriting & required-fields
protographic/src/abstract-selection-rewriter.ts, protographic/src/required-fields-visitor.ts
AbstractSelectionRewriter now treats __typename as always eligible when distributing interface/union selections into inline fragments; RequiredFieldsVisitor skips __typename to avoid generating proto fields for it.
SDL validation visitor changes
protographic/src/sdl-validation-visitor.ts
SDLValidationVisitor builds a parsed schema for type lookups, adds a use-of-typename field-level rule to validate @requires(fields: "...") by parsing and delegating selection validation, removes per-rule enabled gating, and deletes several public helper methods (configureRule/getAvailableRules/hasErrors/hasWarnings).
Selection-set validation visitor (new)
protographic/src/selection-set-validation-visitor.ts
Adds exported SelectionSetValidationVisitor that validates (or auto-fixes) __typename presence inside inline fragments of parsed selection sets and returns structured validation results.
Tests — selection rewriting
protographic/tests/abstract-selection-rewriter/02-advanced.test.ts
Adds test verifying __typename is propagated into inline fragments during normalization.
Tests — sdl-to-proto / federation
protographic/tests/sdl-to-proto/04-federation.test.ts
Adds test asserting proto generation for @requires selections with __typename + interface inline fragments, including oneof instance shapes and omission of __typename in resulting proto.
Tests — SDL validation
protographic/tests/sdl-validation/02-required-validation.test.ts, protographic/tests/sdl-validation/03-sdl-validation-visitor.test.ts
Adds comprehensive tests for @requires selection parsing, __typename presence matrices (parent/fragment/nested), error/warning formatting, parse-failure behavior, and public API behaviors.
Tooling / docs / misc
protographic/vite.config.ts, protographic/.gitignore, protographic/SDL_PROTO_RULES.md
Adds Vitest coverage config, ignores coverage/ in .gitignore, and updates SDL_PROTO_RULES.md with rules for @requires normalization/validation and proto mapping for interface/union inline fragments.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 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 specifically describes the main change: enforcing __typename usage in composite types within @requires directives.

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


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

@codecov
Copy link
Copy Markdown

codecov Bot commented Mar 23, 2026

Codecov Report

❌ Patch coverage is 80.40541% with 29 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.05%. Comparing base (1ca1fd0) to head (c653b65).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...otographic/src/selection-set-validation-visitor.ts 83.67% 16 Missing ⚠️
protographic/src/sdl-validation-visitor.ts 72.91% 13 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #2680       +/-   ##
===========================================
+ Coverage   64.27%   86.05%   +21.77%     
===========================================
  Files         305       20      -285     
  Lines       43266     4445    -38821     
  Branches     4628      984     -3644     
===========================================
- Hits        27811     3825    -23986     
+ Misses      15433      600    -14833     
+ Partials       22       20        -2     
Files with missing lines Coverage Δ
protographic/src/abstract-selection-rewriter.ts 81.89% <100.00%> (ø)
protographic/src/required-fields-visitor.ts 87.50% <100.00%> (ø)
protographic/src/sdl-validation-visitor.ts 83.76% <72.91%> (ø)
...otographic/src/selection-set-validation-visitor.ts 83.67% <83.67%> (ø)

... and 321 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

🧹 Nitpick comments (1)
protographic/tests/sdl-to-proto/04-federation.test.ts (1)

1449-1458: Assert the concrete fragment fields as well.

This still passes if the generator emits the oneof wrapper and empty PalletItem/ContainerItem messages. Please also check name, pallet_count, and container_size so the test protects the actual @requires payload shape, not just the type shell.

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

In `@protographic/tests/sdl-to-proto/04-federation.test.ts` around lines 1449 -
1458, The test only verifies the presence of the oneof wrapper and empty message
names, so update the assertions in the test (the expectations around protoText
and RequireStorageItemInfoById/RequireStorageItemInfoByIdFields) to also assert
that the concrete fragment messages include the expected fields: check that
'PalletItem' contains 'name' and 'pallet_count' and that 'ContainerItem'
contains 'name' and 'container_size' (i.e., add
expect(protoText).toContain('name'),
expect(protoText).toContain('pallet_count'), and
expect(protoText).toContain('container_size') or equivalent assertions
referencing the same protoText used in the test) so the test verifies the actual
`@requires` payload shape rather than just the type shells.
🤖 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/selection-set-validation-visitor.ts`:
- Around line 138-156: The code currently enforces __typename for every inline
fragment; change it to only require __typename when the enclosing field's type
is abstract (interface or union). In the block that begins with if
(!this.isInlineFragment(ctx.parent)) return;, consult the enclosing field type
(e.g., a tracked this.currentFieldType or add a helper like
isAbstractType(type)) and skip the __typename requirement for concrete object
types; only run the selectionSetContainsTypename checks and call
this.ensureTypenameInSelection or push to this.validationResult.errors when the
enclosing field type is an interface or union. Use existing symbols like
isInlineFragment, selectionSetContainsTypename, currentFieldSelectionSet,
ensureTypenameInSelection, and validationResult.errors to locate and implement
the conditional.
- Around line 190-192: When popping the child selection set in the block that
checks this.isFieldNode(ctx.parent), don't leave currentFieldSelectionSet
pointing at the popped child; after calling this.fieldSelectionSetStack.pop()
restore currentFieldSelectionSet to the new top of the stack (peek the last
element or set to undefined if stack is empty) so the parent selection-set
context is correctly re-established for subsequent inline fragments; update the
code around this.isFieldNode, currentFieldSelectionSet, and
fieldSelectionSetStack.pop() to pop first then assign currentFieldSelectionSet =
this.fieldSelectionSetStack[this.fieldSelectionSetStack.length - 1] ||
undefined.

---

Nitpick comments:
In `@protographic/tests/sdl-to-proto/04-federation.test.ts`:
- Around line 1449-1458: The test only verifies the presence of the oneof
wrapper and empty message names, so update the assertions in the test (the
expectations around protoText and
RequireStorageItemInfoById/RequireStorageItemInfoByIdFields) to also assert that
the concrete fragment messages include the expected fields: check that
'PalletItem' contains 'name' and 'pallet_count' and that 'ContainerItem'
contains 'name' and 'container_size' (i.e., add
expect(protoText).toContain('name'),
expect(protoText).toContain('pallet_count'), and
expect(protoText).toContain('container_size') or equivalent assertions
referencing the same protoText used in the test) so the test verifies the actual
`@requires` payload shape rather than just the type shells.
🪄 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: 4f115c0b-a433-4ef1-8b5c-6315a207696b

📥 Commits

Reviewing files that changed from the base of the PR and between f0aa414 and 6fcbf83.

📒 Files selected for processing (7)
  • protographic/src/abstract-selection-rewriter.ts
  • protographic/src/required-fields-visitor.ts
  • protographic/src/sdl-validation-visitor.ts
  • protographic/src/selection-set-validation-visitor.ts
  • protographic/tests/abstract-selection-rewriter/02-advanced.test.ts
  • protographic/tests/sdl-to-proto/04-federation.test.ts
  • protographic/tests/sdl-validation/02-required-validation.test.ts

Comment thread protographic/src/selection-set-validation-visitor.ts
Comment thread protographic/src/selection-set-validation-visitor.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.

Actionable comments posted: 1

🧹 Nitpick comments (2)
protographic/src/sdl-validation-visitor.ts (1)

154-160: Rule description is misleading.

The description says "Validates usage of __typename field which is not supported" but this rule actually enforces that __typename must be present in inline fragments within @requires field sets. The current wording suggests the opposite.

📝 Suggested fix
     const compositeTypeReflectionRule: LintingRule<Kind.FIELD_DEFINITION> = {
       name: 'use-of-typename',
-      description: 'Validates usage of __typename field which is not supported',
+      description: 'Validates that __typename is present in `@requires` selection sets containing inline fragments',
       enabled: true,
       nodeKind: Kind.FIELD_DEFINITION,
       validationFunction: (ctx) => this.validateCompositeTypeReflection(ctx),
     };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@protographic/src/sdl-validation-visitor.ts` around lines 154 - 160, The rule
defined as compositeTypeReflectionRule (name 'use-of-typename',
validationFunction -> this.validateCompositeTypeReflection) has a misleading
description claiming "__typename field ... is not supported" while the validator
actually enforces that __typename must be present in inline fragments for
`@requires` field sets; update the description string to accurately state that the
rule requires __typename to be present in inline fragments used in `@requires`
field sets (and optionally rename the rule from 'use-of-typename' to something
like 'require-typename-in-requires' for clarity) so the name/description match
the behaviour of validateCompositeTypeReflection.
protographic/tests/sdl-validation/03-sdl-validation-visitor.test.ts (1)

103-109: Fragile test relies on implementation details.

This test accesses and modifies the private schema field via (visitor as any) to force a parse error in visit(). This approach is brittle—if the internal property name changes, the test may silently stop testing the intended behavior.

Consider testing the error path by subclassing or using a schema that becomes invalid only during the visit() traversal, or document that this is intentionally testing internal error handling.

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

In `@protographic/tests/sdl-validation/03-sdl-validation-visitor.test.ts` around
lines 103 - 109, The test should not mutate the private schema field via
(visitor as any); instead trigger the visit() error path without touching
internals by either passing an SDL string that will become invalid during
traversal (use cleanSdl variant that contains a construct causing parse-time
failure) or create a test-only subclass of SDLValidationVisitor that overrides
visit() to simulate a parse failure (e.g., class TestVisitor extends
SDLValidationVisitor { visit() { throw new TypeError('simulated parse error'); }
}). Replace the direct (visitor as any).schema assignment with one of these
approaches so the test still asserts that visitor.visit() throws TypeError while
avoiding brittle access to the private schema field.
🤖 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-validation-visitor.ts`:
- Around line 194-200: The call to
this.parsedSchema.getType(parentNode.name.value) may return undefined and is
being force-cast to GraphQLObjectType before passing into
SelectionSetValidationVisitor; add a null/undefined check and a runtime type
guard: call const parentType = this.parsedSchema.getType(parentNode.name.value);
if (!parentType || !(parentType instanceof GraphQLObjectType)) then handle
gracefully (throw a descriptive error or return/skip validation for that node)
otherwise pass parentType into new SelectionSetValidationVisitor; ensure the
error message mentions parentNode.name.value for easier debugging.

---

Nitpick comments:
In `@protographic/src/sdl-validation-visitor.ts`:
- Around line 154-160: The rule defined as compositeTypeReflectionRule (name
'use-of-typename', validationFunction -> this.validateCompositeTypeReflection)
has a misleading description claiming "__typename field ... is not supported"
while the validator actually enforces that __typename must be present in inline
fragments for `@requires` field sets; update the description string to accurately
state that the rule requires __typename to be present in inline fragments used
in `@requires` field sets (and optionally rename the rule from 'use-of-typename'
to something like 'require-typename-in-requires' for clarity) so the
name/description match the behaviour of validateCompositeTypeReflection.

In `@protographic/tests/sdl-validation/03-sdl-validation-visitor.test.ts`:
- Around line 103-109: The test should not mutate the private schema field via
(visitor as any); instead trigger the visit() error path without touching
internals by either passing an SDL string that will become invalid during
traversal (use cleanSdl variant that contains a construct causing parse-time
failure) or create a test-only subclass of SDLValidationVisitor that overrides
visit() to simulate a parse failure (e.g., class TestVisitor extends
SDLValidationVisitor { visit() { throw new TypeError('simulated parse error'); }
}). Replace the direct (visitor as any).schema assignment with one of these
approaches so the test still asserts that visitor.visit() throws TypeError while
avoiding brittle access to the private schema field.
🪄 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: 352d4650-247b-4120-8847-266441b22cfa

📥 Commits

Reviewing files that changed from the base of the PR and between 67c1619 and 65d4fae.

📒 Files selected for processing (5)
  • protographic/.gitignore
  • protographic/src/sdl-validation-visitor.ts
  • protographic/src/selection-set-validation-visitor.ts
  • protographic/tests/sdl-validation/03-sdl-validation-visitor.test.ts
  • protographic/vite.config.ts
✅ Files skipped from review due to trivial changes (2)
  • protographic/vite.config.ts
  • protographic/.gitignore
🚧 Files skipped from review as they are similar to previous changes (1)
  • protographic/src/selection-set-validation-visitor.ts

Comment thread protographic/src/sdl-validation-visitor.ts Outdated
@Noroth Noroth marked this pull request as ready for review March 23, 2026 13:58
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.

♻️ Duplicate comments (1)
protographic/src/selection-set-validation-visitor.ts (1)

179-181: ⚠️ Potential issue | 🟠 Major

Restore the parent selection-set context after popping.

pop() returns the child selection set you're leaving, so assigning it to currentFieldSelectionSet keeps a stale pointer instead of the parent. This could cause subsequent inline fragments in the same enclosing scope to read the wrong __typename context.

🐛 Proposed fix
     if (this.isFieldNode(ctx.parent)) {
-      this.currentFieldSelectionSet = this.fieldSelectionSetStack.pop();
+      this.fieldSelectionSetStack.pop();
+      this.currentFieldSelectionSet = this.fieldSelectionSetStack.at(-1);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@protographic/src/selection-set-validation-visitor.ts` around lines 179 - 181,
When leaving a field node in selection-set-validation-visitor.ts the code
currently assigns the popped child selection set to
this.currentFieldSelectionSet; instead, pop() should remove the child and then
restore the parent. Change the logic in the isFieldNode branch: call
this.fieldSelectionSetStack.pop() to remove the child, then set
this.currentFieldSelectionSet to the stack's new top (e.g.,
this.fieldSelectionSetStack[this.fieldSelectionSetStack.length - 1] ||
undefined) so the parent selection-set context is correctly restored for later
inline fragment checks.
🧹 Nitpick comments (2)
protographic/src/selection-set-validation-visitor.ts (1)

148-156: Mutating readonly selections array violates type contract.

SelectionSetNode.selections is typed as readonly SelectionNode[]. Directly reassigning it bypasses TypeScript's immutability guarantees. While this works at runtime, it's a type violation that could cause issues if the AST is reused elsewhere.

Consider using the visitor's return value mechanism to replace the node immutably:

♻️ Suggested approach using immutable replacement

Instead of mutating in ensureTypenameInSelection, return a new node from the visitor:

 private onEnterSelectionSet(ctx: VisitContext<SelectionSetNode>): void {
+  // ... existing checks ...
+
   if (
     !this.selectionSetContainsTypename(ctx.node) &&
     !this.selectionSetContainsTypename(this.currentFieldSelectionSet)
   ) {
     if (!this.fix) {
       // ... error handling ...
       return;
     }
 
-    this.ensureTypenameInSelection(ctx.node);
+    return {
+      ...ctx.node,
+      selections: [
+        { kind: Kind.FIELD, name: { kind: Kind.NAME, value: '__typename' } },
+        ...ctx.node.selections,
+      ],
+    };
   }
 }

This returns a new node rather than mutating in place.

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

In `@protographic/src/selection-set-validation-visitor.ts` around lines 148 - 156,
ensureTypenameInSelection currently mutates SelectionSetNode.selections (typed
readonly) which violates the AST immutability contract; change the logic to
return a new SelectionSetNode instead of reassigning selections — construct a
fresh node with the same properties but with selections = [{ kind: Kind.FIELD,
name: { kind: Kind.NAME, value: '__typename' } }, ...oldSelections] and have the
visitor use that return value (i.e., return the new node from the visitor method
that calls ensureTypenameInSelection) so the AST is replaced immutably rather
than mutated in place.
protographic/src/sdl-validation-visitor.ts (1)

154-160: Rule description is misleading.

The description says "Validates usage of __typename field which is not supported", but this rule actually requires __typename to be present in inline fragments on composite types. Consider updating to match the actual validation behavior.

📝 Suggested description
     const compositeTypeReflectionRule: LintingRule<Kind.FIELD_DEFINITION> = {
       name: 'use-of-typename',
-      description: 'Validates usage of __typename field which is not supported',
+      description: 'Validates that __typename is present in inline fragments on composite types within `@requires` directives',
       enabled: true,
       nodeKind: Kind.FIELD_DEFINITION,
       validationFunction: (ctx) => this.validateCompositeTypeReflection(ctx),
     };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@protographic/src/sdl-validation-visitor.ts` around lines 154 - 160, The rule
compositeTypeReflectionRule currently has a misleading description ("Validates
usage of __typename field which is not supported") while its validationFunction
(validateCompositeTypeReflection) enforces that __typename must be present in
inline fragments on composite types; update the description string on
compositeTypeReflectionRule to clearly state that the rule requires/validates
presence of __typename in inline fragments for composite types (and optionally
adjust the rule name 'use-of-typename' if you want clearer naming) so the
description matches the actual behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@protographic/src/selection-set-validation-visitor.ts`:
- Around line 179-181: When leaving a field node in
selection-set-validation-visitor.ts the code currently assigns the popped child
selection set to this.currentFieldSelectionSet; instead, pop() should remove the
child and then restore the parent. Change the logic in the isFieldNode branch:
call this.fieldSelectionSetStack.pop() to remove the child, then set
this.currentFieldSelectionSet to the stack's new top (e.g.,
this.fieldSelectionSetStack[this.fieldSelectionSetStack.length - 1] ||
undefined) so the parent selection-set context is correctly restored for later
inline fragment checks.

---

Nitpick comments:
In `@protographic/src/sdl-validation-visitor.ts`:
- Around line 154-160: The rule compositeTypeReflectionRule currently has a
misleading description ("Validates usage of __typename field which is not
supported") while its validationFunction (validateCompositeTypeReflection)
enforces that __typename must be present in inline fragments on composite types;
update the description string on compositeTypeReflectionRule to clearly state
that the rule requires/validates presence of __typename in inline fragments for
composite types (and optionally adjust the rule name 'use-of-typename' if you
want clearer naming) so the description matches the actual behavior.

In `@protographic/src/selection-set-validation-visitor.ts`:
- Around line 148-156: ensureTypenameInSelection currently mutates
SelectionSetNode.selections (typed readonly) which violates the AST immutability
contract; change the logic to return a new SelectionSetNode instead of
reassigning selections — construct a fresh node with the same properties but
with selections = [{ kind: Kind.FIELD, name: { kind: Kind.NAME, value:
'__typename' } }, ...oldSelections] and have the visitor use that return value
(i.e., return the new node from the visitor method that calls
ensureTypenameInSelection) so the AST is replaced immutably rather than mutated
in place.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0c10d3ad-859a-45dd-9aca-85ea8c0ac97d

📥 Commits

Reviewing files that changed from the base of the PR and between 65d4fae and 2ba634c.

📒 Files selected for processing (3)
  • protographic/src/sdl-validation-visitor.ts
  • protographic/src/selection-set-validation-visitor.ts
  • protographic/tests/sdl-validation/02-required-validation.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • protographic/tests/sdl-validation/02-required-validation.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.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
protographic/src/sdl-validation-visitor.ts (1)

95-108: ⚠️ Potential issue | 🟠 Major

Move schema parsing and building into visit() to properly handle errors.

buildASTSchema(parse(schema)) in the constructor can throw and will bypass the error normalization in visit(). Since parsedSchema is only used during visitor execution, move the schema building to inside visit() after parsing, and build from the already-parsed astNode to avoid redundant parsing.

Additionally, line 175 uses string concatenation instead of a template literal:

-    const { error, documentNode } = safeParse('{' + fieldSetValue + '}');
+    const { error, documentNode } = safeParse(`{${fieldSetValue}}`);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@protographic/src/sdl-validation-visitor.ts` around lines 95 - 108, The
constructor currently calls parse() and buildASTSchema() and assigns to
parsedSchema which can throw before visit() can normalize errors; move schema
parsing/building into the visit() method: remove buildASTSchema(parse(schema))
from the constructor, in visit() use the already-parsed astNode (or call parse
once there) and then call buildASTSchema(astNode, {assumeValid: true,
assumeValidSDL: true}) to create parsedSchema just before any validation logic;
update all uses of parsedSchema to reference the instance field populated in
visit(); also replace the string concatenation at the location using '+' (around
the former line 175) with a template literal for clarity.
🧹 Nitpick comments (1)
protographic/src/sdl-validation-visitor.ts (1)

174-176: Prefer a template literal for the wrapped field set.

safeParse(\{${fieldSetValue}}`)` is a little cleaner here and keeps the new path aligned with the repo style.

As per coding guidelines "Use template literals instead of string concatenation".

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

In `@protographic/src/sdl-validation-visitor.ts` around lines 174 - 176, The code
currently concatenates the wrapped field set when calling safeParse using '{' +
fieldSetValue + '}', please replace that concatenation with a template literal
so the call becomes safeParse(`{${fieldSetValue}}`); update the invocation
around the fieldSetValue variable (the safeParse call) to use the template
literal while preserving the existing semantics and surrounding
error/documentNode handling.
🤖 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/SDL_PROTO_RULES.md`:
- Around line 342-345: The SDL block for the Storage type has an inline
`@requires`(fields: "...") example that the project formatter rewrites into a
canonical multi-line form; update the committed content for the Storage type's
itemInfo field (the itemInfo field on type Storage using `@requires` with nested
selection of primaryItem and inline fragments for PalletItem and ContainerItem)
to match the formatter's multi-line output so the repository no longer shows a
dirty diff—run the SDL formatter and commit its rewritten version for the
Storage/itemInfo `@requires` example.
- Around line 308-316: Open SDL_PROTO_RULES.md and update the two fenced code
blocks that show the example GraphQL snippets so they include the language
identifier "graphql"; locate the first block containing "media { id ... on Book
{ author } ... on Movie { director } }" and the second block containing "media {
... on Book { id author } ... on Movie { id director } }" and change their
fenced backticks to start with ```graphql (i.e., ```graphql ... ```).

---

Outside diff comments:
In `@protographic/src/sdl-validation-visitor.ts`:
- Around line 95-108: The constructor currently calls parse() and
buildASTSchema() and assigns to parsedSchema which can throw before visit() can
normalize errors; move schema parsing/building into the visit() method: remove
buildASTSchema(parse(schema)) from the constructor, in visit() use the
already-parsed astNode (or call parse once there) and then call
buildASTSchema(astNode, {assumeValid: true, assumeValidSDL: true}) to create
parsedSchema just before any validation logic; update all uses of parsedSchema
to reference the instance field populated in visit(); also replace the string
concatenation at the location using '+' (around the former line 175) with a
template literal for clarity.

---

Nitpick comments:
In `@protographic/src/sdl-validation-visitor.ts`:
- Around line 174-176: The code currently concatenates the wrapped field set
when calling safeParse using '{' + fieldSetValue + '}', please replace that
concatenation with a template literal so the call becomes
safeParse(`{${fieldSetValue}}`); update the invocation around the fieldSetValue
variable (the safeParse call) to use the template literal while preserving the
existing semantics and surrounding error/documentNode handling.
🪄 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: 3001a44d-c763-4a48-a1fb-4dc7f52dd2d6

📥 Commits

Reviewing files that changed from the base of the PR and between 2ba634c and ef67ab2.

📒 Files selected for processing (2)
  • protographic/SDL_PROTO_RULES.md
  • protographic/src/sdl-validation-visitor.ts

Comment thread protographic/SDL_PROTO_RULES.md Outdated
Comment thread protographic/SDL_PROTO_RULES.md Outdated
Comment thread protographic/src/selection-set-validation-visitor.ts Outdated
Comment thread protographic/src/selection-set-validation-visitor.ts Outdated
Comment thread protographic/src/sdl-validation-visitor.ts Outdated
@Noroth Noroth merged commit 7cc0fdd into main Mar 24, 2026
11 checks passed
@Noroth Noroth deleted the ludwig/eng-9277-include-__typename-for-composite-types-in-protographic branch March 24, 2026 09:06
@coderabbitai coderabbitai Bot mentioned this pull request Mar 30, 2026
5 tasks
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