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

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

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.

Search Document