The shared core for the highly customizable and versatile GraphQL client
—
Utility functions for GraphQL document parsing, request creation, result processing, and various helper operations that support the core functionality of @urql/core.
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
}
}
`;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 commentsCreate 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();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();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);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"]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 callstype 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;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;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;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;
}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 parametersInstall with Tessl CLI
npx tessl i tessl/npm-urql--core