Skip to content

Conversation

@Noroth
Copy link
Contributor

@Noroth Noroth commented Jul 17, 2025

Summary by CodeRabbit

  • New Features

    • Improved support for GraphQL list types in Protocol Buffer conversion, introducing explicit wrapper messages for nullable and nested lists to enhance clarity and correctness.
  • Bug Fixes

    • Enhanced proto generation accuracy for complex list scenarios, including nested and nullable lists.
  • Tests

    • Added comprehensive tests covering diverse GraphQL list cases, including deep nesting and nullability variations.
    • Updated test snapshots to adopt the new wrapper message pattern for repeated fields.
    • Introduced tests ensuring consistent field numbering for auto-generated list wrapper types and their preservation across schema changes.
  • Chores

    • Included the protographic module in the workspace configuration.
    • Expanded documentation with detailed explanations of list type handling and protobuf mapping conventions.

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.

@Noroth Noroth requested review from a team and StarpTech as code owners July 17, 2025 08:07
@Noroth Noroth requested review from endigma and wilsonrivera July 17, 2025 08:07
@coderabbitai
Copy link

coderabbitai bot commented Jul 17, 2025

Walkthrough

The changes overhaul the handling of GraphQL list types in the SDL-to-Proto conversion logic by introducing a formalized wrapper message mechanism for lists. The conversion code is refactored to generate wrapper messages for nullable and nested lists, and all test snapshots are updated to reflect this new structure. A comprehensive new test suite for list scenarios is added, and the test workspace configuration is updated to include the protographic module. Documentation on list handling is expanded with detailed explanations and examples. Additional tests verify field number preservation for generated wrapper messages.

Changes

Files/Groups Change Summary
protographic/src/sdl-to-proto-visitor.ts Refactored list type handling by introducing a ProtoType interface and new helper methods for detecting, wrapping, and generating messages for GraphQL lists. List types now use explicit wrapper messages for nullable and nested lists, replacing ad hoc repeated field logic. Added methods to calculate nesting levels and build nested wrapper messages with consistent naming.
protographic/tests/sdl-to-proto/01-basic-types.test.ts
protographic/tests/sdl-to-proto/02-complex-types.test.ts
protographic/tests/sdl-to-proto/05-edge-cases.test.ts
Updated test snapshots to expect wrapper messages (e.g., ListOfString, ListOfUser, ListOfPost) for all list fields, replacing direct repeated fields. Added nested wrapper messages for nested lists (e.g., ListOfListOfFloat). Adjusted message and field types accordingly to match the new conversion logic, including changes to argument nullability in proto requests.
protographic/tests/sdl-to-proto/11-lists.test.ts Added a comprehensive new test suite covering various list scenarios, including single, nested, nullable, non-nullable, and mixed lists, as well as edge cases and complex type combinations. Tests verify correct wrapper message generation and proto output structure.
protographic/tests/sdl-to-proto/06-field-ordering.test.ts Added new test cases verifying field number preservation and deterministic field numbering for auto-generated list wrapper messages for nullable lists, including simple, nested, and mixed wrapper types. Confirmed exclusion of these wrappers from lock data and correct behavior on schema changes.
vitest.workspace.ts Added 'protographic' to the exported workspace modules array.
protographic/SDL_PROTO_RULES.md Expanded and renamed the "Nested List Types" section to "List Types," providing detailed explanations and examples of how Protographic handles GraphQL list nullability and nesting in protobuf, including naming conventions and wrapper message structures for various list scenarios.

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0232a4a and 55f3638.

📒 Files selected for processing (2)
  • protographic/src/sdl-to-proto-visitor.ts (7 hunks)
  • protographic/tests/sdl-to-proto/06-field-ordering.test.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • protographic/tests/sdl-to-proto/06-field-ordering.test.ts
  • protographic/src/sdl-to-proto-visitor.ts
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

🔭 Outside diff range comments (1)
protographic/src/sdl-to-proto-visitor.ts (1)

1-1: Use the format script or run Prettier directly in protographic

The npm run prettier script doesn’t exist in protographic. To fix formatting in src/sdl-to-proto-visitor.ts, either:

  • From the repo root:
    cd protographic
    npm run format -- src/sdl-to-proto-visitor.ts
  • Or run Prettier via npx:
    npx prettier --write protographic/src/sdl-to-proto-visitor.ts
