Skip to content

Feature Request: Optional namespace grouping for SDK-style generated code #409

Open

Description

@lume-code

I think it'd be a nice addition to have an optional way to group operation access methods under a namespace, so the generated code feels more like an SDK.
Something like:
<Namespace>.<OperationName>()

Taking it a step further (and this is more opinionated), it could also support grouping by a GraphQL directive. For example, the federation @join directive already points to the owning domain or backends could define their own stable grouping directive. This would give client a clean Stripe-style SDK pattern:
<Namespace>.<GroupedByDirective>.<OperationName>()

There are some edge cases to handle:

  • Operations with multiple/different directives (maybe move them to a common namespace with a warning?)
  • Case style conversions

I've actually taken this approach by writing our own SDK generator for a federated API with 300+ operations. It worked well and clean enough that we didn't need another layer on top for shipping as an SDK.
The other nice thing would be: when a document has a single operation, comments can pass directly to the generated method, which keeps docs intact.

Thought maybe share it here if there is an interest from maintainer to allow these internally.

Activity

  1. github-actions commented on Dec 8, 2025

    @github-actions

    👋 @lume-code
    Thank you for raising an issue. I will investigate the issue and get back to you as soon as possible.
    Please make sure you have provided enough context.

    This library is created and maintained by me, @budde377. Please consider supporting my work and ensure our survival by donating here.

  2. budde377 commented on Dec 9, 2025

    @budde377
    Contributor
  3. lume-code commented on Dec 9, 2025

    @lume-code
    ContributorAuthor

    Sure, taking the Stripe SDK example here, the build.yaml could look something like this:

    graphql_codegen:
        options:
          # ... existing options ...
          
          # New namespace options
          namespace:
            enabled: true
            name: StripeSDK  # Root namespace/class name
            
            # Grouping strategy
            groupBy:
              # Option 1: Directive-based grouping
              directive: 
               # According to federation specs:
                name: "join__field"
                argument: "graph"  # Extract value from this argument
                # OR for custom directive:
                # name: "domain"
                # argument: "name"
              
              # Option 2: Manual grouping by file path pattern
              # paths:
              #   - pattern: "lib/graphql/customers/**"
              #     group: "Customers"
              #   - pattern: "lib/graphql/payments/**"
              #     group: "Payments"
            
            # Conflict resolution
            multipleDirectives: "common"  # "common" | "first" | "warn"
            
            # Style
            caseStyle: "pascalCase"  # for group names

    The first option would be a purely backend based grouping (which I like more) while the second option could allow grouping on client-level.

    GraphQL schema:

    type Query {
      # Customers domain
      customer(id: ID!): Customer! 
        @join__field(graph: CUSTOMERS)
    }

    and the document being:

    query GetCustomer($id: ID!) {
      customer(id: $id) {
        id
        email
        name
        defaultPaymentMethod {
          id
          type
        }
        createdAt
      }
    }

    Currently we have:

    final customer = await GraphQLClient.query$getCustomer(id: 'cus_123');

    which would then look like:

    final customer = await Stripe.customers.getCustomer(id: 'cus_123');

    Additionally, I understand the current implementation prioritizes safety, but it does come with some verbosity trade-offs:

    • Variable class names: Most of the time, variables are the only parameter passed to an operation function, yet we still have to write out the full variable class name. spreading the variables in the function signature reduces the boilerplate + a named options parameter for extra options.
    • query$ / mutation$ prefix: I get that this prevents name collisions, but in practice, having a query and mutation with the exact same name is rare. An opt-out or smarter collision detection could help. Maybe add it only if there is a duplicate?
    • Single-operation documents: In my generator, when a document contains only one operation (which is the common case), I flatten the response so you don't have to access results through nested properties. I considered doing the same for Input classes, but that felt like overkill :)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions