shopify_draft_proxy/proxy/graphql_helpers
Mirrors the operation-time helpers from src/proxy/graphql-helpers.ts.
The TS module is a grab bag covering value resolution, scalar reads, projection, pagination, and connection serialization. Keep this module broad enough that endpoint groups can share Shopify-like GraphQL behavior instead of rebuilding local loops and projectors.
Types
How serialize_connection_page_info formats the cursors and
hasNextPage/hasPreviousPage. Mirrors ConnectionPageInfoOptions,
merged with the underlying SelectedFieldOptions for inline-fragment
flattening.
pub type ConnectionPageInfoOptions {
ConnectionPageInfoOptions(
include_inline_fragments: Bool,
prefix_cursors: Bool,
include_cursors: Bool,
fallback_start_cursor: option.Option(String),
fallback_end_cursor: option.Option(String),
)
}
Constructors
-
ConnectionPageInfoOptions( include_inline_fragments: Bool, prefix_cursors: Bool, include_cursors: Bool, fallback_start_cursor: option.Option(String), fallback_end_cursor: option.Option(String), )
The post-paginate slice of a connection: which items survived
first/last/after/before, and whether the caller should advertise
next/previous pages on pageInfo. Mirrors ConnectionWindow<T>.
pub type ConnectionWindow(a) {
ConnectionWindow(
items: List(a),
has_next_page: Bool,
has_previous_page: Bool,
)
}
Constructors
-
ConnectionWindow( items: List(a), has_next_page: Bool, has_previous_page: Bool, )
How paginate_connection_items should interpret the after /
before cursor arguments. The TS version takes an optional
parseCursor; in Gleam we always pass a function, defaulting to the
cursor:-stripping behaviour.
pub type ConnectionWindowOptions {
ConnectionWindowOptions(
parse_cursor: fn(String) -> option.Option(String),
)
}
Constructors
-
ConnectionWindowOptions( parse_cursor: fn(String) -> option.Option(String), )
Lookup table from fragment name to its definition. Mirrors the
FragmentMap returned by getDocumentFragments.
pub type FragmentMap =
dict.Dict(String, ast.Definition)
Whether get_selected_child_fields should also flatten field
selections that appear inside inline fragments. Mirrors the TS
SelectedFieldOptions.includeInlineFragments.
pub type SelectedFieldOptions {
SelectedFieldOptions(include_inline_fragments: Bool)
}
Constructors
-
SelectedFieldOptions(include_inline_fragments: Bool)
Configuration for serialize_connection. Mirrors
SerializeConnectionOptions<T> but uses an explicit record rather
than an options object — Gleam doesn’t have optional fields, so the
record is the natural shape.
pub type SerializeConnectionConfig(a) {
SerializeConnectionConfig(
items: List(a),
has_next_page: Bool,
has_previous_page: Bool,
get_cursor_value: fn(a, Int) -> String,
serialize_node: fn(a, ast.Selection, Int) -> json.Json,
selected_field_options: SelectedFieldOptions,
page_info_options: ConnectionPageInfoOptions,
)
}
Constructors
-
SerializeConnectionConfig( items: List(a), has_next_page: Bool, has_previous_page: Bool, get_cursor_value: fn(a, Int) -> String, serialize_node: fn(a, ast.Selection, Int) -> json.Json, selected_field_options: SelectedFieldOptions, page_info_options: ConnectionPageInfoOptions, )
JSON-shaped source value the projector walks. Mirrors the
Record<string, unknown> source argument in the TS projector. Kept
local so graphql_helpers doesn’t depend on root_field (which
happens to define an identical type for argument resolution).
pub type SourceValue {
SrcNull
SrcString(String)
SrcBool(Bool)
SrcInt(Int)
SrcFloat(Float)
SrcList(List(SourceValue))
SrcObject(dict.Dict(String, SourceValue))
}
Constructors
-
SrcNull -
SrcString(String) -
SrcBool(Bool) -
SrcInt(Int) -
SrcFloat(Float) -
SrcList(List(SourceValue)) -
SrcObject(dict.Dict(String, SourceValue))
Values
pub fn build_synthetic_cursor(id: String) -> String
Synthetic cursor mirror of buildSyntheticCursor. Public because
some handlers build cursors out of band before paginating.
pub fn default_connection_page_info_options() -> ConnectionPageInfoOptions
Defaults: cursors prefixed with cursor:, cursors included in
pageInfo, no fallback when the connection is empty, no inline
fragments flattened.
pub fn default_connection_window_options() -> ConnectionWindowOptions
Default options matching the TS {} argument: cursor strings of the
form cursor:<value> are unwrapped; otherwise the raw string is
returned.
pub fn default_selected_field_options() -> SelectedFieldOptions
Default options matching the TS {} argument.
pub fn default_type_condition_applies(
source: dict.Dict(String, SourceValue),
type_condition: option.Option(String),
) -> Bool
Default __typename-based gate: a type condition applies when the
source object lacks a __typename or its __typename matches the
condition. Mirrors defaultGraphqlTypeConditionApplies.
pub fn get_document_fragments(
document: String,
) -> dict.Dict(String, ast.Definition)
Build a fragment map from a parsed document. Returns an empty map when the document fails to parse — this matches the spirit of the TS code where a parse failure short-circuits the caller before this helper is invoked.
pub fn get_field_response_key(field: ast.Selection) -> String
Response key for a Field selection: the alias if present, otherwise
the underlying field name. Mirrors getFieldResponseKey.
Returns the field’s name.value for non-Field selections, which lets
callers thread the helper through fragment-flattening flows without
needing to special-case shape mismatches. The TS helper isn’t
generic, but Gleam’s exhaustive pattern matching forces us to handle
every variant — and the TS code never calls it on non-Field nodes.
pub fn get_selected_child_fields(
field: ast.Selection,
options: SelectedFieldOptions,
) -> List(ast.Selection)
Direct-child Field selections of a parent Field. Optionally
flattens Field selections from inline fragments. Mirrors
getSelectedChildFields.
pub fn paginate_connection_items(
items: List(a),
field: ast.Selection,
variables: dict.Dict(String, root_field.ResolvedValue),
get_cursor_value: fn(a, Int) -> String,
options: ConnectionWindowOptions,
) -> ConnectionWindow(a)
Apply first/last/after/before to a list of items, returning
the windowed slice plus next/previous-page flags. Mirrors
paginateConnectionItems. The TS version does index arithmetic over
Array.prototype.findIndex; Gleam’s recursive walk produces the
same indices.
pub fn project_graphql_field_value(
value: SourceValue,
field: ast.Selection,
fragments: dict.Dict(String, ast.Definition),
) -> json.Json
Project one selected field from a SourceValue, returning the field value
rather than an enclosing object. Domain-specific projectors can use this
when a few argument-aware fields need custom handling while all sibling
fields should retain the shared projection semantics.
pub fn project_graphql_object(
source: dict.Dict(String, SourceValue),
selections: List(ast.Selection),
fragments: dict.Dict(String, ast.Definition),
) -> json.Json
Project an object through a list of selections, honouring inline
fragments and fragment spreads. Mirrors projectGraphqlObject. Type
conditions use the default __typename gate; the TS overload that
lets callers customise the projector or the gate is intentionally
out of scope for this slice.
pub fn project_graphql_value(
value: SourceValue,
selections: List(ast.Selection),
fragments: dict.Dict(String, ast.Definition),
) -> json.Json
Project a value through a selection set. The TS version short-circuits
arrays element-wise and lets non-objects pass through unchanged;
Gleam mirrors that exactly via the SourceValue constructors.
pub fn read_boolean_value(
value: SourceValue,
) -> option.Option(Bool)
Null-on-mismatch boolean reader for source payload boundaries.
pub fn read_graphql_data_response_payload(
payload: SourceValue,
response_key: String,
) -> SourceValue
Read payload.data[response_key], returning SrcNull for malformed
or absent data to preserve Shopify-like no-data behavior.
pub fn read_nullable_int_argument(
field: ast.Selection,
argument_name: String,
variables: dict.Dict(String, root_field.ResolvedValue),
) -> option.Option(Int)
Read a nullable integer argument from a field, resolving variables
with the same semantics as root_field.get_field_arguments.
pub fn read_nullable_string_argument(
field: ast.Selection,
argument_name: String,
variables: dict.Dict(String, root_field.ResolvedValue),
) -> option.Option(String)
Read a nullable string argument from a field, resolving variables
with the same semantics as root_field.get_field_arguments.
pub fn read_number_value(
value: SourceValue,
) -> option.Option(Float)
Null-on-mismatch number reader for source payload boundaries.
pub fn read_plain_object_array(
value: SourceValue,
) -> List(dict.Dict(String, SourceValue))
Filter a source value down to object-shaped array entries.
pub fn read_string_value(
value: SourceValue,
) -> option.Option(String)
Null-on-mismatch string reader for source payload boundaries.
pub fn resolved_value_to_source(
value: root_field.ResolvedValue,
) -> SourceValue
Convert an argument-resolution value into the source projector shape. This keeps JSON-shaped values moving through shared helper APIs without resource-local conversion trees.
pub fn serialize_connection(
field: ast.Selection,
config: SerializeConnectionConfig(a),
) -> json.Json
Serialize a connection: walks the field’s selection set and emits
nodes, edges, or pageInfo per the items + flags. Mirrors
serializeConnection.
pub fn serialize_connection_page_info(
selection: ast.Selection,
items: List(a),
has_next_page: Bool,
has_previous_page: Bool,
get_cursor_value: fn(a, Int) -> String,
options: ConnectionPageInfoOptions,
) -> json.Json
Serialize a connection’s pageInfo block. Mirrors
serializeConnectionPageInfo. When include_cursors is false, both
startCursor and endCursor are emitted as null.
pub fn serialize_connection_with_field_serializers(
field: ast.Selection,
config: SerializeConnectionConfig(a),
serialize_page_info: fn(ast.Selection) -> option.Option(
json.Json,
),
serialize_unknown_field: fn(ast.Selection) -> json.Json,
) -> json.Json
Full connection serializer with hooks matching the TS helper’s
serializePageInfo and serializeUnknownField options.
pub fn serialize_empty_connection(
field: ast.Selection,
options: SelectedFieldOptions,
) -> json.Json
Serialize an empty connection: nodes and edges become empty
arrays, pageInfo reflects the empty page, anything else becomes
null. Equivalent to calling the TS serializeConnection with
items: [], but specialised for the empty case to avoid pulling
in the rest of the pagination machinery.
pub fn serialize_empty_connection_page_info(
page_info_field: ast.Selection,
options: SelectedFieldOptions,
) -> json.Json
Serialize a connection’s pageInfo block when there are no items —
the only shape the events handler ever needs. Mirrors
serializeEmptyConnectionPageInfo (which delegates to
serializeConnectionPageInfo with empty items).
pub fn source_to_json(value: SourceValue) -> json.Json
Emit a SourceValue as JSON. Used both for terminal projection
results and as the fallback when a leaf field has no selection set.
pub fn src_object(
entries: List(#(String, SourceValue)),
) -> SourceValue
Convenience constructor matching the literal-object shorthand the TS
handlers use. Each entry is (name, value) and is inserted in
list order; later entries with the same key win, matching JS object
literal semantics.