Skip to content

feat(composition): @openfed__requestScoped directive (5/5)#2985

Open
SkArchon wants to merge 2 commits into
milinda/queryCache-directivefrom
milinda/requestScoped-directive
Open

feat(composition): @openfed__requestScoped directive (5/5)#2985
SkArchon wants to merge 2 commits into
milinda/queryCache-directivefrom
milinda/requestScoped-directive

Conversation

@SkArchon

@SkArchon SkArchon commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

@openfed__requestScoped — request-scoped L1 field caching, keyed by {subgraphName}.{key}; fields sharing a key share an L1 entry. Adds RequestScopedFieldConfiguration proto (field 4) + bindings, the RequestScopedFieldConfig type, normalization, a single-field warning, and tests.

More documentation on this: https://app.notion.com/p/wundergraph/Directives-37bb19e0a0ec80b9b505d896beed5897

Summary by CodeRabbit

  • New Features
    • Added support for @openfed__requestScoped(key: String!) to configure per-field request-scoped caching with shared L1 coordination, including new router configuration and engine wiring.
    • Added support for @openfed__queryCache plus @openfed__is key-mapping so query cache keys can be derived from entity @key fields and nested inputs.
    • Added warnings for ineffective request-scoped usage (single field) and for query-cache return entities missing entity-cache configuration.
  • Tests
    • Extended directive and normalization test coverage for request-scoped, query-cache, and key-mapping scenarios, including validation and warning expectations.

@SkArchon SkArchon requested review from a team as code owners June 19, 2026 06:12
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0fe8828b-62f6-4f33-88f6-fa3566b3d493

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Adds @openfed__requestScoped and @openfed__queryCache directives end-to-end. String constants, GraphQL directive definitions, TypeScript configuration types, and AST node shapes are introduced. NormalizationFactory extracts @openfed__queryCache from root query fields, validates entity return types, builds entity-key-field mappings from @openfed__is arguments with comprehensive type and structure validation, and emits warnings for missing entity cache directives. @openfed__requestScoped extraction on each field computes l1Key values, emits single-field warnings, and writes results into entity caching configuration. New RequestScopedConfiguration proto message extends EntityCachingConfiguration; generated bindings and router config builder serialize the data to the router engine.

Changes

Request-scoped and query-cache directives

Layer / File(s) Summary
Directive constants, GraphQL definitions, and AST types
composition/src/utils/string-constants.ts, composition/src/v1/constants/directive-definitions.ts, composition/src/v1/constants/constants.ts, composition/src/directive-definition-data/directive-definition-data.ts, composition/src/v1/normalization/types/types.ts
Defines OPENFED_IS, OPENFED_QUERY_CACHE, OPENFED_REQUEST_SCOPED, and LITERAL_OPEN_BRACE constants. Adds GraphQL directive definitions: OPENFED_QUERY_CACHE_DEFINITION (non-repeatable on FIELD_DEFINITION, maxAge: Int! + optional includeHeaders/shadowMode), OPENFED_IS_DEFINITION (non-repeatable on ARGUMENT_DEFINITION, fields: String!), OPENFED_REQUEST_SCOPED_DEFINITION (non-repeatable on FIELD_DEFINITION, key: String!). Exports REQUEST_SCOPED_DEFINITION_DATA directive metadata. Adds AST node types RequestScopedDirectiveNode, QueryCacheDirectiveNode, and their argument variants. Registers all three directives in DIRECTIVE_DEFINITION_BY_NAME.
Router configuration types for caching
composition/src/router-configuration/types.ts
Adds RequestScopedConfiguration (fieldName, typeName, l1Key), FieldMappingConfig (entityKeyField, argumentPath, isBatch), EntityKeyMappingConfig, and QueryCacheConfig (TTL, flags, entity-key mappings). Extends EntityCachingConfiguration with required requestScopedConfigurations array.
Error message infrastructure and helpers
composition/src/errors/types/params.ts, composition/src/errors/errors.ts
Adds MaxAgeNotPositiveIntegerErrorParams type. Updates maxAgeNotPositiveIntegerErrorMessage() to accept structured params including directiveName. Adds @openfed__queryCache placement/return-type validation errors and comprehensive @openfed__is cache-key mapping validation messages (type mismatches, duplicate mappings, incomplete composite keys, batch constraints, nested input-object validation).
Query-cache extraction and key-mapping validation
composition/src/v1/normalization/normalization-factory.ts
Implements extractQueryCacheConfig() to extract and validate @openfed__queryCache arguments, enforce Query-root and entity return requirements, skip with warning when entity lacks @openfed__entityCache, and build entity key mappings via comprehensive validation helpers. Adds key-mapping pipeline: validateIsDirectivePlacement(), extractKeyFieldInfos() (AST traversal), type-shape helpers (unwrapListType(), namedTypesMatch(), typesMatchIncludingListShape()), getIsFieldValue(), and mapping builders (validateNestedInputObjectMapping(), buildArgumentKeyMappings(), buildExplicitMappings(), buildCompositeIsMapping()) that validate type compatibility, batch constraints, composite completeness, and nested structure. Adds extractRequestScopedConfig() for per-field request-scoped extraction with L1 key coordination. Wires extraction into normalize() field-walk loop with validation of @openfed__is placement when @openfed__queryCache is absent.
Request-scoped extraction and warning system
composition/src/v1/warnings/params.ts, composition/src/v1/warnings/warnings.ts, composition/src/v1/normalization/normalization-factory.ts
Adds RequestScopedSingleFieldWarningParams type and requestScopedSingleFieldWarning() helper warning when @openfed__requestScoped is applied to one field. Adds queryCacheReturnEntityMissingEntityCacheWarning() helper. Implements requestScopedFieldCoordsByL1Key tracking and single-field warning emission after field walk in normalize().
Directive registration and config initialization
composition/src/v1/normalization/utils.ts, composition/src/router-configuration/utils.ts
Registers OPENFED_REQUEST_SCOPED with REQUEST_SCOPED_DEFINITION_DATA in initializeDirectiveDefinitionDatas(). Initializes requestScopedConfigurations array in getOrInitializeEntityCaching().
Protobuf schema, code generation, and router integration
proto/wg/cosmo/node/v1/node.proto, connect/src/wg/cosmo/node/v1/node_pb.ts, shared/src/router-config/builder.ts
Extends EntityCachingConfiguration proto with repeated RequestScopedConfiguration request_scoped_configurations = 4; renumbers queryCacheConfigurations to field 5. Adds RequestScopedConfiguration message (field_name, type_name, l1_key). Generated node_pb.ts adds RequestScopedConfiguration class and updates EntityCachingConfiguration. Extends extractEntityCachingConfiguration() to import RequestScopedConfiguration, accumulate request-scoped/query-cache configs from data.entityCaching, construct protobuf entries, and include in EntityCachingConfiguration constructor with updated empty-check logic.
Test coverage: query-cache extraction, validation, and key-mapping
composition/tests/v1/directives/query-cache.test.ts
Vitest suite verifying @openfed__queryCache config extraction with defaults and option propagation, argument-to-@key mappings via @openfed__is (nested input paths, composite keys, batch semantics), skipped extraction with warning when entity lacks @openfed__entityCache. Validates failures: missing/non-positive maxAge, non-Query/non-entity placement, non-repeatability. Validates @openfed__is: requires @openfed__queryCache pairing, targets must be @key fields, type/list/nullability compatibility, complete composite key coverage, no extra non-key arguments, batch/list mapping constraints, input-object structure validation.
Test coverage: request-scoped directive
composition/tests/v1/directives/request-scoped.test.ts
Vitest suite verifying directive presence in normalized output, multi-field and single-field key extraction with subgraph-prefixed l1Key format, single-field warning emission, validation failures for missing key and non-repeatable constraint.
Test coverage: integration and existing updates
composition/tests/v1/directives/cache-populate.test.ts, composition/tests/v1/directives/entity-cache.test.ts, shared/test/entity-caching.test.ts
Updates cache-populate and entity-cache tests to pass maxAgeNotPositiveIntegerErrorMessage() with object argument. Adds end-to-end entity-caching suite verifying all directive categories map to router protobuf, including request-scoped, entity cache, query cache with key mappings, cache invalidation, cache population, BigInt TTL conversion, batch detection, subscription TTL fallback, and empty-configuration omission.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • wundergraph/cosmo#2980: Both PRs extend the shared EntityCachingConfiguration model in composition/src/router-configuration/types.ts and proto schema with different directive-driven configuration lists, and both modify shared/src/router-config/builder.ts to populate protobuf structures.
  • wundergraph/cosmo#2983: Both PRs modify composition/src/router-configuration/types.ts and composition/src/v1/normalization/normalization-factory.ts to extend entity-caching configuration extraction and handling for different directive features.
  • wundergraph/cosmo#2984: Main PR updates maxAgeNotPositiveIntegerErrorMessage() signature to use { directiveName, value } object argument, and the referenced PR depends on this signature change for @openfed__cachePopulate validation error expectations.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: introducing the @openfed__requestScoped directive as part 5 of a composition feature series, which aligns with the substantial additions across configuration types, normalization logic, and test coverage.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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


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

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown

Router image scan passed

✅ No security vulnerabilities found in image:

ghcr.io/wundergraph/cosmo/router:sha-cfc177df46ccf635bdd7c50dc504ff47244913d1

@SkArchon SkArchon force-pushed the milinda/requestScoped-directive branch from 2859cba to faca30a Compare June 19, 2026 06:24
@SkArchon SkArchon force-pushed the milinda/cachePopulate-directive branch from c7044af to b52c0a2 Compare June 19, 2026 06:24
@codecov

codecov Bot commented Jun 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 47.37%. Comparing base (30c81e0) to head (0c7c9a9).

Additional details and impacted files
@@                       Coverage Diff                        @@
##           milinda/queryCache-directive    #2985      +/-   ##
================================================================
+ Coverage                         47.31%   47.37%   +0.05%     
================================================================
  Files                              1119     1119              
  Lines                            153254   153374     +120     
  Branches                          10181    10193      +12     
================================================================
+ Hits                              72514    72654     +140     
+ Misses                            78923    78916       -7     
+ Partials                           1817     1804      -13     
Files with missing lines Coverage Δ
...ctive-definition-data/directive-definition-data.ts 100.00% <100.00%> (ø)
composition/src/router-configuration/utils.ts 100.00% <100.00%> (ø)
composition/src/utils/string-constants.ts 100.00% <100.00%> (ø)
composition/src/v1/constants/constants.ts 100.00% <100.00%> (ø)
...position/src/v1/constants/directive-definitions.ts 100.00% <100.00%> (ø)
...tion/src/v1/normalization/normalization-factory.ts 91.74% <100.00%> (+0.06%) ⬆️
composition/src/v1/normalization/utils.ts 90.10% <100.00%> (+0.01%) ⬆️
composition/src/v1/warnings/params.ts 100.00% <ø> (ø)
composition/src/v1/warnings/warnings.ts 90.09% <100.00%> (+0.61%) ⬆️
router/gen/proto/wg/cosmo/node/v1/node.pb.go 26.56% <ø> (-0.37%) ⬇️

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

@SkArchon

Copy link
Copy Markdown
Contributor Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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

142-154: ⚡ Quick win

Use interfaces for the new directive AST object shapes.

Lines 142-154 define object-shape type aliases; convert them to interface declarations to match the TypeScript convention in the guidelines.

As per coding guidelines, **/*.{ts,tsx} should prefer interfaces over type aliases for object shapes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@composition/src/v1/normalization/types/types.ts` around lines 142 - 154,
Convert the type aliases RequestScopedDirectiveNode and
RequestScopedArgumentNode to interface declarations to align with TypeScript
coding guidelines that prefer interfaces for object shapes. Change each `type`
keyword to `interface`, remove the equals sign, and keep all the properties and
their readonly modifiers intact within the interface body.

Source: Coding guidelines

composition/src/router-configuration/types.ts (1)

89-98: ⚡ Quick win

Prefer an interface for this new object-shape type.

Line 89 introduces an object-shape type alias; switch it to an interface to align with repository TypeScript rules.

As per coding guidelines, **/*.{ts,tsx} should prefer interfaces over type aliases for object shapes.

