Skip to content

Use GraphQLQuery at runtime

Most data a page needs is injected and arrives in the HTML document. Runtime execution is for what could not have been injected: a detail record chosen by a click, a lookup whose parameters only exist once the user has typed something.

Before reaching for it, check the two things that are not it:

  • A page of the same rows, differently filtered or sorted, is update() on the document you already have.
  • Data that changed because somebody else changed it is useDocumentWatch().

Declare the query the way you declare any other – module scope, literal source, the same rules – and call execute() on it:

import {field, value} from "@qlivedev/qlive-ts/filter"
import Q_FooDetail from "./Q_FooDetail"
// ... detailId is the id of the Foo you want to load in detail
const doc = await Q_FooDetail.execute(
{
config: {
condition: field("id").eq(value(detailId))
}
}
)

execute() posts the query, converts the variables on the way out and the result on the way in, and unwraps the single top-level selection – so it resolves to T, exactly what useInjection() would have handed you for the same query. A query document that comes back this way is a live document like any other: update() works on it.

It still gets its generated result type, because it is still a declared constant with a literal source. Only the injection needs the call site to be readable at build time; execution does not.

For the cases that do not fit – several top-level selections, or you want the wire format – there is graphql():

import graphql, {firstValue} from "@qlivedev/qlive-ts";
const data = await graphql(query, params); // the whole "data" object

It rejects on a transport error or on any GraphQL error in the response. GraphQL errors arrive as a GraphQLResponseError, the same one execute() and a query document’s update() reject with. It carries the errors as the server sent them, and hasClassification() tells an ended session ("UNAUTHENTICATED") from a missing role ("FORBIDDEN"):

try
{
await graphql(query, params);
}
catch (e)
{
if (e instanceof GraphQLResponseError && e.hasClassification("UNAUTHENTICATED"))
{
// send the user to the login
}
}

A request that got no GraphQL response at all rejects with a GraphQLTransportError instead: the server couldn’t be reached (status is null), or answered with something else, like the 503 of a server still starting. The error underneath is its cause.

Nothing converts the result and nothing types it: this is the escape hatch, not the normal path.

Both calls, and firstValue(), are Runtime GraphQL in the API reference.