Skip to content

fix(protographic): use proto wrapper for nullable scalars#2032

Merged
Noroth merged 6 commits intowundergraph:mainfrom
yuzoonc1:paulcho/use-proto-wrapper-for-nullable-scalars
Jul 10, 2025
Merged

fix(protographic): use proto wrapper for nullable scalars#2032
Noroth merged 6 commits intowundergraph:mainfrom
yuzoonc1:paulcho/use-proto-wrapper-for-nullable-scalars

Conversation

@yuzoonc1
Copy link
Copy Markdown
Contributor

@yuzoonc1 yuzoonc1 commented Jul 9, 2025

Use google/protobuf/wrappers.proto wrappers to accurately represent semantic nulls vs zero values.

Corresponding engine changes are in this PR by @Noroth - wundergraph/graphql-go-tools#1212

This change only supports Nullable Scalar types. Support for Nullable fields within Lists/Nest lists will follow. Currently in discussion.

Summary by CodeRabbit

  • Documentation

    • Updated documentation to highlight support for Protocol Buffer wrapper types for nullable fields, improving clarity on nullability handling in generated proto files.
    • Expanded scalar type mapping tables and examples to reflect the use of wrapper types for nullable GraphQL fields.
  • New Features

    • Added support for mapping nullable GraphQL scalar fields to Protocol Buffer wrapper types, allowing explicit distinction between unset and zero values in generated proto schemas.
  • Tests

    • Updated and expanded tests to verify correct conversion of nullable scalar fields to wrapper types and inclusion of necessary imports.
    • Removed the test case for handling empty schemas.
  • Chores

    • Improved proto validation by preloading protobuf wrapper definitions before parsing and resolving references.

Checklist

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jul 9, 2025

Walkthrough

The changes introduce support for Protocol Buffer wrapper types for nullable GraphQL scalar fields in the Protographic project. Documentation, source code, and test cases were updated to map nullable GraphQL scalars to google.protobuf.*Value wrapper types, add necessary import statements, and ensure accurate nullability handling throughout SDL-to-Proto conversion.

Changes

Files/Areas Change Summary
protographic/README.md, protographic/SDL_PROTO_RULES.md Documentation updated to describe and exemplify the use of Protocol Buffer wrapper types for nullable scalar fields, including changes to mapping tables and message examples.
protographic/src/sdl-to-proto-visitor.ts Core logic modified to map nullable GraphQL scalars to protobuf wrapper types, track wrapper usage, insert wrapper imports, and adjust type mapping and nested list wrapper generation accordingly.
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/04-federation.test.ts
protographic/tests/sdl-to-proto/05-edge-cases.test.ts
protographic/tests/sdl-to-proto/09-comments.test.ts
protographic/tests/sdl-to-proto/10-options.test.ts
Test cases and expected proto outputs updated to use wrapper types for nullable scalars, add necessary imports, and remove one obsolete test for empty schemas. One new test added for wrapper mapping; one test removed.
protographic/tests/util.ts Proto validation utility updated to preload wrapper proto definitions and resolve all references during parsing, ensuring correct validation of wrapper types in test outputs.

📜 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 7a31d12 and 632fd5c.

📒 Files selected for processing (3)
  • protographic/src/sdl-to-proto-visitor.ts (6 hunks)
  • protographic/tests/sdl-to-proto/05-edge-cases.test.ts (14 hunks)
  • protographic/tests/util.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • protographic/tests/util.ts
  • protographic/tests/sdl-to-proto/05-edge-cases.test.ts
  • protographic/src/sdl-to-proto-visitor.ts
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 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.

@yuzoonc1 yuzoonc1 marked this pull request as ready for review July 9, 2025 18:30
@yuzoonc1 yuzoonc1 requested review from Noroth and StarpTech as code owners July 9, 2025 18:30
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

1440-1489: Unused innerMostType parameter in createNestedListWrapper.

The method signature was updated to accept innerMostType for preserving nullability information, but this parameter is not used in the method body. The proto type is still derived from baseType on line 1478.

Consider using innerMostType instead of baseType when determining the proto type to properly handle nullability for nested lists.

-    const protoType = this.getProtoTypeFromGraphQL(baseType, true);
+    const protoType = this.getProtoTypeFromGraphQL(innerMostType, true);

1398-1426: Fix nested-list nullability handling

The innerMostType you compute in getProtoTypeFromGraphQL is never actually used when building the wrapper. As a result, the null-vs-non-null semantics for nested lists aren’t preserved.

Locations to update:

  • protographic/src/sdl-to-proto-visitor.ts:
    • getProtoTypeFromGraphQL (≈ lines 1398–1409) – you track innerMostType but don’t apply it
    • createNestedListWrapper signature (line 1440) – innerMostType: GraphQLType is passed in but never referenced

Recommended changes:

  • In createNestedListWrapper, inspect innerMostType (e.g. via isNonNullType(innerMostType)) and use it to decide whether the wrapper or its result field should be optional vs. required in the proto
  • If nullability shouldn’t affect the wrapper, remove the unused innerMostType parameter and simplify the logic
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d53e9d6 and 4c7dc06.

📒 Files selected for processing (10)
  • protographic/README.md (1 hunks)
  • protographic/SDL_PROTO_RULES.md (4 hunks)
  • protographic/src/sdl-to-proto-visitor.ts (8 hunks)
  • protographic/tests/sdl-to-proto/01-basic-types.test.ts (11 hunks)
  • protographic/tests/sdl-to-proto/02-complex-types.test.ts (7 hunks)
  • protographic/tests/sdl-to-proto/04-federation.test.ts (2 hunks)
  • protographic/tests/sdl-to-proto/05-edge-cases.test.ts (16 hunks)
  • protographic/tests/sdl-to-proto/09-comments.test.ts (7 hunks)
  • protographic/tests/sdl-to-proto/10-options.test.ts (2 hunks)
  • protographic/tests/util.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
protographic/tests/sdl-to-proto/01-basic-types.test.ts (2)
protographic/src/index.ts (1)
  • compileGraphQLToProto (52-78)
protographic/tests/util.ts (1)
  • expectValidProto (30-32)
🔇 Additional comments (23)
protographic/README.md (1)

21-21: Documentation accurately describes the new wrapper type feature.

The added line clearly communicates the value of using Protocol Buffer wrappers to distinguish semantic nulls from zero values, which aligns with the PR objectives.

protographic/tests/sdl-to-proto/04-federation.test.ts (2)

402-402: Correctly imports wrapper types when needed.

The conditional import of google/protobuf/wrappers.proto is properly added to support the wrapper types used in the proto definition.


430-432: Proper use of wrapper types for nullable scalar fields.

The nullable scalar fields (endTime, metadata, attachment) are correctly mapped to google.protobuf.StringValue wrapper types, allowing proper distinction between null and empty string values.

protographic/tests/sdl-to-proto/10-options.test.ts (2)

29-29: Correctly imports wrapper types for comprehensive scalar support.

The import statement is properly added to support the various wrapper types used throughout the proto definition.


45-73: Comprehensive wrapper type mapping for all scalar types.

All GraphQL scalar types are correctly mapped to their corresponding protobuf wrapper types:

  • String → google.protobuf.StringValue
  • Int → google.protobuf.Int32Value
  • Float → google.protobuf.DoubleValue
  • Boolean → google.protobuf.BoolValue
  • ID → google.protobuf.StringValue

This ensures consistent nullability handling across all scalar types.

protographic/tests/util.ts (1)

11-22: Properly supports wrapper type validation.

The function correctly preloads the protobuf wrapper definitions before parsing proto text, ensuring that wrapper type references are resolved during validation. The implementation follows protobufjs best practices by:

  1. Creating a new Root instance
  2. Loading wrapper definitions first
  3. Parsing with the pre-loaded root
  4. Calling resolveAll() for complete resolution
protographic/tests/sdl-to-proto/09-comments.test.ts (2)

85-85: Consistent wrapper type imports across all test cases.

The import statements for google/protobuf/wrappers.proto are correctly added in each test case that uses wrapper types, ensuring proper proto compilation.

Also applies to: 236-236, 379-379


117-119: Comprehensive wrapper type usage for nullable fields.

The nullable scalar fields are consistently mapped to their appropriate wrapper types across different scenarios:

  • Pagination parameters (offset, limit) → google.protobuf.Int32Value
  • User fields (name, age) → google.protobuf.StringValue and google.protobuf.Int32Value
  • Optional descriptions → google.protobuf.StringValue

This demonstrates thorough coverage of nullable field handling with wrapper types.

Also applies to: 144-145, 314-314, 511-511

protographic/SDL_PROTO_RULES.md (3)

56-63: LGTM! Clear documentation of nullable scalar type mappings.

The table clearly distinguishes between non-null and nullable GraphQL scalar types and their corresponding Protocol Buffer types. The wrapper types are correctly mapped according to protobuf specifications.


289-299: Example correctly demonstrates wrapper type usage.

The example properly shows:

  • The required import statement for wrapper types
  • Correct application of wrapper types to nullable fields only
  • Non-null fields remaining as primitive types

317-351: Field reservation examples properly updated for wrapper types.

The examples correctly show how nullable fields with wrapper types work alongside the field reservation mechanism, maintaining backward compatibility during schema evolution.

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

23-74: Test correctly validates wrapper type conversion for nullable scalars.

The test properly expects wrapper types for all nullable scalar fields and includes the required import statement.


186-211: Correctly handles mixed nullable and non-null fields.

The test properly expects wrapper types only for nullable fields while keeping primitive types for non-null fields.


231-267: Request arguments properly use wrapper types for nullable fields.

The test correctly expects wrapper types for nullable query arguments (offset, nameFilter).


287-308: Import placement correctly respects existing options.

The test validates that the wrapper import is properly placed after package options.


520-588: Excellent comprehensive test coverage for nullable scalar conversions.

This new test thoroughly validates the wrapper type conversion for all GraphQL scalar types, ensuring complete coverage of the feature.

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

92-133: Input types correctly use wrapper types for nullable fields.

The test properly validates that nullable fields in both input types and regular types use wrapper types.


287-327: Nested input types properly handle nullable fields with wrapper types.

The test correctly validates wrapper type usage in complex nested input structures.

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

6-6: Verify the removal of the empty schema test case.

The AI summary indicates an empty schema test was removed. Please confirm this removal was intentional and doesn't reduce test coverage for edge cases.


25-643: Edge case tests properly updated for wrapper types.

All edge case scenarios correctly use wrapper types for nullable fields, maintaining comprehensive test coverage.

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

52-65: Wrapper type mappings are correctly defined.

The SCALAR_WRAPPER_TYPE_MAP correctly maps GraphQL scalar types to their corresponding Protocol Buffer wrapper types according to the protobuf specification.


444-462: Import insertion logic correctly handles proto file structure.

The implementation properly places the wrapper import after the package declaration and any existing options, maintaining valid protobuf syntax.


1368-1390: Nullability handling logic is correctly implemented.

The method properly distinguishes between nullable and non-null scalar types, using wrapper types only for nullable scalars. The ignoreWrapperTypes parameter provides necessary flexibility for special cases.

Comment thread protographic/tests/sdl-to-proto/02-complex-types.test.ts Outdated
Copy link
Copy Markdown
Contributor

@Noroth Noroth 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 09d49b8 into wundergraph:main Jul 10, 2025
8 checks passed
@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.

2 participants