Proposed change
-export type RequestScopedFieldConfig = {
+export interface RequestScopedFieldConfig {
   fieldName: FieldName;
   typeName: TypeName;
   // L1 cache key used to store/lookup this field's value for the duration of a request.
   // Format: "{subgraphName}.{key}" where `key` is the `@openfed__requestScoped`(key:) argument.
   // All fields in the same subgraph declaring `@openfed__requestScoped` with the same key share
   // the same L1 entry — the first one to resolve populates it, subsequent ones inject
   // from it (subject to widening checks and alias-aware normalization).
   l1Key: string;
-};
+}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@composition/src/router-configuration/types.ts` around lines 89 - 98, The
RequestScopedFieldConfig definition uses a type alias for an object shape, but
repository TypeScript conventions prefer interfaces for object shapes. Convert
the type alias declaration to an interface by replacing the equals sign syntax
with interface syntax, keeping all the properties and their documentation
comments intact.

Source: Coding guidelines

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

4250-4261: ⚡ Quick win

Add an explicit return type and avoid object-shape type aliases in the new method.

Line 4250 should declare an explicit return type, and Lines 4255-4261 should use an interface (or equivalent) instead of an object-shape type alias.

As per coding guidelines, TypeScript functions should use explicit type annotations for return types, and object shapes should prefer interfaces over type aliases.

Proposed change
-  extractRequestScopedFields() {
+  extractRequestScopedFields(): void {
@@
-    type Collected = {
+    interface Collected {
       typeName: string;
       fieldName: string;
       fieldCoords: string;
       key: string;
       l1Key: string;
-    };
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@composition/src/v1/normalization/normalization-factory.ts` around lines 4250
- 4261, The extractRequestScopedFields method lacks an explicit return type
annotation, and the Collected type alias with object shape should be converted
to an interface according to coding guidelines. Add a return type annotation to
the extractRequestScopedFields function signature that returns an array or
collection of the Collected items, and convert the Collected type alias
definition to an interface declaration instead of a type alias.

Source: Coding guidelines

composition/src/v1/warnings/params.ts (1)

20-24: ⚡ Quick win

Prefer an interface for warning params shape.

Line 20 adds an object-shape type alias; please switch this to an interface for consistency with the TypeScript rules.

