UNPKG

@urql/vue

Version:

A highly customizable and versatile GraphQL client for vue

662 lines (654 loc) 26.3 kB
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 };