Skip to main content

Getting Started with Tailcall Directives

Tailcall DSL builds on your existing GraphQL knowledge by allowing the addition of some custom directives. These directives provide powerful compile time guarantees to ensure your API composition is tight and robust. Behind the scenes, Tailcall automatically generates highly optimized resolver logic for your types using the information in the directives.

Here is a list of all the custom directives supported by Tailcall:

OperatorDescription
@addFieldSimplifies data structures and queries by adding, inlining, or flattening fields or nodes within the schema.
@cacheEnables caching for the query, field or type applied to.
@callInvokes a query or mutation from another query or mutation field.
@discriminateAllows to customize the discriminator while working with union types.
@exprAllows embedding of a constant response within the schema.
@graphQLResolves a field or node by a GraphQL API.
@grpcResolves a field or node by a gRPC API.
@httpResolves a field or node by a REST API.
@linkImports external resources such as config files, certs, protobufs, etc in the schema.
@modifyEnables changes to attributes of fields or nodes in the schema.
@omitExcludes fields or nodes from the generated schema, making them inaccessible through the GraphQL API.
@protectedAdds authentication and authorization controls to fields or nodes in the schema.
@restAllows exposing REST endpoints on top of GraphQL.
@serverProvides server configurations for behavior tuning and tailcall optimization in specific use-cases.
@telemetryIntegrates with open-telemetry to provide observability of the running tailcall service.
@upstreamControls aspects of the upstream server connection, including timeouts and keep-alive settings.

Resolvable Directives

Resolvable directives are used to fetch actual data from external sources. These include the following directives: @call, @expr, @graphQL, @grpc, and @http.

Combining Resolvable Directives on Fields

When multiple resolvable directives (such as @call, @expr, @graphQL, @grpc, or @http) are applied to a field, the order in which they are defined in the schema is important. Each directive contributes a part of the final result, and the outputs are combined by performing a deep merge of all partial results.

Example: Combining Resolvable Directives

type Query {
data: Data
# This request resolves the `{ "foo": "..." }` part of the response
@http(url: "http://api.com/foo")
# This request resolves the `{ "bar": "..." }` part of the response
# After executing both requests, the results are merged into a single `Data` object
@http(url: "http://api.com/bar")

dataList: [Data]
# This request resolves 3 entries of data: `[.., .., ..]`
@http(url: "http://api.com/list/foo")
# This request resolves 2 entries of data: `[.., ..]`
# After executing both requests, the results are merged into a single list
# containing 5 entries
@http(url: "http://api.com/list/bar")
}

type Data {
foo: String
bar: String
}

Key Points

  1. Order Matters: The schema's order of directives determines how partial results are combined.
  2. Deep Merge: Partial outputs from each directive are deep-merged to produce the final result.
  3. Versatility: Resolvable directives can fetch data from various sources, making them powerful tools for flexible schema design.