Skip to content

Conversation

@Aenimus
Copy link
Member

@Aenimus Aenimus commented Oct 2, 2025

Summary by CodeRabbit

  • New Features

    • requireFetchReasons directive now allowed on interfaces; interface-level entries and tracked fields are emitted.
  • Refactor

    • Centralized directive inheritance and fetch-reason propagation.
    • Public shapes/types shifted to strong name aliases (TypeName/FieldName/SubgraphName/DirectiveName); several keys renamed (e.g., interfaceObjectSubgraphNames, argumentTypeNodeByName, enumValueDataByName).
    • Added composite-node helpers and guards (COMPOSITE_OUTPUT_NODE_KINDS, isCompositeOutputNodeKind).
  • Tests

    • Expanded tests for interface support, propagation, and renamed shapes.

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

coderabbitai bot commented Oct 2, 2025

Walkthrough

Adds composite output node kinds and guards, permits REQUIRE_FETCH_REASONS on INTERFACE, centralizes field-inheritable directive handling, converts many string-keyed maps/sets to typed aliases (SubgraphName/TypeName/FieldName/DirectiveName), initializes requireFetchReasons tracking in federation nodes, and updates tests/fixtures to match renamed fields.

Changes

Cohort / File(s) Summary
AST kinds & node guards
composition/src/ast/utils.ts, composition/src/v1/utils/string-constants.ts, composition/src/v1/utils/utils.ts
Adds InterfaceNodeKind, ObjectNodeKind, CompositeOutputNodeKind; exports COMPOSITE_OUTPUT_NODE_KINDS; adds isCompositeOutputNodeKind and renames isNodeKindObjectisObjectNodeKind.
Schema-building typed keys & name aliases
composition/src/schema-building/types.ts, composition/src/schema-building/utils.ts
Replaces many Map/Set string keys with SubgraphName/TypeName/FieldName/DirectiveName; updates signatures and initializations (e.g., directivesByDirectiveName, root operation maps); updates InvalidFieldNames to use FieldName/SubgraphName.
Normalization: centralized handler & param types
composition/src/v1/normalization/normalization-factory.ts, composition/src/v1/normalization/params.ts, composition/src/v1/normalization/walkers.ts, composition/src/v1/normalization/directive-definition-data.ts, composition/src/v1/normalization/types.ts
Introduces handleFieldInheritableDirectives + HandleFieldInheritableDirectivesParams; renames flag doesParentObjectRequireFetchReasonsdoesParentRequireFetchReasons; moves many maps/sets to typed aliases; renames argument/enum maps to *ByName; updates directive-definition initializations and adds INTERFACE to some directive locations.
Federation wiring & federation-factory updates
composition/src/v1/federation/federation-factory.ts, composition/src/v1/federation/utils.ts, composition/src/v1/utils/utils.ts
Renames interfaceObjectSubgraphsinterfaceObjectSubgraphNames; initializes requireFetchReasonsFieldNames on interface/object node data; updates FederationFactory params and related maps to use TypeName/SubgraphName.
Directive constants & locations
composition/src/v1/utils/constants.ts, composition/src/v1/utils/string-constants.ts
Expands REQUIRE_FETCH_REASONS_DEFINITION locations to include INTERFACE; exports composite-kind constant used by guards.
Schema-building/federation utils typed migrations
composition/src/v1/federation/utils.ts, composition/src/schema-building/utils.ts, composition/src/v1/federation/utils.ts (overlap)
Updates public param/map key types to TypeName/SubgraphName across federation and schema-building utilities; adjusts signatures and map initializations accordingly.
Tests & fixtures updates
composition/tests/v1/directives/require-fetch-reasons.test.ts, composition/tests/v1/utils/utils.ts, composition/tests/v1/directives/interface-object.test.ts, composition/tests/v1/entity-interface.test.ts, composition/tests/v1/types/enums.test.ts
Update test expectations and fixtures to use new field names (interfaceObjectSubgraphNames), enumValueDataByName, include INTERFACE in directive locations/expectations, and align shapes to typed-name changes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ 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 concisely and accurately summarizes the primary change by indicating that the @openfed__requireFetchReasons directive will now be propagated on interface types. It precisely names the directive and the target (Interfaces), matching the extensive updates to directive definitions, normalization logic, and tests. The wording is clear, specific, and follows the Conventional Commits style used by the project.
✨ Finishing touches
  • 📝 Generate docstrings

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

@github-actions
Copy link

github-actions bot commented Oct 2, 2025

Router-nonroot image scan passed

✅ No security vulnerabilities found in image:

ghcr.io/wundergraph/cosmo/router:sha-12f0e25b3d17fe5f69a3559665776de2c2754f76-nonroot

Copy link

@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

Caution

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

⚠️ Outside diff range comments (2)
composition/src/schema-building/types.ts (1)