As per coding guidelines, **/*.{ts,tsx} should prefer interfaces over type aliases for object shapes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@composition/src/v1/warnings/params.ts` around lines 20 - 24, The
RequestScopedSingleFieldWarningParams is currently defined as a type alias but
should be converted to an interface for consistency with TypeScript coding
guidelines that prefer interfaces over type aliases for object shapes. Replace
the type keyword with interface while keeping the same object shape definition
with subgraphName, key, and fieldCoords properties unchanged.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@composition/src/v1/normalization/normalization-factory.ts`:
- Around line 4300-4302: In the loop iterating over coordsByKey, the condition
checking coordsList.length uses the loose equality operator (==) instead of
strict equality (===). Replace the == operator with === in the coordsList.length
== 1 comparison to comply with strict equality requirements and avoid potential
type coercion issues.

---

Nitpick comments:
In `@composition/src/router-configuration/types.ts`:
- Around line 89-98: The RequestScopedFieldConfig definition uses a type alias
for an object shape, but repository TypeScript conventions prefer interfaces for
object shapes. Convert the type alias declaration to an interface by replacing
the equals sign syntax with interface syntax, keeping all the properties and
their documentation comments intact.

In `@composition/src/v1/normalization/normalization-factory.ts`:
- Around line 4250-4261: The extractRequestScopedFields method lacks an explicit
return type annotation, and the Collected type alias with object shape should be
converted to an interface according to coding guidelines. Add a return type
annotation to the extractRequestScopedFields function signature that returns an
array or collection of the Collected items, and convert the Collected type alias
definition to an interface declaration instead of a type alias.

In `@composition/src/v1/normalization/types/types.ts`:
- Around line 142-154: Convert the type aliases RequestScopedDirectiveNode and
RequestScopedArgumentNode to interface declarations to align with TypeScript
coding guidelines that prefer interfaces for object shapes. Change each `type`
keyword to `interface`, remove the equals sign, and keep all the properties and
their readonly modifiers intact within the interface body.

In `@composition/src/v1/warnings/params.ts`:
- Around line 20-24: The RequestScopedSingleFieldWarningParams is currently
defined as a type alias but should be converted to an interface for consistency
with TypeScript coding guidelines that prefer interfaces over type aliases for
object shapes. Replace the type keyword with interface while keeping the same
object shape definition with subgraphName, key, and fieldCoords properties
unchanged.
🪄 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: 97ff9f05-9eb4-445c-902b-3c0c09d00fb7

📥 Commits

Reviewing files that changed from the base of the PR and between dc7e324 and 49f93f1.

⛔ Files ignored due to path filters (2)
  • connect-go/gen/proto/wg/cosmo/node/v1/node.pb.go is excluded by !**/*.pb.go, !**/gen/**
  • router/gen/proto/wg/cosmo/node/v1/node.pb.go is excluded by !**/*.pb.go, !**/gen/**
📒 Files selected for processing (14)
  • composition/src/directive-definition-data/directive-definition-data.ts
  • composition/src/router-configuration/types.ts
  • composition/src/utils/string-constants.ts
  • composition/src/v1/constants/constants.ts
  • composition/src/v1/constants/directive-definitions.ts
  • composition/src/v1/normalization/normalization-factory.ts
  • composition/src/v1/normalization/types/types.ts
  • composition/src/v1/normalization/utils.ts
  • composition/src/v1/warnings/params.ts
  • composition/src/v1/warnings/warnings.ts
  • composition/tests/v1/directives/request-scoped.test.ts
  • connect/src/wg/cosmo/node/v1/node_pb.ts
  • proto/wg/cosmo/node/v1/node.proto
  • shared/src/router-config/builder.ts

Comment thread composition/src/v1/normalization/normalization-factory.ts Outdated
Base automatically changed from milinda/cachePopulate-directive to main June 22, 2026 19:37
Restacks @openfed__requestScoped on top of the queryCache branch. The
resulting tree is identical to the previous combined stack tip; this commit
re-applies the requestScoped feature (including its assertions in
shared/test/entity-caching.test.ts) on top of queryCache.
@SkArchon SkArchon changed the title feat(composition): @openfed__requestScoped directive (4/5) feat(composition): @openfed__requestScoped directive (5/5) Jun 23, 2026
@SkArchon SkArchon changed the base branch from main to milinda/queryCache-directive June 23, 2026 07:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (1)
composition/src/v1/normalization/normalization-factory.ts (1)

4290-4491: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Tighten TypeScript typing in the new helper set (any + implicit returns).

The newly added helpers rely on inferred return types, and Line 4408 uses readonly any[]. This weakens type safety in a critical normalization path.

♻️ Suggested typing direction
-  extractQueryCacheConfig(
+  extractQueryCacheConfig(
     parentTypeName: string,
     configurationTypeName: string,
     fieldName: string,
     fieldData: FieldData,
     operationType: OperationTypeNode | undefined,
-  ) {
+  ): void {

-  validateIsDirectivePlacement(fieldCoords: string, fieldData: FieldData) {
+  validateIsDirectivePlacement(fieldCoords: string, fieldData: FieldData): void {

-  const walkSelections = (selections: readonly any[], currentTypeName: string, pathPrefix: string) => {
+  const walkSelections = (
+    selections: ReadonlyArray<SelectionNode>,
+    currentTypeName: string,
+    pathPrefix: string,
+  ): void => {
// If not already present:
import type { SelectionNode } from 'graphql';

As per coding guidelines, **/*.{ts,tsx} requires explicit function return annotations and avoiding any in TypeScript.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@composition/src/v1/normalization/normalization-factory.ts` around lines 4290
- 4491, The new helper methods lack explicit return type annotations and the
walkSelections function uses `readonly any[]` instead of properly typed
parameters, violating TypeScript coding guidelines. Add explicit return type
annotations (void or appropriate types) to extractQueryCacheConfig and
validateIsDirectivePlacement methods. In the walkSelections nested function
within extractKeyFieldInfos, replace the `readonly any[]` parameter type with
the proper GraphQL AST type `readonly SelectionNode[]`. Import SelectionNode
from the graphql package if not already imported at the top of the file.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@composition/src/v1/normalization/normalization-factory.ts`:
- Around line 4965-4966: The filter for determining extraArgs at line 4965 and
the similar filter at line 5005 are currently excluding unmapped arguments when
their name matches a key-field path in allKeyFieldPaths, which can lead to
unsafe incomplete cache-key coverage. Remove the `!allKeyFieldPaths.has(a.name)`
condition from both filter expressions so that all unmapped arguments (those
where !a.isFieldValue is true) are treated as extra arguments regardless of
whether their name happens to match any key-field path.

---

