@urql/core
Version:
The shared core for the highly customizable and versatile GraphQL client
974 lines (970 loc) • 69.2 kB
TypeScript
import * as GraphQLWeb from '@0no-co/graphql.web';
import { GraphQLError as GraphQLError$1, ValueNode, TypeNode, Kind, DirectiveNode } from '@0no-co/graphql.web';
/*@ts-ignore*/
import * as GraphQL from 'graphql';
import { Source, Subscription } from 'wonka';
type OrNever<T> = void extends T ? never : T;
type GraphQLError = GraphQLWeb.GraphQLError | OrNever<GraphQL.GraphQLError>;
type DocumentNode = GraphQLWeb.DocumentNode | OrNever<GraphQL.DocumentNode>;
type DefinitionNode = GraphQLWeb.DefinitionNode | OrNever<GraphQL.DefinitionNode>;
/** Configuration options passed when creating a new {@link Client}.
*
* @remarks
* The `ClientOptions` are passed when creating a new {@link Client}, and
* are used to instantiate the pipeline of {@link Exchange | Exchanges}, configure
* options used to initialize {@link OperationContext | OperationContexts}, or to
* change the general behaviour of the {@link Client}.
*/
interface ClientOptions {
/** Target URL used by fetch exchanges to make GraphQL API requests to.
*
* @remarks
* This is the URL that fetch exchanges will call to make GraphQL API requests.
* This value is copied to {@link OperationContext.url}.
*/
url: string;
/** Additional options used by fetch exchanges that'll be passed to the `fetch` call on API requests.
*
* @remarks
* The options in this object or an object returned by a callback function will be merged into the
* {@link RequestInit} options passed to the `fetch` call.
*
* Hint: If you're trying to implement more complex changes per {@link Operation}, it's worth considering
* to use the {@link mapExchange} instead, which allows you to change `Operation`s and `OperationResult`s.
*
* Hint: If you're trying to use this as a function for authentication, consider checking out
* `@urql/exchange-auth` instead, which allows you to handle refresh auth flows, and more
* complex auth flows.
*
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/fetch} for a description of this object.
*/
fetchOptions?: RequestInit | (() => RequestInit);
/** A `fetch` function polyfill used by fetch exchanges to make API calls.
*
* @remarks
* This is the fetch polyfill used by any fetch exchange to make an API request. By default, when this
* option isn't set, any fetch exchange will attempt to use the globally available `fetch` function
* to make a request instead.
*
* It's recommended to only pass a polyfill, if any of the environments you're running the {@link Client}
* in don't support the Fetch API natively.
*
* Hint: If you're using the "Incremental Delivery" multipart spec, for instance with `@defer` directives,
* you're better off using the native `fetch` function, or must ensure that your polyfill supports streamed
* results. However, a "Streaming requests unsupported" error will be thrown, to let you know that your `fetch`
* API doesn't support incrementally streamed responses, if this mode is used.
*
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API} for the Fetch API spec.
*/
fetch?: typeof fetch;
/** Allows a subscription to be executed using a `fetch` API request.
*
* @remarks
* If your API supports the `text/event-stream` and/or `multipart/mixed` response protocol, and you use
* this protocol to handle subscriptions, then you may switch this flag to `true`.
*
* This means you won’t have to create a {@link subscriptionExchange} to handle subscriptions with an
* external transport, and will instead be able to use GraphQL over HTTP transports.
*/
fetchSubscriptions?: boolean;
/** A list of `Exchange`s that will be used to create the `Client`'s execution pipeline.
*
* @remarks
* The {@link Client} accepts and composes a list of {@link Exchange | Exchanges} into an “exchange pipeline”
* which receive a stream of {@link Operation | Operations} the `Client` wishes to execute, and return a stream
* of {@link OperationResult | OperationResults}.
*
* This is the basis for how `urql` handles GraphQL operations, and exchanges handle the creation, execution,
* and control flow of exchanges for the `Client`.
*
* To easily get started you should consider using the {@link cacheExchange} and {@link fetchExchange}
* these are all exported from the core package.
*
* @see {@link https://urql.dev/goto/docs/architecture/#the-client-and-exchanges} for more information
* on what `Exchange`s are and how they work.
*/
exchanges: Exchange[];
/** A configuration flag indicating whether support for "Suspense" is activated.
*
* @remarks
* This configuration flag is only relevant for using `urql` with the React or Preact bindings.
* When activated it allows `useQuery` to "suspend" instead of returning a loading state, which
* will stop updates in a querying component and instead cascade
* to a higher suspense boundary for a loading state.
*
* Hint: While, when this option is enabled, by default all `useQuery` hooks will suspense, you can
* disable Suspense selectively for each hook.
*
* @see {@link https://beta.reactjs.org/blog/2022/03/29/react-v18#new-suspense-features} for more information on React Suspense.
*/
suspense?: boolean;
/** The request and caching strategy that all `Operation`s on this `Client` will use by default.
*
* @remarks
* The {@link RequestPolicy} instructs cache exchanges how to use and treat their cached results.
* By default `cache-first` is set and used, which will use cache results, and only make an API request
* on a cache miss.
*
* The `requestPolicy` can be overriden per operation, since it's added to the {@link OperationContext},
* which allows you to change the policy per `Operation`, rather than changing it by default here.
*
* Hint: We don’t recommend changing this from the default `cache-first` option, unless you know what
* you‘re doing. Setting this to `cache-and-network` is not recommend and may not lead to the behaviour
* you expect. If you’re looking to always update your cache frequently, use `@urql/exchange-request-policy`
* instead.
*/
requestPolicy?: RequestPolicy;
/** Instructs fetch exchanges to use a GET request.
*
* @remarks
* This changes the {@link OperationContext.preferGetMethod} option, which tells fetch exchanges
* to use GET requests for queries instead of POST requests.
*
* When set to `true` or `'within-url-limit'`, built-in fetch exchanges will always attempt to send query
* operations as GET requests, unless the resulting URL exceeds a length of 2,048 characters.
* If you want to bypass this restriction, set this option to `'force'` instead, to always send GET.
* requests for queries.
*/
preferGetMethod?: boolean | 'force' | 'within-url-limit';
}
/** The `Client` is the central hub for your GraphQL operations and holds `urql`'s state.
*
* @remarks
* The `Client` manages your active GraphQL operations and their state, and contains the
* {@link Exchange} pipeline to execute your GraphQL operations.
*
* It contains methods that allow you to execute GraphQL operations manually, but the `Client`
* is also interacted with by bindings (for React, Preact, Vue, Svelte, etc) to execute GraphQL
* operations.
*
* While {@link Exchange | Exchanges} are ultimately responsible for the control flow of operations,
* sending API requests, and caching, the `Client` still has the important responsibility for
* creating operations, managing consumers of active operations, sharing results for operations,
* and more tasks as a “central hub”.
*
* @see {@link https://urql.dev/goto/docs/architecture/#requests-and-operations-on-the-client} for more information
* on what the `Client` is and does.
*/
interface Client {
new (options: ClientOptions): Client;
/** Exposes the stream of `Operation`s that is passed to the `Exchange` pipeline.
*
* @remarks
* This is a Wonka {@link Source} that issues the {@link Operation | Operations} going into
* the exchange pipeline.
* @internal
*/
operations$: Source<Operation>;
/** Flag indicating whether support for “Suspense” is activated.
*
* @remarks
* This flag indicates whether support for “Suspense” has been activated via the
* {@link ClientOptions.suspense} flag.
*
* When this is enabled, the {@link Client} itself doesn’t function any differently, and the flag
* only serves as an instructions for the React/Preact bindings to change their behaviour.
*
* @see {@link ClientOptions.suspense} for more information.
* @internal
*/
suspense: boolean;
/** Dispatches an `Operation` to the `Exchange` pipeline, if this `Operation` is active.
*
* @remarks
* This method is frequently used in {@link Exchange | Exchanges}, for instance caches, to reexecute
* an operation. It’s often either called because an `Operation` will need to be queried against the
* cache again, if a cache result has changed or been invalidated, or it’s called with an {@link Operation}'s
* {@link RequestPolicy} set to `network-only` to issue a network request.
*
* This method will only dispatch an {@link Operation} if it has active consumers, meaning,
* active subscribers to the sources of {@link OperationResult}. For instance, if no bindings
* (e.g. `useQuery`) is subscribed to the `Operation`, then `reexecuteOperation` will do nothing.
*
* All operations are put onto a queue and executed after a micro-tick. The queue of operations is
* emptied eagerly and synchronously, similar to a trampoline scheduler.
*/
reexecuteOperation(operation: Operation): void;
/** Subscribe method to add an event listener to debug events.
*
* @param onEvent - A callback called with new debug events, each time an `Exchange` issues them.
* @returns A Wonka {@link Subscription} which is used to optionally terminate the event listener.
*
* @remarks
* This is a method that's only available in development, and allows the `urql-devtools` to receive
* to debug events that are issued by exchanges, giving the devtools more information about the flow
* and execution of {@link Operation | Operations}.
*
* @see {@link DebugEventTypes} for a description of all debug events.
* @internal
*/
subscribeToDebugTarget?(onEvent: (event: DebugEvent) => void): Subscription;
/** Creates an `Operation` from a `GraphQLRequest` and optionally, overriding `OperationContext` options.
*
* @param kind - The {@link OperationType} of GraphQL operation, i.e. `query`, `mutation`, or `subscription`.
* @param request - A {@link GraphQLRequest} created prior to calling this method.
* @param opts - {@link OperationContext} options that'll override and be merged with options from the {@link ClientOptions}.
* @returns An {@link Operation} created from the parameters.
*
* @remarks
* This method is expected to be called with a `kind` set to the `OperationType` of the GraphQL operation.
* In development, this is enforced by checking that the GraphQL document's operation matches this `kind`.
*
* Hint: While bindings will use this method combined with {@link Client.executeRequestOperation}, if
* you’re executing operations manually, you can use one of the other convenience methods instead.
*
* @see {@link Client.executeRequestOperation} for the method used to execute operations.
* @see {@link createRequest} which creates a `GraphQLRequest` from a `DocumentNode` and variables.
*/
createRequestOperation<Data = any, Variables extends AnyVariables = AnyVariables>(kind: OperationType, request: GraphQLRequest<Data, Variables>, opts?: Partial<OperationContext> | undefined): Operation<Data, Variables>;
/** Creates a `Source` that executes the `Operation` and issues `OperationResult`s for this `Operation`.
*
* @param operation - {@link Operation} that will be executed.
* @returns A Wonka {@link Source} of {@link OperationResult | OperationResults} for the passed `Operation`.
*
* @remarks
* The {@link Operation} will be dispatched to the pipeline of {@link Exchange | Exchanges} when
* subscribing to the returned {@link Source}, which issues {@link OperationResult | OperationResults}
* belonging to this `Operation`.
*
* Internally, {@link OperationResult | OperationResults} are filtered and deliverd to this source by
* comparing the {@link Operation.key} on the operation and the {@link OperationResult.operation}.
* For mutations, the {@link OperationContext._instance | `OperationContext._instance`} will additionally be compared, since two mutations
* with, even given the same variables, will have two distinct results and will be executed separately.
*
* The {@link Client} dispatches the {@link Operation} when we subscribe to the returned {@link Source}
* and will from then on consider the `Operation` as “active” until we unsubscribe. When all consumers unsubscribe
* from an `Operation` and it becomes “inactive” a `teardown` signal will be dispatched to the
* {@link Exchange | Exchanges}.
*
* Hint: While bindings will use this method, if you’re executing operations manually, you can use one
* of the other convenience methods instead, like {@link Client.executeQuery} et al.
*/
executeRequestOperation<Data = any, Variables extends AnyVariables = AnyVariables>(operation: Operation<Data, Variables>): OperationResultSource<OperationResult<Data, Variables>>;
/** Creates a `Source` that executes the GraphQL query operation created from the passed parameters.
*
* @param query - a GraphQL document containing the query operation that will be executed.
* @param variables - the variables used to execute the operation.
* @param opts - {@link OperationContext} options that'll override and be merged with options from the {@link ClientOptions}.
* @returns A {@link OperationResultSource} issuing the {@link OperationResult | OperationResults} for the GraphQL operation.
*
* @remarks
* The `Client.query` method is useful to programmatically create and issue a GraphQL query operation.
* It automatically calls {@link createRequest}, {@link client.createRequestOperation}, and
* {@link client.executeRequestOperation} for you, and is a convenience method.
*
* Since it returns a {@link OperationResultSource} it may be chained with a `toPromise()` call to only
* await a single result in an async function.
*
* Hint: This is the recommended way to create queries programmatically when not using the bindings,
* or when you’re trying to get a single, promisified result.
*
* @example
* ```ts
* const getBookQuery = gql`
* query GetBook($id: ID!) {
* book(id: $id) {
* id
* name
* author {
* name
* }
* }
* }
* `;
*
* async function getBook(id) {
* const result = await client.query(getBookQuery, { id }).toPromise();
* if (result.error) {
* throw result.error;
* }
*
* return result.data.book;
* }
* ```
*/
query<Data = any, Variables extends AnyVariables = AnyVariables>(query: DocumentInput<Data, Variables>, variables: Variables, context?: Partial<OperationContext>): OperationResultSource<OperationResult<Data, Variables>>;
/** Returns the first synchronous result a `Client` provides for a given operation.
*
* @param query - a GraphQL document containing the query operation that will be executed.
* @param variables - the variables used to execute the operation.
* @param opts - {@link OperationContext} options that'll override and be merged with options from the {@link ClientOptions}.
* @returns An {@link OperationResult} if one became available synchronously or `null`.
*
* @remarks
* The `Client.readQuery` method returns a result synchronously or defaults to `null`. This is useful
* as it limits the result for a query operation to whatever the cache {@link Exchange} of a {@link Client}
* had stored and available at that moment.
*
* In `urql`, it's expected that cache exchanges return their results synchronously. The bindings
* and this method exploit this by using synchronous results, like these, to check what data is already
* in the cache.
*
* This method is similar to what all bindings do to synchronously provide the initial state for queries,
* regardless of whether effects afterwards that subscribe to the query operation update this state synchronously
* or asynchronously.
*/
readQuery<Data = any, Variables extends AnyVariables = AnyVariables>(query: DocumentInput<Data, Variables>, variables: Variables, context?: Partial<OperationContext>): OperationResult<Data, Variables> | null;
/** Creates a `Source` that executes the GraphQL query operation for the passed `GraphQLRequest`.
*
* @param query - a {@link GraphQLRequest}
* @param opts - {@link OperationContext} options that'll override and be merged with options from the {@link ClientOptions}.
* @returns A {@link PromisifiedSource} issuing the {@link OperationResult | OperationResults} for the GraphQL operation.
*
* @remarks
* The `Client.executeQuery` method is used to programmatically issue a GraphQL query operation.
* It automatically calls {@link client.createRequestOperation} and {@link client.executeRequestOperation} for you,
* but requires you to create a {@link GraphQLRequest} using {@link createRequest} yourself first.
*
* @see {@link Client.query} for a method that doesn't require calling {@link createRequest} yourself.
*/
executeQuery<Data = any, Variables extends AnyVariables = AnyVariables>(query: GraphQLRequest<Data, Variables>, opts?: Partial<OperationContext> | undefined): OperationResultSource<OperationResult<Data, Variables>>;
/** Creates a `Source` that executes the GraphQL subscription operation created from the passed parameters.
*
* @param query - a GraphQL document containing the subscription operation that will be executed.
* @param variables - the variables used to execute the operation.
* @param opts - {@link OperationContext} options that'll override and be merged with options from the {@link ClientOptions}.
* @returns A Wonka {@link Source} issuing the {@link OperationResult | OperationResults} for the GraphQL operation.
*
* @remarks
* The `Client.subscription` method is useful to programmatically create and issue a GraphQL subscription operation.
* It automatically calls {@link createRequest}, {@link client.createRequestOperation}, and
* {@link client.executeRequestOperation} for you, and is a convenience method.
*
* Hint: This is the recommended way to create subscriptions programmatically when not using the bindings.
*
* @example
* ```ts
* import { pipe, subscribe } from 'wonka';
*
* const getNewsSubscription = gql`
* subscription GetNews {
* breakingNews {
* id
* text
* createdAt
* }
* }
* `;
*
* function subscribeToBreakingNews() {
* const subscription = pipe(
* client.subscription(getNewsSubscription, {}),
* subscribe(result => {
* if (result.data) {
* console.log(result.data.breakingNews.text);
* }
* })
* );
*
* return subscription.unsubscribe;
* }
* ```
*/
subscription<Data = any, Variables extends AnyVariables = AnyVariables>(query: DocumentInput<Data, Variables>, variables: Variables, context?: Partial<OperationContext>): OperationResultSource<OperationResult<Data, Variables>>;
/** Creates a `Source` that executes the GraphQL subscription operation for the passed `GraphQLRequest`.
*
* @param query - a {@link GraphQLRequest}
* @param opts - {@link OperationContext} options that'll override and be merged with options from the {@link ClientOptions}.
* @returns A {@link PromisifiedSource} issuing the {@link OperationResult | OperationResults} for the GraphQL operation.
*
* @remarks
* The `Client.executeSubscription` method is used to programmatically issue a GraphQL subscription operation.
* It automatically calls {@link client.createRequestOperation} and {@link client.executeRequestOperation} for you,
* but requires you to create a {@link GraphQLRequest} using {@link createRequest} yourself first.
*
* @see {@link Client.subscription} for a method that doesn't require calling {@link createRequest} yourself.
*/
executeSubscription<Data = any, Variables extends AnyVariables = AnyVariables>(query: GraphQLRequest<Data, Variables>, opts?: Partial<OperationContext> | undefined): OperationResultSource<OperationResult<Data, Variables>>;
/** Creates a `Source` that executes the GraphQL mutation operation created from the passed parameters.
*
* @param query - a GraphQL document containing the mutation operation that will be executed.
* @param variables - the variables used to execute the operation.
* @param opts - {@link OperationContext} options that'll override and be merged with options from the {@link ClientOptions}.
* @returns A {@link PromisifiedSource} issuing the {@link OperationResult | OperationResults} for the GraphQL operation.
*
* @remarks
* The `Client.mutation` method is useful to programmatically create and issue a GraphQL mutation operation.
* It automatically calls {@link createRequest}, {@link client.createRequestOperation}, and
* {@link client.executeRequestOperation} for you, and is a convenience method.
*
* Since it returns a {@link PromisifiedSource} it may be chained with a `toPromise()` call to only
* await a single result in an async function. Since mutations will only typically issue one result,
* using this method is recommended.
*
* Hint: This is the recommended way to create mutations programmatically when not using the bindings,
* or when you’re trying to get a single, promisified result.
*
* @example
* ```ts
* const createPostMutation = gql`
* mutation CreatePost($text: String!) {
* createPost(text: $text) {
* id
* text
* }
* }
* `;
*
* async function createPost(text) {
* const result = await client.mutation(createPostMutation, {
* text,
* }).toPromise();
* if (result.error) {
* throw result.error;
* }
*
* return result.data.createPost;
* }
* ```
*/
mutation<Data = any, Variables extends AnyVariables = AnyVariables>(query: DocumentInput<Data, Variables>, variables: Variables, context?: Partial<OperationContext>): OperationResultSource<OperationResult<Data, Variables>>;
/** Creates a `Source` that executes the GraphQL mutation operation for the passed `GraphQLRequest`.
*
* @param query - a {@link GraphQLRequest}
* @param opts - {@link OperationContext} options that'll override and be merged with options from the {@link ClientOptions}.
* @returns A {@link PromisifiedSource} issuing the {@link OperationResult | OperationResults} for the GraphQL operation.
*
* @remarks
* The `Client.executeMutation` method is used to programmatically issue a GraphQL mutation operation.
* It automatically calls {@link client.createRequestOperation} and {@link client.executeRequestOperation} for you,
* but requires you to create a {@link GraphQLRequest} using {@link createRequest} yourself first.
*
* @see {@link Client.mutation} for a method that doesn't require calling {@link createRequest} yourself.
*/
executeMutation<Data = any, Variables extends AnyVariables = AnyVariables>(query: GraphQLRequest<Data, Variables>, opts?: Partial<OperationContext> | undefined): OperationResultSource<OperationResult<Data, Variables>>;
}
declare const Client: new (opts: ClientOptions) => Client;
/** Accepts `ClientOptions` and creates a `Client`.
* @param opts - A {@link ClientOptions} objects with options for the `Client`.
* @returns A {@link Client} instantiated with `opts`.
*/
declare const createClient: (opts: ClientOptions) => Client;
/** An abstracted `Error` that provides either a `networkError` or `graphQLErrors`.
*
* @remarks
* During a GraphQL request, either the request can fail entirely, causing a network error,
* or the GraphQL execution or fields can fail, which will cause an {@link ExecutionResult}
* to contain an array of GraphQL errors.
*
* The `CombinedError` abstracts and normalizes both failure cases. When {@link OperationResult.error}
* is set to this error, the `CombinedError` abstracts all errors, making it easier to handle only
* a subset of error cases.
*
* @see {@link https://urql.dev/goto/docs/basics/errors} for more information on handling
* GraphQL errors and the `CombinedError`.
*/
declare class CombinedError extends Error {
name: string;
message: string;
/** A list of GraphQL errors rehydrated from a {@link ExecutionResult}.
*
* @remarks
* If an {@link ExecutionResult} received from the API contains a list of errors,
* the `CombinedError` will rehydrate them, normalize them to
* {@link GraphQLError | GraphQLErrors} and list them here.
* An empty list indicates that no GraphQL error has been sent by the API.
*/
graphQLErrors: GraphQLError$1[];
/** Set to an error, if a GraphQL request has failed outright.
*
* @remarks
* A GraphQL over HTTP request may fail and not reach the API. Any error that
* prevents a GraphQl request outright, will be considered a “network error” and
* set here.
*/
networkError?: Error;
/** Set to the {@link Response} object a fetch exchange received.
*
* @remarks
* If a built-in fetch {@link Exchange} is used in `urql`, this may
* be set to the {@link Response} object of the Fetch API response.
* However, since `urql` doesn’t assume that all users will use HTTP
* as the only or exclusive transport for GraphQL this property is
* neither typed nor guaranteed and may be re-used for other purposes
* by non-fetch exchanges.
*
* Hint: It can be useful to use `response.status` here, however, if
* you plan on relying on this being a {@link Response} in your app,
* which it is by default, then make sure you add some extra checks
* before blindly assuming so!
*/
response?: any;
constructor(input: {
networkError?: Error;
graphQLErrors?: Array<string | ErrorLike>;
response?: any;
});
toString(): string;
}
/** A GraphQL persisted document will contain `documentId` that replaces its definitions */
interface PersistedDocument extends DocumentNode {
documentId?: string;
}
/** A GraphQL `DocumentNode` with attached generics for its result data and variables.
*
* @remarks
* A GraphQL {@link DocumentNode} defines both the variables it accepts on request and the `data`
* shape it delivers on a response in the GraphQL query language.
*
* To bridge the gap to TypeScript, tools may be used to generate TypeScript types that define the shape
* of `data` and `variables` ahead of time. These types are then attached to GraphQL documents using this
* `TypedDocumentNode` type.
*
* Using a `DocumentNode` that is typed like this will cause any `urql` API to type its input `variables`
* and resulting `data` using the types provided.
*
* @privateRemarks
* For compatibility reasons this type has been copied and internalized from:
* https://github.com/dotansimha/graphql-typed-document-node/blob/3711b12/packages/core/src/index.ts#L3-L10
*
* @see {@link https://github.com/dotansimha/graphql-typed-document-node} for more information.
*/
type TypedDocumentNode<Result = {
[key: string]: any;
}, Variables = {
[key: string]: any;
}> = DocumentNode & {
/** Type to support `@graphql-typed-document-node/core`
* @internal
*/
__apiType?: (variables: Variables) => Result;
/** Type to support `TypedQueryDocumentNode` from `graphql`
* @internal
*/
__ensureTypesOfVariablesAndResultMatching?: (variables: Variables) => Result;
};
/** GraphQL nodes with added `_directives` dictionary on nodes with directives.
*
* @remarks
* The {@link formatDocument} utility processes documents to add `__typename`
* fields to them. It additionally provides additional directives processing
* and outputs this type.
*
* When applied, every node with non-const directives, will have an additional
* `_directives` dictionary added to it, and filter directives starting with
* a leading `_` underscore from the directives array.
*/
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;
/** Any GraphQL `DocumentNode` or query string input.
*
* @remarks
* Wherever any `urql` bindings or API expect a query, it accepts either a query string,
* a `DocumentNode`, or a {@link TypedDocumentNode}.
*/
type DocumentInput<Result = {
[key: string]: any;
}, Variables = {
[key: string]: any;
}> = string | DocumentNode | TypedDocumentNode<Result, Variables>;
/** A list of errors on {@link ExecutionResult | ExecutionResults}.
* @see {@link https://spec.graphql.org/draft/#sec-Errors.Error-Result-Format} for the GraphQL Error Result format spec.
*/
type ErrorLike = Partial<GraphQLError> | Error;
/** Extensions which may be placed on {@link ExecutionResult | ExecutionResults}.
* @see {@link https://spec.graphql.org/draft/#sel-EAPHJCAACCoGu9J} for the GraphQL Error Result format spec.
*/
type Extensions = Record<string, any>;
/** Extensions sub-property on `persistedQuery` for Automatic Persisted Queries.
*
* @remarks
* This is part of the Automatic Persisted Query defacto standard and allows an API
* request to omit the `query`, instead sending this `sha256Hash`.
*/
interface PersistedRequestExtensions {
version?: 1;
sha256Hash: string;
/** Set when a `sha256Hash` previously experienced a miss which will force `query` to be sent. */
miss?: boolean;
}
/** Extensions which may be palced on {@link GraphQLRequest | GraphQLRequests}.
* @see {@link https://github.com/graphql/graphql-over-http/blob/1928447/spec/GraphQLOverHTTP.md#request-parameters} for the GraphQL over HTTP spec
*/
interface RequestExtensions {
persistedQuery?: PersistedRequestExtensions;
[extension: string]: any;
}
type Path = readonly (string | number)[];
/** Incremental Payloads sent as part of "Incremental Delivery" patching prior result data.
*
* @remarks
* "Incremental Delivery" works by allowing APIs to stream patches to the client, whih update
* prior results at the specified `path`.
*
* @see {@link https://github.com/graphql/graphql-spec/blob/94363c9/spec/Section%207%20--%20Response.md#incremental} for the incremental payload spec
*/
interface IncrementalPayload {
/** Optional label for the incremental payload that corresponds to directives' labels.
*
* @remarks
* All incremental payloads are labelled by the label that `@stream` or `@defer` directives
* specified, to identify which directive they originally belonged to.
*/
label?: string | null;
/** JSON patch at which to apply the `data` patch or append the `items`.
*
* @remarks
* The `path` indicates the JSON path of a prior result’s `data` structure at which
* to insert the patch’s data.
* When `items` is set instead, which represents a list of items to insert, the last
* entry of the `path` will be an index number at which to start setting the range of
* items.
*/
path?: Path;
/** An id pointing at an entry in the "pending" set of deferred results
*
* @remarks
* When we resolve this id it will give us the path to the deferred Fragment, this
* can be afterwards combined with the subPath to get the eventual location of the data.
*/
id?: string;
/** A path array from the defer/stream fragment to the location of our data. */
subPath?: Path;
/** Data to patch into the result data at the given `path`.
*
* @remarks
* This `data`, when set, is merged into the object at the given `path` of the last
* result that has been delivered.
* This isn't set when `items` is set.
*/
data?: Record<string, unknown> | null;
/** List of items to patch into the result data at the given `path`.
*
* @remarks
* The `items`, when provided, is set onto a range in an array, at the given JSON
* `path`. The start index is the last entry of the `path` and the end index is
* the length of the `items` list added to this index.
* This isn't set when `data` is set.
*/
items?: readonly unknown[] | null;
/** Contains a list of errors raised by incremental payloads.
*
* @remarks
* The list of `errors` on `incremental` payloads is merged into the list of prior
* results’ errors.
*
* @see {@link https://spec.graphql.org/October2021/#sec-Errors} for the GraphQL Errors Response spec
*/
errors?: ErrorLike[] | readonly ErrorLike[];
/** Additional metadata that a GraphQL API may choose to send that is out of spec.
* @see {@link https://spec.graphql.org/October2021/#sel-EAPHJCAACCoGu9J} for the GraphQL Response spec
*/
extensions?: Extensions;
}
type PendingIncrementalResult = {
path: Path;
id: string;
label?: string;
};
interface ExecutionResult {
/** Payloads we are still waiting for from the server.
*
* @remarks
* This was nely introduced in the defer/stream spec iteration of June 2023 https://github.com/graphql/defer-stream-wg/discussions/69
* Pending can be present on both Incremental as well as normal execution results, the presence of pending on an incremental
* result points at a nested deferred/streamed fragment.
*/
pending?: readonly PendingIncrementalResult[];
/** Incremental patches to be applied to a previous result as part of "Incremental Delivery".
*
* @remarks
* When this is set `data` and `errors` is typically not set on the result. Instead, the incremental payloads
* are applied as patches to a prior result's `data`.
*
* @see {@link https://github.com/graphql/graphql-spec/blob/94363c9/spec/Section%207%20--%20Response.md#incremental} for the incremental payload spec
*/
incremental?: IncrementalPayload[];
/** The result of the execution of the GraphQL operation.
* @see {@link https://spec.graphql.org/October2021/#sec-Data} for the GraphQL Data Response spec
*/
data?: null | Record<string, any>;
/** Contains a list of errors raised by fields or the request itself.
* @see {@link https://spec.graphql.org/October2021/#sec-Errors} for the GraphQL Errors Response spec
*/
errors?: ErrorLike[] | readonly ErrorLike[];
/** Additional metadata that a GraphQL API may choose to send that is out of spec.
* @see {@link https://spec.graphql.org/October2021/#sel-EAPHJCAACCoGu9J} for the GraphQL Response spec
*/
extensions?: Extensions;
/** Flag indicating whether a future, incremental response may update this response.
* @see {@link https://github.com/graphql/graphql-wg/blob/main/rfcs/DeferStream.md#payload-format} for the DeferStream spec
*/
hasNext?: boolean;
payload?: Omit<ExecutionResult, 'payload'>;
}
/** A source of {@link OperationResult | OperationResults}, convertable to a promise, subscribable, or Wonka Source.
*
* @remarks
* The {@link Client} will often return a `OperationResultSource` to provide a more flexible Wonka {@link Source}.
*
* While a {@link Source} may require you to import helpers to convert it to a `Promise` for a single result, or
* to subscribe to it, the `OperationResultSource` is a `PromiseLike` and has methods to convert it to a promise,
* or to subscribe to it with a single method call.
*/
type OperationResultSource<T extends OperationResult> = Source<T> & PromiseLike<T> & {
/** Returns the first non-stale, settled results of the source.
* @remarks
* The `toPromise` method gives you the first result of an `OperationResultSource`
* that has `hasNext: false` and `stale: false` set as a `Promise`.
*
* Hint: If you're trying to get updates for your results, this won't work.
* This gives you only a single, promisified result, so it won't receive
* cache or other updates.
*/
toPromise(): Promise<T>;
/** Alias for Wonka's `subscribe` and calls `onResult` when subscribed to for each new `OperationResult`. */
subscribe(onResult: (value: T) => void): Subscription;
};
/** A type of Operation, either a GraphQL `query`, `mutation`, or `subscription`; or a `teardown` signal.
*
* @remarks
* Internally, {@link Operation | Operations} instruct the {@link Client} to perform a certain action on its exchanges.
* Any of the three GraphQL operations tell it to execute these operations, and the `teardown` signal instructs it that
* the operations are cancelled and/or have ended.
*
* The `teardown` signal is sent when nothing is subscribed to an operation anymore and no longer interested in its results
* or any updates.
*/
type OperationType = 'subscription' | 'query' | 'mutation' | 'teardown';
/** The request and caching strategy that is used by exchanges to retrive cached results.
*
* @remarks
* The `RequestPolicy` is used by cache exchanges to decide how a query operation may be resolved with cached results.h
* A cache exchange may behave differently depending on which policy is returned.
*
* - `cache-first` (the default) prefers cached results and falls back to sending an API request.
* - `cache-and-network` returns cached results but also always sends an API request in the background.
* - `network-only` will ignore any cached results and send an API request.
* - `cache-only` will always return cached results and prevent API requests.
*/
type RequestPolicy = 'cache-first' | 'cache-and-network' | 'network-only' | 'cache-only';
/** A metadata flag set by cache exchanges to indicate whether a cache miss, a cache hit, or a partial cache hit has occurred.
*
* @remarks
* A cache exchange may update {@link OperationDebugMeta.cacheOutcome} on {@link OperationContext.meta} to indicate whether
* an operation has been resolved from the cache.
*
* A cache hit is considered a result that has fully come from a cache. A partial result is a result that has come from a cache
* but is incomplete, which may trigger another API request. A cache miss means a result must be requested from the API as no
* cache result has been delivered.
*/
type CacheOutcome = 'miss' | 'partial' | 'hit';
/** A default type for variables.
*
* @remarks
* While {@link TypedDocumentNode} can be used by generators to add TypeScript types for a GraphQL operation’s
* variables and result, when this isn’t the case this type is used as a fallback for the `Variables` generic.
*/
type AnyVariables = {
[prop: string]: any;
} | void | undefined;
/** A GraphQL request representing a single execution in GraphQL.
*
* @remarks
* A `GraphQLRequest` is a single executable request that may be used by a cache or a GraphQL API to deliver a result.
* A request contains a `DocumentNode` for the query document of a GraphQL operation and the `variables` for the given
* request.
*
* A unique `key` is generated to identify the request internally by `urql`. Two requests with the same query and
* variables will share the same `key`.
*
* The `Data` and `Variables` generics may be provided by a {@link TypedDocumentNode}, adding TypeScript types for what
* the result shape and variables shape are.
*
* @see {@link https://spec.graphql.org/October2021/#sec-Executing-Requests} for more information on GraphQL reuqests.
*/
interface GraphQLRequest<Data = any, Variables extends AnyVariables = AnyVariables> {
/** Unique identifier for the `GraphQLRequest`.
*
* @remarks
* This is a key that combines the unique key of the `query` and the `variables` into a unique
* `key` for the `GraphQLRequest`. Any request with the same query and variables will have a unique
* `key` by which results and requests can be identified as identical.
*
* Internally, a stable, cached `key` is generated for the `DocumentNode` and for the `variables` and
* both will be combined into a combined `key` which is set here, based on a DJB2 hash,
*
* The `variables` will change the key even if they contain a non-JSON reference. If you pass a custom
* class instance to `variables` that doesn't contain a `toString` or `toJSON` method, a stable but random
* identifier will replace this class to generate a key.
*/
key: number;
/** A GraphQL document to execute against a cache or API.
*
* @remarks
* A `GraphQLRequest` is executed against an operation in a GraphQL document.
* In `urql`, we expect a document to only contain a single operation that is executed rather than
* multiple ones by convention.
*/
query: DocumentNode | PersistedDocument | TypedDocumentNode<Data, Variables>;
/** Variables used to execute the `query` document.
*
* @remarks
* The `variables`, based either on the {@link AnyVariables} type or the {@link TypedDocumentNode}'s provided
* generic, are sent to the GraphQL API to execute a request.
*/
variables: Variables;
/** Additional metadata that a GraphQL API may accept for spec extensions.
* @see {@link https://github.com/graphql/graphql-over-http/blob/1928447/spec/GraphQLOverHTTP.md#request-parameters} for the GraphQL over HTTP spec
*/
extensions?: RequestExtensions | undefined;
}
/** Parameters from which {@link GraphQLRequest | GraphQLRequests} are created from.
*
* @remarks
* A `GraphQLRequest` is a single executable request with a generated `key` to identify
* their results, whereas `GraphQLRequestParams` is a utility type used to generate
* inputs for `urql` to create requests from, i.e. it only contains a `query` and
* `variables`. The type conditionally makes the `variables` property completely
* optional.
*
* @privateRemarks
* The wrapping union type is needed for passthrough or wrapper utilities that wrap
* functions like `useQuery` with generics.
*/
type GraphQLRequestParams<Data = any, Variables extends AnyVariables = AnyVariables> = ({
query: DocumentInput<Data, Variables>;
} & (Variables extends void ? {
variables?: Variables;
} : Variables extends {
[P in keyof Variables]: Exclude<Variables[P], null | void>;
} ? Variables extends {
[P in keyof Variables]: never;
} ? {
variables?: Variables;
} : {
variables: Variables;
} : {
variables?: Variables;
})) | {
query: DocumentInput<Data, Variables>;
variables: Variables;
};
/** Metadata used to annotate an `Operation` in development for the `urql-devtools`.
*
* @remarks
* The `OperationDebugMeta` is found on {@link OperationContext.meta} only in development,
* and is used to send additional metadata to the `urql-devtools` about the {@link Operation}.
*
* In production, most of this metadata will be missing, and it must not be used outside
* of development, and should only be used by the `urql-devtools`.
*/
interface OperationDebugMeta {
/** A label for the source of the `Operation`.
*
* @remarks
* The `source` string indicates a human readable originator for the `Operation`.
* This may be set to a component name or function name to indicate what originally
* triggered the `Operation`.
*/
source?: string;
/** A type of caching outcome set by cache exchanges on `OperationResult`s.
*
* @remarks
* The `cacheOutcome` flag is set to a {@link CacheOutcome} on {@link Operation | Operations}
* after they passed through the cache exchange. This flag indicates whether a cache hit, miss,
* or partial cache hit has occurred.
*/
cacheOutcome?: CacheOutcome;
/** Reserved to indicate the time it took for a GraphQL request to receive a response from a GraphQL API.
*
* @remarks
* The `networkLatency` may be set to the time it took (in ms) for a GraphQL API to respond to a request
* and deliver a result.
* @internal
*/
networkLatency?: number;
/** Reserved to indicate the timestamp at which a GraphQL request was sent to a GraphQL API.
*
* @remarks
* The `startTime` is set to an epoch timestamp (in ms) at which a GraphQL request was started
* and sent to a GraphQL API.
* @internal
*/
startTime?: number;
}
/** A unique identity for GraphQL mutations.
*
* @remarks
* GraphQL mutations not only use {@link GraphQLRequest.key} to identify a result, but instead use
* an identity to mark which result belongs to them.
*
* While two GraphQL queries and subscriptions sharing the same variables and the same operation
* (i.e. `DocumentNode`) are considered identical, two mutations are not.
* Two GraphQL queries or subscription results with the same {@link GraphQLRequest.key} can be used
* to resolve any {@link GraphQLRequest} with this same `key`.
* This is because identical queries and subscriptions are idempotent.
*
* However, two mutations with the same variables may receive different results from a GraphQL API,
* since they may trigger side-effects.
* This means that `urql` needs an additional identifier to differentiate between two mutations with
* the same `DocumentNode`s and `variables`.
*/
type OperationInstance = number & {
/** Marker to indicate that an `OperationInstance` may not be created by a user.
*
* @remarks
* The {@link Client} creates `OperationInstance` indentities automatically and uses them internally
* to identify mutations results as belonging to mutation operations. These are just integers (numbers),
* however, they're used as if they are objects (e.g. `{}`). However, since instances of arrays and
* objects are not serialisable numbers are used instead.
*
* Because these are internal, the TypeScript type is marked using a `unique symbol` because they're
* created opaquely and privately.
*
* @internal
*/
readonly _opaque: unique symbol;
};
/** Additional metadata for an `Operation` used to execute it.
*
* @remarks
* The `OperationContext` is found on {@link Operation.context} and gives exchanges additional metadata
* and options used to execute the operation.
*
* The context can often be changed on a per-operation basis, meaning, APIs on the {@link Client} or
* bindings can pass a partial context that alters these options for a single operation.
*
* The `OperationContext` is populated mostly from the initial options passed to the `Client` at its
* time of creation, but may also be modified by exchanges when an {@link Operation} is passed through
* to the next exchange or when a result is returned.
*/
interface OperationContext {
/** A unique identity for GraphQL mutations.
*
* @remarks
* This is an internal property set by the `Client` to an identity of type {@link OperationInstance}.
* An `OperationInstance` is an identifier that's used to tell two mutation operations with identical
* `query` documents and `variables` apart from one another.
* @internal
*/
readonly _instance?: OperationInstance | undefined;
/** Additional cache tags for `@urql/core`'s document `cacheExchange`.
*
* @remarks
* The built-in {@link cacheExchange} in `@urql/core` is a document cache that uses `__typename`s in
* mutation results to invalidate past, cached queries.
* The `additionalTypenames` array may be set to the list of custom typenames whenever a result may
* not deliver `__typename` properties, e.g. when an empty array may be sent.
*
* By providing a list of custom typenames you may "tag" a result as containing a certain type, which
* helps the document cache associate mutations with queries when either don't actually contain a
* `__typename` in the JSON result.
*/
additionalTypenames?: string[];
/** The `fetch` function used to make API calls.
*
* @remarks
* This is the fetch polyfill used by any fetch exchange to make an API request. By default, when this
* option isn't set, any fetch exchange will attempt to use the globally available `fetch` function
* to make a request instead.
*
* @see {@link https://developer.mozilla.org/en-US/d