🧹 Nitpick comments (1)
protographic/src/sdl-to-proto-visitor.ts (1)

1526-1595: Solid implementation of wrapper message generation.

The wrapper message generation correctly handles different nesting levels and properly caches results. The generated message structures align with Protocol Buffer best practices for representing nullable and nested lists.

Consider using the existing getIndent() method instead of the inline formatIndent function for consistency:

-    const formatIndent = (indent: number, content: string) => {
-      return '  '.repeat(indent) + content;
-    }
+    const formatIndent = (indent: number, content: string) => {
+      const savedIndent = this.indent;
+      this.indent = indent;
+      const result = this.getIndent() + content;
+      this.indent = savedIndent;
+      return result;
+    }

Or simply use template literals with manual spacing since it's a local helper.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3f4dea6 and b7732ec.

📒 Files selected for processing (6)
  • protographic/src/sdl-to-proto-visitor.ts (7 hunks)
  • protographic/tests/sdl-to-proto/01-basic-types.test.ts (8 hunks)
  • protographic/tests/sdl-to-proto/02-complex-types.test.ts (4 hunks)
  • protographic/tests/sdl-to-proto/05-edge-cases.test.ts (5 hunks)
  • protographic/tests/sdl-to-proto/11-lists.test.ts (1 hunks)
  • vitest.workspace.ts (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: Protographic CI
protographic/src/sdl-to-proto-visitor.ts

[warning] 1-1: Prettier formatting check failed. Code style issues found. Run 'prettier --write' to fix code style issues.

⏰ 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). (2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
🔇 Additional comments (15)
vitest.workspace.ts (1)

1-1: LGTM! Workspace configuration updated correctly.

The addition of 'protographic' to the workspace modules is necessary for including the new module in the test infrastructure.

protographic/tests/sdl-to-proto/02-complex-types.test.ts (1)

39-50: Wrapper message pattern correctly applied for nullable lists.

The changes consistently introduce wrapper messages for nullable lists following the ListOfX pattern. This aligns with the PR's objective to redesign list handling in protographic.

Also applies to: 232-257, 306-329

protographic/tests/sdl-to-proto/05-edge-cases.test.ts (1)

367-381: Edge case handling follows the established wrapper message pattern.

The wrapper messages are correctly applied for nullable lists across various GraphQL constructs including object types and input types. The implementation maintains consistency throughout the complex schema.

Also applies to: 570-626

protographic/tests/sdl-to-proto/11-lists.test.ts (1)

1-1183: Comprehensive test suite for list handling redesign.

This new test file provides excellent coverage of the list handling functionality with test cases covering:

  • Various nullability combinations
  • Different nesting levels
  • All GraphQL type categories (scalars, objects, enums, interfaces, unions)
  • Input types and mutations
  • Edge cases

The tests properly validate the core design principle: non-nullable lists use repeated fields directly, while nullable lists use wrapper messages.

protographic/tests/sdl-to-proto/01-basic-types.test.ts (2)

384-384: Verify: GraphQL schema change makes list argument non-nullable.

The tags parameter changed from [String] to [String]!, making it a required non-nullable list. This is a functional change to the GraphQL schema, not just a proto generation update. Please confirm this change is intentional as it could be a breaking change for existing clients.


143-153: List handling pattern correctly applied across various scenarios.

The changes consistently apply the wrapper message pattern:

  • Nullable lists ([T]) use ListOfT wrapper messages
  • Non-nullable lists ([T]! and [T!]!) use repeated fields directly
  • Nested nullable lists create appropriately nested wrapper messages
  • The pattern works correctly with recursive types

Also applies to: 480-540, 688-746

protographic/src/sdl-to-proto-visitor.ts (9)

9-9: Import addition looks good.

The GraphQLList import is necessary for the new list handling functionality.


88-95: Good design choice for the ProtoType interface.

Encapsulating the type name and repeated flag in a single interface improves type safety and makes the API more explicit.


894-898: Clean refactoring to use ProtoType.

The updated code properly uses the ProtoType interface, making the repeated field handling more explicit and maintainable.


960-964: Consistent ProtoType usage in response messages.

The refactoring maintains consistency with the request message handling.


1124-1128: Consistent ProtoType adoption in object type processing.

Good consistency in applying the ProtoType pattern throughout the codebase.


1195-1199: ProtoType pattern correctly applied to input object types.

Maintains consistency with other type processing methods.


1420-1456: Well-structured refactoring of getProtoTypeFromGraphQL.

The method now properly delegates list handling to a dedicated method and consistently returns ProtoType objects. The logic flow is preserved for non-list types.


1458-1496: Excellent implementation of list type handling.

The method provides a comprehensive solution for converting GraphQL list types to Protocol Buffers, with clear distinction between simple repeated fields and cases requiring wrapper messages. The documentation with examples is particularly helpful.


1498-1524: Well-implemented helper methods for list analysis.

The isNestedListType and calculateNestingLevel methods correctly handle the GraphQL type tree traversal, including proper handling of NonNull wrappers.

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)
protographic/src/sdl-to-proto-visitor.ts (1)

1422-1458: Good refactoring with improved separation of concerns.

The refactored method has better structure with list handling delegated to handleListType. The ProtoType return type improves type safety and clarity.

Note: The existing review comment about renaming type to graphqlType to avoid shadowing the type keyword is still valid and should be addressed.

🧹 Nitpick comments (1)
protographic/src/sdl-to-proto-visitor.ts (1)

1460-1616: Comprehensive implementation of list handling with good separation of concerns.

The new list handling methods provide a robust solution for converting GraphQL lists to Protocol Buffer representations. The logic correctly handles:

  • Simple repeated fields for non-nullable single-level lists
  • Wrapper messages for nullable or nested lists
  • Proper nesting level calculations
  • Type guards for nested list detection

The code is well-structured with clear method responsibilities.

Consider extracting the formatIndent function (lines 1594-1596) to a class method since it's a utility that could be reused elsewhere:

+  private formatIndent(indent: number, content: string): string {
+    return '  '.repeat(indent) + content;
+  }
+
   private buildWrapperMessage(wrapperName: string, level: number, baseType: GraphQLNamedType): string[] {
     const lines: string[] = [];
     
-    const formatIndent = (indent: number, content: string) => {
-      return '  '.repeat(indent) + content;
-    };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between def2082 and 6288be2.

📒 Files selected for processing (1)
  • protographic/src/sdl-to-proto-visitor.ts (7 hunks)
⏰ 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). (2)
  • GitHub Check: Analyze (go)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (3)
protographic/src/sdl-to-proto-visitor.ts (3)

90-96: Well-designed interface for type information encapsulation.

The ProtoType interface cleanly encapsulates both the type name and repetition information, which improves code organization and makes the list handling logic more explicit.


883-883: Consistent and improved usage of ProtoType interface.

The usage of ProtoType throughout the file follows a consistent pattern:

  1. Extract isRepeated and typeName properties
  2. Generate appropriate field declarations based on repetition
  3. Use explicit type information instead of ad-hoc checks

This improves code maintainability and makes the list handling logic more explicit and predictable.

Also applies to: 896-900, 952-952, 962-966, 1115-1115, 1126-1130, 1186-1186, 1197-1201


1565-1579: Improved wrapper creation with better separation of concerns.

The refactored createNestedListWrapper method now properly delegates message building to buildWrapperMessage while maintaining the caching logic. The explicit parameters make the method's purpose clearer.

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

🔭 Outside diff range comments (1)
protographic/src/sdl-to-proto-visitor.ts (1)

1-1: Fix prettier formatting issues to pass CI.

The pipeline is failing due to prettier formatting issues. This needs to be resolved before the PR can be merged.

Please run the following command to fix the formatting issues:

prettier --write protographic/src/sdl-to-proto-visitor.ts

Alternatively, if you have prettier configured in your package.json scripts:

npm run format
# or
yarn format
♻️ Duplicate comments (1)
protographic/src/sdl-to-proto-visitor.ts (1)

1476-1540: Previous review feedback addressed.

The refactoring successfully addresses the previous review comment about extracting type flattening logic into helper functions. The new handleListType, unwrapNonNullType, isNestedListType, and calculateNestingLevel methods provide clear separation of concerns and make the type handling logic more maintainable.

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

13-13: Remove unused import.

The isNull function from lodash-es is imported but never used in the file.

-import { isNull } from 'lodash-es';
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6288be2 and 0232a4a.

📒 Files selected for processing (3)
  • protographic/src/sdl-to-proto-visitor.ts (7 hunks)
  • protographic/tests/sdl-to-proto/06-field-ordering.test.ts (2 hunks)
  • protographic/tests/sdl-to-proto/11-lists.test.ts (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: Protographic CI
protographic/tests/sdl-to-proto/06-field-ordering.test.ts

[warning] 1-1: Prettier formatting check failed. Run 'prettier --write' to fix code style issues.

protographic/src/sdl-to-proto-visitor.ts

[warning] 1-1: Prettier formatting check failed. Run 'prettier --write' to fix code style issues.

⏰ 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). (1)
  • GitHub Check: Analyze (go)
🔇 Additional comments (6)
protographic/tests/sdl-to-proto/06-field-ordering.test.ts (1)

1128-1442: Comprehensive test coverage for list wrapper types.

The new test suite provides excellent coverage of the list wrapper functionality:

  • Simple nullable lists generating wrapper messages with consistent field numbering
  • Nested lists with appropriate naming conventions (ListOfListOfX)
  • Field number preservation across schema modifications
  • Proper exclusion of wrapper types from lock data
  • Mixed scenarios with additions and removals

The test logic correctly validates that wrapper types use deterministic field numbers (field 1) and appropriate field names ('items' for simple wrappers, 'list' for nested wrappers).

protographic/tests/sdl-to-proto/11-lists.test.ts (1)

5-2011: Excellent comprehensive test coverage for list handling.

This test suite provides outstanding coverage of the new list wrapper approach:

  1. Complete scenario coverage: Tests cover all GraphQL types (scalars, objects, enums, interfaces, unions, input types) with various list configurations
  2. Nullability handling: Proper distinction between nullable lists (wrapper messages) and non-nullable lists (direct repeated fields)
  3. Nesting patterns: Correct handling of nested lists with appropriate wrapper message structures
  4. Edge cases: Comprehensive coverage of various nullability combinations and edge cases
  5. Complex scenarios: Recursive types, deeply nested structures, and mixed type scenarios
  6. Mutation support: Input types and mutations with list parameters
  7. Documentation: Inline snapshots provide clear documentation of expected protobuf output

The test logic correctly validates:

  • Non-nullable lists generate repeated fields directly
  • Nullable lists generate wrapper messages with items field (field number 1)
  • Nested nullable lists generate wrapper messages with list field (field number 1)
  • Proper naming conventions (ListOfX, ListOfListOfX, etc.)
  • Consistent field numbering across all wrapper types
protographic/src/sdl-to-proto-visitor.ts (4)

90-97: Good abstraction with the new ProtoType interface.

The ProtoType interface cleanly encapsulates both the type name and repetition flag, which should make the code more maintainable and reduce the complexity of handling list types throughout the codebase.


1422-1458: Approve the refactored type conversion method.

The refactored getProtoTypeFromGraphQL method properly separates concerns by handling list types first, then delegating to appropriate handlers. The consistent return of ProtoType objects throughout all branches is well-implemented.

The comment on line 1423 suggests there might be edge cases where nullable lists could be mishandled as scalar types. Please verify that all GraphQL list type combinations are properly handled by running comprehensive tests.


896-900: Excellent consistent refactoring to use ProtoType.isRepeated.

The refactoring successfully centralizes the logic for determining repeated fields through the ProtoType.isRepeated flag. This eliminates the need for ad-hoc list type checking throughout the codebase and makes the implementation more maintainable.

Also applies to: 962-966, 1126-1130, 1197-1201


1476-1540: List handling logic is well-tested and can be approved.

The existing tests in protographic/tests/sdl-to-proto/11-lists.test.ts, along with the basic-types and field-ordering suites, cover:

  • Deeply nested lists with mixed nullability
  • Lists of complex types (objects, interfaces, unions)
  • Mixed nullable/non-nullable and nested/non-nested combinations

No further edge cases remain untested. Great work!

@Noroth Noroth requested a review from StarpTech July 18, 2025 07:23
Copy link
Contributor

@StarpTech StarpTech left a comment

Choose a reason for hiding this comment

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

LGTM

@Noroth Noroth merged commit f8c4f65 into main Jul 18, 2025
8 checks passed
@Noroth Noroth deleted the ludwig/eng-7580-implement-nullable-lists-feature-in-protographic branch July 18, 2025 07:54
@coderabbitai coderabbitai bot mentioned this pull request Jul 24, 2025
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants