GraphQL interop#

Meta: this is the page that justifies the language. Lead with "schema-as-stdlib" — when you import Dagger, every type and root function in the schema becomes part of the language. Import wiring (dang.toml, import) lives in Modules and imports; type machinery in Types and nullability; record/object access in Objects (type).

Schema-as-stdlib#

Calling a field#

let users = users(limit: 10)

Multi-field selection#

user.{{ name, email, posts.{{ title, createdAt }} }}
user.{{ posts(first: 5).{{ title }} }}

Inline fragments#

node(id: "x").{{
  ... on User { name, email }
  ... on Post { title }
}}

Lazy inline fragments#

Lists of objects#

users.{{ name, email }}

Mutations#

Laziness: GraphQL field access in Dang is lazy. A GraphQLValue accumulates a query chain (.field, .{{...}} selections, args); no request is sent until the value is forced — i.e. materialized at an expected-type boundary (assertion, print, assignment to a typed field, indexing into a result, etc.). Forcing runs the built-up selection as a single Execute against the endpoint. This is the desugaring that makes user.{{ name, posts.{{ title }} }} one round-trip. See Mutation and copy-on-write for how forcing interacts with side effects.

Errors from the server#

Talking to multiple endpoints#