gen fn sdl(contract: String) -> String
Emits a module exporting sdlText() -> String, the contract's SDL as a constant.
Type to search, or try , or .
12 exports, from std/graphql.vyrn.
The contract as a GraphQL SDL document, built on generator imports. sdl(contract) returns a module exporting sdlText() -> String, baked at generation time from the reflected type sources and procedure signatures.
import { sdl } from "std/graphql" import { sdlText } from sdl("./contract")
Mapping rules:
type and an input twin (Book, BookInput); a non-Option field is non-null (!).Int64 and the sized ints => Int, Float64/Float32 => Float, String => String, Bool => Boolean.BookId = Int64 where value >= 0) becomes a named scalar whose description carries its base and constraint.Map<String, V> becomes scalar JSON; a named map alias its own scalar.Result<A, B>) becomes an object with one nullable field per variant (nullary => Boolean, one payload => its type, more => JSON); a nullary-only enum is a GraphQL enum.mut fn is a Mutation field, any other procedure a Query field (FnInfo.mutates). A procedure with a parameter takes (input: <Req>Input). An empty Mutation is omitted._placeholder: Boolean, since GraphQL requires one field; the executor answers it too.Query, Mutation, JSON, or Foo beside FooInput), or one starting with __, is reported, not renamed./// docs on types become descriptions. Reflection carries no procedure docs, so operations have none.graphqlServer emits graphqlHandle(req) -> Option<Response> answering POST /graphql. It walks the same iface.functions and bakes its type graph from the same gqlMembers, so schema and executor agree by construction. The graph keeps each field's ! markers, which decide how far a null propagates.
The import graph shows the whole library.
gen fn sdl(contract: String) -> String
Emits a module exporting sdlText() -> String, the contract's SDL as a constant.
type GqlSel = { key: String, name: String, args: Array<JsonField>, subs: Array<GqlSel>, }
One selected field: the response key (the alias, else the field name), the field it names, its arguments as a JSON tree, and its subselections.
type GqlQuery = { root: String, sels: Array<GqlSel>, err: String }
A parsed operation: its root ("query" or "mutation"), its fields, and err != "" when it did not parse.
fn gqlParseQuery(src: String) -> GqlQuery
One executable operation: an optional query or mutation keyword and name, then a selection set. A second operation is refused.
type GqlErr = { message: String, path: Array<Json> }
One GraphQL error: its message and the response path to the fault, response keys and list indices as JStr and JNum in one array.
type GqlOut = { value: Json, errs: Array<GqlErr>, failed: Bool }
A completed position: its value, every error at or below it, and whether its null is still climbing (failed), as a fault under a non-null position does.
fn gqlProject( v: Json, sels: Array<GqlSel>, tref: String, path: Array<Json>, schema: fn(String, String) -> String, ) -> GqlOut
Completes one field position: projects sels out of v at path, against tref, the field's type reference with its wrappers. An empty sels takes the value whole.
This is a projection over a value the procedure already computed: a leaf is omitted, not avoided. A lazy field (.lazy) would be the one case where omission must also skip the work.
A fault becomes a null at its position and climbs through non-null (!) positions. This is the one place a climb stops: at a nullable position.
fn gqlQueryText(body: String) -> String
The query text of a request body: the query member of a JSON envelope, or the body itself (application/graphql). A GraphQL document is not JSON, so the two cannot be confused.
fn gqlErrorBody(message: String) -> String
{"errors":[{"message":"..."}]}: a fault before execution (an unparseable document, a second operation, a validation fault), with no data. A 200, because a GraphQL client reads errors, not the status line.
type GqlArg = { json: String, err: String }
One argument as the JSON text fromJson reads, or err != "".
fn gqlAnswer( body: String, resolve: fn(String, String, Array<JsonField>) -> Result<Json, String>, schema: fn(String, String) -> String, ) -> Response
Answers one GraphQL request body with the two baked tables: resolve (root, field, args -> the encoded value or why not) and schema, the type graph. The whole tree is validated before any procedure runs, so a typo'd subfield of a mut fn never performs the mutation. Each root field then completes on its own: a fault puts its message in errors at its path and leaves the siblings in data. Argument decode faults surface per field.
gen fn graphqlServer(contract: String) -> String
Emits a module exposing graphqlHandle(req: Request) -> Option<Response>, answering POST /graphql for the contract sdl(contract) documents. It mounts beside rpcHandle and connectHandle. The generator and its module link into one flat namespace, so the generator is not named graphqlHandle.
31 test blocks in std/graphql.vyrn. CI runs all of them.
2 programs in examples/ import this module. Each runs as WebAssembly and as a native binary.