## Summary: Previously, we actually allowed you to put several genqlient directives on the same node, but the semantics were undocumented (and somewhat confusing, when it comes to `typename`). In order to support directives on input options, we're actually going to be encouraging this usage (see notes in #14), so it's time to fix it. To avoid confusion, I just had conflicting directives be an error, rather than defining which one "wins". The same applies to specifying the same option several times in one directive. I also fixed two small bugs: - `typename` on an operation would incorrectly cascade down to all input types in a query (causing conflicts). - directive parse errors had useless positions, now they're correct ## Test plan: make check Author: benjaminjkraft Reviewers: StevenACoffman, dnerdy, aberkan, jvoll, mahtabsabet, MiguelCastillo Required Reviewers: Approved By: StevenACoffman, dnerdy Checks: ⌛ Test (1.17), ⌛ Test (1.16), ⌛ Test (1.15), ⌛ Test (1.14), ⌛ Lint, ⌛ Test (1.17), ⌛ Test (1.16), ⌛ Test (1.15), ⌛ Test (1.14), ⌛ Lint Pull Request URL: https://github.com/Khan/genqlient/pull/105
149 lines
5.8 KiB
GraphQL
149 lines
5.8 KiB
GraphQL
# 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.
|
|
# Directives on the line preceding the query 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.
|
|
directive genqlient(
|
|
|
|
# If set, this argument 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 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.)
|
|
#
|
|
# 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.
|
|
#
|
|
# 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. Fragments are often easier to use (see the discussion of
|
|
# code-sharing in FAQ.md).
|
|
#
|
|
# 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).
|
|
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
|