# The quasi-directive @genqlient is used to configure genqlient on a
# query-by-query basis.
#
# The syntax of the directive is just like a GraphQL directive (as defined
# below), except it goes in a comment on the line immediately preceding the
# field.  (This is because GraphQL expects directives in queries to be defined
# by the server, not by the client, so it would reject a real @genqlient
# directive as nonexistent.)
#
# Directives may be applied to fields, arguments, or the entire query or named
# fragment.  Directives on the line preceding the query or a named fragment
# apply to all relevant nodes in the query; other directives apply to all nodes
# on the following line.  (In all cases it's fine for there to be other
# comments in between the directive and the node(s) to which it applies.)  For
# example, in the following query:
#  # @genqlient(n: "a")
#
#  # @genqlient(n: "b")
#  #
#  # Comment describing the query
#  #
#  # @genqlient(n: "c")
#  query MyQuery(arg1: String,
#    # @genqlient(n: "d")
#    arg2: String, arg3: MyInput,
#    arg4: String,
#  ) {
#    # @genqlient(n: "e")
#    field1, field2
#    # @genqlient(n: "f")
#    field3 {
#      field4
#    }
#  }
# the directive "a" is ignored, "b" and "c" apply to all relevant nodes in the
# query, "d" applies to arg2 and arg3, "e" applies to field1 and field2, and
# "f" applies to field3.
#
# Except as noted below, directives on nodes take precedence over ones on the
# entire query (so "d", "e", and "f" take precedence over "b" and "c"), and
# multiple directives on the same node ("b" and "c") must not conflict.  Note
# that directives on nodes do *not* apply to their "children", so "d" does not
# apply to the fields of MyInput, and "f" does not apply to field4.  (But
# directives on operations and fragments do: both "b" and "c" apply to fields
# of MyInput and to field4.)
directive genqlient(

  # If set to a string "MyType.myField", this entire @genqlient directive
  # will be treated as if it were applied to the specified field of the
  # specified type.  It must be applied to an entire operation or fragment.
  #
  # This is especially useful for input-type options like omitempty and
  # pointer, which are equally meaningful on input-type fields as on arguments,
  # but there's no natural syntax to put them on fields.
  #
  # Note that for input types, unless the type has the "typename" option set,
  # all operations and fragments in the same package which use this type should
  # have matching directives.  (This is to avoid needing to give them more
  # complex type-names.)  This is not currently validated, but will be
  # validated in the future (see issue #123).
  #
  # For example, given the following query:
  #  # @genqlient(for: "MyInput.myField", omitempty: true)
  #  # @genqlient(for: "MyInput.myOtherField", pointer: true)
  #  # @genqlient(for: "MyOutput.id", bind: "path/to/pkg.MyOutputID")
  #  query MyQuery(
  #    $arg: MyInput
  #  ) { ... }
  # genqlient will generate a type
  #  type MyInput struct {
  #    MyField      <type>  `json:"myField,omitempty"`
  #    MyOtherField *<type> `json:"myField"`
  #    MyThirdField <type>  `json:"myThirdField"`
  #  }
  # and use it for the argument to MyQuery, and similarly if `MyOutput.id` is
  # ever requested in the response, it will be set to use the given type.
  for: String

  # If set, this argument (or input-type field, see "for") will be omitted if
  # it has an empty value, defined (the same as in encoding/json) as false, 0,
  # a nil pointer, a nil interface value, and any empty array, slice, map, or
  # string.
  #
  # For example, given the following query:
  #  # @genqlient(omitempty: true)
  #  query MyQuery($arg: String) { ... }
  # genqlient will generate a function
  #  MyQuery(ctx context.Context, client graphql.Client, arg string) ...
  # which will pass {"arg": null} to GraphQL if arg is "", and the actual
  # value otherwise.
  #
  # Only applicable to arguments of nullable types.  Ignored for types with
  # custom marshalers (see their documentation in genqlient.yaml for details).
  omitempty: Boolean

  # If set, this argument or field will use a pointer type in Go.  Response
  # types always use pointers, but otherwise we typically do not.
  #
  # This can be useful if it's a type you'll need to pass around (and want a
  # pointer to save copies) or if you wish to distinguish between the Go
  # zero value and null (for nullable fields).
  pointer: Boolean

  # If set, this field will use a struct type in Go, even if it's an interface.
  #
  # This is useful when you have a query like
  #  query MyQuery {
  #    myInterface { myField }
  #  }
  # where you are requesting only shared fields of an interface.  By default,
  # genqlient still generates an interface type, for consistency.  But this
  # isn't necessary: a struct would do just fine since there are no
  # type-specific fields.  Setting `struct: true` tells genqlient to do that.
  #
  # Note that this is only allowed when there are no fragments in play, such
  # that all fields are on the interface type.  Note that if you later add a
  # fragment, you'll have to remove this option, and the types will change.
  struct: Boolean

  # If set, this field's selection must contain a single fragment-spread; we'll
  # use the type of that fragment-spread as the type of the field.
  #
  # For example, given a query like
  #  query MyQuery {
  #    myField {
  #      ...MyFragment
  #    }
  #  }
  # by default genqlient will generate these types:
  #  type MyQueryResponse struct {
  #    MyField MyQueryMyFieldMyType
  #  }
  #  type MyQueryMyFieldMyType struct {
  #    MyFragment
  #  }
  # If we instead do:
  #  query MyQuery {
  #    # @genqlient(flatten: true)
  #    myField {
  #      ...MyFragment
  #    }
  #  }
  # genqlient will simplify things:
  #  type MyQueryResponse struct {
  #    MyField MyFragment
  #  }
  #
  # This is only applicable to fields whose selection is a single
  # fragment-spread, such that the field-type implements the fragment-type
  # (i.e. we can't do this if MyFragment is on one implementation of the type
  # of MyField; what if we got back the other type?).
  flatten: Boolean

  # If set, this argument or field will use the given Go type instead of a
  # genqlient-generated type.
  #
  # The value should be the fully-qualified type name to use for the field,
  # for example:
  #  time.Time
  #  map[string]interface{}
  #  []github.com/you/yourpkg/subpkg.MyType
  # Note that the type is the type of the whole field, e.g. if your field in
  # GraphQL has type `[DateTime]`, you'd do
  #  # @genqlient(bind: "[]time.Time")
  # (But you're not required to; if you want to map to some type DateList,
  # you can do that, as long as its UnmarshalJSON method can accept a list
  # of datetimes.)
  #
  # Note that the type you bind to must be defined elsewhere in your code.
  # If you want genqlient to create the type definition, use "typename"
  # instead.
  #
  # See bindings in genqlient.yaml for more details; this is effectively to a
  # local version of that global setting and should be used with similar care.
  # If set to "-", overrides any such global setting and uses a
  # genqlient-generated type.
  bind: String

  # If set, the type of this field will have the given name in Go.
  #
  # For example, given the following query:
  #  # @genqlient(typename: "MyResp")
  #  query MyQuery {
  #    # @genqlient(typename: "User")
  #    user {
  #      id
  #    }
  #  }
  # genqlient will generate
  #  type Resp struct {
  #    User User
  #  }
  #  type User struct {
  #    Id string
  #  }
  # instead of its usual, more verbose type names.
  #
  # You may also use "typename" on basic types, and Go will create a
  # type definition for that basic type.  For instance:
  #  query MyQuery {
  #    user {
  #      # @genqlient(typename: "NameType")
  #      name
  #    }
  #  }
  # will cause gnqlient to generate:
  #  type Resp struct {
  #    User User
  #  }
  #  type NameType string
  #  type User struct {
  #    Name NameType
  #  }
  # (Compare this to @genqlient(bind: "path/to/pkg.NameType"), which does
  # something similar but depends on "NameType" being defined in some
  # other package, rather than having genqlient define it for you.)
  #
  # With great power comes great responsibility: when using typename you'll
  # need to avoid comments; genqlient will complain if you use the same
  # type-name in multiple places unless they request the exact same fields, or
  # if your type-name conflicts with an autogenerated one (again, unless they
  # request the exact same fields).  They must even have the fields in the
  # same order.  They should also have matching @genqlient directives, although
  # this is not currently validated (see issue #123).  Fragments are often
  # easier to use (see the discussion of code-sharing in FAQ.md, and the
  # "flatten" option above).
  #
  # Note that unlike most directives, if applied to the entire operation,
  # typename affects the overall response type, rather than being propagated
  # down to all child fields (which would cause conflicts).
  #
  # To avoid confusion, typename may not be combined with local or global
  # bindings; to use typename instead of a global binding do
  # `typename: "MyTypeName", bind: "-"`.
  typename: String

# Multiple genqlient directives are allowed in the same location, as long as
# they don't have conflicting options.
) repeatable on
  # genqlient directives can go almost anywhere, although some options are only
  # applicable in certain locations as described above.
  | QUERY
  | MUTATION
  | SUBSCRIPTION
  | FIELD
  | FRAGMENT_DEFINITION
  | VARIABLE_DEFINITION