97-118: Standardize per-subgraph collections on SubgraphName
Replace all Map<string, …> and Set<string> in per-subgraph fields with Map<SubgraphName, …> and Set<SubgraphName> in:

  • composition/src/schema-building/types.ts (FieldData.externalFieldDataBySubgraphName, ScalarDefinitionData.configureDescriptionDataBySubgraphName, EntityData.keyFieldSetDatasBySubgraphName, EntityInterfaceFederationData.interfaceObjectSubgraphs)
  • composition/src/federation/types.ts (MutualParentDefinitionData.configureDescriptionDataBySubgraphName)
  • all instantiations across normalization, federation‐utils, schema-building utils, v1 utils and tests (e.g. new Map<string,…>()new Map<SubgraphName,…>(), new Set<string>()new Set<SubgraphName>()).
    This ensures consistent typing for all per-subgraph maps/sets.
composition/src/v1/normalization/normalization-factory.ts (1)

606-631: Fix sticky parent-state: reset per-parent flags before scanning a composite type’s directives

doesParentRequireFetchReasons (new) and the existing isParentObjectExternal/isParentObjectShareable are not reset per parent. Once set true on a previous type, they will leak into subsequent types without their own directives, causing incorrect field injections and unvalidated external markings.

Reset them at the start of extractDirectives for composite output types.

