@urql/vue
Version:
A highly customizable and versatile GraphQL client for vue
662 lines (654 loc) • 26.3 kB
TypeScript
import { AnyVariables, OperationContext, GraphQLRequestParams, CombinedError, Operation, RequestPolicy, OperationResult, DocumentInput, Client, ClientOptions } from '@urql/core';
export * from '@urql/core';
import { Ref, App } from 'vue';
/** Input arguments for the {@link useSubscription} function.
*
* @param query - The GraphQL subscription document that `useSubscription` executes.
* @param variables - The variables for the GraphQL subscription that `useSubscription` executes.
*/
type UseSubscriptionArgs<Data = any, Variables extends AnyVariables = AnyVariables> = {
/** Prevents {@link useSubscription} from automatically executing GraphQL subscription operations.
*
* @remarks
* `pause` may be set to `true` to stop {@link useSubscription} from starting
* its subscription automatically. This will pause the subscription until
* {@link UseSubscriptionResponse.resume} is called, or, if `pause` is a reactive
* ref of a boolean, until this ref changes to `true`.
*/
pause?: MaybeRef<boolean>;
/** Updates the {@link OperationContext} for the executed GraphQL subscription operation.
*
* @remarks
* `context` may be passed to {@link useSubscription}, to update the {@link OperationContext}
* of a subscription operation. This may be used to update the `context` that exchanges
* will receive for a single hook.
*
* @example
* ```ts
* const result = useQuery({
* query,
* context: {
* additionalTypenames: ['Item'],
* },
* });
* ```
*/
context?: MaybeRef<Partial<OperationContext>>;
} & MaybeRefObj<GraphQLRequestParams<Data, MaybeRefObj<Variables>>>;
/** Combines previous data with an incoming subscription result’s data.
*
* @remarks
* A `SubscriptionHandler` may be passed to {@link useSubscription} to
* aggregate subscription results into a combined {@link UseSubscriptionResponse.data}
* value.
*
* This is useful when a subscription event delivers a single item, while
* you’d like to display a list of events.
*
* @example
* ```ts
* const NotificationsSubscription = gql`
* subscription { newNotification { id, text } }
* `;
*
* const combineNotifications = (notifications = [], data) => {
* return [...notifications, data.newNotification];
* };
*
* const result = useSubscription(
* { query: NotificationsSubscription },
* combineNotifications,
* );
* ```
*/
type SubscriptionHandler<T, R> = (prev: R | undefined, data: T) => R;
/** A {@link SubscriptionHandler} or a reactive ref of one. */
type SubscriptionHandlerArg<T, R> = Ref<SubscriptionHandler<T, R>> | SubscriptionHandler<T, R>;
/** State of the current query, your {@link useSubscription} function is executing.
*
* @remarks
* `UseSubscriptionResponse` is returned by {@link useSubscription} and
* gives you the updating {@link OperationResult} of GraphQL subscriptions.
*
* Each value that is part of the result is wrapped in a reactive ref
* and updates as results come in.
*
* Hint: Even when the query and variables update, the prior state of
* the last result is preserved.
*/
interface UseSubscriptionResponse<T = any, R = T, V extends AnyVariables = AnyVariables> {
/** Indicates whether `useSubscription`’s subscription is active.
*
* @remarks
* When `useSubscription` starts a subscription, the `fetching` flag
* is set to `true` and will remain `true` until the subscription
* completes on the API, or `useSubscription` is paused.
*/
fetching: Ref<boolean>;
/** Indicates that the subscription result is not fresh.
*
* @remarks
* This is mostly unused for subscriptions and will rarely affect you, and
* is more relevant for queries.
*
* @see {@link OperationResult.stale} for the source of this value.
*/
stale: Ref<boolean>;
/** Reactive {@link OperationResult.data} for the executed subscription, or data returned by the handler.
*
* @remarks
* `data` will be set to the last {@link OperationResult.data} value
* received for the subscription.
*
* It will instead be set to the values that {@link SubscriptionHandler}
* returned, if a handler has been passed to {@link useSubscription}.
*/
data: Ref<R | undefined>;
/** Reactive {@link OperationResult.error} for the executed subscription. */
error: Ref<CombinedError | undefined>;
/** Reactive {@link OperationResult.extensions} for the executed mutation. */
extensions: Ref<Record<string, any> | undefined>;
/** Reactive {@link Operation} that the current state is for.
*
* @remarks
* This is the subscription {@link Operation} that is currently active.
* When {@link UseSubscriptionResponse.fetching} is `true`, this is the
* last `Operation` that the current state was for.
*/
operation: Ref<Operation<T, V> | undefined>;
/** Indicates whether {@link useSubscription} is currently paused.
*
* @remarks
* When `useSubscription` has been paused, it will stop receiving updates
* from the {@link Client} and won’t execute the subscription, until
* {@link UseSubscriptionArgs.pause} becomes true or
* {@link UseSubscriptionResponse.resume} is called.
*/
isPaused: Ref<boolean>;
/** Resumes {@link useSubscription} if it’s currently paused.
*
* @remarks
* Resumes or starts {@link useSubscription}’s subscription, if it’s currently paused.
*/
resume(): void;
/** Pauses {@link useSubscription} to stop the subscription.
*
* @remarks
* Pauses {@link useSubscription}’s subscription, which stops it
* from receiving updates from the {@link Client} and to stop executing
* the subscription operation.
*/
pause(): void;
/** Triggers {@link useQuery} to reexecute a GraphQL subscription operation.
*
* @param opts - optionally, context options that will be merged with
* {@link UseQueryArgs.context} and the `Client`’s options.
*
* @remarks
* When called, {@link useSubscription} will re-execute the GraphQL subscription
* operation it currently holds, unless it’s currently paused.
*/
executeSubscription(opts?: Partial<OperationContext>): void;
}
/** Function to run a GraphQL subscription and get reactive GraphQL results.
*
* @param args - a {@link UseSubscriptionArgs} object, to pass a `query`, `variables`, and options.
* @param handler - optionally, a {@link SubscriptionHandler} function to combine multiple subscription results.
* @returns a {@link UseSubscriptionResponse} object.
*
* @remarks
* `useSubscription` allows GraphQL subscriptions to be defined and executed inside
* Vue `setup` functions.
* Given {@link UseSubscriptionArgs.query}, it executes the GraphQL subscription with the
* provided {@link Client}.
*
* The returned result updates when the `Client` has new results
* for the subscription, and `data` is updated with the result’s data
* or with the `data` that a `handler` returns.
*
* @example
* ```ts
* import { gql, useSubscription } from '@urql/vue';
*
* const NotificationsSubscription = gql`
* subscription { newNotification { id, text } }
* `;
*
* export default {
* setup() {
* const result = useSubscription(
* { query: NotificationsSubscription },
* function combineNotifications(notifications = [], data) {
* return [...notifications, data.newNotification];
* },
* );
* // ...
* },
* };
* ```
*/
declare function useSubscription<T = any, R = T, V extends AnyVariables = AnyVariables>(args: UseSubscriptionArgs<T, V>, handler?: SubscriptionHandlerArg<T, R>): UseSubscriptionResponse<T, R, V>;
type MaybeRef<T> = T | (() => T) | Ref<T>;
type MaybeRefObj<T> = T extends {} ? {
[K in keyof T]: MaybeRef<T[K]>;
} : T;
/** Input arguments for the {@link useQuery} function.
*
* @param query - The GraphQL query that `useQuery` executes.
* @param variables - The variables for the GraphQL query that `useQuery` executes.
*/
type UseQueryArgs<Data = any, Variables extends AnyVariables = AnyVariables> = {
/** Updates the {@link RequestPolicy} for the executed GraphQL query operation.
*
* @remarks
* `requestPolicy` modifies the {@link RequestPolicy} of the GraphQL query operation
* that `useQuery` executes, and indicates a caching strategy for cache exchanges.
*
* For example, when set to `'cache-and-network'`, {@link useQuery} will
* receive a cached result with `stale: true` and an API request will be
* sent in the background.
*
* @see {@link OperationContext.requestPolicy} for where this value is set.
*/
requestPolicy?: MaybeRef<RequestPolicy>;
/** Updates the {@link OperationContext} for the executed GraphQL query operation.
*
* @remarks
* `context` may be passed to {@link useQuery}, to update the {@link OperationContext}
* of a query operation. This may be used to update the `context` that exchanges
* will receive for a single hook.
*
* @example
* ```ts
* const result = useQuery({
* query,
* context: {
* additionalTypenames: ['Item'],
* },
* });
* ```
*/
context?: MaybeRef<Partial<OperationContext>>;
/** Prevents {@link useQuery} from automatically executing GraphQL query operations.
*
* @remarks
* `pause` may be set to `true` to stop {@link useQuery} from executing
* automatically. This will pause the query until {@link UseQueryState.resume}
* is called, or, if `pause` is a reactive ref of a boolean, until this
* ref changes to `true`.
*
* @see {@link https://urql.dev/goto/docs/basics/vue#pausing-usequery} for
* documentation on the `pause` option.
*/
pause?: MaybeRef<boolean>;
} & MaybeRefObj<GraphQLRequestParams<Data, MaybeRefObj<Variables>>>;
/** State of the current query, your {@link useQuery} function is executing.
*
* @remarks
* `UseQueryState` is returned by {@link useQuery} and
* gives you the updating {@link OperationResult} of
* GraphQL queries.
*
* Each value that is part of the result is wrapped in a reactive ref
* and updates as results come in.
*
* Hint: Even when the query and variables update, the previous state of
* the last result is preserved, which allows you to display the
* previous state, while implementing a loading indicator separately.
*/
interface UseQueryState<T = any, V extends AnyVariables = AnyVariables> {
/** Indicates whether `useQuery` is waiting for a new result.
*
* @remarks
* When `useQuery` receives a new query and/or variables, it will
* start executing the new query operation and `fetching` is set to
* `true` until a result arrives.
*
* Hint: This is subtly different than whether the query is actually
* fetching, and doesn’t indicate whether a query is being re-executed
* in the background. For this, see {@link UseQueryState.stale}.
*/
fetching: Ref<boolean>;
/** Indicates that the state is not fresh and a new result will follow.
*
* @remarks
* The `stale` flag is set to `true` when a new result for the query
* is expected and `useQuery` is waiting for it. This may indicate that
* a new request is being requested in the background.
*
* @see {@link OperationResult.stale} for the source of this value.
*/
stale: Ref<boolean>;
/** Reactive {@link OperationResult.data} for the executed query. */
data: Ref<T | undefined>;
/** Reactive {@link OperationResult.error} for the executed query. */
error: Ref<CombinedError | undefined>;
/** Reactive {@link OperationResult.extensions} for the executed query. */
extensions: Ref<Record<string, any> | undefined>;
/** Reactive {@link Operation} that the current state is for.
*
* @remarks
* This is the {@link Operation} that is currently being executed.
* When {@link UseQueryState.fetching} is `true`, this is the
* last `Operation` that the current state was for.
*/
operation: Ref<Operation<T, V> | undefined>;
/** Indicates whether {@link useQuery} is currently paused.
*
* @remarks
* When `useQuery` has been paused, it will stop receiving updates
* from the {@link Client} and won’t execute query operations, until
* {@link UseQueryArgs.pause} becomes `true` or {@link UseQueryState.resume}
* is called.
*
* @see {@link https://urql.dev/goto/docs/basics/vue#pausing-usequery} for
* documentation on the `pause` option.
*/
isPaused: Ref<boolean>;
/** The {@link OperationResult.hasNext} for the executed query. */
hasNext: Ref<boolean>;
/** Resumes {@link useQuery} if it’s currently paused.
*
* @remarks
* Resumes or starts {@link useQuery}’s query, if it’s currently paused.
*
* @see {@link https://urql.dev/goto/docs/basics/vue#pausing-usequery} for
* documentation on the `pause` option.
*/
resume(): void;
/** Pauses {@link useQuery} to stop it from executing the query.
*
* @remarks
* Pauses {@link useQuery}’s query, which stops it from receiving updates
* from the {@link Client} and to stop the ongoing query operation.
*
* @see {@link https://urql.dev/goto/docs/basics/vue#pausing-usequery} for
* documentation on the `pause` option.
*/
pause(): void;
/** Triggers {@link useQuery} to execute a new GraphQL query operation.
*
* @param opts - optionally, context options that will be merged with
* {@link UseQueryArgs.context} and the `Client`’s options.
*
* @remarks
* When called, {@link useQuery} will re-execute the GraphQL query operation
* it currently holds, unless it’s currently paused.
*
* This is useful for re-executing a query and get a new network result,
* by passing a new request policy.
*
* ```ts
* const result = useQuery({ query });
*
* const refresh = () => {
* // Re-execute the query with a network-only policy, skipping the cache
* result.executeQuery({ requestPolicy: 'network-only' });
* };
* ```
*/
executeQuery(opts?: Partial<OperationContext>): UseQueryResponse<T, V>;
}
/** Return value of {@link useQuery}, which is an awaitable {@link UseQueryState}.
*
* @remarks
* {@link useQuery} returns a {@link UseQueryState} but may also be
* awaited inside a Vue `async setup()` function. If it’s awaited
* the query is executed before resolving.
*/
type UseQueryResponse<T, V extends AnyVariables = AnyVariables> = UseQueryState<T, V> & PromiseLike<UseQueryState<T, V>>;
/** Function to run a GraphQL query and get reactive GraphQL results.
*
* @param args - a {@link UseQueryArgs} object, to pass a `query`, `variables`, and options.
* @returns a {@link UseQueryResponse} object.
*
* @remarks
* `useQuery` allows GraphQL queries to be defined and executed inside
* Vue `setup` functions.
* Given {@link UseQueryArgs.query}, it executes the GraphQL query with the
* provided {@link Client}.
*
* The returned result’s reactive values update when the `Client` has
* new results for the query, and changes when your input `args` change.
*
* Additionally, `useQuery` may also be awaited inside an `async setup()`
* function to use Vue’s Suspense feature.
*
* @see {@link https://urql.dev/goto/docs/basics/vue#queries} for `useQuery` docs.
*
* @example
* ```ts
* import { gql, useQuery } from '@urql/vue';
*
* const TodosQuery = gql`
* query { todos { id, title } }
* `;
*
* export default {
* setup() {
* const result = useQuery({ query: TodosQuery });
* return { data: result.data };
* },
* };
* ```
*/
declare function useQuery<T = any, V extends AnyVariables = AnyVariables>(args: UseQueryArgs<T, V>): UseQueryResponse<T, V>;
/** State of the last mutation executed by {@link useMutation}.
*
* @remarks
* `UseMutationResponse` is returned by {@link useMutation} and
* gives you the {@link OperationResult} of the last executed mutation,
* and a {@link UseMutationResponse.executeMutation} method to
* start mutations.
*
* Even if the mutation document passed to {@link useMutation} changes,
* the state isn’t reset, so you can keep displaying the previous result.
*/
interface UseMutationResponse<T, V extends AnyVariables = AnyVariables> {
/** Indicates whether `useMutation` is currently executing a mutation. */
fetching: Ref<boolean>;
/** Indicates that the mutation result is not fresh.
*
* @remarks
* The `stale` flag is set to `true` when a new result for the mutation
* is expected.
* This is mostly unused for mutations and will rarely affect you, and
* is more relevant for queries.
*
* @see {@link OperationResult.stale} for the source of this value.
*/
stale: Ref<boolean>;
/** Reactive {@link OperationResult.data} for the executed mutation. */
data: Ref<T | undefined>;
/** Reactive {@link OperationResult.error} for the executed mutation. */
error: Ref<CombinedError | undefined>;
/** Reactive {@link OperationResult.extensions} for the executed mutation. */
extensions: Ref<Record<string, any> | undefined>;
/** Reactive {@link Operation} that the current state is for.
*
* @remarks
* This is the mutation {@link Operation} that has last been executed.
* When {@link UseQueryState.fetching} is `true`, this is the
* last `Operation` that the current state was for.
*/
operation: Ref<Operation<T, V> | undefined>;
/** The {@link OperationResult.hasNext} for the executed query. */
hasNext: Ref<boolean>;
/** Triggers {@link useMutation} to execute its GraphQL mutation operation.
*
* @param variables - variables using which the mutation will be executed.
* @param context - optionally, context options that will be merged with
* the `Client`’s options.
* @returns the {@link OperationResult} of the mutation.
*
* @remarks
* When called, {@link useMutation} will start the GraphQL mutation
* it currently holds and use the `variables` passed to it.
*
* Once the mutation response comes back from the API, its
* returned promise will resolve to the mutation’s {@link OperationResult}
* and the {@link UseMutationResponse} will be updated with the result.
*
* @example
* ```ts
* const result = useMutation(UpdateTodo);
* const start = async ({ id, title }) => {
* const result = await result.executeMutation({ id, title });
* };
*/
executeMutation(variables: V, context?: Partial<OperationContext>): Promise<OperationResult<T>>;
}
/** Function to create a GraphQL mutation, run by passing variables to {@link UseMutationResponse.executeMutation}
*
* @param query - a GraphQL mutation document which `useMutation` will execute.
* @returns a {@link UseMutationResponse} object.
*
* @remarks
* `useMutation` allows GraphQL mutations to be defined inside Vue `setup` functions,
* and keeps its state after the mutation is started. Mutations can be started by calling
* {@link UseMutationResponse.executeMutation} with variables.
*
* The returned result updates when a mutation is executed and keeps
* track of the last mutation result.
*
* @see {@link https://urql.dev/goto/docs/basics/vue#mutations} for `useMutation` docs.
*
* @example
* ```ts
* import { gql, useMutation } from '@urql/vue';
*
* const UpdateTodo = gql`
* mutation ($id: ID!, $title: String!) {
* updateTodo(id: $id, title: $title) {
* id, title
* }
* }
* `;
*
* export default {
* setup() {
* const result = useMutation(UpdateTodo);
* const start = async ({ id, title }) => {
* const result = await result.executeMutation({ id, title });
* };
* // ...
* },
* };
* ```
*/
declare function useMutation<T = any, V extends AnyVariables = AnyVariables>(query: DocumentInput<T, V>): UseMutationResponse<T, V>;
/** Handle to create GraphQL operations outside of Vue’s `setup` functions.
*
* @remarks
* The `ClientHandle` object is created inside a Vue `setup` function but
* allows its methods to be called outside of `setup` functions, delaying
* the creation of GraphQL operations, as an alternative to pausing queries
* or subscriptions.
*
* This is also important when chaining multiple functions inside an
* `async setup()` function.
*
* Hint: If you only need a single, non-updating result and want to execute
* queries programmatically, it may be easier to call the {@link Client.query}
* method.
*/
interface ClientHandle {
/** The {@link Client} that’ll be used to execute GraphQL operations. */
client: Client;
/** Calls {@link useQuery} outside of a synchronous Vue `setup` function.
*
* @param args - a {@link UseQueryArgs} object, to pass a `query`, `variables`, and options.
* @returns a {@link UseQueryResponse} object.
*
* @remarks
* Creates a {@link UseQueryResponse} outside of a synchronous Vue `setup`
* function or when chained in an `async setup()` function.
*/
useQuery<T = any, V extends AnyVariables = AnyVariables>(args: UseQueryArgs<T, V>): UseQueryResponse<T, V>;
/** Calls {@link useSubscription} outside of a synchronous Vue `setup` function.
*
* @param args - a {@link UseSubscriptionArgs} object, to pass a `query`, `variables`, and options.
* @param handler - optionally, a {@link SubscriptionHandler} function to combine multiple subscription results.
* @returns a {@link UseSubscriptionResponse} object.
*
* @remarks
* Creates a {@link UseSubscriptionResponse} outside of a synchronous Vue `setup`
* function or when chained in an `async setup()` function.
*/
useSubscription<T = any, R = T, V extends AnyVariables = AnyVariables>(args: UseSubscriptionArgs<T, V>, handler?: SubscriptionHandlerArg<T, R>): UseSubscriptionResponse<T, R, V>;
/** Calls {@link useMutation} outside of a synchronous Vue `setup` function.
*
* @param query - a GraphQL mutation document which `useMutation` will execute.
* @returns a {@link UseMutationResponse} object.
*
* @remarks
* Creates a {@link UseMutationResponse} outside of a synchronous Vue `setup`
* function or when chained in an `async setup()` function.
*/
useMutation<T = any, V extends AnyVariables = AnyVariables>(query: DocumentInput<T, V>): UseMutationResponse<T, V>;
}
/** Creates a {@link ClientHandle} inside a Vue `setup` function.
*
* @remarks
* `useClientHandle` creates and returns a {@link ClientHandle}
* when called in a Vue `setup` function, which allows queries,
* mutations, and subscriptions to be created _outside_ of
* `setup` functions.
*
* This is also important when chaining multiple functions inside an
* `async setup()` function.
*
* {@link useQuery} and other GraphQL functions must usually
* be created in Vue `setup` functions so they can stop GraphQL
* operations when your component unmounts. However, while they
* queries and subscriptions can be paused, sometimes it’s easier
* to delay the creation of their response objects.
*
*
* @example
* ```ts
* import { ref, computed } from 'vue';
* import { gql, useClientHandle } from '@urql/vue';
*
* export default {
* async setup() {
* const handle = useClientHandle();
*
* const pokemons = await handle.useQuery({
* query: gql`{ pokemons(limit: 10) { id, name } }`,
* });
*
* const index = ref(0);
*
* // The `handle` allows another `useQuery` call to now be setup again
* const pokemon = await handle.useQuery({
* query: gql`
* query ($id: ID!) {
* pokemon(id: $id) { id, name }
* }
* `,
* variables: computed(() => ({
* id: pokemons.data.value.pokemons[index.value].id,
* }),
* });
* }
* };
* ```
*/
declare function useClientHandle(): ClientHandle;
/** Provides a {@link Client} to a component’s children.
*
* @param opts - {@link ClientOptions}, a {@link Client}, or a reactive ref object of a `Client`.
*
* @remarks
* `provideClient` provides a {@link Client} to `@urql/vue`’s GraphQL
* functions in children components.
*
* Hint: GraphQL functions and {@link useClient} will see the
* provided `Client`, even if `provideClient` has been called
* in the same component’s `setup` function.
*
* @example
* ```ts
* import { provideClient } from '@urql/vue';
* // All of `@urql/core` is also re-exported by `@urql/vue`:
* import { Client, cacheExchange, fetchExchange } from '@urql/core';
*
* export default {
* setup() {
* provideClient(new Client({
* url: 'https://API',
* exchanges: [cacheExchange, fetchExchange],
* }));
* },
* };
* ```
*/
declare function provideClient(opts: ClientOptions | Client | Ref<Client>): Client;
/** Provides a {@link Client} to a Vue app.
*
* @param app - the Vue {@link App}
* @param opts - {@link ClientOptions}, a {@link Client}, or a reactive ref object of a `Client`.
*
* @remarks
* `install` provides a {@link Client} to `@urql/vue`’s GraphQL
* functions in a Vue app.
*
* @example
* ```ts
* import * as urql from '@urql/vue';
* // All of `@urql/core` is also re-exported by `@urql/vue`:
* import { cacheExchange, fetchExchange } from '@urql/core';
*
* import { createApp } from 'vue';
* import Root from './App.vue';
*
* const app = createApp(Root);
* app.use(urql, {
* url: 'http://localhost:3000/graphql',
* exchanges: [cacheExchange, fetchExchange],
* });
* ```
*/
declare function install(app: App, opts: ClientOptions | Client | Ref<Client>): void;
export { ClientHandle, SubscriptionHandler, SubscriptionHandlerArg, UseMutationResponse, UseQueryArgs, UseQueryResponse, UseQueryState, UseSubscriptionArgs, UseSubscriptionResponse, install as default, install, provideClient, useClientHandle, useMutation, useQuery, useSubscription };