bsdkrun/graphql_transport
The HTTP half of the GraphQL transport used by bsdkrun/client: one
POST per query or mutation, plus URL normalization. The WebSocket half
(subscriptions) is bsdkrun/ws.
Mirrors web/src/lib/graphql.ts’s gql() and
web/src/lib/connection.ts’s normalizeUrl — same request shape, same
status/error interpretation, same URL rules, just over :httpc
(bsdkrun_remote_ffi.erl’s http_post/3) instead of fetch.
parse_response — the status-code/body interpretation — is factored out
from execute specifically so it can be unit-tested against literal
(status, body) pairs with no socket involved (see test/client_test.gleam),
per this feature’s own suggested fallback for testing the HTTP layer.
Values
pub fn execute(
url: String,
token: String,
query: String,
variables: json.Json,
) -> Result(dynamic.Dynamic, error.Error)
Run one GraphQL query or mutation against url (the full endpoint URL,
e.g. http://host:50052/graphql) with token, and return its data
field as a Dynamic for the caller to decode.
pub fn execute_raw(
url: String,
token: String,
query: String,
variables_json: String,
) -> Result(dynamic.Dynamic, error.Error)
Like execute, but takes variables as an already-serialized JSON
string rather than a gleam_json-built Json value. Used by
bsdkrun/client’s request/subscribe escape hatch, whose caller hands
in a Dynamic — bsdkrun_remote_ffi.erl’s dynamic_to_json/1 turns
that into a JSON string directly, with nowhere for a Json value to come
from in between.
pub fn normalize_url(input: String) -> String
Accept what a person actually types or pastes and turn it into the
GraphQL endpoint URL: trim, add http:// when no scheme is given, strip
trailing slashes, append /graphql unless the path already ends with it.
Mirrors web/src/lib/connection.ts’s normalizeUrl exactly, including
leaving an empty/blank input as "" rather than inventing an endpoint.
pub fn parse_response(
status: Int,
body: String,
) -> Result(dynamic.Dynamic, error.Error)
Interpret one HTTP response: a 401 is always an AuthError; otherwise
the body is parsed as JSON and, if errors is a non-empty array, its
first entry becomes an AuthError (when extensions.code is
"UNAUTHENTICATED") or a GraphqlError (any other error). With no
errors, the data field is returned as-is for the caller to decode.