The shared core for the highly customizable and versatile GraphQL client
—
Execute GraphQL queries, mutations, and subscriptions with full type safety and reactive streams. Operations provide both Promise-based and stream-based APIs for handling GraphQL requests.
Execute GraphQL queries with caching support and synchronous cache reads.
/**
* Execute a GraphQL query operation
* @param query - GraphQL document or query string
* @param variables - Variables for the query
* @param context - Optional operation context overrides
* @returns OperationResultSource with query results
*/
query<Data = any, Variables extends AnyVariables = AnyVariables>(
query: DocumentInput<Data, Variables>,
variables: Variables,
context?: Partial<OperationContext>
): OperationResultSource<OperationResult<Data, Variables>>;
/**
* Read cached query result synchronously
* @param query - GraphQL document or query string
* @param variables - Variables for the query
* @param context - Optional operation context overrides
* @returns Cached result or null if not available
*/
readQuery<Data = any, Variables extends AnyVariables = AnyVariables>(
query: DocumentInput<Data, Variables>,
variables: Variables,
context?: Partial<OperationContext>
): OperationResult<Data, Variables> | null;
/**
* Execute query from a pre-created GraphQLRequest
* @param request - Pre-created GraphQL request
* @param opts - Optional operation context overrides
* @returns OperationResultSource with query results
*/
executeQuery<Data = any, Variables extends AnyVariables = AnyVariables>(
request: GraphQLRequest<Data, Variables>,
opts?: Partial<OperationContext> | undefined
): OperationResultSource<OperationResult<Data, Variables>>;Usage Examples:
import { createClient, gql, cacheExchange, fetchExchange } from "@urql/core";
const client = createClient({
url: "https://api.example.com/graphql",
exchanges: [cacheExchange, fetchExchange],
});
const GetUserQuery = gql`
query GetUser($id: ID!) {
user(id: $id) {
id
name
email
}
}
`;
// Promise-based query execution
const result = await client.query(GetUserQuery, { id: "123" }).toPromise();
if (result.error) {
console.error("Query failed:", result.error);
} else {
console.log("User:", result.data.user);
}
// Stream-based query (for cache updates)
const { unsubscribe } = client.query(GetUserQuery, { id: "123" }).subscribe(result => {
if (result.data) {
console.log("User data updated:", result.data.user);
}
});
// Check cache synchronously
const cached = client.readQuery(GetUserQuery, { id: "123" });
if (cached && !cached.stale) {
console.log("Fresh cached data:", cached.data.user);
}Execute GraphQL mutations with automatic cache invalidation.
/**
* Execute a GraphQL mutation operation
* @param query - GraphQL document or mutation string
* @param variables - Variables for the mutation
* @param context - Optional operation context overrides
* @returns OperationResultSource with mutation results
*/
mutation<Data = any, Variables extends AnyVariables = AnyVariables>(
query: DocumentInput<Data, Variables>,
variables: Variables,
context?: Partial<OperationContext>
): OperationResultSource<OperationResult<Data, Variables>>;
/**
* Execute mutation from a pre-created GraphQLRequest
* @param request - Pre-created GraphQL request
* @param opts - Optional operation context overrides
* @returns OperationResultSource with mutation results
*/
executeMutation<Data = any, Variables extends AnyVariables = AnyVariables>(
request: GraphQLRequest<Data, Variables>,
opts?: Partial<OperationContext> | undefined
): OperationResultSource<OperationResult<Data, Variables>>;Usage Examples:
const UpdateUserMutation = gql`
mutation UpdateUser($id: ID!, $input: UserInput!) {
updateUser(id: $id, input: $input) {
id
name
email
updatedAt
}
}
`;
// Execute mutation
const result = await client.mutation(UpdateUserMutation, {
id: "123",
input: { name: "New Name", email: "new@example.com" }
}).toPromise();
if (result.error) {
console.error("Mutation failed:", result.error);
} else {
console.log("User updated:", result.data.updateUser);
}
// Mutation with cache invalidation hints
await client.mutation(
UpdateUserMutation,
{ id: "123", input: { name: "Updated Name" } },
{ additionalTypenames: ['User'] }
).toPromise();Execute GraphQL subscriptions for real-time data updates.
/**
* Execute a GraphQL subscription operation
* @param query - GraphQL document or subscription string
* @param variables - Variables for the subscription
* @param context - Optional operation context overrides
* @returns OperationResultSource with subscription results
*/
subscription<Data = any, Variables extends AnyVariables = AnyVariables>(
query: DocumentInput<Data, Variables>,
variables: Variables,
context?: Partial<OperationContext>
): OperationResultSource<OperationResult<Data, Variables>>;
/**
* Execute subscription from a pre-created GraphQLRequest
* @param request - Pre-created GraphQL request
* @param opts - Optional operation context overrides
* @returns OperationResultSource with subscription results
*/
executeSubscription<Data = any, Variables extends AnyVariables = AnyVariables>(
request: GraphQLRequest<Data, Variables>,
opts?: Partial<OperationContext> | undefined
): OperationResultSource<OperationResult<Data, Variables>>;Usage Examples:
import { pipe, subscribe } from 'wonka';
const ChatMessagesSubscription = gql`
subscription ChatMessages($roomId: ID!) {
messageAdded(roomId: $roomId) {
id
text
user {
id
name
}
createdAt
}
}
`;
// Subscribe to real-time updates
const { unsubscribe } = pipe(
client.subscription(ChatMessagesSubscription, { roomId: "room-123" }),
subscribe(result => {
if (result.data) {
console.log("New message:", result.data.messageAdded);
}
if (result.error) {
console.error("Subscription error:", result.error);
}
})
);
// Unsubscribe when done
setTimeout(() => unsubscribe(), 30000);Advanced operation creation and execution for custom use cases.
/**
* Create an operation from a request and context
* @param kind - Type of GraphQL operation
* @param request - GraphQL request object
* @param opts - Optional context overrides
* @returns Created operation
*/
createRequestOperation<Data = any, Variables extends AnyVariables = AnyVariables>(
kind: OperationType,
request: GraphQLRequest<Data, Variables>,
opts?: Partial<OperationContext> | undefined
): Operation<Data, Variables>;
/**
* Execute an operation and return result source
* @param operation - Operation to execute
* @returns OperationResultSource with results
*/
executeRequestOperation<Data = any, Variables extends AnyVariables = AnyVariables>(
operation: Operation<Data, Variables>
): OperationResultSource<OperationResult<Data, Variables>>;
/**
* Re-execute an operation if it has active consumers
* @param operation - Operation to re-execute
*/
reexecuteOperation(operation: Operation): void;Usage Examples:
import { createRequest } from "@urql/core";
// Create request and operation manually
const request = createRequest(GetUserQuery, { id: "123" });
const operation = client.createRequestOperation('query', request, {
requestPolicy: 'network-only'
});
// Execute the operation
const result = await client.executeRequestOperation(operation).toPromise();
// Re-execute operation (useful in exchanges)
client.reexecuteOperation(operation);type OperationType = 'subscription' | 'query' | 'mutation' | 'teardown';
interface Operation<Data = any, Variables extends AnyVariables = AnyVariables>
extends GraphQLRequest<Data, Variables> {
readonly kind: OperationType;
context: OperationContext;
}
interface GraphQLRequest<Data = any, Variables extends AnyVariables = AnyVariables> {
key: number;
query: DocumentNode | PersistedDocument | TypedDocumentNode<Data, Variables>;
variables: Variables;
extensions?: RequestExtensions | undefined;
}interface OperationResult<Data = any, Variables extends AnyVariables = AnyVariables> {
/** The operation this result is for */
operation: Operation<Data, Variables>;
/** GraphQL response data */
data?: Data;
/** Combined GraphQL and network errors */
error?: CombinedError;
/** Additional response metadata */
extensions?: Record<string, any>;
/** Whether result is stale and will be updated */
stale: boolean;
/** Whether more results will follow (subscriptions/streaming) */
hasNext: boolean;
}
type OperationResultSource<T extends OperationResult> = Source<T> &
PromiseLike<T> & {
/** Convert to Promise for single result */
toPromise(): Promise<T>;
/** Subscribe to result stream */
subscribe(onResult: (value: T) => void): Subscription;
};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;
}
type AnyVariables = { [prop: string]: any } | void | undefined;interface RequestExtensions {
/** Automatic Persisted Queries support */
persistedQuery?: PersistedRequestExtensions;
[extension: string]: any;
}
interface PersistedRequestExtensions {
version?: 1;
sha256Hash: string;
miss?: boolean;
}type OperationInstance = number & {
readonly _opaque: unique symbol;
};Install with Tessl CLI
npx tessl i tessl/npm-urql--core