Nitpick comments:
In `@composition/src/v1/normalization/normalization-factory.ts`:
- Around line 4290-4491: The new helper methods lack explicit return type
annotations and the walkSelections function uses `readonly any[]` instead of
properly typed parameters, violating TypeScript coding guidelines. Add explicit
return type annotations (void or appropriate types) to extractQueryCacheConfig
and validateIsDirectivePlacement methods. In the walkSelections nested function
within extractKeyFieldInfos, replace the `readonly any[]` parameter type with
the proper GraphQL AST type `readonly SelectionNode[]`. Import SelectionNode
from the graphql package if not already imported at the top of the file.
🪄 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: a033a452-0d2b-463c-a18a-d7f8fe0f042e

📥 Commits

Reviewing files that changed from the base of the PR and between 840f24d and e96a801.

⛔ Files ignored due to path filters (2)
  • connect-go/gen/proto/wg/cosmo/node/v1/node.pb.go is excluded by !**/*.pb.go, !**/gen/**
  • router/gen/proto/wg/cosmo/node/v1/node.pb.go is excluded by !**/*.pb.go, !**/gen/**
📒 Files selected for processing (19)
  • composition/src/directive-definition-data/directive-definition-data.ts
  • composition/src/errors/errors.ts
  • composition/src/errors/types/params.ts
  • composition/src/router-configuration/types.ts
  • composition/src/utils/string-constants.ts
  • composition/src/v1/constants/constants.ts
  • composition/src/v1/constants/directive-definitions.ts
  • composition/src/v1/normalization/normalization-factory.ts
  • composition/src/v1/normalization/types/types.ts
  • composition/src/v1/normalization/utils.ts
  • composition/src/v1/warnings/params.ts
  • composition/src/v1/warnings/warnings.ts
  • composition/tests/v1/directives/cache-populate.test.ts
  • composition/tests/v1/directives/entity-cache.test.ts
  • composition/tests/v1/directives/query-cache.test.ts
  • connect/src/wg/cosmo/node/v1/node_pb.ts
  • proto/wg/cosmo/node/v1/node.proto
  • shared/src/router-config/builder.ts
  • shared/test/entity-caching.test.ts
✅ Files skipped from review due to trivial changes (1)
  • connect/src/wg/cosmo/node/v1/node_pb.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • composition/src/v1/normalization/utils.ts
  • composition/src/directive-definition-data/directive-definition-data.ts
  • shared/src/router-config/builder.ts
  • composition/src/v1/warnings/params.ts
  • proto/wg/cosmo/node/v1/node.proto

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🧹 Nitpick comments (1)
composition/src/v1/normalization/normalization-factory.ts (1)

4290-4491: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Tighten TypeScript typing in the new helper set (any + implicit returns).

The newly added helpers rely on inferred return types, and Line 4408 uses readonly any[]. This weakens type safety in a critical normalization path.

♻️ Suggested typing direction
-  extractQueryCacheConfig(
+  extractQueryCacheConfig(
     parentTypeName: string,
     configurationTypeName: string,
     fieldName: string,
     fieldData: FieldData,
     operationType: OperationTypeNode | undefined,
-  ) {
+  ): void {

-  validateIsDirectivePlacement(fieldCoords: string, fieldData: FieldData) {
+  validateIsDirectivePlacement(fieldCoords: string, fieldData: FieldData): void {

-  const walkSelections = (selections: readonly any[], currentTypeName: string, pathPrefix: string) => {
+  const walkSelections = (
+    selections: ReadonlyArray<SelectionNode>,
+    currentTypeName: string,
+    pathPrefix: string,
+  ): void => {
// If not already present:
import type { SelectionNode } from 'graphql';

As per coding guidelines, **/*.{ts,tsx} requires explicit function return annotations and avoiding any in TypeScript.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@composition/src/v1/normalization/normalization-factory.ts` around lines 4290
- 4491, The new helper methods lack explicit return type annotations and the
walkSelections function uses `readonly any[]` instead of properly typed
parameters, violating TypeScript coding guidelines. Add explicit return type
annotations (void or appropriate types) to extractQueryCacheConfig and
validateIsDirectivePlacement methods. In the walkSelections nested function
within extractKeyFieldInfos, replace the `readonly any[]` parameter type with
the proper GraphQL AST type `readonly SelectionNode[]`. Import SelectionNode
from the graphql package if not already imported at the top of the file.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@composition/src/v1/normalization/normalization-factory.ts`:
- Around line 4965-4966: The filter for determining extraArgs at line 4965 and
the similar filter at line 5005 are currently excluding unmapped arguments when
their name matches a key-field path in allKeyFieldPaths, which can lead to
unsafe incomplete cache-key coverage. Remove the `!allKeyFieldPaths.has(a.name)`
condition from both filter expressions so that all unmapped arguments (those
where !a.isFieldValue is true) are treated as extra arguments regardless of
whether their name happens to match any key-field path.