Apply this diff:

   extractDirectives(
     node:
       | TypeDefinitionNode
       | TypeExtensionNode
       | FieldDefinitionNode
       | InputValueDefinitionNode
       | EnumValueDefinitionNode
       | SchemaNode,
     directivesByDirectiveName: Map<string, Array<ConstDirectiveNode>>,
   ) {
+    // Reset per-parent flags when visiting a new composite output type node
+    if (isCompositeOutputNodeKind(node.kind)) {
+      this.doesParentRequireFetchReasons = false;
+      this.isParentObjectExternal = false;
+      this.isParentObjectShareable = false;
+    }
     if (!node.directives) {
       return directivesByDirectiveName;
     }
🧹 Nitpick comments (6)
composition/src/v1/utils/constants.ts (1)

675-679: Fix comment: use INTERFACE (not INTERFACE_DEFINITION).

The code correctly uses INTERFACE; the comment should match.

Apply:

-// directive @openfed__requireFetchReasons repeatable on FIELD_DEFINITION | INTERFACE_DEFINITION | OBJECT
+// directive @openfed__requireFetchReasons repeatable on FIELD_DEFINITION | INTERFACE | OBJECT
composition/src/v1/normalization/params.ts (1)

10-15: Good addition; consider Readonly for params.*

Parameters represent inputs; ReadonlyMap/ReadonlySet/readonly arrays can reduce accidental mutation.

Example:

export type HandleFieldInheritableDirectivesParams = {
  readonly directivesByDirectiveName: ReadonlyMap<DirectiveName, readonly ConstDirectiveNode[]>;
  readonly fieldName: FieldName;
  readonly inheritedDirectiveNames: ReadonlySet<DirectiveName>;
  readonly parentData: CompositeOutputData;
};
composition/src/v1/federation/federation-factory.ts (1)

1141-1143: Confirm empty-set initialization for requireFetchReasonsFieldNames

copyParentDefinitionData usually copies sets from sourceData; initializing an empty Set here deviates and can drop pre-populated values. If the source already carries interface-level requireFetchReasons (from normalization), consider copying instead.

-          requireFetchReasonsFieldNames: new Set<FieldName>(),
+          requireFetchReasonsFieldNames: new Set<FieldName>(sourceData.requireFetchReasonsFieldNames),

If you adopt this, mirror the same for the OBJECT case for consistency. Please confirm the intended semantics (reset vs. copy).

composition/src/v1/utils/string-constants.ts (1)

63-68: Make COMPOSITE_OUTPUT_NODE_KINDS immutable

Use ReadonlySet to prevent accidental mutation and better convey intent.

-export const COMPOSITE_OUTPUT_NODE_KINDS = new Set<Kind>([
+export const COMPOSITE_OUTPUT_NODE_KINDS: ReadonlySet<Kind> = new Set<Kind>([
   Kind.INTERFACE_TYPE_DEFINITION,
   Kind.INTERFACE_TYPE_EXTENSION,
   Kind.OBJECT_TYPE_DEFINITION,
   Kind.OBJECT_TYPE_EXTENSION,
 ]);
composition/src/v1/utils/utils.ts (1)

36-38: Use type-only import for CompositeOutputNodeKind

Avoids unnecessary runtime import in ESM builds.

-import { CompositeOutputNodeKind } from '../../ast/utils';
+import type { CompositeOutputNodeKind } from '../../ast/utils';
composition/src/v1/normalization/normalization-factory.ts (1)

627-631: Gating looks good; consider minor cleanup

The isCompositeOutputNodeKind check here is correct to narrow parent-scope logic. With the per-parent reset added above, this block is robust.

Nit: hoist a const isComposite = isCompositeOutputNodeKind(node.kind) at the top of the function and reuse to avoid recompute.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 32483b8 and 0b13fba.

📒 Files selected for processing (12)
  • composition/src/ast/utils.ts (1 hunks)
  • composition/src/schema-building/types.ts (13 hunks)
  • composition/src/v1/federation/federation-factory.ts (1 hunks)
  • composition/src/v1/normalization/directive-definition-data.ts (1 hunks)
  • composition/src/v1/normalization/normalization-factory.ts (13 hunks)
  • composition/src/v1/normalization/params.ts (1 hunks)
  • composition/src/v1/normalization/walkers.ts (5 hunks)
  • composition/src/v1/utils/constants.ts (1 hunks)
  • composition/src/v1/utils/string-constants.ts (2 hunks)
  • composition/src/v1/utils/utils.ts (2 hunks)
  • composition/tests/v1/directives/require-fetch-reasons.test.ts (29 hunks)
  • composition/tests/v1/utils/utils.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (8)
composition/src/v1/federation/federation-factory.ts (2)
composition/src/resolvability-graph/types/types.ts (1)
  • FieldName (7-7)
composition/src/types/types.ts (1)
  • FieldName (5-5)
composition/src/v1/normalization/directive-definition-data.ts (1)
composition/src/utils/string-constants.ts (3)
  • FIELD_DEFINITION_UPPER (54-54)
  • INTERFACE_UPPER (76-76)
  • OBJECT_UPPER (105-105)
composition/src/v1/normalization/params.ts (3)
composition/src/v1/federation/params.ts (1)
  • ValidateOneOfDirectiveParams (5-9)
composition/src/schema-building/types.ts (2)
  • InputObjectDefinitionData (120-132)
  • CompositeOutputData (252-252)
composition/src/types/types.ts (1)
  • DirectiveName (3-3)
composition/tests/v1/directives/require-fetch-reasons.test.ts (1)
composition/src/utils/string-constants.ts (1)
  • INTERFACE (75-75)
composition/src/schema-building/types.ts (1)
composition/src/types/types.ts (2)
  • SubgraphName (9-9)
  • FieldName (5-5)
composition/src/v1/utils/constants.ts (2)
composition/src/ast/utils.ts (1)
  • stringArrayToNameNodeArray (84-90)
composition/src/utils/string-constants.ts (3)
  • FIELD_DEFINITION_UPPER (54-54)
  • INTERFACE_UPPER (76-76)
  • OBJECT_UPPER (105-105)
composition/src/v1/utils/utils.ts (2)
composition/src/ast/utils.ts (1)
  • CompositeOutputNodeKind (295-295)
composition/src/v1/utils/string-constants.ts (1)
  • COMPOSITE_OUTPUT_NODE_KINDS (63-68)
composition/src/v1/normalization/normalization-factory.ts (6)
composition/src/resolvability-graph/types/types.ts (2)
  • SubgraphName (13-13)
  • FieldName (7-7)
composition/src/v1/normalization/params.ts (1)
  • HandleFieldInheritableDirectivesParams (10-15)
composition/src/utils/string-constants.ts (3)
  • REQUIRE_FETCH_REASONS (120-120)
  • EXTERNAL (46-46)
  • SHAREABLE (135-135)
composition/src/utils/utils.ts (1)
  • generateSimpleDirective (161-166)
composition/src/v1/utils/utils.ts (2)
  • isObjectDefinitionData (446-451)
  • isCompositeOutputNodeKind (442-444)
composition/src/schema-building/utils.ts (1)
  • isTypeRequired (124-126)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (15)
  • GitHub Check: build_test
  • GitHub Check: build_push_image
  • GitHub Check: build_test
  • GitHub Check: build_push_image (nonroot)
  • GitHub Check: build_push_image
  • GitHub Check: integration_test (./telemetry)
  • GitHub Check: integration_test (./. ./fuzzquery ./lifecycle ./modules)
  • GitHub Check: integration_test (./events)
  • GitHub Check: build_test
  • GitHub Check: build_test
  • GitHub Check: image_scan
  • GitHub Check: image_scan (nonroot)
  • GitHub Check: build_push_image
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
🔇 Additional comments (13)
composition/src/v1/normalization/directive-definition-data.ts (1)

652-652: Extending locations to INTERFACE looks correct.

Matches other directives (e.g., KEY, REQUIRES_SCOPES) and aligns with the PR goal.

Please confirm normalization/walkers now read interface-level openfed__requireFetchReasons and propagate to fields as intended.

composition/tests/v1/utils/utils.ts (1)

47-55: Test schema update aligns with behavior change.

Including INTERFACE here is correct.

composition/src/ast/utils.ts (1)

293-296: New kind aliases are clear and useful.

Good public typing for composite output nodes.

composition/src/v1/utils/utils.ts (1)

442-444: Type guard LGTM

Simple, correct set-membership check over COMPOSITE_OUTPUT_NODE_KINDS.

composition/src/v1/normalization/walkers.ts (3)

364-369: Centralizing field-inheritable directives: verify parity

Good refactor. Please verify the new handler preserves prior behaviors:

  • Inheritance of @Shareable and @external for both interface/object parents
  • Handling/rejection rules for incompatible combinations
  • Setting/propagating @openfed__requireFetchReasons to parentData.requireFetchReasonsFieldNames

485-501: Resetting doesParentRequireFetchReasons on Interface leaves is correct

Prevents state leakage between interfaces and their fields/extensions.


523-526: Resetting doesParentRequireFetchReasons on Object leaves is correct

Consistent with interface handling; avoids cross-parent contamination.

Also applies to: 549-552

composition/tests/v1/directives/require-fetch-reasons.test.ts (1)

29-32: Approve tests: INTERFACE export confirmed
INTERFACE is re-exported by composition/src/index.ts, so the test’s import from '../../../src' will succeed.

composition/src/v1/normalization/normalization-factory.ts (5)

380-381: Import updates look correct

Bringing HandleFieldInheritableDirectivesParams from ./params aligns with the new handler. No issues.


410-410: New parent-level flag is fine; relies on proper reset

Adding doesParentRequireFetchReasons is good but must be reset per parent (see separate comment).

Ensure tests cover: parent A (with @openfed__requireFetchReasons) followed by parent B (without it). Fields on B must not inherit the directive.


1284-1286: Interface/object tracking + config emission LGTM

  • New InterfaceDefinitionData.requireFetchReasonsFieldNames Set and subsequent emission to configurationData are correct.
  • Also fine for Object types and final config copy.

Confirm downstream consumers of ConfigurationData read requireFetchReasonsFieldNames and updated tests assert interface-level behavior.

Also applies to: 1364-1365, 3636-3638


1037-1039: Type-narrowing to Set/FieldName is consistent

The generics tightening across data models improves type safety. No functional concerns.

Also applies to: 1177-1177, 1234-1236, 1452-1453, 443-443, 82-85


577-604: No action – handler invocation present
The call to handleFieldInheritableDirectives is in composition/src/v1/normalization/walkers.ts (around line 363) for every composite output field (objects and interfaces) before addFieldDataByNode.

Likely an incorrect or invalid review comment.

@Aenimus Aenimus marked this pull request as draft October 2, 2025 18:46
@Aenimus Aenimus marked this pull request as ready for review October 10, 2025 11:07
Copy link

@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

Caution

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

⚠️ Outside diff range comments (1)
composition/src/v1/normalization/directive-definition-data.ts (1)

111-119: Rename argumentTypeNodeByArgumentName to argumentTypeNodeByName in ExtractArgumentDataResult and its usages.
In composition/src/v1/normalization/types.ts and normalization-factory.ts, update the type property and local variables to argumentTypeNodeByName for consistency with directive data.

♻️ Duplicate comments (1)
composition/src/v1/normalization/normalization-factory.ts (1)

577-604: Address the past review feedback: mark REQUIRE_FETCH_REASONS as referenced when injected.

When handleFieldInheritableDirectives injects @openfed__requireFetchReasons into a field (line 584), the directive is not added to referencedDirectiveNames. Downstream at lines 3491-3493, the schema only includes REQUIRE_FETCH_REASONS_DEFINITION if referencedDirectiveNames contains it. This means the injected directive won't have its definition in the emitted SDL, which will break schema validation.

This issue was flagged in a previous review but has not been addressed yet.

Apply this diff to mark the directive as referenced when injecting:

  handleFieldInheritableDirectives({
    directivesByDirectiveName,
    fieldName,
    inheritedDirectiveNames,
    parentData,
  }: HandleFieldInheritableDirectivesParams) {
    if (this.doesParentRequireFetchReasons && !directivesByDirectiveName.has(REQUIRE_FETCH_REASONS)) {
      directivesByDirectiveName.set(REQUIRE_FETCH_REASONS, [generateSimpleDirective(REQUIRE_FETCH_REASONS)]);
+     this.referencedDirectiveNames.add(REQUIRE_FETCH_REASONS);
      inheritedDirectiveNames.add(REQUIRE_FETCH_REASONS);
    }
    if (this.doesParentRequireFetchReasons || directivesByDirectiveName.has(REQUIRE_FETCH_REASONS)) {
+     this.referencedDirectiveNames.add(REQUIRE_FETCH_REASONS);
      parentData.requireFetchReasonsFieldNames.add(fieldName);
    }
🧹 Nitpick comments (1)
composition/src/v1/federation/federation-factory.ts (1)

1099-1101: Copy enum values using enumValueDataByName.

Naming mismatch: helper is still copyEnumValueDataByValueName while handling ByName maps. Consider renaming for clarity in a follow-up.

-  copyEnumValueDataByValueName(
+  copyEnumValueDataByName(
     sourceData.enumValueDataByName,
     sourceData.isInaccessible,
   ),
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0b13fba and 9803be4.

📒 Files selected for processing (13)
  • composition/src/schema-building/types.ts (7 hunks)
  • composition/src/schema-building/utils.ts (12 hunks)
  • composition/src/v1/federation/federation-factory.ts (14 hunks)
  • composition/src/v1/federation/utils.ts (2 hunks)
  • composition/src/v1/normalization/directive-definition-data.ts (28 hunks)
  • composition/src/v1/normalization/normalization-factory.ts (21 hunks)
  • composition/src/v1/normalization/walkers.ts (6 hunks)
  • composition/src/v1/utils/constants.ts (1 hunks)
  • composition/src/v1/utils/string-constants.ts (2 hunks)
  • composition/src/v1/utils/utils.ts (5 hunks)
  • composition/tests/v1/directives/interface-object.test.ts (3 hunks)
  • composition/tests/v1/entity-interface.test.ts (1 hunks)
  • composition/tests/v1/types/enums.test.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (9)
composition/src/v1/normalization/walkers.ts (1)
composition/src/errors/errors.ts (1)
  • duplicateEnumValueDefinitionError (120-122)
composition/src/v1/utils/constants.ts (2)
composition/src/ast/utils.ts (1)
  • stringArrayToNameNodeArray (84-90)
composition/src/utils/string-constants.ts (3)
  • FIELD_DEFINITION_UPPER (54-54)
  • INTERFACE_UPPER (76-76)
  • OBJECT_UPPER (105-105)
composition/src/v1/utils/utils.ts (2)
composition/src/ast/utils.ts (1)
  • CompositeOutputNodeKind (295-295)
composition/src/v1/utils/string-constants.ts (1)
  • COMPOSITE_OUTPUT_NODE_KINDS (63-68)
composition/src/v1/federation/utils.ts (3)
composition/src/types/types.ts (2)
  • TypeName (11-11)
  • SubgraphName (9-9)
composition/src/schema-building/types.ts (4)
  • AuthorizationData (309-315)
  • EntityData (268-275)
  • EntityInterfaceFederationData (322-330)
  • ParentDefinitionData (242-248)
composition/src/subgraph/types.ts (1)
  • InternalSubgraph (24-38)
composition/src/v1/normalization/normalization-factory.ts (7)
composition/src/types/types.ts (2)
  • SubgraphName (9-9)
  • FieldName (5-5)
composition/src/v1/normalization/params.ts (1)
  • HandleFieldInheritableDirectivesParams (10-15)
composition/src/utils/string-constants.ts (3)
  • REQUIRE_FETCH_REASONS (120-120)
  • EXTERNAL (46-46)
  • SHAREABLE (135-135)
composition/src/utils/utils.ts (1)
  • generateSimpleDirective (161-166)
composition/src/v1/utils/utils.ts (3)
  • isObjectDefinitionData (446-451)
  • isCompositeOutputNodeKind (442-444)
  • isObjectNodeKind (438-440)
composition/src/schema-building/utils.ts (2)
  • isTypeRequired (124-126)
  • childMapToValueArray (233-247)
composition/src/schema-building/types.ts (1)
  • EnumValueData (73-85)
composition/src/v1/federation/federation-factory.ts (4)
composition/src/schema-building/types.ts (1)
  • EnumValueData (73-85)
composition/src/resolvability-graph/types/types.ts (1)
  • FieldName (7-7)
composition/src/types/types.ts (1)
  • FieldName (5-5)
composition/src/schema-building/ast.ts (1)
  • getTypeNodeNamedTypeName (281-290)
composition/src/v1/normalization/directive-definition-data.ts (3)
composition/src/schema-building/types.ts (2)
  • ArgumentData (30-34)
  • DirectiveDefinitionData (41-50)
composition/src/utils/string-constants.ts (4)
  • FIELD_DEFINITION_UPPER (54-54)
  • INTERFACE_UPPER (76-76)
  • OBJECT_UPPER (105-105)
  • REQUIRE_FETCH_REASONS (120-120)
composition/src/v1/utils/constants.ts (1)
  • REQUIRE_FETCH_REASONS_DEFINITION (676-681)
composition/src/schema-building/types.ts (2)
composition/src/types/types.ts (4)
  • SubgraphName (9-9)
  • DirectiveName (3-3)
  • TypeName (11-11)
  • FieldName (5-5)
composition/src/v1/normalization/types.ts (1)
  • KeyFieldSetData (14-19)
composition/src/schema-building/utils.ts (5)
composition/src/schema-building/types.ts (2)
  • PersistedDirectivesData (202-207)
  • CompositeOutputData (252-252)
composition/src/types/types.ts (4)
  • DirectiveName (3-3)
  • TypeName (11-11)
  • FieldName (5-5)
  • SubgraphName (9-9)
composition/src/v1/normalization/normalization-factory.ts (2)
  • isTypeNameRootType (489-491)
  • getRenamedRootTypeName (1294-1307)
composition/src/utils/string-constants.ts (1)
  • ROOT_TYPE_NAMES (170-170)
composition/src/utils/types.ts (1)
  • InvalidRequiredInputValueData (33-37)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: build_push_image
  • GitHub Check: build_test
  • GitHub Check: build_test
  • GitHub Check: Analyze (go)
  • GitHub Check: build_test
  • GitHub Check: build_test
  • GitHub Check: build_push_image
  • GitHub Check: build_push_image
  • GitHub Check: image_scan
  • GitHub Check: integration_test (./events)
  • GitHub Check: integration_test (./telemetry)
  • GitHub Check: build_push_image (nonroot)
  • GitHub Check: integration_test (./. ./fuzzquery ./lifecycle ./modules)
🔇 Additional comments (22)
composition/tests/v1/types/enums.test.ts (1)

645-657: LGTM! Field rename aligns with typed-key refactor.

The update from enumValueDataByValueName to enumValueDataByName is consistent with the broader refactor introducing strongly-typed keys (SubgraphName, TypeName, FieldName, DirectiveName) across the codebase. The test logic remains unchanged—only the property accessor is updated.

composition/src/schema-building/types.ts (3)

28-28: LGTM! Import enables typed-key refactor.

The import of strongly-typed aliases (DirectiveName, FieldName, SubgraphName, TypeName) is essential for the typed-key refactor throughout this file. This improves type safety and clarity across the public API surface.


169-169: LGTM! New field supports interface-level fetch reasons tracking.

The addition of requireFetchReasonsFieldNames: Set<FieldName> to InterfaceDefinitionData directly supports the PR objective of propagating @openfed__requireFetchReasons on Interfaces. This mirrors the existing field in ObjectDefinitionData (line 188), maintaining consistency across composite output types.


327-327: LGTM! Rename clarifies intent and aligns with typed conventions.

The rename from interfaceObjectSubgraphs to interfaceObjectSubgraphNames with type Set<SubgraphName> improves clarity (it's a set of names, not full subgraph objects) and aligns with other typed-key naming conventions in the codebase (e.g., subgraphNames, concreteTypeNames).

composition/src/schema-building/utils.ts (1)

83-792: LGTM! Function signatures consistently updated with typed aliases.

All function signature updates throughout this file correctly adopt the typed aliases (DirectiveName, FieldName, SubgraphName, TypeName) for Map/Set keys, replacing primitive string keys. The changes maintain existing logic while improving type safety. The iteration over argumentDataByName (line 528) is consistent with the field rename in PersistedDirectiveDefinitionData.

composition/tests/v1/directives/interface-object.test.ts (1)

777-777: LGTM! Test expectations updated for field rename.

The updates from interfaceObjectSubgraphs to interfaceObjectSubgraphNames in test expectations are consistent with the field rename in EntityInterfaceFederationData (composition/src/schema-building/types.ts, line 327). The test logic remains unchanged—only the expected field name is updated.

Also applies to: 870-870, 905-905

composition/src/v1/utils/string-constants.ts (1)

28-28: LGTM! New constant provides useful abstraction for composite output nodes.

The new COMPOSITE_OUTPUT_NODE_KINDS constant groups interface and object definition/extension kinds, which is useful for type guards and kind checking throughout the codebase. The use of ReadonlySet ensures immutability. This aligns well with the CompositeOutputData union type (InterfaceDefinitionData | ObjectDefinitionData) in the type system.

Also applies to: 63-68

composition/src/v1/normalization/normalization-factory.ts (3)

619-640: LGTM! Composite-output directive handling is correctly gated.

The addition of composite-output kind checks correctly broadens @openfed__requireFetchReasons support to interfaces while maintaining object-specific handling for @external and @shareable. The gating logic ensures:

  • Only composite output types (objects and interfaces) can set doesParentRequireFetchReasons
  • Only objects inherit @external and @shareable

443-443: LGTM! Type aliases improve code clarity.

The replacement of raw string types with typed aliases (SubgraphName, FieldName) improves type documentation and makes the codebase more maintainable. Since these are type aliases (per composition/src/types/types.ts), there's no runtime impact.

Also applies to: 1039-1039, 1179-1179, 1236-1237, 1286-1287, 1366-1366, 1454-1454


410-410: doesParentRequireFetchReasons reset confirmed State is reset in walkers.ts leave() handlers for each parent node, no further action required.

composition/tests/v1/entity-interface.test.ts (1)

175-176: Rename aligns with public API (interfaceObjectSubgraphNames).

Expectation matches the new field name used across federation data. Looks good.

composition/src/v1/utils/constants.ts (1)

675-681: Enable @openfed__requireFetchReasons on INTERFACE.

Directive locations now include INTERFACE. This matches the PR intent and related tests.

composition/src/v1/utils/utils.ts (2)

1-2: Type-only imports and new kind guards look good.

  • type imports reduce runtime footprint.
  • isObjectNodeKind and isCompositeOutputNodeKind are correct and idiomatic.

Also applies to: 36-38, 438-445


151-152: No stale references to interfaceObjectSubgraphs

All occurrences use interfaceObjectSubgraphNames; the old identifier isn’t present in the codebase.

composition/src/v1/normalization/walkers.ts (3)

485-486: Reset doesParentRequireFetchReasons on leave hooks.

State reset for Interface/Object leave hooks prevents leakage across parents. Good.

Also applies to: 497-498, 524-526, 550-552


291-296: Switch to enumValueDataByName map verified. No remaining enumValueDataByValueName usages found.


363-368: Field-inheritable directives handler covers interface-level requireFetchReasons
The normalization-factory sets doesParentRequireFetchReasons for interfaces and handleFieldInheritableDirectives adds and tracks @openfed__requireFetchReasons on fields, with the flag reset in InterfaceTypeDefinition.leave.

composition/src/v1/federation/federation-factory.ts (4)

597-615: Enum values merge updated to enumValueDataByName.

Upsert path correctly targets the new map; propagations intact.


1141-1161: Initialize requireFetchReasonsFieldNames on federated nodes.

Placeholder Set is fine and clearly annotated as unused for federated nodes.


1213-1226: Handle interface-object subgraph shape via interfaceObjectSubgraphNames.

Promotion of OBJECT defs to INTERFACE when sourced from interface-object subgraphs is correct and keyed to subgraph membership.

Also applies to: 1232-1234


1607-1612: Iterate interfaceObjectSubgraphNames when wiring interface-objects.

Loop updated to new field; downstream config propagation remains consistent.

composition/src/v1/normalization/directive-definition-data.ts (1)

649-657: Broaden REQUIRE_FETCH_REASONS to INTERFACE in normalization metadata.

Locations set aligns with constants.ts; normalization should now accept INTERFACE placements.

Copy link

@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: 0

♻️ Duplicate comments (1)
composition/src/v1/normalization/normalization-factory.ts (1)

577-604: Add injected directive to referencedDirectiveNames.

When handleFieldInheritableDirectives injects @openfed__requireFetchReasons (lines 583–586), it does not add the directive to referencedDirectiveNames. Downstream (line 3491), the schema only emits REQUIRE_FETCH_REASONS_DEFINITION if the directive is in referencedDirectiveNames. If the directive appears only via injection and not in the original AST, its definition will be missing from the output.

Apply this diff to ensure the definition is emitted:

  if (this.doesParentRequireFetchReasons && !directivesByDirectiveName.has(REQUIRE_FETCH_REASONS)) {
    directivesByDirectiveName.set(REQUIRE_FETCH_REASONS, [generateSimpleDirective(REQUIRE_FETCH_REASONS)]);
+   this.referencedDirectiveNames.add(REQUIRE_FETCH_REASONS);
    inheritedDirectiveNames.add(REQUIRE_FETCH_REASONS);
  }

Defensively, also add it when the directive already exists on the field:

  if (this.doesParentRequireFetchReasons || directivesByDirectiveName.has(REQUIRE_FETCH_REASONS)) {
+   this.referencedDirectiveNames.add(REQUIRE_FETCH_REASONS);
    parentData.requireFetchReasonsFieldNames.add(fieldName);
  }
🧹 Nitpick comments (1)
composition/src/v1/federation/federation-factory.ts (1)

1138-1139: Clarify the purpose of initializing unused fields.

The requireFetchReasonsFieldNames field is initialized with an empty Set<FieldName>() and marked with a comment stating it's "not required for the federated node." This could be confusing for future maintainers.

Consider either:

  1. Adding more context to the comment explaining why it must be initialized (e.g., "required by type definition" or "used in other contexts")
  2. Making the field optional if it's truly not needed in this context

Based on learnings.

Also applies to: 1156-1157

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9803be4 and f0c33ee.

📒 Files selected for processing (4)
  • composition/src/v1/federation/federation-factory.ts (15 hunks)
  • composition/src/v1/normalization/normalization-factory.ts (24 hunks)
  • composition/src/v1/normalization/types.ts (1 hunks)
  • composition/src/v1/utils/utils.ts (7 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
composition/src/v1/normalization/types.ts (1)
composition/src/schema-building/types.ts (1)
  • ArgumentData (30-34)
composition/src/v1/normalization/normalization-factory.ts (7)
composition/src/types/types.ts (2)
  • SubgraphName (9-9)
  • FieldName (5-5)
composition/src/v1/normalization/params.ts (1)
  • HandleFieldInheritableDirectivesParams (10-15)
composition/src/utils/string-constants.ts (3)
  • REQUIRE_FETCH_REASONS (120-120)
  • EXTERNAL (46-46)
  • SHAREABLE (135-135)
composition/src/utils/utils.ts (1)
  • generateSimpleDirective (161-166)
composition/src/v1/utils/utils.ts (3)
  • isObjectDefinitionData (447-452)
  • isCompositeOutputNodeKind (443-445)
  • isObjectNodeKind (439-441)
composition/src/schema-building/types.ts (2)
  • ArgumentData (30-34)
  • EnumValueData (73-85)
composition/src/schema-building/utils.ts (1)
  • childMapToValueArray (233-247)
composition/src/v1/utils/utils.ts (5)
composition/src/types/types.ts (2)
  • SubgraphName (9-9)
  • TypeName (11-11)
composition/src/schema-building/types.ts (1)
  • EntityData (268-275)
composition/src/v1/normalization/types.ts (1)
  • KeyFieldSetData (14-19)
composition/src/ast/utils.ts (1)
  • CompositeOutputNodeKind (295-295)
composition/src/v1/utils/string-constants.ts (1)
  • COMPOSITE_OUTPUT_NODE_KINDS (63-68)
composition/src/v1/federation/federation-factory.ts (3)
composition/src/schema-building/types.ts (1)
  • EnumValueData (73-85)
composition/src/resolvability-graph/types/types.ts (1)
  • FieldName (7-7)
composition/src/schema-building/ast.ts (1)
  • getTypeNodeNamedTypeName (281-290)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: build_test
  • GitHub Check: build_push_image (nonroot)
  • GitHub Check: integration_test (./. ./fuzzquery ./lifecycle ./modules)
  • GitHub Check: image_scan
  • GitHub Check: integration_test (./telemetry)
  • GitHub Check: build_push_image
  • GitHub Check: build_test
  • GitHub Check: image_scan (nonroot)
  • GitHub Check: Analyze (go)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: build_test
  • GitHub Check: build_test
  • GitHub Check: build_push_image
  • GitHub Check: build_push_image
🔇 Additional comments (12)
composition/src/v1/utils/utils.ts (4)

1-2: LGTM! Type-only imports improve build output.

Using type-only imports for DocumentNode and FieldConfiguration is correct since these are only used in type annotations and should not generate runtime imports.


36-38: LGTM! Typed aliases improve type safety.

The addition of SubgraphName and TypeName typed aliases, along with CompositeOutputNodeKind and COMPOSITE_OUTPUT_NODE_KINDS, supports the PR's objective of improving type safety across the codebase.


439-445: Rename complete; new type guard implementation is correct.


152-169: Rename is consistent across codebase
No occurrences of interfaceObjectSubgraphs remain; interfaceObjectSubgraphNames is applied uniformly.

composition/src/v1/normalization/types.ts (1)

37-37: LGTM! More concise naming.

The rename from argumentTypeNodeByArgumentName to argumentTypeNodeByName removes redundancy and aligns with the naming pattern used elsewhere in the codebase (e.g., enumValueDataByName).

composition/src/v1/federation/federation-factory.ts (4)

597-614: LGTM! Consistent naming improvements.

The parameter rename from enumValueDataByValueName to enumValueDataByName removes redundancy and aligns with similar naming patterns like argumentDataByName. The function correctly handles the renamed parameter.


1057-1071: LGTM! Function rename matches parameter updates.

The function rename from copyEnumValueDataByValueName to copyEnumValueDataByName is consistent with the parameter renamings and improves code clarity.


1219-1230: LGTM! Consistent naming improvements.

The rename from interfaceObjectSubgraphs to interfaceObjectSubgraphNames is consistent with the changes in composition/src/v1/utils/utils.ts and improves naming clarity.


1342-1369: LGTM! Consistent parameter naming.

The rename from argumentDataByArgumentName to argumentDataByName throughout the upsertPersistedDirectiveDefinitionData method removes redundancy and aligns with the naming pattern used for similar maps.

composition/src/v1/normalization/normalization-factory.ts (3)

82-84: LGTM! Type safety and naming improvements.

The imported type guards (isCompositeOutputNodeKind, isObjectDefinitionData, isObjectNodeKind) enable proper differentiation between composite output types (interfaces and objects) and objects specifically. The renaming of doesParentObjectRequireFetchReasons to doesParentRequireFetchReasons accurately reflects that the directive now propagates to interfaces as well. The SubgraphName typing improves type safety.

Also applies to: 380-380, 410-410, 443-443


619-640: LGTM! Correctly differentiates composite vs. object-only directives.

The logic properly detects REQUIRE_FETCH_REASONS on all composite output types (interfaces and objects) while restricting EXTERNAL and SHAREABLE detection to objects only. This aligns with the federation specification and enables correct propagation in handleFieldInheritableDirectives.


1286-1287: LGTM! Properly tracks and emits requireFetchReasonsFieldNames.

The field set is correctly initialized on both interface and object definition data, then transferred to the configuration data when non-empty. This completes the feature implementation for tracking fields with @openfed__requireFetchReasons.

Also applies to: 1364-1364, 3638-3640

@Aenimus Aenimus enabled auto-merge (squash) October 10, 2025 12:51
@Aenimus Aenimus merged commit 2a31f95 into main Oct 10, 2025
33 checks passed
@Aenimus Aenimus deleted the david/eng-8262-propagate-interface-fetch-reasons branch October 10, 2025 12:58
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.

4 participants