CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-urql--core

The shared core for the highly customizable and versatile GraphQL client

Pending
Overview
Eval results
Files

utilities.mddocs/

Utilities and Parsing

Utility functions for GraphQL document parsing, request creation, result processing, and various helper operations that support the core functionality of @urql/core.

Capabilities

GraphQL Document Parsing

Parse GraphQL documents with fragment merging and caching optimizations.

/**
 * Parse GraphQL documents with fragment merging and deduplication
 * @param strings - Template strings array
 * @param interpolations - Interpolated document fragments or strings
 * @returns Parsed and cached TypedDocumentNode
 */
function gql<Data = any, Variables extends AnyVariables = AnyVariables>(
  strings: TemplateStringsArray,
  ...interpolations: Array<TypedDocumentNode | DocumentNode | string>
): TypedDocumentNode<Data, Variables>;

/**
 * Parse GraphQL document from string
 * @param string - GraphQL document string
 * @returns Parsed TypedDocumentNode
 */
function gql<Data = any, Variables extends AnyVariables = AnyVariables>(
  string: string
): TypedDocumentNode<Data, Variables>;

Usage Examples:

import { gql } from "@urql/core";

// Template literal parsing with fragments
const UserFragment = gql`
  fragment UserInfo on User {
    id
    name
    email
  }
`;

const GetUserQuery = gql`
  query GetUser($id: ID!) {
    user(id: $id) {
      ...UserInfo
    }
  }
  ${UserFragment}
`;

// String parsing
const simpleQuery = gql(`
  query GetPosts {
    posts {
      id
      title
    }
  }
`);

// With TypeScript generics
interface User {
  id: string;
  name: string;
  email: string;
}

interface GetUserData {
  user: User;
}

interface GetUserVars {
  id: string;
}

const typedQuery = gql<GetUserData, GetUserVars>`
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
      email
    }
  }
`;

String Utilities

Stable string representations for GraphQL variables and documents.

/**
 * A stable stringifier for GraphQL variables objects
 * @param x - Any JSON-like data
 * @param includeFiles - Whether to include File/Blob objects
 * @returns A stable JSON string
 */
function stringifyVariables(x: any, includeFiles?: boolean): string;

/**
 * A cached printing function for GraphQL documents  
 * @param node - A string of a document or a DocumentNode
 * @returns A normalized printed string of the passed GraphQL document
 */
function stringifyDocument(node: string | DefinitionNode | DocumentNode): string;

Usage Examples:

import { stringifyVariables, stringifyDocument, gql } from "@urql/core";

// Stable variable stringification (for caching keys)
const variables = { id: "123", filters: { name: "Alice" } };
const key = stringifyVariables(variables);
console.log(key); // {"filters":{"name":"Alice"},"id":"123"}

// Same variables always produce same string
const sameKey = stringifyVariables({ filters: { name: "Alice" }, id: "123" });
console.log(key === sameKey); // true

// Document stringification with comment removal
const query = gql`
  # This is a comment
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
    }
  }
`;

const queryString = stringifyDocument(query);
console.log(queryString); // Clean query without comments

Request Creation

Create GraphQL requests with automatic key generation and caching.

/**
 * Create a GraphQL request with generated key for caching
 * @param query - GraphQL document or string
 * @param variables - Variables for the request
 * @param extensions - Optional request extensions (APQ, etc.)
 * @returns GraphQL request with unique key
 */
function createRequest<Data = any, Variables extends AnyVariables = AnyVariables>(
  query: DocumentInput<Data, Variables>,
  variables: Variables,
  extensions?: RequestExtensions | undefined
): GraphQLRequest<Data, Variables>;

/**
 * Extract operation name from GraphQL document
 * @param document - GraphQL document
 * @returns Operation name or undefined
 */
function getOperationName(document: DocumentNode): string | undefined;

Usage Examples:

import { createRequest, getOperationName, gql } from "@urql/core";

const GetUserQuery = gql`
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
    }
  }
`;

// Create request with variables
const request = createRequest(GetUserQuery, { id: "123" });
console.log(request.key); // Unique hash for caching
console.log(request.variables); // { id: "123" }

// Extract operation name
const operationName = getOperationName(GetUserQuery);
console.log(operationName); // "GetUser"

// Use with client operations
const result = await client.executeQuery(request).toPromise();

Operation Management

Create and manipulate operations with context and metadata.

/**
 * Create or copy an operation with context
 * @param kind - Type of operation
 * @param request - GraphQL request
 * @param context - Operation context
 * @returns Operation ready for execution
 */
function makeOperation<Data = any, Variables extends AnyVariables = AnyVariables>(
  kind: OperationType,
  request: GraphQLRequest<Data, Variables>,
  context: OperationContext
): Operation<Data, Variables>;

Usage Examples:

import { makeOperation, createRequest } from "@urql/core";

const request = createRequest(GetUserQuery, { id: "123" });

