Skip to content

fix: allow interface subtype for implemented interface fields#2764

Merged
Aenimus merged 3 commits intomainfrom
david/eng-9373-allow-interface-subtypes-for-implemented-interface-fields
Apr 14, 2026
Merged

fix: allow interface subtype for implemented interface fields#2764
Aenimus merged 3 commits intomainfrom
david/eng-9373-allow-interface-subtypes-for-implemented-interface-fields

Conversation

@Aenimus
Copy link
Copy Markdown
Member

@Aenimus Aenimus commented Apr 14, 2026

Summary by CodeRabbit

  • New Features

    • Added support for interface-to-interface implementation relationships during composition.
  • Bug Fixes

    • Improved validation so implementations across concrete and interface chains are correctly recognized as valid subtypes.
  • Tests

    • Added normalization and federation tests (with fixtures) covering concrete and interface-to-interface implementation scenarios.

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/docs-website.
  • I have read the Contributors Guide.

Open Source AI Manifesto

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

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 14, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 45.79%. Comparing base (e14c41b) to head (45daebd).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2764      +/-   ##
==========================================
+ Coverage   41.55%   45.79%   +4.23%     
==========================================
  Files         785     1037     +252     
  Lines      112455   139274   +26819     
  Branches     8667     8679      +12     
==========================================
+ Hits        46730    63777   +17047     
- Misses      65362    73771    +8409     
- Partials      363     1726    +1363     
Files with missing lines Coverage Δ
composition/src/ast/utils.ts 93.13% <ø> (ø)
composition/src/schema-building/params.ts 100.00% <100.00%> (ø)
composition/src/schema-building/utils.ts 92.14% <100.00%> (+1.14%) ⬆️
composition/src/utils/string-constants.ts 100.00% <100.00%> (ø)
...omposition/src/v1/federation/federation-factory.ts 88.77% <100.00%> (+0.02%) ⬆️
...tion/src/v1/normalization/normalization-factory.ts 89.91% <100.00%> (+0.08%) ⬆️

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

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 14, 2026

Router-nonroot image scan failed

❌ Security vulnerabilities found in image:

ghcr.io/wundergraph/cosmo/router:sha-599e388f31426343a83a5f13a46658721e7ea0d2-nonroot

Please check the security vulnerabilities found in the PR.

If you believe this is a false positive, please add the vulnerability to the .trivyignore file and re-run the scan.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 14, 2026

Caution

Review failed

Pull request was closed or merged during review

Walkthrough

Adds explicit tracking and typing for interface-to-interface implementations across composition. Introduces new type aliases and constants, refactors type-validation to accept a params object, threads an interfaceImplementationTypeNamesByInterfaceTypeName map through normalization and federation, and updates tests to cover interface implementation chains.

Changes

Cohort / File(s) Summary
AST / basic types
composition/src/ast/utils.ts, composition/src/types/types.ts, composition/src/utils/string-constants.ts
Added ParentTypeNode union; new type aliases AbstractTypeName and InterfaceTypeName; added INTERFACE_NODE_KINDS constant.
Normalization types
composition/src/normalization/types.ts
Tightened several Map key/value types to use TypeName, AbstractTypeName, InterfaceTypeName, SubgraphName; added interfaceImplementationTypeNamesByInterfaceTypeName to NormalizationSuccess and BatchNormalizationSuccess.
Schema-building validation
composition/src/schema-building/params.ts, composition/src/schema-building/utils.ts
Added IsTypeValidImplementationParams type; refactored isTypeValidImplementation to accept a single params object and consult both concrete and interface implementation maps; added exported isInterfaceNode type guard.
Utility types
composition/src/utils/types.ts
Changed InvalidFieldImplementation.unimplementedArguments from Set<string> to Set<ArgumentName> and updated imports.
Federation wiring
composition/src/v1/federation/params.ts, composition/src/v1/federation/federation-factory.ts
Propagated new interfaceImplementationTypeNamesByInterfaceTypeName through FederationFactoryParams and FederationFactory; updated validation calls and unimplementedArguments typing.
Normalization factory implementation
composition/src/v1/normalization/normalization-factory.ts
Extracts and merges interface-to-interface implementation mappings, narrows helper signatures to interfaces/objects, tightens map key types, and returns the new interface-implementation map in normalization results.
Tests and fixtures
composition/tests/v1/types/interfaces.test.ts
Added test fixtures and four tests (two normalization, two federation) covering concrete and interface-to-interface implementation chains.

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 'fix: allow interface subtype for implemented interface fields' accurately summarizes the main change: enabling interface types to be valid subtypes for fields typed as implemented interfaces.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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

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 (4)
composition/src/utils/types.ts (1)

1-2: Remove unused imports.

