Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.

docs(packages): Add TSDocs to all remaining packages (#3079)

+5
.changeset/lucky-months-fail.md
···
+
---
+
'@urql/core': patch
+
---
+
+
Add missing type exports of SSR-related types (`SerializedResult`, `SSRExchangeParams`, `SSRExchange`, and `SSRData`) to `@urql/core`'s type exports.
+7
.changeset/strong-shirts-hear.md
···
+
---
+
'@urql/introspection': patch
+
'@urql/storage-rn': patch
+
'next-urql': patch
+
---
+
+
Add TSDocs to `@urql/*` packages.
+8
.changeset/tricky-cherries-glow.md
···
+
---
+
'@urql/preact': patch
+
'@urql/svelte': patch
+
'urql': patch
+
'@urql/vue': patch
+
---
+
+
Add TSDocs to all `urql` bindings packages.
+7
packages/core/src/exchanges/index.ts
···
export { composeExchanges } from './compose';
export type {
+
SerializedResult,
+
SSRExchangeParams,
+
SSRExchange,
+
SSRData,
+
} from './ssr';
+
+
export type {
SubscriptionOperation,
SubscriptionForwarder,
SubscriptionExchangeOpts,
+15
packages/introspection/src/getIntrospectedSchema.ts
···
getIntrospectionQuery,
} from 'graphql';
+
/** Returns an {@link IntrospectionQuery} result for a given GraphQL schema.
+
*
+
* @param input - A GraphQL schema, either as an SDL string, or a {@link GraphQLSchema} object.
+
* @returns an {@link IntrospectionQuery} result.
+
*
+
* @remarks
+
* `getIntrospectedSchema` can be used to get a Schema Introspection result from
+
* a given GraphQL schema. The schema can be passed as an SDL string or a
+
* {@link GraphQLSchema} object. If an {@link IntrospectionQuery} object is
+
* passed, it'll be passed through.
+
*
+
* @throws
+
* If `input` cannot be parsed or converted into a {@link GraphQLSchema} then
+
* a {@link TypeError} will be thrown.
+
*/
export const getIntrospectedSchema = (
input: string | IntrospectionQuery | GraphQLSchema
): IntrospectionQuery => {
+39 -5
packages/introspection/src/minifyIntrospectionQuery.ts
···
}
};
+
/** Input parameters for the {@link minifyIntrospectionQuery} function. */
export interface MinifySchemaOptions {
-
/** Includes scalar names (instead of an `Any` replacement) in the output when enabled. */
+
/** Includes scalars instead of removing them.
+
*
+
* @remarks
+
* By default, all scalars will be replaced by a single scalar called `Any`
+
* in the output, unless this option is set to `true`.
+
*/
includeScalars?: boolean;
-
/** Includes enums (instead of an `Any` replacement) in the output when enabled. */
+
/** Includes enums instead of removing them.
+
*
+
* @remarks
+
* By default, all enums will be replaced by a single scalar called `Any`
+
* in the output, unless this option is set to `true`.
+
*/
includeEnums?: boolean;
-
/** Includes all input objects (instead of an `Any` replacement) in the output when enabled. */
+
/** Includes inputs instead of removing them.
+
*
+
* @remarks
+
* By default, all inputs will be replaced by a single scalar called `Any`
+
* in the output, unless this option is set to `true`.
+
*/
includeInputs?: boolean;
-
/** Includes all directives in the output when enabled. */
+
/** Includes directives instead of removing them. */
includeDirectives?: boolean;
}
-
/** Removes extraneous information from introspected schema data to minify it and prepare it for use on the client-side. */
+
/** Minifies an {@link IntrospectionQuery} for use with Graphcache or the `populateExchange`.
+
*
+
* @param schema - An {@link IntrospectionQuery} object to be minified.
+
* @param opts - An optional {@link MinifySchemaOptions} configuration object.
+
* @returns the minified {@link IntrospectionQuery} object.
+
*
+
* @remarks
+
* `minifyIntrospectionQuery` reduces the size of an {@link IntrospectionQuery} by
+
* removing data and information that a client-side consumer, like Graphcache or the
+
* `populateExchange`, may not require.
+
*
+
* At the very least, it will remove system types, descriptions, depreactions,
+
* and source locations. Unless disabled via the options passed, it will also
+
* by default remove all scalars, enums, inputs, and directives.
+
*
+
* @throws
+
* If `schema` receives an object that isn’t an {@link IntrospectionQuery}, a
+
* {@link TypeError} will be thrown.
+
*/
export const minifyIntrospectionQuery = (
schema: IntrospectionQuery,
opts: MinifySchemaOptions = {}
+25 -1
packages/next-urql/src/init-urql-client.ts
···
let urqlClient: Client | null = null;
+
/** Resets the `Client` that {@link initUrqlClient} returns.
+
*
+
* @remarks
+
* `resetClient` will force {@link initUrqlClient} to create a new
+
* {@link Client}, rather than reusing the same `Client` it already
+
* created on the client-side.
+
*
+
* This may be used to force the cache and any state in the `Client`
+
* to be cleared and reset.
+
*/
export function resetClient() {
urqlClient = null;
}
+
/** Creates a {@link Client} the given options.
+
*
+
* @param clientOptions - {@link ClientOptions} to create the `Client` with.
+
* @param canEnableSuspense - Enables React Suspense on the server-side for `react-ssr-prepass`.
+
* @returns the created {@link Client}
+
*
+
* @remarks
+
* `initUrqlClient` creates a {@link Client} with the given options,
+
* like {@link createClient} does, but reuses the same client when
+
* run on the client-side.
+
*
+
* As long as `canEnableSuspense` is set to `true`, it enables React Suspense
+
* mode on the server-side for `react-ssr-prepass`.
+
*/
export function initUrqlClient(
clientOptions: ClientOptions,
canEnableSuspense: boolean
-
): Client | null {
+
): Client {
// Create a new Client for every server-side rendered request.
// This ensures we reset the state for each rendered page.
// If there is an exising client instance on the client-side, use it.
+76 -32
packages/next-urql/src/types.ts
···
-
import { GraphQLError } from 'graphql';
-
import { ClientOptions, Exchange, Client } from 'urql';
-
import { NextPageContext } from 'next';
-
import { AppContext } from 'next/app';
+
import type { ClientOptions, Client, SSRExchange, SSRData } from '@urql/core';
+
import type { NextPageContext } from 'next';
+
import type { AppContext } from 'next/app';
+
/** The Next.js {@link NextPageContext}, as modified by `next-urql`. */
export interface NextUrqlPageContext extends NextPageContext {
urqlClient: Client;
}
+
/** The Next.js {@link AppContext}, as modified by `next-urql`. */
export interface NextUrqlAppContext extends AppContext {
urqlClient: Client;
}
export type NextUrqlContext = NextUrqlPageContext | NextUrqlAppContext;
+
/** Passed to {@link withUrqlClient} returning the options a {@link Client} is created with.
+
*
+
* @param ssrExchange - the `ssrExchange` you must use in your `exchanges` array.
+
* @param ctx - Passed when `getInitialProps` is used and set to Next.js’ {@link NextPageContext}.
+
* @returns a {@link ClientOptions} configuration object to create a {@link Client} with.
+
*
+
* @remarks
+
* You must define a `getClientConfig` function and pass it to {@link withUrqlClient}.
+
*
+
* This function defines the options passed to {@link initUrqlClient}.
+
* It passes you an `ssrExchange` that you must use in your `exchanges` array.
+
*
+
* @example
+
* ```ts
+
* import { cacheExchange, fetchExchange } from '@urql/core';
+
* import { withUrqlClient } from 'next-urql';
+
*
+
* const WrappedPage = withUrqlClient(
+
* (ssrExchange) => ({
+
* url: 'https://YOUR_API',
+
* exchanges: [cacheExchange, ssrExchange, fetchExchange],
+
* })
+
* )(Page);
+
* ```
+
*/
export type NextUrqlClientConfig = (
ssrExchange: SSRExchange,
ctx?: NextPageContext
) => ClientOptions;
-
export interface WithUrqlState {
-
urqlState?: SSRData;
-
}
-
-
export interface WithUrqlClient {
+
/** Props that {@link withUrqlClient} components pass on to your component. */
+
export interface WithUrqlProps {
+
/** The {@link Client} that {@link withUrqlClient} created for your component. */
urqlClient?: Client;
-
}
-
-
export interface WithUrqlProps extends WithUrqlClient, WithUrqlState {
-
resetUrqlClient?: () => void;
+
/** Next.js’ `pageProps` prop, as passed to it by Next.js. */
pageProps: any;
+
/** The SSR data that {@link withUrqlClient} created for your component. */
+
urqlState?: SSRData;
+
/** Resets the `Client` that on the client-side.
+
*
+
* @remarks
+
* `resetUrqlClient` will force a new {@link Client} to be created
+
* on the client-side, rather than the same `Client` with the same
+
* server-side data to be reused.
+
*
+
* This may be used to force the cache and any state in the `Client`
+
* to be cleared and reset.
+
*/
+
resetUrqlClient?(): void;
[key: string]: any;
}
-
export interface SerializedResult {
-
data?: any;
-
error?: {
-
graphQLErrors: Array<Partial<GraphQLError> | string>;
-
networkError?: string;
-
};
-
}
-
-
export interface SSRData {
-
[key: string]: SerializedResult;
-
}
-
-
export interface SSRExchange extends Exchange {
-
/** Rehydrates cached data */
-
restoreData(data: SSRData): void;
-
/** Extracts cached data */
-
extractData(): SSRData;
-
}
-
+
/** Options that may be passed to the {@link withUrqlClient} wrapper function. */
export interface WithUrqlClientOptions {
+
/** Enables automatic server-side rendering mode.
+
*
+
* @remarks
+
* When enabled, {@link withUrqlClient} will add a `getInitialProps`
+
* function to the resulting component, even if you haven't defined
+
* one.
+
*
+
* This function will automatically capture `urql`'s SSR state on the
+
* server-side and rehydrate it on the client-side, unless
+
* {@link WithUrqlClientOptions.neverSuspend} is `true`.
+
*/
ssr?: boolean;
+
/** Disables automatic server-side rendering, even if a `getInitialProps` function is defined.
+
*
+
* @remarks
+
* When enabled, {@link withUrqlClient} will never execute queries
+
* on the server-side automatically, and will instead rely on you
+
* to do so manually.
+
*/
neverSuspend?: boolean;
+
/** Enables reexecuting operations on the client-side after rehydration.
+
*
+
* @remarks
+
* When enabled, `staleWhileRevalidate` will reexecute GraphQL queries on
+
* the client-side, if they’ve been rehydrated from SSR state.
+
*
+
* This is useful if you, for instance, cache your server-side rendered
+
* pages, or if you use `getStaticProps` and wish to get this data
+
* updated.
+
*/
staleWhileRevalidate?: boolean;
}
+40 -17
packages/next-urql/src/with-urql-client.ts
···
ReactNode,
ReactElement,
} from 'react';
-
import ssrPrepass from 'react-ssr-prepass';
-
import { NextComponentType, NextPage, NextPageContext } from 'next';
-
import NextApp, { AppContext } from 'next/app';
import {
Provider,
+
SSRExchange,
ssrExchange,
-
dedupExchange,
cacheExchange,
fetchExchange,
} from 'urql';
+
import ssrPrepass from 'react-ssr-prepass';
+
import { NextComponentType, NextPage, NextPageContext } from 'next';
+
import NextApp, { AppContext } from 'next/app';
+
import { initUrqlClient, resetClient } from './init-urql-client';
import {
···
NextUrqlContext,
WithUrqlProps,
WithUrqlClientOptions,
-
SSRExchange,
} from './types';
let ssr: SSRExchange;
···
getLayout?: (page: ReactElement) => ReactNode;
};
+
/** Creates a wrapper for Next.js Page, App, or Document components that rehydrates `urql` state.
+
*
+
* @param getClientConfig - function used to create the {@link Client}
+
* @param options - optional {@link WithUrqlClientOptions} configuration options
+
* @returns a higher-order component function, which you can pass a Next.js page or app component.
+
*
+
* @remarks
+
* Used to wrap a Next.js page or app component. It will create a {@link Client} and passes
+
* it on to the child component and adds a React Provider for it.
+
*
+
* It will restore any page’s `pageProps.urqlState` with the {@link SSRExchange} and also
+
* supports doing this automatically when the {@link WithUrqlClientOptions.ssr} option
+
* is enabled.
+
*
+
* If you don’t define the above option, you will have to write `getServerSideProps` or
+
* `getStaticProps` methods on your component manually.
+
*
+
* @see {@link https://urql.dev/goto/docs/advanced/server-side-rendering/#nextjs} for more documentation.
+
*
+
* @example
+
* ```ts
+
* import { cacheExchange, fetchExchange } from '@urql/core';
+
* import { withUrqlClient } from 'next-urql';
+
*
+
* const WrappedPage = withUrqlClient(
+
* (ssrExchange) => ({
+
* url: 'https://YOUR_API',
+
* exchanges: [cacheExchange, ssrExchange, fetchExchange],
+
* }),
+
* { ssr: true },
+
* )(Page);
+
* ```
+
*/
export function withUrqlClient(
getClientConfig: NextUrqlClientConfig,
options?: WithUrqlClientOptions
···
const clientConfig = getClientConfig(ssr);
if (!clientConfig.exchanges) {
// When the user does not provide exchanges we make the default assumption.
-
clientConfig.exchanges = [
-
dedupExchange,
-
cacheExchange,
-
ssr,
-
fetchExchange,
-
];
+
clientConfig.exchanges = [cacheExchange, ssr, fetchExchange];
}
return initUrqlClient(clientConfig, shouldEnableSuspense)!;
···
const clientConfig = getClientConfig(ssrCache, ctx);
if (!clientConfig.exchanges) {
// When the user does not provide exchanges we make the default assumption.
-
clientConfig.exchanges = [
-
dedupExchange,
-
cacheExchange,
-
ssrCache,
-
fetchExchange,
-
];
+
clientConfig.exchanges = [cacheExchange, ssrCache, fetchExchange];
}
const urqlClient = initUrqlClient(clientConfig, !options!.neverSuspend);
+30 -12
packages/preact-urql/src/components/Mutation.ts
···
import { VNode } from 'preact';
import { DocumentNode } from 'graphql';
-
import {
-
AnyVariables,
-
TypedDocumentNode,
-
OperationResult,
-
OperationContext,
-
} from '@urql/core';
-
import { useMutation, UseMutationState } from '../hooks';
+
import { AnyVariables, TypedDocumentNode } from '@urql/core';
+
+
import { useMutation, UseMutationState, UseMutationExecute } from '../hooks';
+
/** Props accepted by {@link Mutation}.
+
*
+
* @remarks
+
* `MutationProps` are the props accepted by the {@link Mutation} component.
+
*
+
* The result, the {@link MutationState} object, will be passed to
+
* a {@link MutationProps.children} function, passed as children
+
* to the `Mutation` component.
+
*/
export interface MutationProps<
Data = any,
Variables extends AnyVariables = AnyVariables
> {
+
/* The GraphQL mutation document that {@link useMutation} will execute. */
query: DocumentNode | TypedDocumentNode<Data, Variables> | string;
-
children: (arg: MutationState<Data, Variables>) => VNode<any>;
+
children(arg: MutationState<Data, Variables>): VNode<any>;
}
+
/** Object that {@link MutationProps.children} is called with.
+
*
+
* @remarks
+
* This is an extented {@link UseMutationstate} with an added
+
* {@link MutationState.executeMutation} method, which is usually
+
* part of a tuple returned by {@link useMutation}.
+
*/
export interface MutationState<
Data = any,
Variables extends AnyVariables = AnyVariables
> extends UseMutationState<Data, Variables> {
-
executeMutation: (
-
variables: Variables,
-
context?: Partial<OperationContext>
-
) => Promise<OperationResult<Data, Variables>>;
+
/** Alias to {@link useMutation}’s `executeMutation` function. */
+
executeMutation: UseMutationExecute<Data, Variables>;
}
+
/** Component Wrapper around {@link useMutation} to run a GraphQL query.
+
*
+
* @remarks
+
* `Mutation` is a component wrapper around the {@link useMutation} hook
+
* that calls the {@link MutationProps.children} prop, as a function,
+
* with the {@link MutationState} object.
+
*/
export function Mutation<
Data = any,
Variables extends AnyVariables = AnyVariables
+35 -4
packages/preact-urql/src/components/Query.ts
···
import { VNode } from 'preact';
-
import { AnyVariables, OperationContext } from '@urql/core';
-
import { useQuery, UseQueryArgs, UseQueryState } from '../hooks';
+
import { AnyVariables } from '@urql/core';
+
+
import {
+
useQuery,
+
UseQueryArgs,
+
UseQueryState,
+
UseQueryExecute,
+
} from '../hooks';
+
/** Props accepted by {@link Query}.
+
*
+
* @remarks
+
* `QueryProps` are the props accepted by the {@link Query} component,
+
* which is identical to {@link UseQueryArgs}.
+
*
+
* The result, the {@link QueryState} object, will be passed to
+
* a {@link QueryProps.children} function, passed as children
+
* to the `Query` component.
+
*/
export type QueryProps<
Data = any,
Variables extends AnyVariables = AnyVariables
> = UseQueryArgs<Variables, Data> & {
-
children: (arg: QueryState<Data, Variables>) => VNode<any>;
+
children(arg: QueryState<Data, Variables>): VNode<any>;
};
+
/** Object that {@link QueryProps.children} is called with.
+
*
+
* @remarks
+
* This is an extented {@link UseQueryState} with an added
+
* {@link QueryState.executeQuery} method, which is usually
+
* part of a tuple returned by {@link useQuery}.
+
*/
export interface QueryState<
Data = any,
Variables extends AnyVariables = AnyVariables
> extends UseQueryState<Data, Variables> {
-
executeQuery: (opts?: Partial<OperationContext>) => void;
+
/** Alias to {@link useQuery}’s `executeQuery` function. */
+
executeQuery: UseQueryExecute;
}
+
/** Component Wrapper around {@link useQuery} to run a GraphQL query.
+
*
+
* @remarks
+
* `Query` is a component wrapper around the {@link useQuery} hook
+
* that calls the {@link QueryProps.children} prop, as a function,
+
* with the {@link QueryState} object.
+
*/
export function Query<
Data = any,
Variables extends AnyVariables = AnyVariables
+32 -3
packages/preact-urql/src/components/Subscription.ts
···
import { VNode } from 'preact';
-
import { AnyVariables, OperationContext } from '@urql/core';
+
import { AnyVariables } from '@urql/core';
import {
useSubscription,
UseSubscriptionArgs,
UseSubscriptionState,
+
UseSubscriptionExecute,
SubscriptionHandler,
} from '../hooks';
+
/** Props accepted by {@link Subscription}.
+
*
+
* @remarks
+
* `SubscriptionProps` are the props accepted by the {@link Subscription} component,
+
* which is identical to {@link UseSubscriptionArgs} with an added
+
* {@link SubscriptionProps.handler} prop, which {@link useSubscription} usually
+
* accepts as an additional argument.
+
*
+
* The result, the {@link SubscriptionState} object, will be passed to
+
* a {@link SubscriptionProps.children} function, passed as children
+
* to the `Subscription` component.
+
*/
export type SubscriptionProps<
Data = any,
Result = Data,
Variables extends AnyVariables = AnyVariables
> = UseSubscriptionArgs<Variables, Data> & {
+
/** Accepts the {@link SubscriptionHandler} as a prop. */
handler?: SubscriptionHandler<Data, Result>;
-
children: (arg: SubscriptionState<Result, Variables>) => VNode<any>;
+
children(arg: SubscriptionState<Result, Variables>): VNode<any>;
};
+
/** Object that {@link SubscriptionProps.children} is called with.
+
*
+
* @remarks
+
* This is an extented {@link UseSubscriptionState} with an added
+
* {@link SubscriptionState.executeSubscription} method, which is usually
+
* part of a tuple returned by {@link useSubscription}.
+
*/
export interface SubscriptionState<
Data = any,
Variables extends AnyVariables = AnyVariables
> extends UseSubscriptionState<Data, Variables> {
-
executeSubscription: (opts?: Partial<OperationContext>) => void;
+
/** Alias to {@link useSubscription}’s `executeMutation` function. */
+
executeSubscription: UseSubscriptionExecute;
}
+
/** Component Wrapper around {@link useSubscription} to run a GraphQL subscription.
+
*
+
* @remarks
+
* `Subscription` is a component wrapper around the {@link useSubscription} hook
+
* that calls the {@link SubscriptionProps.children} prop, as a function,
+
* with the {@link SubscriptionState} object.
+
*/
export function Subscription<
Data = any,
Result = Data,
+54
packages/preact-urql/src/context.ts
···
import { Client } from '@urql/core';
const OBJ = {};
+
+
/** `@urql/preact`'s Preact Context.
+
*
+
* @remarks
+
* The Preact Context that `urql`’s {@link Client} will be provided with.
+
* You may use the reexported {@link Provider} to provide a `Client` as well.
+
*/
export const Context: import('preact').Context<Client | object> =
createContext(OBJ);
+
+
/** Provider for `urql`’s {@link Client} to GraphQL hooks.
+
*
+
* @remarks
+
* `Provider` accepts a {@link Client} and provides it to all GraphQL hooks,
+
* and {@link useClient}.
+
*
+
* You should make sure to create a {@link Client} and provide it with the
+
* `Provider` to parts of your component tree that use GraphQL hooks.
+
*
+
* @example
+
* ```tsx
+
* import { Provider } from '@urql/preact';
+
* // All of `@urql/core` is also re-exported by `@urql/preact`:
+
* import { Client, cacheExchange, fetchExchange } from '@urql/core';
+
*
+
* const client = new Client({
+
* url: 'https://API',
+
* exchanges: [cacheExchange, fetchExchange],
+
* });
+
*
+
* const App = () => (
+
* <Provider value={client}>
+
* <Component />
+
* </Provider>
+
* );
+
* ```
+
*/
+
export const Provider: import('preact').Provider<Client | object> =
Context.Provider;
+
+
/** Preact Consumer component, providing the {@link Client} provided on a parent component.
+
* @remarks
+
* This is an alias for {@link Context.Consumer}.
+
*/
export const Consumer: import('preact').Consumer<Client | object> =
Context.Consumer;
Context.displayName = 'UrqlContext';
+
/** Hook returning a {@link Client} from {@link Context}.
+
*
+
* @remarks
+
* `useClient` is a convenience hook, which accesses `@urql/preact`'s {@link Context}
+
* and returns the {@link Client} defined on it.
+
*
+
* This will be the {@link Client} you passed to a {@link Provider}
+
* you wrapped your elements containing this hook with.
+
*
+
* @throws
+
* In development, if the component you call `useClient()` in is
+
* not wrapped in a {@link Provider}, an error is thrown.
+
*/
export const useClient = (): Client => {
const client = useContext(Context);
+110 -7
packages/preact-urql/src/hooks/useMutation.ts
···
import { useClient } from '../context';
import { initialState } from './constants';
+
/** State of the last mutation executed by your {@link useMutation} hook.
+
*
+
* @remarks
+
* `UseMutationState` is returned (in a tuple) by {@link useMutation} and
+
* gives you the {@link OperationResult} of the last mutation executed
+
* with {@link UseMutationExecute}.
+
*
+
* Even if the mutation document passed to {@link useMutation} changes,
+
* the state isn’t reset, so you can keep displaying the previous result.
+
*/
export interface UseMutationState<
Data = any,
Variables extends AnyVariables = AnyVariables
> {
+
/** Indicates whether `useMutation` is currently executing a mutation. */
fetching: 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: boolean;
+
/** The {@link OperationResult.data} for the executed mutation. */
data?: Data;
+
/** The {@link OperationResult.error} for the executed mutation. */
error?: CombinedError;
+
/** The {@link OperationResult.extensions} for the executed mutation. */
extensions?: Record<string, any>;
+
/** The {@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?: Operation<Data, Variables>;
}
+
/** 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 hook's
+
* {@link UseQueryArgs.context} options and 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 UseMutationState} will be updated with the result.
+
*
+
* @example
+
* ```ts
+
* const [result, executeMutation] = useMutation(UpdateTodo);
+
* const start = async ({ id, title }) => {
+
* const result = await executeMutation({ id, title });
+
* };
+
*/
+
export type UseMutationExecute<
+
Data = any,
+
Variables extends AnyVariables = AnyVariables
+
> = (
+
variables: Variables,
+
context?: Partial<OperationContext>
+
) => Promise<OperationResult<Data, Variables>>;
+
+
/** Result tuple returned by the {@link useMutation} hook.
+
*
+
* @remarks
+
* Similarly to a `useState` hook’s return value,
+
* the first element is the {@link useMutation}’s state, updated
+
* as mutations are executed with the second value, which is
+
* used to start mutations and is a {@link UseMutationExecute}
+
* function.
+
*/
export type UseMutationResponse<
Data = any,
Variables extends AnyVariables = AnyVariables
-
> = [
-
UseMutationState<Data, Variables>,
-
(
-
variables: Variables,
-
context?: Partial<OperationContext>
-
) => Promise<OperationResult<Data, Variables>>
-
];
+
> = [UseMutationState<Data, Variables>, UseMutationExecute<Data, Variables>];
+
/** Hook to create a GraphQL mutation, run by passing variables to the returned execute function.
+
*
+
* @param query - a GraphQL mutation document which `useMutation` will execute.
+
* @returns a {@link UseMutationResponse} tuple of a {@link UseMutationState} result,
+
* and an execute function to start the mutation.
+
*
+
* @remarks
+
* `useMutation` allows GraphQL mutations to be defined and keeps its state
+
* after the mutation is started with the returned execute function.
+
*
+
* Given a GraphQL mutation document it returns state to keep track of the
+
* mutation state and a {@link UseMutationExecute} function, which accepts
+
* variables for the mutation to be executed.
+
* Once called, the mutation executes and the state will be updated with
+
* the mutation’s result.
+
*
+
* @see {@link https://urql.dev/goto/docs/basics/react-preact/#mutations} for `useMutation` docs.
+
*
+
* @example
+
* ```ts
+
* import { gql, useMutation } from '@urql/preact';
+
*
+
* const UpdateTodo = gql`
+
* mutation ($id: ID!, $title: String!) {
+
* updateTodo(id: $id, title: $title) {
+
* id, title
+
* }
+
* }
+
* `;
+
*
+
* const UpdateTodo = () => {
+
* const [result, executeMutation] = useMutation(UpdateTodo);
+
* const start = async ({ id, title }) => {
+
* const result = await executeMutation({ id, title });
+
* };
+
* // ...
+
* };
+
* ```
+
*/
export function useMutation<
Data = any,
Variables extends AnyVariables = AnyVariables
+159 -5
packages/preact-urql/src/hooks/useQuery.ts
···
import { useRequest } from './useRequest';
import { initialState } from './constants';
+
/** Input arguments for the {@link useQuery} hook.
+
*
+
* @param query - The GraphQL query that `useQuery` executes.
+
* @param variables - The variables for the GraphQL query that `useQuery` executes.
+
*/
export type UseQueryArgs<
Variables extends AnyVariables = AnyVariables,
Data = any
> = {
+
/** 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?: 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.
+
*
+
* Hint: This should be wrapped in a `useMemo` hook, to make sure that your
+
* component doesn’t infinitely update.
+
*
+
* @example
+
* ```ts
+
* const [result, reexecute] = useQuery({
+
* query,
+
* context: useMemo(() => ({
+
* additionalTypenames: ['Item'],
+
* }), [])
+
* });
+
* ```
+
*/
context?: 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. The hook will stop receiving updates from the {@link Client}
+
* and won’t execute the query operation, until either it’s set to `false`
+
* or the {@link UseQueryExecute} function is called.
+
*
+
* @see {@link https://urql.dev/goto/docs/basics/react-preact/#pausing-usequery} for
+
* documentation on the `pause` option.
+
*/
pause?: boolean;
} & GraphQLRequestParams<Data, Variables>;
+
/** State of the current query, your {@link useQuery} hook is executing.
+
*
+
* @remarks
+
* `UseQueryState` is returned (in a tuple) by {@link useQuery} and
+
* gives you the updating {@link OperationResult} of GraphQL queries.
+
*
+
* Even when the query and variables passed to {@link useQuery} change,
+
* this state preserves the prior state and sets the `fetching` flag to
+
* `true`.
+
* This allows you to display the previous state, while implementing
+
* a separate loading indicator separately.
+
*/
export interface UseQueryState<
Data = any,
Variables extends AnyVariables = AnyVariables
> {
+
/** Indicates whether `useQuery` is waiting for a new result.
+
*
+
* @remarks
+
* When `useQuery` is passed 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: 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: boolean;
+
/** The {@link OperationResult.data} for the executed query. */
data?: Data;
+
/** The {@link OperationResult.error} for the executed query. */
error?: CombinedError;
+
/** The {@link OperationResult.extensions} for the executed query. */
extensions?: Record<string, any>;
+
/** The {@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?: Operation<Data, Variables>;
}
+
/** Triggers {@link useQuery} to execute a new GraphQL query operation.
+
*
+
* @remarks
+
* When called, {@link useQuery} will re-execute the GraphQL query operation
+
* it currently holds, even if {@link UseQueryArgs.pause} is set to `true`.
+
*
+
* This is useful for executing a paused query or re-executing a query
+
* and get a new network result, by passing a new request policy.
+
*
+
* ```ts
+
* const [result, reexecuteQuery] = useQuery({ query });
+
*
+
* const refresh = () => {
+
* // Re-execute the query with a network-only policy, skipping the cache
+
* reexecuteQuery({ requestPolicy: 'network-only' });
+
* };
+
* ```
+
*/
+
export type UseQueryExecute = (opts?: Partial<OperationContext>) => void;
+
+
/** Result tuple returned by the {@link useQuery} hook.
+
*
+
* @remarks
+
* Similarly to a `useState` hook’s return value,
+
* the first element is the {@link useQuery}’s result and state,
+
* a {@link UseQueryState} object,
+
* and the second is used to imperatively re-execute the query
+
* via a {@link UseQueryExecute} function.
+
*/
export type UseQueryResponse<
Data = any,
Variables extends AnyVariables = AnyVariables
-
> = [
-
UseQueryState<Data, Variables>,
-
(opts?: Partial<OperationContext>) => void
-
];
+
> = [UseQueryState<Data, Variables>, UseQueryExecute];
-
/** Convert the Source to a React Suspense source on demand */
+
/** Convert the Source to a React Suspense source on demand
+
* @internal
+
*/
function toSuspenseSource<T>(source: Source<T>): Source<T> {
const shared = share(source);
let cache: T | void;
···
const sources = new Map<number, Source<OperationResult>>();
+
/** Hook to run a GraphQL query and get updated GraphQL results.
+
*
+
* @param args - a {@link UseQueryArgs} object, to pass a `query`, `variables`, and options.
+
* @returns a {@link UseQueryResponse} tuple of a {@link UseQueryState} result, and re-execute function.
+
*
+
* @remarks
+
* `useQuery` allows GraphQL queries to be defined and executed.
+
* Given {@link UseQueryArgs.query}, it executes the GraphQL query with the
+
* context’s {@link Client}.
+
*
+
* The returned result updates when the `Client` has new results
+
* for the query, and changes when your input `args` change.
+
*
+
* Additionally, if the `suspense` option is enabled on the `Client`,
+
* the `useQuery` hook will suspend instead of indicating that it’s
+
* waiting for a result via {@link UseQueryState.fetching}.
+
*
+
* @see {@link https://urql.dev/goto/docs/basics/react-preact/#queries} for `useQuery` docs.
+
*
+
* @example
+
* ```ts
+
* import { gql, useQuery } from '@urql/preact';
+
*
+
* const TodosQuery = gql`
+
* query { todos { id, title } }
+
* `;
+
*
+
* const Todos = () => {
+
* const [result, reexecuteQuery] = useQuery({
+
* query: TodosQuery,
+
* variables: {},
+
* });
+
* // ...
+
* };
+
* ```
+
*/
export function useQuery<
Data = any,
Variables extends AnyVariables = AnyVariables
+3 -1
packages/preact-urql/src/hooks/useRequest.ts
···
createRequest,
} from '@urql/core';
-
/** Creates a request from a query and variables but preserves reference equality if the key isn't changing */
+
/** Creates a request from a query and variables but preserves reference equality if the key isn't changing
+
* @internal
+
*/
export function useRequest<
Data = any,
Variables extends AnyVariables = AnyVariables
+175 -4
packages/preact-urql/src/hooks/useSubscription.ts
···
import { useRequest } from './useRequest';
import { initialState } from './constants';
+
/** Input arguments for the {@link useSubscription} hook.
+
*
+
* @param query - The GraphQL subscription document that `useSubscription` executes.
+
* @param variables - The variables for the GraphQL subscription that `useSubscription` executes.
+
*/
export type UseSubscriptionArgs<
Variables extends AnyVariables = AnyVariables,
Data = any
> = {
+
/** Prevents {@link useSubscription} from automatically starting GraphQL subscriptions.
+
*
+
* @remarks
+
* `pause` may be set to `true` to stop {@link useSubscription} from starting its subscription
+
* automatically. The hook will stop receiving updates from the {@link Client}
+
* and won’t start the subscription operation, until either it’s set to `false`
+
* or the {@link UseSubscriptionExecute} function is called.
+
*/
pause?: 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.
+
*
+
* Hint: This should be wrapped in a `useMemo` hook, to make sure that your
+
* component doesn’t infinitely update.
+
*
+
* @example
+
* ```ts
+
* const [result, reexecute] = useSubscription({
+
* query,
+
* context: useMemo(() => ({
+
* additionalTypenames: ['Item'],
+
* }), [])
+
* });
+
* ```
+
*/
context?: Partial<OperationContext>;
} & GraphQLRequestParams<Data, 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 UseSubscriptionState.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, executeSubscription] = useSubscription(
+
* { query: NotificationsSubscription },
+
* combineNotifications,
+
* );
+
* ```
+
*/
export type SubscriptionHandler<T, R> = (prev: R | undefined, data: T) => R;
+
/** State of the current subscription, your {@link useSubscription} hook is executing.
+
*
+
* @remarks
+
* `UseSubscriptionState` is returned (in a tuple) by {@link useSubscription} and
+
* gives you the updating {@link OperationResult} of GraphQL subscriptions.
+
*
+
* If a {@link SubscriptionHandler} has been passed to `useSubscription` then
+
* {@link UseSubscriptionState.data} is instead the updated data as returned
+
* by the handler, otherwise it’s the latest result’s data.
+
*
+
* Hint: Even when the query and variables passed to {@link useSubscription} change,
+
* this state preserves the prior state.
+
*/
export interface UseSubscriptionState<
Data = any,
Variables 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 the {@link UseSubscriptionArgs.pause}
+
* flag is set to `true`.
+
*/
fetching: 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: boolean;
+
/** The {@link OperationResult.data} for the executed subscription, or data returned by a 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?: Data;
+
/** The {@link OperationResult.error} for the executed subscription. */
error?: CombinedError;
+
/** The {@link OperationResult.extensions} for the executed mutation. */
extensions?: Record<string, any>;
+
/** The {@link Operation} that the current state is for.
+
*
+
* @remarks
+
* This is the subscription {@link Operation} that is currently active.
+
* When {@link UseSubscriptionState.fetching} is `true`, this is the
+
* last `Operation` that the current state was for.
+
*/
operation?: Operation<Data, Variables>;
}
+
/** Triggers {@link useSubscription} to reexecute a GraphQL subscription operation.
+
*
+
* @param opts - optionally, context options that will be merged with the hook's
+
* {@link UseSubscriptionArgs.context} options and the `Client`’s options.
+
*
+
* @remarks
+
* When called, {@link useSubscription} will restart the GraphQL subscription
+
* operation it currently holds. If {@link UseSubscriptionArgs.pause} is set
+
* to `true`, it will start executing the subscription.
+
*
+
* ```ts
+
* const [result, executeSubscription] = useSubscription({
+
* query,
+
* pause: true,
+
* });
+
*
+
* const start = () => {
+
* executeSubscription();
+
* };
+
* ```
+
*/
+
export type UseSubscriptionExecute = (opts?: Partial<OperationContext>) => void;
+
+
/** Result tuple returned by the {@link useSubscription} hook.
+
*
+
* @remarks
+
* Similarly to a `useState` hook’s return value,
+
* the first element is the {@link useSubscription}’s state,
+
* a {@link UseSubscriptionState} object,
+
* and the second is used to imperatively re-execute or start the subscription
+
* via a {@link UseMutationExecute} function.
+
*/
export type UseSubscriptionResponse<
Data = any,
Variables extends AnyVariables = AnyVariables
-
> = [
-
UseSubscriptionState<Data, Variables>,
-
(opts?: Partial<OperationContext>) => void
-
];
+
> = [UseSubscriptionState<Data, Variables>, UseSubscriptionExecute];
+
/** Hook to run a GraphQL subscription and get updated 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} tuple of a {@link UseSubscriptionState} result, and an execute function.
+
*
+
* @remarks
+
* `useSubscription` allows GraphQL subscriptions to be defined and executed.
+
* Given {@link UseSubscriptionArgs.query}, it executes the GraphQL subscription with the
+
* context’s {@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/preact';
+
*
+
* const NotificationsSubscription = gql`
+
* subscription { newNotification { id, text } }
+
* `;
+
*
+
* const combineNotifications = (notifications = [], data) => {
+
* return [...notifications, data.newNotification];
+
* };
+
*
+
* const Notifications = () => {
+
* const [result, executeSubscription] = useSubscription(
+
* { query: NotificationsSubscription },
+
* combineNotifications,
+
* );
+
* // ...
+
* };
+
* ```
+
*/
export function useSubscription<
Data = any,
Result = Data,
+30 -12
packages/react-urql/src/components/Mutation.ts
···
import { DocumentNode } from 'graphql';
import { ReactElement } from 'react';
-
import {
-
AnyVariables,
-
TypedDocumentNode,
-
OperationResult,
-
OperationContext,
-
} from '@urql/core';
-
import { useMutation, UseMutationState } from '../hooks';
+
import { AnyVariables, TypedDocumentNode } from '@urql/core';
+
+
import { useMutation, UseMutationState, UseMutationExecute } from '../hooks';
+
/** Props accepted by {@link Mutation}.
+
*
+
* @remarks
+
* `MutationProps` are the props accepted by the {@link Mutation} component.
+
*
+
* The result, the {@link MutationState} object, will be passed to
+
* a {@link MutationProps.children} function, passed as children
+
* to the `Mutation` component.
+
*/
export interface MutationProps<
Data = any,
Variables extends AnyVariables = AnyVariables
> {
+
/* The GraphQL mutation document that {@link useMutation} will execute. */
query: DocumentNode | TypedDocumentNode<Data, Variables> | string;
-
children: (arg: MutationState<Data, Variables>) => ReactElement<any>;
+
children(arg: MutationState<Data, Variables>): ReactElement<any>;
}
+
/** Object that {@link MutationProps.children} is called with.
+
*
+
* @remarks
+
* This is an extented {@link UseMutationstate} with an added
+
* {@link MutationState.executeMutation} method, which is usually
+
* part of a tuple returned by {@link useMutation}.
+
*/
export interface MutationState<
Data = any,
Variables extends AnyVariables = AnyVariables
> extends UseMutationState<Data, Variables> {
-
executeMutation: (
-
variables: Variables,
-
context?: Partial<OperationContext>
-
) => Promise<OperationResult<Data, Variables>>;
+
/** Alias to {@link useMutation}’s `executeMutation` function. */
+
executeMutation: UseMutationExecute<Data, Variables>;
}
+
/** Component Wrapper around {@link useMutation} to run a GraphQL query.
+
*
+
* @remarks
+
* `Mutation` is a component wrapper around the {@link useMutation} hook
+
* that calls the {@link MutationProps.children} prop, as a function,
+
* with the {@link MutationState} object.
+
*/
export function Mutation<
Data = any,
Variables extends AnyVariables = AnyVariables
+35 -4
packages/react-urql/src/components/Query.ts
···
import { ReactElement } from 'react';
-
import { AnyVariables, OperationContext } from '@urql/core';
-
import { useQuery, UseQueryArgs, UseQueryState } from '../hooks';
+
import { AnyVariables } from '@urql/core';
+
+
import {
+
useQuery,
+
UseQueryArgs,
+
UseQueryState,
+
UseQueryExecute,
+
} from '../hooks';
+
/** Props accepted by {@link Query}.
+
*
+
* @remarks
+
* `QueryProps` are the props accepted by the {@link Query} component,
+
* which is identical to {@link UseQueryArgs}.
+
*
+
* The result, the {@link QueryState} object, will be passed to
+
* a {@link QueryProps.children} function, passed as children
+
* to the `Query` component.
+
*/
export type QueryProps<
Data = any,
Variables extends AnyVariables = AnyVariables
> = UseQueryArgs<Variables, Data> & {
-
children: (arg: QueryState<Data, Variables>) => ReactElement<any>;
+
children(arg: QueryState<Data, Variables>): ReactElement<any>;
};
+
/** Object that {@link QueryProps.children} is called with.
+
*
+
* @remarks
+
* This is an extented {@link UseQueryState} with an added
+
* {@link QueryState.executeQuery} method, which is usually
+
* part of a tuple returned by {@link useQuery}.
+
*/
export interface QueryState<
Data = any,
Variables extends AnyVariables = AnyVariables
> extends UseQueryState<Data, Variables> {
-
executeQuery: (opts?: Partial<OperationContext>) => void;
+
/** Alias to {@link useQuery}’s `executeQuery` function. */
+
executeQuery: UseQueryExecute;
}
+
/** Component Wrapper around {@link useQuery} to run a GraphQL query.
+
*
+
* @remarks
+
* `Query` is a component wrapper around the {@link useQuery} hook
+
* that calls the {@link QueryProps.children} prop, as a function,
+
* with the {@link QueryState} object.
+
*/
export function Query<
Data = any,
Variables extends AnyVariables = AnyVariables
+31 -3
packages/react-urql/src/components/Subscription.ts
···
import { ReactElement } from 'react';
-
import { AnyVariables, OperationContext } from '@urql/core';
+
import { AnyVariables } from '@urql/core';
import {
useSubscription,
UseSubscriptionArgs,
UseSubscriptionState,
+
UseSubscriptionExecute,
SubscriptionHandler,
} from '../hooks';
+
/** Props accepted by {@link Subscription}.
+
*
+
* @remarks
+
* `SubscriptionProps` are the props accepted by the {@link Subscription} component,
+
* which is identical to {@link UseSubscriptionArgs} with an added
+
* {@link SubscriptionProps.handler} prop, which {@link useSubscription} usually
+
* accepts as an additional argument.
+
*
+
* The result, the {@link SubscriptionState} object, will be passed to
+
* a {@link SubscriptionProps.children} function, passed as children
+
* to the `Subscription` component.
+
*/
export type SubscriptionProps<
Data = any,
Result = Data,
Variables extends AnyVariables = AnyVariables
> = UseSubscriptionArgs<Variables, Data> & {
handler?: SubscriptionHandler<Data, Result>;
-
children: (arg: SubscriptionState<Result, Variables>) => ReactElement<any>;
+
children(arg: SubscriptionState<Result, Variables>): ReactElement<any>;
};
+
/** Object that {@link SubscriptionProps.children} is called with.
+
*
+
* @remarks
+
* This is an extented {@link UseSubscriptionState} with an added
+
* {@link SubscriptionState.executeSubscription} method, which is usually
+
* part of a tuple returned by {@link useSubscription}.
+
*/
export interface SubscriptionState<
Data = any,
Variables extends AnyVariables = AnyVariables
> extends UseSubscriptionState<Data, Variables> {
-
executeSubscription: (opts?: Partial<OperationContext>) => void;
+
/** Alias to {@link useSubscription}’s `executeMutation` function. */
+
executeSubscription: UseSubscriptionExecute;
}
+
/** Component Wrapper around {@link useSubscription} to run a GraphQL subscription.
+
*
+
* @remarks
+
* `Subscription` is a component wrapper around the {@link useSubscription} hook
+
* that calls the {@link SubscriptionProps.children} prop, as a function,
+
* with the {@link SubscriptionState} object.
+
*/
export function Subscription<
Data = any,
Result = Data,
+53
packages/react-urql/src/context.ts
···
import { Client } from '@urql/core';
const OBJ = {};
+
+
/** `urql`'s React Context.
+
*
+
* @remarks
+
* The React Context that `urql`’s {@link Client} will be provided with.
+
* You may use the reexported {@link Provider} to provide a `Client` as well.
+
*/
export const Context: import('react').Context<Client | object> =
createContext(OBJ);
+
+
/** Provider for `urql`'s {@link Client} to GraphQL hooks.
+
*
+
* @remarks
+
* `Provider` accepts a {@link Client} and provides it to all GraphQL hooks,
+
* and {@link useClient}.
+
*
+
* You should make sure to create a {@link Client} and provide it with the
+
* `Provider` to parts of your component tree that use GraphQL hooks.
+
*
+
* @example
+
* ```tsx
+
* import { Provider } from 'urql';
+
* // All of `@urql/core` is also re-exported by `urql`:
+
* import { Client, cacheExchange, fetchExchange } from '@urql/core';
+
*
+
* const client = new Client({
+
* url: 'https://API',
+
* exchanges: [cacheExchange, fetchExchange],
+
* });
+
*
+
* const App = () => (
+
* <Provider value={client}>
+
* <Component />
+
* </Provider>
+
* );
+
* ```
+
*/
export const Provider: import('react').Provider<Client | object> =
Context.Provider;
+
+
/** React Consumer component, providing the {@link Client} provided on a parent component.
+
* @remarks
+
* This is an alias for {@link Context.Consumer}.
+
*/
export const Consumer: import('react').Consumer<Client | object> =
Context.Consumer;
Context.displayName = 'UrqlContext';
+
/** Hook returning a {@link Client} from {@link Context}.
+
*
+
* @remarks
+
* `useClient` is a convenience hook, which accesses `urql`'s {@link Context}
+
* and returns the {@link Client} defined on it.
+
*
+
* This will be the {@link Client} you passed to a {@link Provider}
+
* you wrapped your elements containing this hook with.
+
*
+
* @throws
+
* In development, if the component you call `useClient()` in is
+
* not wrapped in a {@link Provider}, an error is thrown.
+
*/
export const useClient = (): Client => {
const client = useContext(Context);
+110 -7
packages/react-urql/src/hooks/useMutation.ts
···
import { useClient } from '../context';
import { initialState } from './state';
+
/** State of the last mutation executed by your {@link useMutation} hook.
+
*
+
* @remarks
+
* `UseMutationState` is returned (in a tuple) by {@link useMutation} and
+
* gives you the {@link OperationResult} of the last mutation executed
+
* with {@link UseMutationExecute}.
+
*
+
* Even if the mutation document passed to {@link useMutation} changes,
+
* the state isn’t reset, so you can keep displaying the previous result.
+
*/
export interface UseMutationState<
Data = any,
Variables extends AnyVariables = AnyVariables
> {
+
/** Indicates whether `useMutation` is currently executing a mutation. */
fetching: 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: boolean;
+
/** The {@link OperationResult.data} for the executed mutation. */
data?: Data;
+
/** The {@link OperationResult.error} for the executed mutation. */
error?: CombinedError;
+
/** The {@link OperationResult.extensions} for the executed mutation. */
extensions?: Record<string, any>;
+
/** The {@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?: Operation<Data, Variables>;
}
+
/** 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 hook's
+
* {@link UseQueryArgs.context} options and 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 UseMutationState} will be updated with the result.
+
*
+
* @example
+
* ```ts
+
* const [result, executeMutation] = useMutation(UpdateTodo);
+
* const start = async ({ id, title }) => {
+
* const result = await executeMutation({ id, title });
+
* };
+
*/
+
export type UseMutationExecute<
+
Data = any,
+
Variables extends AnyVariables = AnyVariables
+
> = (
+
variables: Variables,
+
context?: Partial<OperationContext>
+
) => Promise<OperationResult<Data, Variables>>;
+
+
/** Result tuple returned by the {@link useMutation} hook.
+
*
+
* @remarks
+
* Similarly to a `useState` hook’s return value,
+
* the first element is the {@link useMutation}’s state, updated
+
* as mutations are executed with the second value, which is
+
* used to start mutations and is a {@link UseMutationExecute}
+
* function.
+
*/
export type UseMutationResponse<
Data = any,
Variables extends AnyVariables = AnyVariables
-
> = [
-
UseMutationState<Data, Variables>,
-
(
-
variables: Variables,
-
context?: Partial<OperationContext>
-
) => Promise<OperationResult<Data, Variables>>
-
];
+
> = [UseMutationState<Data, Variables>, UseMutationExecute<Data, Variables>];
+
/** Hook to create a GraphQL mutation, run by passing variables to the returned execute function.
+
*
+
* @param query - a GraphQL mutation document which `useMutation` will execute.
+
* @returns a {@link UseMutationResponse} tuple of a {@link UseMutationState} result,
+
* and an execute function to start the mutation.
+
*
+
* @remarks
+
* `useMutation` allows GraphQL mutations to be defined and keeps its state
+
* after the mutation is started with the returned execute function.
+
*
+
* Given a GraphQL mutation document it returns state to keep track of the
+
* mutation state and a {@link UseMutationExecute} function, which accepts
+
* variables for the mutation to be executed.
+
* Once called, the mutation executes and the state will be updated with
+
* the mutation’s result.
+
*
+
* @see {@link https://urql.dev/goto/urql/docs/basics/react-preact/#mutations} for `useMutation` docs.
+
*
+
* @example
+
* ```ts
+
* import { gql, useMutation } from 'urql';
+
*
+
* const UpdateTodo = gql`
+
* mutation ($id: ID!, $title: String!) {
+
* updateTodo(id: $id, title: $title) {
+
* id, title
+
* }
+
* }
+
* `;
+
*
+
* const UpdateTodo = () => {
+
* const [result, executeMutation] = useMutation(UpdateTodo);
+
* const start = async ({ id, title }) => {
+
* const result = await executeMutation({ id, title });
+
* };
+
* // ...
+
* };
+
* ```
+
*/
export function useMutation<
Data = any,
Variables extends AnyVariables = AnyVariables
+159 -4
packages/react-urql/src/hooks/useQuery.ts
···
import { getCacheForClient } from './cache';
import { initialState, computeNextState, hasDepsChanged } from './state';
+
/** Input arguments for the {@link useQuery} hook.
+
*
+
* @param query - The GraphQL query that `useQuery` executes.
+
* @param variables - The variables for the GraphQL query that `useQuery` executes.
+
*/
export type UseQueryArgs<
Variables extends AnyVariables = AnyVariables,
Data = any
> = {
+
/** 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?: 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.
+
*
+
* Hint: This should be wrapped in a `useMemo` hook, to make sure that your
+
* component doesn’t infinitely update.
+
*
+
* @example
+
* ```ts
+
* const [result, reexecute] = useQuery({
+
* query,
+
* context: useMemo(() => ({
+
* additionalTypenames: ['Item'],
+
* }), [])
+
* });
+
* ```
+
*/
context?: 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. The hook will stop receiving updates from the {@link Client}
+
* and won’t execute the query operation, until either it’s set to `false`
+
* or the {@link UseQueryExecute} function is called.
+
*
+
* @see {@link https://urql.dev/goto/docs/basics/react-preact/#pausing-usequery} for
+
* documentation on the `pause` option.
+
*/
pause?: boolean;
} & GraphQLRequestParams<Data, Variables>;
+
/** State of the current query, your {@link useQuery} hook is executing.
+
*
+
* @remarks
+
* `UseQueryState` is returned (in a tuple) by {@link useQuery} and
+
* gives you the updating {@link OperationResult} of GraphQL queries.
+
*
+
* Even when the query and variables passed to {@link useQuery} change,
+
* this state preserves the prior state and sets the `fetching` flag to
+
* `true`.
+
* This allows you to display the previous state, while implementing
+
* a separate loading indicator separately.
+
*/
export interface UseQueryState<
Data = any,
Variables extends AnyVariables = AnyVariables
> {
+
/** Indicates whether `useQuery` is waiting for a new result.
+
*
+
* @remarks
+
* When `useQuery` is passed 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: 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: boolean;
+
/** The {@link OperationResult.data} for the executed query. */
data?: Data;
+
/** The {@link OperationResult.error} for the executed query. */
error?: CombinedError;
+
/** The {@link OperationResult.extensions} for the executed query. */
extensions?: Record<string, any>;
+
/** The {@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?: Operation<Data, Variables>;
}
+
/** Triggers {@link useQuery} to execute a new GraphQL query operation.
+
*
+
* @param opts - optionally, context options that will be merged with the hook's
+
* {@link UseQueryArgs.context} options and the `Client`’s options.
+
*
+
* @remarks
+
* When called, {@link useQuery} will re-execute the GraphQL query operation
+
* it currently holds, even if {@link UseQueryArgs.pause} is set to `true`.
+
*
+
* This is useful for executing a paused query or re-executing a query
+
* and get a new network result, by passing a new request policy.
+
*
+
* ```ts
+
* const [result, reexecuteQuery] = useQuery({ query });
+
*
+
* const refresh = () => {
+
* // Re-execute the query with a network-only policy, skipping the cache
+
* reexecuteQuery({ requestPolicy: 'network-only' });
+
* };
+
* ```
+
*/
+
export type UseQueryExecute = (opts?: Partial<OperationContext>) => void;
+
+
/** Result tuple returned by the {@link useQuery} hook.
+
*
+
* @remarks
+
* Similarly to a `useState` hook’s return value,
+
* the first element is the {@link useQuery}’s result and state,
+
* a {@link UseQueryState} object,
+
* and the second is used to imperatively re-execute the query
+
* via a {@link UseQueryExecute} function.
+
*/
export type UseQueryResponse<
Data = any,
Variables extends AnyVariables = AnyVariables
-
> = [
-
UseQueryState<Data, Variables>,
-
(opts?: Partial<OperationContext>) => void
-
];
+
> = [UseQueryState<Data, Variables>, UseQueryExecute];
const isSuspense = (client: Client, context?: Partial<OperationContext>) =>
client.suspense && (!context || context.suspense !== false);
+
/** Hook to run a GraphQL query and get updated GraphQL results.
+
*
+
* @param args - a {@link UseQueryArgs} object, to pass a `query`, `variables`, and options.
+
* @returns a {@link UseQueryResponse} tuple of a {@link UseQueryState} result, and re-execute function.
+
*
+
* @remarks
+
* `useQuery` allows GraphQL queries to be defined and executed.
+
* Given {@link UseQueryArgs.query}, it executes the GraphQL query with the
+
* context’s {@link Client}.
+
*
+
* The returned result updates when the `Client` has new results
+
* for the query, and changes when your input `args` change.
+
*
+
* Additionally, if the `suspense` option is enabled on the `Client`,
+
* the `useQuery` hook will suspend instead of indicating that it’s
+
* waiting for a result via {@link UseQueryState.fetching}.
+
*
+
* @see {@link https://urql.dev/goto/urql/docs/basics/react-preact/#queries} for `useQuery` docs.
+
*
+
* @example
+
* ```ts
+
* import { gql, useQuery } from 'urql';
+
*
+
* const TodosQuery = gql`
+
* query { todos { id, title } }
+
* `;
+
*
+
* const Todos = () => {
+
* const [result, reexecuteQuery] = useQuery({
+
* query: TodosQuery,
+
* variables: {},
+
* });
+
* // ...
+
* };
+
* ```
+
*/
export function useQuery<
Data = any,
Variables extends AnyVariables = AnyVariables
+3 -1
packages/react-urql/src/hooks/useRequest.ts
···
createRequest,
} from '@urql/core';
-
/** Creates a request from a query and variables but preserves reference equality if the key isn't changing */
+
/** Creates a request from a query and variables but preserves reference equality if the key isn't changing
+
* @internal
+
*/
export function useRequest<
Data = any,
Variables extends AnyVariables = AnyVariables
+175 -4
packages/react-urql/src/hooks/useSubscription.ts
···
import { useRequest } from './useRequest';
import { initialState, computeNextState, hasDepsChanged } from './state';
+
/** Input arguments for the {@link useSubscription} hook.
+
*
+
* @param query - The GraphQL subscription document that `useSubscription` executes.
+
* @param variables - The variables for the GraphQL subscription that `useSubscription` executes.
+
*/
export type UseSubscriptionArgs<
Variables extends AnyVariables = AnyVariables,
Data = any
> = {
+
/** Prevents {@link useSubscription} from automatically starting GraphQL subscriptions.
+
*
+
* @remarks
+
* `pause` may be set to `true` to stop {@link useSubscription} from starting its subscription
+
* automatically. The hook will stop receiving updates from the {@link Client}
+
* and won’t start the subscription operation, until either it’s set to `false`
+
* or the {@link UseSubscriptionExecute} function is called.
+
*/
pause?: 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.
+
*
+
* Hint: This should be wrapped in a `useMemo` hook, to make sure that your
+
* component doesn’t infinitely update.
+
*
+
* @example
+
* ```ts
+
* const [result, reexecute] = useSubscription({
+
* query,
+
* context: useMemo(() => ({
+
* additionalTypenames: ['Item'],
+
* }), [])
+
* });
+
* ```
+
*/
context?: Partial<OperationContext>;
} & GraphQLRequestParams<Data, 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 UseSubscriptionState.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, executeSubscription] = useSubscription(
+
* { query: NotificationsSubscription },
+
* combineNotifications,
+
* );
+
* ```
+
*/
export type SubscriptionHandler<T, R> = (prev: R | undefined, data: T) => R;
+
/** State of the current subscription, your {@link useSubscription} hook is executing.
+
*
+
* @remarks
+
* `UseSubscriptionState` is returned (in a tuple) by {@link useSubscription} and
+
* gives you the updating {@link OperationResult} of GraphQL subscriptions.
+
*
+
* If a {@link SubscriptionHandler} has been passed to `useSubscription` then
+
* {@link UseSubscriptionState.data} is instead the updated data as returned
+
* by the handler, otherwise it’s the latest result’s data.
+
*
+
* Hint: Even when the query and variables passed to {@link useSubscription} change,
+
* this state preserves the prior state.
+
*/
export interface UseSubscriptionState<
Data = any,
Variables 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 the {@link UseSubscriptionArgs.pause}
+
* flag is set to `true`.
+
*/
fetching: 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: boolean;
+
/** The {@link OperationResult.data} for the executed subscription, or data returned by a 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?: Data;
+
/** The {@link OperationResult.error} for the executed subscription. */
error?: CombinedError;
+
/** The {@link OperationResult.extensions} for the executed mutation. */
extensions?: Record<string, any>;
+
/** The {@link Operation} that the current state is for.
+
*
+
* @remarks
+
* This is the subscription {@link Operation} that is currently active.
+
* When {@link UseSubscriptionState.fetching} is `true`, this is the
+
* last `Operation` that the current state was for.
+
*/
operation?: Operation<Data, Variables>;
}
+
/** Triggers {@link useSubscription} to reexecute a GraphQL subscription operation.
+
*
+
* @param opts - optionally, context options that will be merged with the hook's
+
* {@link UseSubscriptionArgs.context} options and the `Client`’s options.
+
*
+
* @remarks
+
* When called, {@link useSubscription} will restart the GraphQL subscription
+
* operation it currently holds. If {@link UseSubscriptionArgs.pause} is set
+
* to `true`, it will start executing the subscription.
+
*
+
* ```ts
+
* const [result, executeSubscription] = useSubscription({
+
* query,
+
* pause: true,
+
* });
+
*
+
* const start = () => {
+
* executeSubscription();
+
* };
+
* ```
+
*/
+
export type UseSubscriptionExecute = (opts?: Partial<OperationContext>) => void;
+
+
/** Result tuple returned by the {@link useSubscription} hook.
+
*
+
* @remarks
+
* Similarly to a `useState` hook’s return value,
+
* the first element is the {@link useSubscription}’s state,
+
* a {@link UseSubscriptionState} object,
+
* and the second is used to imperatively re-execute or start the subscription
+
* via a {@link UseMutationExecute} function.
+
*/
export type UseSubscriptionResponse<
Data = any,
Variables extends AnyVariables = AnyVariables
-
> = [
-
UseSubscriptionState<Data, Variables>,
-
(opts?: Partial<OperationContext>) => void
-
];
+
> = [UseSubscriptionState<Data, Variables>, UseSubscriptionExecute];
+
/** Hook to run a GraphQL subscription and get updated 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} tuple of a {@link UseSubscriptionState} result, and an execute function.
+
*
+
* @remarks
+
* `useSubscription` allows GraphQL subscriptions to be defined and executed.
+
* Given {@link UseSubscriptionArgs.query}, it executes the GraphQL subscription with the
+
* context’s {@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';
+
*
+
* const NotificationsSubscription = gql`
+
* subscription { newNotification { id, text } }
+
* `;
+
*
+
* const combineNotifications = (notifications = [], data) => {
+
* return [...notifications, data.newNotification];
+
* };
+
*
+
* const Notifications = () => {
+
* const [result, executeSubscription] = useSubscription(
+
* { query: NotificationsSubscription },
+
* combineNotifications,
+
* );
+
* // ...
+
* };
+
* ```
+
*/
export function useSubscription<
Data = any,
Result = Data,
+27 -3
packages/storage-rn/src/makeAsyncStorage.ts
···
import AsyncStorage from '@react-native-async-storage/async-storage';
import NetInfo from '@react-native-community/netinfo';
-
export type StorageOptions = {
+
export interface StorageOptions {
+
/** Name of the `AsyncStorage` key that’s used for persisted data.
+
* @defaultValue `'graphcache-data'`
+
*/
dataKey?: string;
+
/** Name of the `AsyncStorage` key that’s used for persisted metadata.
+
* @defaultValue `'graphcache-metadata'`
+
*/
metadataKey?: string;
-
maxAge?: number; // Number of days
-
};
+
/** Maximum age of cache entries (in days) after which data is discarded.
+
* @defaultValue `7` days
+
*/
+
maxAge?: number;
+
}
const parseData = (persistedData: any, fallback: any) => {
try {
···
let disconnect;
+
/** React Native storage adapter persisting to `AsyncStorage`. */
export interface DefaultAsyncStorage extends StorageAdapter {
+
/** Clears the entire `AsyncStorage`. */
clear(): Promise<any>;
}
+
/** Creates a {@link StorageAdapter} which uses React Native’s `AsyncStorage`.
+
*
+
* @param opts - A {@link StorageOptions} configuration object.
+
* @returns the created {@link DefaultAsyncStorage} adapter.
+
*
+
* @remarks
+
* `makeAsyncStorage` creates a storage adapter for React Native,
+
* which persisted to `AsyncStorage` via the `@react-native-async-storage/async-storage`
+
* package.
+
*
+
* Note: We have no data on stability of this storage and our Offline Support
+
* for large APIs or longterm use. Proceed with caution.
+
*/
export const makeAsyncStorage: (
ops?: StorageOptions
) => DefaultAsyncStorage = ({
+64 -1
packages/svelte-urql/src/common.ts
···
import type { AnyVariables, OperationResult } from '@urql/core';
import { Source, make } from 'wonka';
+
/** An {@link OperationResult} with an added {@link OperationResultState.fetching} flag.
+
*
+
* @remarks
+
* Stores will contain a readable state based on {@link OperationResult | OperationResults}
+
* they received.
+
*/
export interface OperationResultState<
Data = any,
Variables extends AnyVariables = AnyVariables
> extends OperationResult<Data, Variables> {
+
/** Indicates whether the store is waiting for a new {@link OperationResult}.
+
*
+
* @remarks
+
* When a store starts executing a GraphQL operation, `fetching` is
+
* set to `true` until a result arrives.
+
*
+
* Hint: This is subtly different than whether the operation is actually
+
* fetching, and doesn’t indicate whether an operation is being re-executed
+
* in the background. For this, see {@link OperationResult.stale}.
+
*/
fetching: boolean;
}
-
/** A Readable containing an `OperationResult` with a fetching flag. */
+
/** A Readable store of {@link OperationResultState}. */
export type OperationResultStore<
Data = any,
Variables extends AnyVariables = AnyVariables
> = Readable<OperationResultState<Data, Variables>>;
+
/** Consumes a {@link Readable} as a {@link Source}.
+
* @internal
+
*/
export const fromStore = <T>(store$: Readable<T>): Source<T> =>
make(observer => store$.subscribe(observer.next));
···
stale: false,
};
+
/** A pausable Svelte store.
+
*
+
* @remarks
+
* The {@link queryStore} and {@link useSubscription} store allow
+
* you to pause execution and resume it later on, which is managed
+
* by a `pause` option passed to them.
+
*
+
* A `Pauseable` allows execution of GraphQL operations to be paused,
+
* which means a {@link OperationResultStore} won’t update with new
+
* results or execute new operations, and to be resumed later on.
+
*/
export interface Pausable {
+
/** Indicates whether a store is currently paused.
+
*
+
* @remarks
+
* When a {@link OperationResultStore} has been paused, it will stop
+
* receiving updates from the {@link Client} and won’t execute GraphQL
+
* operations, until this writable becomes `true` or
+
* {@link Pausable.resume} is called.
+
*
+
* @see {@link https://urql.dev/goto/docs/basics/svelte#pausing-queries} for
+
* documentation on the `Pausable`.
+
*/
isPaused$: Writable<boolean>;
+
/** Pauses a GraphQL operation to stop it from executing.
+
*
+
* @remarks
+
* Pauses an {@link OperationResultStore}’s GraphQL operation, which
+
* stops it from receiving updates from the {@link Client} and to stop
+
* an ongoing operation.
+
*
+
* @see {@link https://urql.dev/goto/docs/basics/svelte#pausing-queries} for
+
* documentation on the `Pausable`.
+
*/
pause(): void;
+
/** Resumes a paused GraphQL operation if it’s currently paused.
+
*
+
* @remarks
+
* Resumes or starts {@link OperationResultStore}’s GraphQL operation,
+
* if it’s currently paused.
+
*
+
* @see {@link https://urql.dev/goto/docs/basics/svelte#pausing-queries} for
+
* documentation on the `Pausable`.
+
*/
resume(): void;
}
+
/** Creates a {@link Pausable}.
+
* @internal
+
*/
export const createPausable = (isPaused$: Writable<boolean>): Pausable => ({
isPaused$,
pause() {
+32 -3
packages/svelte-urql/src/context.ts
···
const _contextKey = '$$_urql';
-
/** Retrieves a Client from Svelte's context */
+
/** Returns a provided {@link Client}.
+
*
+
* @remarks
+
* `getContextClient` returns the {@link Client} that’s previously
+
* been provided on Svelte’s context with {@link setContextClient}.
+
*
+
* This is useful to create a `Client` on Svelte’s context once, and
+
* then pass it to all GraphQL store functions without importing it
+
* from a singleton export.
+
*
+
* @throws
+
* In development, if `getContextClient` can’t get a {@link Client}
+
* from Svelte’s context, an error will be thrown.
+
*/
export const getContextClient = (): Client => {
const client = getContext(_contextKey);
if (process.env.NODE_ENV !== 'production' && !client) {
···
return client as Client;
};
-
/** Sets a Client on Svelte's context */
+
/** Provides a {@link Client} to a component’s children.
+
*
+
* @remarks
+
* `setContextClient` updates the Svelte context to provide
+
* a {@link Client} to be later retrieved using the
+
* {@link getContextClient} function.
+
*/
export const setContextClient = (client: Client): void => {
setContext(_contextKey, client);
};
-
/** Creates Client and adds it to Svelte's context */
+
/** Creates a {@link Client} and provides it to a component’s children.
+
*
+
* @param args - a {@link ClientOptions} object to create a `Client` with.
+
* @returns the created {@link Client}.
+
*
+
* @remarks
+
* `initContextClient` is a convenience wrapper around
+
* `setContextClient` that accepts {@link ClientOptions},
+
* creates a {@link Client} and provides it to be later
+
* retrieved using the {@link getContextClient} function.
+
*/
export const initContextClient = (args: ClientOptions): Client => {
const client = new Client(args);
setContextClient(client);
+7
packages/svelte-urql/src/index.ts
···
export * from '@urql/core';
+
+
export type {
+
Pausable,
+
OperationResultStore,
+
OperationResultState,
+
} from './common';
+
export * from './queryStore';
export * from './mutationStore';
export * from './subscriptionStore';
+67
packages/svelte-urql/src/mutationStore.ts
···
initialResult,
} from './common';
+
/** Input arguments for the {@link mutationStore} function.
+
*
+
* @param query - The GraphQL mutation that the `mutationStore` executes.
+
* @param variables - The variables for the GraphQL mutation that `mutationStore` executes.
+
*/
export type MutationArgs<
Data = any,
Variables extends AnyVariables = AnyVariables
> = {
+
/** The {@link Client} using which the subscription will be started.
+
*
+
* @remarks
+
* If you’ve previously provided a {@link Client} on Svelte’s context
+
* this can be set to {@link getContextClient}’s return value.
+
*/
client: Client;
+
/** Updates the {@link OperationContext} for the GraphQL mutation operation.
+
*
+
* @remarks
+
* `context` may be passed to {@link mutationStore}, to update the
+
* {@link OperationContext} of a mutation operation. This may be used to update
+
* the `context` that exchanges will receive for a single hook.
+
*
+
* @example
+
* ```ts
+
* mutationStore({
+
* query,
+
* context: {
+
* additionalTypenames: ['Item'],
+
* },
+
* });
+
* ```
+
*/
context?: Partial<OperationContext>;
} & GraphQLRequestParams<Data, Variables>;
+
/** Function to create a `mutationStore` that runs a GraphQL mutation and updates with a GraphQL result.
+
*
+
* @param args - a {@link MutationArgs} object, to pass a `query`, `variables`, and options.
+
* @returns a {@link OperationResultStore} of the mutation’s result.
+
*
+
* @remarks
+
* `mutationStore` allows a GraphQL mutation to be defined as a Svelte store.
+
* Given {@link MutationArgs.query}, it executes the GraphQL mutation on the
+
* {@link MutationArgs.client}.
+
*
+
* The returned store updates with an {@link OperationResult} when
+
* the `Client` returns a result for the mutation.
+
*
+
* Hint: It’s often easier to use {@link Client.mutation} if you’re
+
* creating a mutation imperatively and don’t need a store.
+
*
+
* @see {@link https://urql.dev/goto/docs/basics/svelte#mutations} for
+
* `mutationStore` docs.
+
*
+
* @example
+
* ```ts
+
* import { mutationStore, gql, getContextClient } from '@urql/svelte';
+
*
+
* const client = getContextClient();
+
*
+
* let result;
+
* function updateTodo({ id, title }) {
+
* result = queryStore({
+
* client,
+
* query: gql`
+
* mutation($id: ID!, $title: String!) {
+
* updateTodo(id: $id, title: $title) { id, title }
+
* }
+
* `,
+
* variables: { id, title },
+
* });
+
* }
+
* ```
+
*/
export function mutationStore<
Data = any,
Variables extends AnyVariables = AnyVariables
+76
packages/svelte-urql/src/queryStore.ts
···
fromStore,
} from './common';
+
/** Input arguments for the {@link queryStore} function.
+
*
+
* @param query - The GraphQL query that the `queryStore` executes.
+
* @param variables - The variables for the GraphQL query that `queryStore` executes.
+
*/
export type QueryArgs<
Data = any,
Variables extends AnyVariables = AnyVariables
> = {
+
/** The {@link Client} using which the query will be executed.
+
*
+
* @remarks
+
* If you’ve previously provided a {@link Client} on Svelte’s context
+
* this can be set to {@link getContextClient}’s return value.
+
*/
client: Client;
+
/** Updates the {@link OperationContext} for the executed GraphQL query operation.
+
*
+
* @remarks
+
* `context` may be passed to {@link queryStore}, 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
+
* queryStore({
+
* query,
+
* context: {
+
* additionalTypenames: ['Item'],
+
* },
+
* });
+
* ```
+
*/
context?: Partial<OperationContext>;
+
/** Sets the {@link RequestPolicy} for the executed GraphQL query operation.
+
*
+
* @remarks
+
* `requestPolicy` modifies the {@link RequestPolicy} of the GraphQL query operation
+
* that the {@link queryStore} executes, and indicates a caching strategy for cache exchanges.
+
*
+
* For example, when set to `'cache-and-network'`, the `queryStore` 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?: RequestPolicy;
+
/** Prevents the {@link queryStore} from automatically executing GraphQL query operations.
+
*
+
* @remarks
+
* `pause` may be set to `true` to stop the {@link queryStore} from executing
+
* automatically. The store will stop receiving updates from the {@link Client}
+
* and won’t execute the query operation, until either it’s set to `false`
+
* or {@link Pausable.resume} is called.
+
*
+
* @see {@link https://urql.dev/goto/docs/basics/svelte#pausing-queries} for
+
* documentation on the `pause` option.
+
*/
pause?: boolean;
} & GraphQLRequestParams<Data, Variables>;
+
/** Function to create a `queryStore` that runs a GraphQL query and updates with GraphQL results.
+
*
+
* @param args - a {@link QueryArgs} object, to pass a `query`, `variables`, and options.
+
* @returns a {@link OperationResultStore} of query results, which implements {@link Pausable}.
+
*
+
* @remarks
+
* `queryStore` allows GraphQL queries to be defined as Svelte stores.
+
* Given {@link QueryArgs.query}, it executes the GraphQL query on the
+
* {@link QueryArgs.client}.
+
*
+
* The returned store updates with {@link OperationResult} values when
+
* the `Client` has new results for the query.
+
*
+
* @see {@link https://urql.dev/goto/docs/basics/svelte#queries} for `queryStore` docs.
+
*
+
* @example
+
* ```ts
+
* import { queryStore, gql, getContextClient } from '@urql/svelte';
+
*
+
* const todos = queryStore({
+
* client: getContextClient(),
+
* query: gql`{ todos { id, title } }`,
+
* });
+
* ```
+
*/
export function queryStore<
Data = any,
Variables extends AnyVariables = AnyVariables
+93
packages/svelte-urql/src/subscriptionStore.ts
···
fromStore,
} from './common';
+
/** Combines previous data with an incoming subscription result’s data.
+
*
+
* @remarks
+
* A `SubscriptionHandler` may be passed to {@link subscriptionStore} to
+
* aggregate subscription results into a combined `data` value on the
+
* {@link OperationResultStore}.
+
*
+
* 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 } }
+
* `;
+
*
+
* subscriptionStore(
+
* { query: NotificationsSubscription },
+
* function combineNotifications(notifications = [], data) {
+
* return [...notifications, data.newNotification];
+
* },
+
* );
+
* ```
+
*/
export type SubscriptionHandler<T, R> = (prev: R | undefined, data: T) => R;
+
/** Input arguments for the {@link subscriptionStore} function.
+
*
+
* @param query - The GraphQL subscription that the `subscriptionStore` executes.
+
* @param variables - The variables for the GraphQL subscription that `subscriptionStore` executes.
+
*/
export type SubscriptionArgs<
Data = any,
Variables extends AnyVariables = AnyVariables
> = {
+
/** The {@link Client} using which the subscription will be started.
+
*
+
* @remarks
+
* If you’ve previously provided a {@link Client} on Svelte’s context
+
* this can be set to {@link getContextClient}’s return value.
+
*/
client: Client;
+
/** Updates the {@link OperationContext} for the GraphQL subscription operation.
+
*
+
* @remarks
+
* `context` may be passed to {@link subscriptionStore}, 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
+
* subscriptionStore({
+
* query,
+
* context: {
+
* additionalTypenames: ['Item'],
+
* },
+
* });
+
* ```
+
*/
context?: Partial<OperationContext>;
+
/** Prevents the {@link subscriptionStore} from automatically starting the GraphQL subscription.
+
*
+
* @remarks
+
* `pause` may be set to `true` to stop the {@link subscriptionStore} from starting
+
* its subscription automatically. The store won't execute the subscription operation,
+
* until either it’s set to `false` or {@link Pausable.resume} is called.
+
*/
pause?: boolean;
} & GraphQLRequestParams<Data, Variables>;
+
/** Function to create a `subscriptionStore` that starts a GraphQL subscription.
+
*
+
* @param args - a {@link QueryArgs} object, to pass a `query`, `variables`, and options.
+
* @param handler - optionally, a {@link SubscriptionHandler} function to combine multiple subscription results.
+
* @returns a {@link OperationResultStore} of subscription results, which implements {@link Pausable}.
+
*
+
* @remarks
+
* `subscriptionStore` allows GraphQL subscriptions to be defined as Svelte stores.
+
* Given {@link SubscriptionArgs.query}, it executes the GraphQL subsription on the
+
* {@link SubscriptionArgs.client}.
+
*
+
* The returned store updates with {@link OperationResult} values when
+
* the `Client` has new results for the subscription.
+
*
+
* @see {@link https://urql.dev/goto/docs/advanced/subscriptions#svelte} for
+
* `subscriptionStore` docs.
+
*
+
* @example
+
* ```ts
+
* import { subscriptionStore, gql, getContextClient } from '@urql/svelte';
+
*
+
* const todos = subscriptionStore({
+
* client: getContextClient(),
+
* query: gql`
+
* subscription {
+
* newNotification { id, text }
+
* }
+
* `,
+
* function combineNotifications(notifications = [], data) {
+
* return [...notifications, data.newNotification];
+
* },
+
* });
+
* ```
+
*/
export function subscriptionStore<
Data,
Result = Data,
+1 -2
packages/vue-urql/src/index.ts
···
export type {
UseSubscriptionArgs,
UseSubscriptionResponse,
-
UseSubscriptionState,
SubscriptionHandlerArg,
SubscriptionHandler,
} from './useSubscription';
export { useMutation } from './useMutation';
-
export type { UseMutationResponse, UseMutationState } from './useMutation';
+
export type { UseMutationResponse } from './useMutation';
import { install } from './useClient';
+65
packages/vue-urql/src/useClient.ts
···
const clientsPerInstance = new WeakMap<{}, Ref<Client>>();
+
/** 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],
+
* }));
+
* },
+
* };
+
* ```
+
*/
export function provideClient(opts: ClientOptions | Client | Ref<Client>) {
let client: Ref<Client>;
if (!isRef(opts)) {
···
return client.value;
}
+
/** 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],
+
* });
+
* ```
+
*/
export function install(app: App, opts: ClientOptions | Client | Ref<Client>) {
let client: Ref<Client>;
if (!isRef(opts)) {
···
app.provide('$urql', client);
}
+
/** Returns a provided reactive ref object of a {@link Client}.
+
*
+
* @remarks
+
* `useClient` may be called in Vue `setup` functions to retrieve a
+
* reactive rev object of a {@link Client} that’s previously been
+
* provided with {@link provideClient} in the current or a parent’s
+
* `setup` function.
+
*
+
* @throws
+
* In development, if `useClient` is called outside of a Vue `setup`
+
* function or no {@link Client} was provided, an error will be thrown.
+
*/
export function useClient(): Ref<Client> {
const instance = getCurrentInstance();
if (process.env.NODE_ENV !== 'production' && !instance) {
+92
packages/vue-urql/src/useClientHandle.ts
···
UseSubscriptionResponse,
} from './useSubscription';
+
/** 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.
+
*/
export 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: TypedDocumentNode<T, V> | DocumentNode | string
): 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,
+
* }),
+
* });
+
* }
+
* };
+
* ```
+
*/
export function useClientHandle(): ClientHandle {
const client = useClient();
const stops: WatchStopHandle[] = [];
+95 -8
packages/vue-urql/src/useMutation.ts
···
import { useClient } from './useClient';
import { unwrapPossibleProxy } from './utils';
-
export interface UseMutationState<T, V extends AnyVariables = AnyVariables> {
+
/** 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.
+
*/
+
export 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>;
-
executeMutation: (
+
/** 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
+
* {@link UseMutationArgs.context} and 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>>;
+
): Promise<OperationResult<T>>;
}
-
export type UseMutationResponse<
-
T,
-
V extends AnyVariables = AnyVariables
-
> = UseMutationState<T, V>;
-
+
/** 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 });
+
* };
+
* // ...
+
* },
+
* };
+
* ```
+
*/
export function useMutation<T = any, V extends AnyVariables = AnyVariables>(
query: TypedDocumentNode<T, V> | DocumentNode | string
): UseMutationResponse<T, V> {
+180 -5
packages/vue-urql/src/useQuery.ts
···
type MaybeRef<T> = T | Ref<T>;
type MaybeRefObj<T extends {}> = { [K in keyof T]: MaybeRef<T[K]> };
+
/** 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.
+
*/
export 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, Variables>>;
-
export type QueryPartialState<
-
T = any,
-
V extends AnyVariables = AnyVariables
-
> = Partial<OperationResult<T, V>> & { fetching?: boolean };
-
+
/** 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.
+
*/
export 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>;
+
/** 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.
+
*/
export type UseQueryResponse<
T,
V extends AnyVariables = AnyVariables
···
flush: 'pre' as const,
};
+
/** 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 };
+
* },
+
* };
+
* ```
+
*/
export function useQuery<T = any, V extends AnyVariables = AnyVariables>(
args: UseQueryArgs<T, V>
): UseQueryResponse<T, V> {
+174 -11
packages/vue-urql/src/useSubscription.ts
···
type MaybeRef<T> = Exclude<T, void> | Ref<Exclude<T, void>>;
type MaybeRefObj<T extends {}> = { [K in keyof T]: MaybeRef<T[K]> };
+
/** 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.
+
*/
export 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 UseSubscriptonState.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, 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,
+
* );
+
* ```
+
*/
export type SubscriptionHandler<T, R> = (prev: R | undefined, data: T) => R;
+
+
/** A {@link SubscriptionHandler} or a reactive ref of one. */
export type SubscriptionHandlerArg<T, R> = MaybeRef<SubscriptionHandler<T, R>>;
-
export interface UseSubscriptionState<
+
/** 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.
+
*/
+
export 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 UseQueryState.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;
}
-
export type UseSubscriptionResponse<
-
T = any,
-
R = T,
-
V extends AnyVariables = AnyVariables
-
> = UseSubscriptionState<T, R, V>;
-
const watchOptions = {
flush: 'pre' as const,
};
+
/** 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];
+
* },
+
* );
+
* // ...
+
* },
+
* };
+
* ```
+
*/
export function useSubscription<
T = any,
R = T,
V extends AnyVariables = AnyVariables
>(
args: UseSubscriptionArgs<T, V>,
-
handler?: SubscriptionHandlerArg<T, R>
+
handler?: MaybeRef<SubscriptionHandler<T, R>>
): UseSubscriptionResponse<T, R, V> {
return callUseSubscription(args, handler);
}
···
V extends AnyVariables = AnyVariables
>(
_args: UseSubscriptionArgs<T, V>,
-
handler?: SubscriptionHandlerArg<T, R>,
+
handler?: MaybeRef<SubscriptionHandler<T, R>>,
client: Ref<Client> = useClient(),
stops: WatchStopHandle[] = []
): UseSubscriptionResponse<T, R, V> {
···
}, watchOptions)
);
-
const state: UseSubscriptionState<T, R, V> = {
+
const state: UseSubscriptionResponse<T, R, V> = {
data,
stale,
error,
···
isPaused,
executeSubscription(
opts?: Partial<OperationContext>
-
): UseSubscriptionState<T, R, V> {
+
): UseSubscriptionResponse<T, R, V> {
source.value = client.value.executeSubscription<T, V>(request.value, {
...unwrapPossibleProxy(args.context),
...opts,