// Create a query operation
const operation = makeOperation('query', request, {
  url: "https://api.example.com/graphql",
  requestPolicy: 'cache-first',
  fetchOptions: {
    headers: { authorization: 'Bearer token' }
  }
});

// Use in custom exchange
const result = await client.executeRequestOperation(operation).toPromise();

Result Processing

Convert and manipulate GraphQL execution results.

/**
 * Convert ExecutionResult to OperationResult
 * @param operation - Source operation
 * @param result - Raw GraphQL execution result
 * @param response - Optional fetch response
 * @returns Processed OperationResult
 */
function makeResult<Data = any, Variables extends AnyVariables = AnyVariables>(
  operation: Operation<Data, Variables>,
  result: ExecutionResult,
  response?: Response
): OperationResult<Data, Variables>;

/**
 * Create an error OperationResult
 * @param operation - Source operation
 * @param error - Error instance
 * @param response - Optional execution result
 * @returns Error OperationResult
 */
function makeErrorResult<Data = any, Variables extends AnyVariables = AnyVariables>(
  operation: Operation<Data, Variables>,
  error: Error | CombinedError,
  response?: ExecutionResult
): OperationResult<Data, Variables>;

/**
 * Merge incremental delivery patches into result data
 * @param prevResult - Previous result to patch
 * @param nextResult - New execution result with incremental data
 * @param response - Optional response object
 * @param pending - Optional pending execution result
 * @returns Merged result with combined data
 */
function mergeResultPatch(
  prevResult: OperationResult,
  nextResult: ExecutionResult,
  response?: any,
  pending?: ExecutionResult['pending']
): OperationResult;

Usage Examples:

import { makeResult, makeErrorResult, mergeResultPatch } from "@urql/core";

// Convert raw API response to OperationResult
const executionResult = {
  data: { user: { id: "123", name: "Alice" } }
};

const result = makeResult(operation, executionResult);

// Create error result
const errorResult = makeErrorResult(
  operation,
  new Error("Network failure")
);

// Handle incremental delivery (@defer/@stream)
const initialResult = makeResult(operation, { data: { user: { id: "123" } } });
const patch = makeResult(operation, {
  incremental: [{
    path: ['user'],
    data: { name: "Alice", email: "alice@example.com" }
  }]
});

const mergedResult = mergeResultPatch(initialResult, patch);

Document Processing

Process GraphQL documents for enhanced functionality.

/**
 * Add __typename fields and process directives in GraphQL documents
 * @param document - GraphQL document to format
 * @returns Formatted document with __typename fields
 */
function formatDocument<T extends DocumentNode>(document: T): FormattedNode<T>;

/**
 * Collect all __typename values from result data
 * @param data - GraphQL result data
 * @returns Array of typename strings found
 */
function collectTypenames(data: any): string[];

Usage Examples:

import { formatDocument, collectTypenames, gql } from "@urql/core";

const query = gql`
  query GetUser($id: ID!) {
    user(id: $id) {
      id
      name
      profile {
        bio
      }
    }
  }
`;

// Add __typename fields automatically
const formattedQuery = formatDocument(query);
// Result will include __typename fields for caching

// Extract typenames from result data
const resultData = {
  user: {
    __typename: "User",
    id: "123",
    profile: {
      __typename: "Profile", 
      bio: "Software developer"
    }
  }
};

const typenames = collectTypenames(resultData);
console.log(typenames); // ["User", "Profile"]

Variable Processing

Handle variable serialization and processing for GraphQL requests.

/**
 * Stable JSON stringify for GraphQL variables
 * @param variables - Variables object to stringify
 * @returns Stable string representation
 */
function stringifyVariables(variables: any): string;

/**
 * Stable string representation of GraphQL documents
 * @param document - Document to stringify
 * @returns Cached string representation
 */
function stringifyDocument(document: DocumentNode): string;

Usage Examples:

import { stringifyVariables, stringifyDocument } from "@urql/core";

// Consistent variable serialization (key generation)
const vars1 = { id: "123", name: "Alice" };
const vars2 = { name: "Alice", id: "123" };

console.log(stringifyVariables(vars1) === stringifyVariables(vars2)); // true

// Document caching
const query = gql`query GetUser { user { id } }`;
const docString = stringifyDocument(query);
// Cached for performance on subsequent calls

Types

Document Types

type DocumentInput<Result = { [key: string]: any }, Variables = { [key: string]: any }> = 
  string | DocumentNode | TypedDocumentNode<Result, Variables>;

interface TypedDocumentNode<Result = { [key: string]: any }, Variables = { [key: string]: any }> 
  extends DocumentNode {
  __apiType?: (variables: Variables) => Result;
  __ensureTypesOfVariablesAndResultMatching?: (variables: Variables) => Result;
}

interface PersistedDocument extends DocumentNode {
  documentId?: string;
}

type FormattedNode<Node> = Node extends readonly (infer Child)[]
  ? readonly FormattedNode<Child>[]
  : Node extends ValueNode | TypeNode
    ? Node
    : Node extends { kind: Kind }
      ? {
          [K in Exclude<keyof Node, 'directives' | 'loc'>]: FormattedNode<
            Node[K]
          >;
        } extends infer Node
        ? Node extends {
            kind: Kind.FIELD | Kind.INLINE_FRAGMENT | Kind.FRAGMENT_SPREAD;
          }
          ? Node & {
              _generated?: boolean;
              _directives?: Record<string, DirectiveNode> | undefined;
            }
          : Node
        : Node
      : Node;

Request Types

interface GraphQLRequest<Data = any, Variables extends AnyVariables = AnyVariables> {
  /** Unique cache key for the request */
  key: number;
  /** GraphQL document to execute */
  query: DocumentNode | PersistedDocument | TypedDocumentNode<Data, Variables>;
  /** Variables for the operation */
  variables: Variables;
  /** Additional request extensions */
  extensions?: RequestExtensions | undefined;
}

type AnyVariables = { [prop: string]: any } | void | undefined;

Result Types

interface ExecutionResult {
  /** GraphQL response data */
  data?: null | Record<string, any>;
  /** GraphQL errors from execution */
  errors?: ErrorLike[] | readonly ErrorLike[];
  /** Additional metadata */
  extensions?: Extensions;
  /** Incremental delivery patches */
  incremental?: IncrementalPayload[];
  /** Whether more results will follow */
  hasNext?: boolean;
  /** Pending incremental results */
  pending?: readonly PendingIncrementalResult[];
}

type ErrorLike = Partial<GraphQLError> | Error;

Incremental Delivery Types

interface IncrementalPayload {
  /** Label for the incremental payload */
  label?: string | null;
  /** Path where to apply the patch */
  path?: readonly (string | number)[];
  /** ID for pending deferred results */
  id?: string;
  /** Sub-path from defer/stream fragment */
  subPath?: readonly (string | number)[];
  /** Data to patch into result */
  data?: Record<string, unknown> | null;
  /** Items to patch into array */
  items?: readonly unknown[] | null;
  /** Errors from incremental payload */
  errors?: ErrorLike[] | readonly ErrorLike[];
  /** Additional metadata */
  extensions?: Extensions;
}

Internal Fetch Utilities

Advanced HTTP transport utilities for custom fetch implementations and exchanges.

/**
 * Create GraphQL HTTP request body from operation
 * @param operation - GraphQL operation to convert
 * @returns Request body for HTTP transport
 */
function makeFetchBody(operation: Operation): FetchBody;

/**
 * Create request URL for GraphQL operation (with GET support)
 * @param operation - GraphQL operation
 * @param body - Request body (for URL encoding in GET requests)
 * @returns Complete request URL
 */
function makeFetchURL(operation: Operation, body?: FetchBody): string;

/**
 * Create fetch RequestInit options for GraphQL operation
 * @param operation - GraphQL operation
 * @param body - Request body
 * @returns RequestInit options for fetch call
 */
function makeFetchOptions(operation: Operation, body?: FetchBody): RequestInit;

/**
 * HTTP transport with streaming and multipart response support
 * @param operation - GraphQL operation to execute
 * @param url - GraphQL endpoint URL
 * @param fetchOptions - Fetch request options
 * @param fetch - Fetch implementation
 * @returns Source of ExecutionResults
 */
function makeFetchSource(
  operation: Operation,
  url: string,
  fetchOptions: RequestInit,
  fetch: typeof globalThis.fetch
): Source<ExecutionResult>;

interface FetchBody {
  query: string;
  variables?: any;
  operationName?: string;
  extensions?: any;
}

Usage Examples:

import { 
  makeFetchBody, 
  makeFetchURL, 
  makeFetchOptions, 
  makeFetchSource 
} from "@urql/core/internal";

// Custom fetch exchange implementation
const customFetchExchange: Exchange = ({ forward }) => ops$ => {
  return pipe(
    ops$,
    filter(operation => operation.kind !== 'teardown'),
    mergeMap(operation => {
      // Create request components
      const body = makeFetchBody(operation);
      const url = makeFetchURL(operation, body);
      const fetchOptions = makeFetchOptions(operation, body);
      
      // Use streaming fetch source
      return makeFetchSource(
        operation,
        url,
        fetchOptions,
        operation.context.fetch || fetch
      );
    })
  );
};

// GET request handling
const operation = makeOperation('query', request, {
  url: "https://api.example.com/graphql",
  preferGetMethod: true
});

const body = makeFetchBody(operation);
const getUrl = makeFetchURL(operation, body);
// URL will include query and variables as parameters

Install with Tessl CLI

npx tessl i tessl/npm-urql--core

docs

client.md

errors.md

exchanges.md

index.md

internal.md

operations.md

utilities.md

tile.json