## Summary:
genqlient has some code (`imports.go`) dedicated to tracking which
imports we need and avoiding conflicts, as well as converting a
(restricted) Go expression like `map[string]github.com/me/mypkg.MyType`
to an import (`github.com/me/mypkg`) and a type-reference
(`map[string]mypkg.MyType`) to be used in the context of that import,
and at least making some attempt to track conflicts. (Right now the
conflict-avoidance is not very smart, and not very well tested, but it
comes up rarely anyway.) Sadly, that code was a bit cumbersome to use,
because you had to first register the imports (typically from
`convert.go`), then use them (often from the template).
In this commit I refactor the order we write things in order to allow a
significant simplification of how we import; in particular we no longer
have to guess in advance what imports which template will need; it can
just do `{{ref <expr>}}` as before, and it just works. To do this, I:
- changed the importer to have only one API, which adds the import if
needed, and returns the reference either way
- added a check that we don't add imports after they're written
- reorganized the toplevel templates a bit to make sure that check never
fires; we now generate all the types and operations, then write the
imports and glue it all together
This removes a bunch of silly code, and should simplify the process of
adding custom (un)marshalers (#38).
While I was at it, I put the documentation of what expressions we
support in a more visible place, and added a type-assertion that your
custom context type implements context.Context (if applicable).
## 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/101
127 lines
5.3 KiB
YAML
127 lines
5.3 KiB
YAML
# genqlient.yaml is genqlient's configuration file. This genqlient.yaml is an
|
|
# example; use `go run github.com/Khan/genqlient --init` to generate a simple
|
|
# starting point.
|
|
|
|
# The filename with the GraphQL schema (in SDL format), relative to
|
|
# genqlient.yaml.
|
|
schema: schema.graphql
|
|
|
|
# Filenames or globs with the operations for which to generate code, relative
|
|
# to genqlient.yaml.
|
|
#
|
|
# These may be .graphql files, containing the queries in SDL format, or
|
|
# Go files, in which case any string-literal starting with (optional
|
|
# whitespace and) the string "# @genqlient" will be extracted as a query.
|
|
operations:
|
|
- genqlient.graphql
|
|
- "pkg/*.go"
|
|
|
|
# The filename to which to write the generated code, relative to
|
|
# genqlient.yaml.
|
|
generated: generated/genqlient.go
|
|
|
|
# The package name for the output code; defaults to the directory name of
|
|
# the generated-code file.
|
|
package: mygenerated
|
|
|
|
# If set, a file at this path (relative to genqlient.yaml) will be generated
|
|
# containing the exact operations that genqlient will send to the server.
|
|
#
|
|
# This is useful for systems which require queries to be explicitly
|
|
# safelisted (e.g. [1]), especially for cases like queries involving fragments
|
|
# where it may not exactly match the input queries, or for other static
|
|
# analysis. The JSON is an object of the form
|
|
# {"operations": [{
|
|
# "operationName": "operationname",
|
|
# "query": "query operationName { ... }",
|
|
# "sourceLocation": "myqueriesfile.graphql",
|
|
# }]}
|
|
# Keys may be added in the future.
|
|
#
|
|
# By default, no such file is written.
|
|
#
|
|
# [1] https://www.apollographql.com/docs/studio/operation-registry/
|
|
export_operations: operations.json
|
|
|
|
# Set to the fully-qualified name of a Go type which generated helpers
|
|
# should accept and use as the context.Context for HTTP requests.
|
|
#
|
|
# Defaults to context.Context; set to "-" to omit context entirely (i.e.
|
|
# use context.Background()). Must be a type which implements
|
|
# context.Context.
|
|
context_type: context.Context
|
|
|
|
# If set, a function to get a graphql.Client, perhaps from the context.
|
|
# By default, the client must be passed explicitly to each genqlient
|
|
# generated query-helper.
|
|
#
|
|
# This is useful if you have a shared client, either a global, or
|
|
# available from context, and don't want to pass it explicitly. In this
|
|
# case the signature of the genqlient-generated helpers will omit the
|
|
# `graphql.Context` and they will call this function instead.
|
|
#
|
|
# Must be the fully-qualified name of a function which accepts a context
|
|
# (of the type configured as ContextType (above), which defaults to
|
|
# `context.Context`, or a function of no arguments if ContextType is set
|
|
# to the empty string) and returns (graphql.Client, error). If the
|
|
# client-getter returns an error, the helper will return the error
|
|
# without making a query.
|
|
client_getter: "github.com/you/yourpkg.GetClient"
|
|
|
|
# A map from GraphQL type name to Go fully-qualified type name to override
|
|
# the Go type genqlient will use for this GraphQL type.
|
|
#
|
|
# This is primarily used for custom scalars, or to map builtin scalars to
|
|
# a nonstandard type. By default, builtin scalars are mapped to the
|
|
# obvious Go types (String and ID to string, Int to int, Float to float64,
|
|
# and Boolean to bool), but this setting will extend or override those
|
|
# mappings.
|
|
#
|
|
# genqlient does not validate these types in any way; they must define
|
|
# whatever logic is needed (MarshalJSON/UnmarshalJSON or JSON tags) to
|
|
# convert to/from JSON. For this reason, it's not recommended to use this
|
|
# setting to map object, interface, or union types, because nothing
|
|
# guarantees that the fields requested in the query match those present in
|
|
# the Go type.
|
|
#
|
|
# To get equivalent behavior in just one query, use @genqlient(bind: ...);
|
|
# see genqlient_directive.graphql for more details.
|
|
bindings:
|
|
# To bind a scalar:
|
|
DateTime:
|
|
# The fully-qualified name of the Go type to which to bind. For example:
|
|
# time.Time
|
|
# map[string]interface{}
|
|
# github.com/you/yourpkg/subpkg.MyType
|
|
# Specifically, this can be any of the following expressions:
|
|
# - any named type (qualified by the full package path)
|
|
# - any predeclared basic type (string, int, etc.)
|
|
# - interface{}
|
|
# - for any allowed type T, *T, []T, [N]T, and map[string]T
|
|
# but can't be, for example:
|
|
# - an inline (unnamed) struct or interface type
|
|
# - a map whose key-type is not string
|
|
# - a nonstandard way of spelling those, (interface {/* hi */},
|
|
# map[ string ]T)
|
|
type: time.Time
|
|
|
|
# To bind an object type:
|
|
MyType:
|
|
type: github.com/you/yourpkg.GoType
|
|
# If set, a GraphQL selection which must exactly match the fields
|
|
# requested whenever this type is used. Only applies if the GraphQL type
|
|
# is a composite output type (object, interface, or union).
|
|
#
|
|
# This is useful if Type is a struct whose UnmarshalJSON or other methods
|
|
# expect that you requested certain fields. For example, given the below
|
|
# config, genqlient will reject if you make a query
|
|
# { fieldOfMytype { id title } }
|
|
# The fields must match exactly, including the ordering: "{ name id }"
|
|
# will be rejected. But the arguments and directives, if any, need not
|
|
# match.
|
|
#
|
|
# TODO(benkraft): Also add ExpectIncludesFields and ExpectSubsetOfFields,
|
|
# or something, if you want to say, for example, that you have to request
|
|
# certain fields but others are optional.
|
|
expect_exact_fields: "{ id name }"
|