InterfaceTypeDefinitionNode and InterfaceTypeExtensionNode are imported but not used anywhere in this file. Only ArgumentName is actually utilized (line 18).

♻️ Proposed fix
-import { InterfaceTypeDefinitionNode, InterfaceTypeExtensionNode, type Kind } from 'graphql';
+import { type Kind } from 'graphql';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@composition/src/utils/types.ts` around lines 1 - 2, Remove the unused GraphQL
imports: delete InterfaceTypeDefinitionNode and InterfaceTypeExtensionNode (and
Kind if it's not referenced elsewhere) from the top import line and only import
the types that are actually used; keep the existing import of ArgumentName (and
SubgraphName if used) from '../types/types' and update the import statement so
it only lists the required symbols (e.g., remove InterfaceTypeDefinitionNode,
InterfaceTypeExtensionNode, and Kind if unused).
composition/src/schema-building/params.ts (1)

4-9: Consider using an interface instead of a type alias.

Per coding guidelines, interfaces are preferred over type aliases for object shapes.

♻️ Proposed fix
-export type IsTypeValidImplementationParams = {
+export interface IsTypeValidImplementationParams {
   concreteTypeNamesByAbstractTypeName: Map<TypeName, Set<TypeName>>;
   implementationType: TypeNode;
   interfaceImplementationTypeNamesByInterfaceTypeName: Map<InterfaceTypeName, Set<InterfaceTypeName>>;
   originalType: TypeNode;
-};
+}

As per coding guidelines: "Prefer interfaces over type aliases for object shapes in TypeScript"

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

In `@composition/src/schema-building/params.ts` around lines 4 - 9, Replace the
type alias IsTypeValidImplementationParams with an interface of the same name to
follow the guideline preferring interfaces for object shapes: declare interface
IsTypeValidImplementationParams { concreteTypeNamesByAbstractTypeName:
Map<TypeName, Set<TypeName>>; implementationType: TypeNode;
interfaceImplementationTypeNamesByInterfaceTypeName: Map<InterfaceTypeName,
Set<InterfaceTypeName>>; originalType: TypeNode; } and keep all field names
unchanged so existing usages (references to IsTypeValidImplementationParams and
its properties concreteTypeNamesByAbstractTypeName, implementationType,
interfaceImplementationTypeNamesByInterfaceTypeName, originalType) continue to
work without further edits.
composition/src/v1/normalization/normalization-factory.ts (1)

458-458: Type inconsistency between factory and types definition.

The map is typed as Map<AbstractTypeName, Set<AbstractTypeName>> here, but in composition/src/normalization/types.ts (line 77), the BatchNormalizationSuccess interface types this property as Map<InterfaceTypeName, Set<InterfaceTypeName>>. Similarly, NormalizationSuccess (line 45) uses Map<AbstractTypeName, Set<AbstractTypeName>>.

Consider aligning these types for consistency. Since this map specifically tracks interface-to-interface implementations, InterfaceTypeName seems more semantically accurate.

♻️ Suggested type alignment
-  interfaceImplementationTypeNamesByInterfaceTypeName = new Map<AbstractTypeName, Set<AbstractTypeName>>();
+  interfaceImplementationTypeNamesByInterfaceTypeName = new Map<InterfaceTypeName, Set<InterfaceTypeName>>();

You'll also need to update the corresponding usages and imports to use InterfaceTypeName.

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

In `@composition/src/v1/normalization/normalization-factory.ts` at line 458, The
map interfaceImplementationTypeNamesByInterfaceTypeName is declared with
Map<AbstractTypeName, Set<AbstractTypeName>> but the BatchNormalizationSuccess
type expects Map<InterfaceTypeName, Set<InterfaceTypeName>>; change the map
declaration to Map<InterfaceTypeName, Set<InterfaceTypeName>> to match
semantics, update any local imports/usages to use InterfaceTypeName instead of
AbstractTypeName, and ensure the related types
NormalizationSuccess/BatchNormalizationSuccess signatures and code paths that
read/write interfaceImplementationTypeNamesByInterfaceTypeName are adjusted
accordingly so the types align throughout.
composition/src/normalization/types.ts (1)

45-45: Type inconsistency between NormalizationSuccess and BatchNormalizationSuccess.

The interfaceImplementationTypeNamesByInterfaceTypeName property has different types:

  • Line 45 (NormalizationSuccess): Map<AbstractTypeName, Set<AbstractTypeName>>
  • Line 77 (BatchNormalizationSuccess): Map<InterfaceTypeName, Set<InterfaceTypeName>>

Since this map specifically tracks which interfaces implement other interfaces, InterfaceTypeName is more semantically accurate. Consider aligning both to use InterfaceTypeName.

♻️ Suggested fix for consistency
-  interfaceImplementationTypeNamesByInterfaceTypeName: Map<AbstractTypeName, Set<AbstractTypeName>>;
+  interfaceImplementationTypeNamesByInterfaceTypeName: Map<InterfaceTypeName, Set<InterfaceTypeName>>;

Also applies to: 77-77

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

In `@composition/src/normalization/types.ts` at line 45, NormalizationSuccess's
property interfaceImplementationTypeNamesByInterfaceTypeName uses
Map<AbstractTypeName, Set<AbstractTypeName>> which conflicts with
BatchNormalizationSuccess and is semantically wrong; change the property type in
the NormalizationSuccess interface to Map<InterfaceTypeName,
Set<InterfaceTypeName>> so both NormalizationSuccess and
BatchNormalizationSuccess use InterfaceTypeName, and update any associated type
references/imports (replace AbstractTypeName usage for this property) to keep
types consistent across the two interfaces.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@composition/src/normalization/types.ts`:
- Line 45: NormalizationSuccess's property
interfaceImplementationTypeNamesByInterfaceTypeName uses Map<AbstractTypeName,
Set<AbstractTypeName>> which conflicts with BatchNormalizationSuccess and is
semantically wrong; change the property type in the NormalizationSuccess
interface to Map<InterfaceTypeName, Set<InterfaceTypeName>> so both
NormalizationSuccess and BatchNormalizationSuccess use InterfaceTypeName, and
update any associated type references/imports (replace AbstractTypeName usage
for this property) to keep types consistent across the two interfaces.

In `@composition/src/schema-building/params.ts`:
- Around line 4-9: Replace the type alias IsTypeValidImplementationParams with
an interface of the same name to follow the guideline preferring interfaces for
object shapes: declare interface IsTypeValidImplementationParams {
concreteTypeNamesByAbstractTypeName: Map<TypeName, Set<TypeName>>;
implementationType: TypeNode;
interfaceImplementationTypeNamesByInterfaceTypeName: Map<InterfaceTypeName,
Set<InterfaceTypeName>>; originalType: TypeNode; } and keep all field names
unchanged so existing usages (references to IsTypeValidImplementationParams and
its properties concreteTypeNamesByAbstractTypeName, implementationType,
interfaceImplementationTypeNamesByInterfaceTypeName, originalType) continue to
work without further edits.

In `@composition/src/utils/types.ts`:
- Around line 1-2: Remove the unused GraphQL imports: delete
InterfaceTypeDefinitionNode and InterfaceTypeExtensionNode (and Kind if it's not
referenced elsewhere) from the top import line and only import the types that
are actually used; keep the existing import of ArgumentName (and SubgraphName if
used) from '../types/types' and update the import statement so it only lists the
required symbols (e.g., remove InterfaceTypeDefinitionNode,
InterfaceTypeExtensionNode, and Kind if unused).

In `@composition/src/v1/normalization/normalization-factory.ts`:
- Line 458: The map interfaceImplementationTypeNamesByInterfaceTypeName is
declared with Map<AbstractTypeName, Set<AbstractTypeName>> but the
BatchNormalizationSuccess type expects Map<InterfaceTypeName,
Set<InterfaceTypeName>>; change the map declaration to Map<InterfaceTypeName,
Set<InterfaceTypeName>> to match semantics, update any local imports/usages to
use InterfaceTypeName instead of AbstractTypeName, and ensure the related types
NormalizationSuccess/BatchNormalizationSuccess signatures and code paths that
read/write interfaceImplementationTypeNamesByInterfaceTypeName are adjusted
accordingly so the types align throughout.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a873489a-78b6-48f1-b4a1-9a53ece7c7d6

📥 Commits

Reviewing files that changed from the base of the PR and between e14c41b and bc50913.

📒 Files selected for processing (12)
  • composition-go/index.global.js
  • composition/src/ast/utils.ts
  • composition/src/normalization/types.ts
  • composition/src/schema-building/params.ts
  • composition/src/schema-building/utils.ts
  • composition/src/types/types.ts
  • composition/src/utils/string-constants.ts
  • composition/src/utils/types.ts
  • composition/src/v1/federation/federation-factory.ts
  • composition/src/v1/federation/params.ts
  • composition/src/v1/normalization/normalization-factory.ts
  • composition/tests/v1/types/interfaces.test.ts

@Aenimus Aenimus enabled auto-merge (squash) April 14, 2026 17:55
@Aenimus Aenimus merged commit 8fe04a8 into main Apr 14, 2026
39 of 43 checks passed
@Aenimus Aenimus deleted the david/eng-9373-allow-interface-subtypes-for-implemented-interface-fields branch April 14, 2026 18:07
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.

2 participants