---

Nitpick comments:
In `@composition/src/v1/normalization/normalization-factory.ts`:
- Around line 4290-4491: The new helper methods lack explicit return type
annotations and the walkSelections function uses `readonly any[]` instead of
properly typed parameters, violating TypeScript coding guidelines. Add explicit
return type annotations (void or appropriate types) to extractQueryCacheConfig
and validateIsDirectivePlacement methods. In the walkSelections nested function
within extractKeyFieldInfos, replace the `readonly any[]` parameter type with
the proper GraphQL AST type `readonly SelectionNode[]`. Import SelectionNode
from the graphql package if not already imported at the top of the file.
🪄 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: a033a452-0d2b-463c-a18a-d7f8fe0f042e

📥 Commits

Reviewing files that changed from the base of the PR and between 840f24d and e96a801.

⛔ Files ignored due to path filters (2)
  • connect-go/gen/proto/wg/cosmo/node/v1/node.pb.go is excluded by !**/*.pb.go, !**/gen/**
  • router/gen/proto/wg/cosmo/node/v1/node.pb.go is excluded by !**/*.pb.go, !**/gen/**
📒 Files selected for processing (19)
  • composition/src/directive-definition-data/directive-definition-data.ts
  • composition/src/errors/errors.ts
  • composition/src/errors/types/params.ts
  • composition/src/router-configuration/types.ts
  • composition/src/utils/string-constants.ts
  • composition/src/v1/constants/constants.ts
  • composition/src/v1/constants/directive-definitions.ts
  • composition/src/v1/normalization/normalization-factory.ts
  • composition/src/v1/normalization/types/types.ts
  • composition/src/v1/normalization/utils.ts
  • composition/src/v1/warnings/params.ts
  • composition/src/v1/warnings/warnings.ts
  • composition/tests/v1/directives/cache-populate.test.ts
  • composition/tests/v1/directives/entity-cache.test.ts
  • composition/tests/v1/directives/query-cache.test.ts
  • connect/src/wg/cosmo/node/v1/node_pb.ts
  • proto/wg/cosmo/node/v1/node.proto
  • shared/src/router-config/builder.ts
  • shared/test/entity-caching.test.ts
✅ Files skipped from review due to trivial changes (1)
  • connect/src/wg/cosmo/node/v1/node_pb.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • composition/src/v1/normalization/utils.ts
  • composition/src/directive-definition-data/directive-definition-data.ts
  • shared/src/router-config/builder.ts
  • composition/src/v1/warnings/params.ts
  • proto/wg/cosmo/node/v1/node.proto
🛑 Comments failed to post (1)
composition/src/v1/normalization/normalization-factory.ts (1)

4965-4966: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Treat unmapped arguments as extra regardless of argument name.

Line 4965 and Line 5005 currently exclude non-@openfed__is arguments from extraArgs when the argument name happens to match any key-field path. That can let query-cache extraction accept incomplete cache-key coverage and produce unsafe mappings.

💡 Suggested fix
-      const extraArgs = argumentInfos.filter((a) => !a.isFieldValue && !allKeyFieldPaths.has(a.name));
+      const extraArgs = argumentInfos.filter((a) => !a.isFieldValue);
...
-      const globalExtraArgs = argumentInfos.filter((a) => !a.isFieldValue && !allKeyFieldPaths.has(a.name));
+      const globalExtraArgs = argumentInfos.filter((a) => !a.isFieldValue);

Also applies to: 5005-5006

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@composition/src/v1/normalization/normalization-factory.ts` around lines 4965
- 4966, The filter for determining extraArgs at line 4965 and the similar filter
at line 5005 are currently excluding unmapped arguments when their name matches
a key-field path in allKeyFieldPaths, which can lead to unsafe incomplete
cache-key coverage. Remove the `!allKeyFieldPaths.has(a.name)` condition from
both filter expressions so that all unmapped arguments (those where
!a.isFieldValue is true) are treated as extra arguments regardless of whether
their name happens to match any key-field path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant