Shopify / tapioca

The swiss army knife of RBI generation

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support for custom GraphQL input preparation

eapache-opslevel opened this issue · comments

GraphQL arguments can define prepare blocks (via kwarg), and input objects can define prepare methods, both of which get used to transform the argument before execution.

In a very similar vein to #1659 (thank you @nicoco007!), it would be more correct if the generated DSL for an argument used the return type of its prepare block, if present, before falling back to the raw type of the argument, since that can be of a different type entirely.

This should be very similar to the support that already exists for argument.loads but is a bit more general.

cc @DougEdey

To provide a bit more context (since sorbet's interactions with procs are complicated), as a minimal first pass it should be possible to add typing support for cases like https://graphql-ruby.org/type_definitions/input_objects.html#converting-to-other-ruby-objects.

If I have an argument :foo, SomeInputType and SomeInputType defines a method prepare, then the argument foo should get typed as the return type of the prepare method, instead of as SomeType.

But ideally it would be possible to use the return type from a custom prepare lambda (if sorbet can infer its type, or it has a signature.

argument :foo, SomeType, prepare: ->(foo, context) { 123 }

foo should get a generate type of Integer, in theory at least.

Doug very kindly did part of this in #1720.

@KaanOzkan Is there a way to add signatures to lambdas?

i.e.:

PREPARE = ->(input, context) { # do something that changes input to a different type }

argument :foo, InputType, prepare: PREPARE

I assume you don't want to generate signatures for a lambda but to retrieve a type specific for a lambda.

I thought you could use T.let but that's not the case.

Lambda's return type can be typed using a method definition that returns the lambda or by casting the return type. However, I doubt a user would go for that option instead of defining a prepare method.

sig { returns(String) }
def bar; end

argument :foo, InputType, prepare: bar

Added part (2) which adds support for prepare: :method_name or prepare: "method_name" options, it doesn't support lambda at this time.

@eapache-opslevel I don't think there's anything else to do for this now

  • Can't do lambdas
  • The prepare method on the mutation root isn't supported

👍 yup, thanks