···11+---
22+'@urql/core': patch
33+---
44+55+Add TSDoc annotations to all external `@urql/core` APIs.
+422-16
packages/core/src/client.ts
···5151 getOperationType,
5252} from './utils';
53535454-/** Options for configuring the URQL [client]{@link Client}. */
5454+/** Configuration options passed when creating a new {@link Client}.
5555+ *
5656+ * @remarks
5757+ * The `ClientOptions` are passed when creating a new {@link Client}, and
5858+ * are used to instantiate the pipeline of {@link Exchange | Exchanges}, configure
5959+ * options used to initialize {@link OperationContext | OperationContexts}, or to
6060+ * change the general behaviour of the {@link Client}.
6161+ */
5562export interface ClientOptions {
5656- /** Target endpoint URL such as `https://my-target:8080/graphql`. */
6363+ /** Target URL used by fetch exchanges to make GraphQL API requests to.
6464+ *
6565+ * @remarks
6666+ * This is the URL that fetch exchanges will call to make GraphQL API requests.
6767+ * This value is copied to {@link OperationContext.url}.
6868+ */
5769 url: string;
5858- /** Any additional options to pass to fetch. */
7070+ /** Additional options used by fetch exchanges that'll be passed to the `fetch` call on API requests.
7171+ *
7272+ * @remarks
7373+ * The options in this object or an object returned by a callback function will be merged into the
7474+ * {@link RequestInit} options passed to the `fetch` call.
7575+ *
7676+ * Hint: If you're trying to implement more complex changes per {@link Operation}, it's worth considering
7777+ * to use the {@link mapExchange} instead, which allows you to change `Operation`s and `OperationResult`s.
7878+ *
7979+ * Hint: If you're trying to use this as a function for authentication, consider checking out
8080+ * `@urql/exchange-auth` instead, which allows you to handle refresh auth flows, and more
8181+ * complex auth flows.
8282+ *
8383+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/fetch} for a description of this object.
8484+ */
5985 fetchOptions?: RequestInit | (() => RequestInit);
6060- /** An alternative fetch implementation. */
8686+ /** A `fetch` function polyfill used by fetch exchanges to make API calls.
8787+ *
8888+ * @remarks
8989+ * This is the fetch polyfill used by any fetch exchange to make an API request. By default, when this
9090+ * option isn't set, any fetch exchange will attempt to use the globally available `fetch` function
9191+ * to make a request instead.
9292+ *
9393+ * It's recommended to only pass a polyfill, if any of the environments you're running the {@link Client}
9494+ * in don't support the Fetch API natively.
9595+ *
9696+ * Hint: If you're using the "Incremental Delivery" multipart spec, for instance with `@defer` directives,
9797+ * you're better off using the native `fetch` function, or must ensure that your polyfill supports streamed
9898+ * results. However, a "Streaming requests unsupported" error will be thrown, to let you know that your `fetch`
9999+ * API doesn't support incrementally streamed responses, if this mode is used.
100100+ *
101101+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API} for the Fetch API spec.
102102+ */
61103 fetch?: typeof fetch;
6262- /** An ordered array of Exchanges. */
104104+ /** A list of `Exchange`s that will be used to create the `Client`'s execution pipeline.
105105+ *
106106+ * @remarks
107107+ * The {@link Client} accepts and composes a list of {@link Exchange | Exchanges} into an “exchange pipeline”
108108+ * which receive a stream of {@link Operation | Operations} the `Client` wishes to execute, and return a stream
109109+ * of {@link OperationResult | OperationResults}.
110110+ *
111111+ * This is the basis for how `urql` handles GraphQL operations, and exchanges handle the creation, execution,
112112+ * and control flow of exchanges for the `Client`.
113113+ *
114114+ * When this option is left out, the `Client` defaults to a list of {@link defaultExchanges}. By default, these
115115+ * will implement deduping, caching (via a document cache), and fetching (GraphQL over HTTP).
116116+ *
117117+ * @see {@link https://formidable.com/open-source/urql/docs/architecture/#the-client-and-exchanges} for more information
118118+ * on what `Exchange`s are and how they work.
119119+ */
63120 exchanges?: Exchange[];
6464- /** Activates support for Suspense. */
121121+ /** A configuration flag indicating whether support for "Suspense" is activated.
122122+ *
123123+ * @remarks
124124+ * This configuration flag is only relevant for using `urql` with the React or Preact bindings.
125125+ * When activated it allows `useQuery` to "suspend" instead of returning a loading state, which
126126+ * will stop updates in a querying component and instead cascade
127127+ * to a higher suspense boundary for a loading state.
128128+ *
129129+ * Hint: While, when this option is enabled, by default all `useQuery` hooks will suspense, you can
130130+ * disable Suspense selectively for each hook.
131131+ *
132132+ * @see {@link https://beta.reactjs.org/blog/2022/03/29/react-v18#new-suspense-features} for more information on React Suspense.
133133+ */
65134 suspense?: boolean;
6666- /** The default request policy for requests. */
135135+ /** The request and caching strategy that all `Operation`s on this `Client` will use by default.
136136+ *
137137+ * @remarks
138138+ * The {@link RequestPolicy} instructs cache exchanges how to use and treat their cached results.
139139+ * By default `cache-first` is set and used, which will use cache results, and only make an API request
140140+ * on a cache miss.
141141+ *
142142+ * The `requestPolicy` can be overriden per operation, since it's added to the {@link OperationContext},
143143+ * which allows you to change the policy per `Operation`, rather than changing it by default here.
144144+ *
145145+ * Hint: We don’t recommend changing this from the default `cache-first` option, unless you know what
146146+ * you‘re doing. Setting this to `cache-and-network` is not recommend and may not lead to the behaviour
147147+ * you expect. If you’re looking to always update your cache frequently, use `@urql/exchange-request-policy`
148148+ * instead.
149149+ */
67150 requestPolicy?: RequestPolicy;
6868- /** Use HTTP GET for queries. */
151151+ /** Instructs fetch exchanges to use a GET request.
152152+ *
153153+ * @remarks
154154+ * This changes the {@link OperationContext.preferGetMethod} option, which tells fetch exchanges
155155+ * to use GET requests for queries instead of POST requests.
156156+ *
157157+ * When set to `true` or `'within-url-limit'`, built-in fetch exchanges will always attempt to send query
158158+ * operations as GET requests, unless the resulting URL exceeds a length of 2,048 characters.
159159+ * If you want to bypass this restriction, set this option to `'force'` instead, to always send GET.
160160+ * requests for queries.
161161+ */
69162 preferGetMethod?: boolean | 'force' | 'within-url-limit';
7070- /** Mask __typename from results. */
163163+ /** Instructs the `Client` to remove `__typename` properties on all results.
164164+ *
165165+ * @remarks
166166+ * By default, cache exchanges will alter your GraphQL documents to request `__typename` fields
167167+ * for all selections. However, this means that your GraphQL data will now contain `__typename` fields you
168168+ * didn't ask for. This is why the {@link Client} supports “masking” this field by marking it
169169+ * as non-enumerable via this option.
170170+ *
171171+ * Only use this option if you absolutely have to. It's popular to model mutation inputs in
172172+ * GraphQL schemas after the object types they modify, and if you're using this option to make
173173+ * it possible to directly pass objects from results as inputs to your mutation variables, it's
174174+ * more performant and idomatic to instead create a new input object.
175175+ *
176176+ * Hint: With `@urql/exchange-graphcache` you will never need this option, as it selects fields on
177177+ * the client-side according to which fields you specified, rather than the fields it modified.
178178+ *
179179+ * @see {@link https://spec.graphql.org/October2021/#sec-Type-Name-Introspection} for more information
180180+ * on typename introspection via the `__typename` field.
181181+ */
71182 maskTypename?: boolean;
72183}
73184185185+/** The `Client` is the central hub for your GraphQL operations and holds `urql`'s state.
186186+ *
187187+ * @remarks
188188+ * The `Client` manages your active GraphQL operations and their state, and contains the
189189+ * {@link Exchange} pipeline to execute your GraphQL operations.
190190+ *
191191+ * It contains methods that allow you to execute GraphQL operations manually, but the `Client`
192192+ * is also interacted with by bindings (for React, Preact, Vue, Svelte, etc) to execute GraphQL
193193+ * operations.
194194+ *
195195+ * While {@link Exchange | Exchanges} are ultimately responsible for the control flow of operations,
196196+ * sending API requests, and caching, the `Client` still has the important responsibility for
197197+ * creating operations, managing consumers of active operations, sharing results for operations,
198198+ * and more tasks as a “central hub”.
199199+ *
200200+ * @see {@link https://formidable.com/open-source/urql/docs/architecture/#requests-and-operations-on-the-client} for more information
201201+ * on what the `Client` is and does.
202202+ */
74203export interface Client {
75204 new (options: ClientOptions): Client;
76205206206+ /** Exposes the stream of `Operation`s that is passed to the `Exchange` pipeline.
207207+ *
208208+ * @remarks
209209+ * This is a Wonka {@link Source} that issues the {@link Operation | Operations} going into
210210+ * the exchange pipeline.
211211+ * @internal
212212+ */
77213 operations$: Source<Operation>;
214214+215215+ /** Flag indicating whether support for “Suspense” is activated.
216216+ *
217217+ * @remarks
218218+ * This flag indicates whether support for “Suspense” has been activated via the
219219+ * {@link ClientOptions.suspense} flag.
220220+ *
221221+ * When this is enabled, the {@link Client} itself doesn’t function any differently, and the flag
222222+ * only serves as an instructions for the React/Preact bindings to change their behaviour.
223223+ *
224224+ * @see {@link ClientOptions.suspense} for more information.
225225+ * @internal
226226+ */
78227 suspense: boolean;
792288080- /** Start an operation from an exchange */
8181- reexecuteOperation: (operation: Operation) => void;
8282- /** Event target for monitoring, e.g. for @urql/devtools */
8383- subscribeToDebugTarget?: (onEvent: (e: DebugEvent) => void) => Subscription;
229229+ /** Dispatches an `Operation` to the `Exchange` pipeline, if this `Operation` is active.
230230+ *
231231+ * @remarks
232232+ * This method is frequently used in {@link Exchange | Exchanges}, for instance caches, to reexecute
233233+ * an operation. It’s often either called because an `Operation` will need to be queried against the
234234+ * cache again, if a cache result has changed or been invalidated, or it’s called with an {@link Operation}'s
235235+ * {@link RequestPolicy} set to `network-only` to issue a network request.
236236+ *
237237+ * This method will only dispatch an {@link Operation} if it has active consumers, meaning,
238238+ * active subscribers to the sources of {@link OperationResult}. For instance, if no bindings
239239+ * (e.g. `useQuery`) is subscribed to the `Operation`, then `reexecuteOperation` will do nothing.
240240+ *
241241+ * All operations are put onto a queue and executed after a micro-tick. The queue of operations is
242242+ * emptied eagerly and synchronously, similar to a trampoline scheduler.
243243+ */
244244+ reexecuteOperation(operation: Operation): void;
84245246246+ /** Subscribe method to add an event listener to debug events.
247247+ *
248248+ * @param onEvent - A callback called with new debug events, each time an `Exchange` issues them.
249249+ * @returns A Wonka {@link Subscription} which is used to optionally terminate the event listener.
250250+ *
251251+ * @remarks
252252+ * This is a method that's only available in development, and allows the `urql-devtools` to receive
253253+ * to debug events that are issued by exchanges, giving the devtools more information about the flow
254254+ * and execution of {@link Operation | Operations}.
255255+ *
256256+ * @see {@link DebugEventTypes} for a description of all debug events.
257257+ * @internal
258258+ */
259259+ subscribeToDebugTarget?(onEvent: (event: DebugEvent) => void): Subscription;
260260+261261+ /** Creates an `Operation` from a `GraphQLRequest` and optionally, overriding `OperationContext` options.
262262+ *
263263+ * @param kind - The {@link OperationType} of GraphQL operation, i.e. `query`, `mutation`, or `subscription`.
264264+ * @param request - A {@link GraphQLRequest} created prior to calling this method.
265265+ * @param opts - {@link OperationContext} options that'll override and be merged with options from the {@link ClientOptions}.
266266+ * @returns An {@link Operation} created from the parameters.
267267+ *
268268+ * @remarks
269269+ * This method is expected to be called with a `kind` set to the `OperationType` of the GraphQL operation.
270270+ * In development, this is enforced by checking that the GraphQL document's operation matches this `kind`.
271271+ *
272272+ * Hint: While bindings will use this method combined with {@link Client.executeRequestOperation}, if
273273+ * you’re executing operations manually, you can use one of the other convenience methods instead.
274274+ *
275275+ * @see {@link Client.executeRequestOperation} for the method used to execute operations.
276276+ * @see {@link createRequest} which creates a `GraphQLRequest` from a `DocumentNode` and variables.
277277+ */
85278 createRequestOperation<
86279 Data = any,
87280 Variables extends AnyVariables = AnyVariables
···91284 opts?: Partial<OperationContext> | undefined
92285 ): Operation<Data, Variables>;
932869494- /** Executes an Operation by sending it through the exchange pipeline It returns an observable that emits all related exchange results and keeps track of this observable's subscribers. A teardown signal will be emitted when no subscribers are listening anymore. */
287287+ /** Creates a `Source` that executes the `Operation` and issues `OperationResult`s for this `Operation`.
288288+ *
289289+ * @param operation - {@link Operation} that will be executed.
290290+ * @returns A Wonka {@link Source} of {@link OperationResult | OperationResults} for the passed `Operation`.
291291+ *
292292+ * @remarks
293293+ * The {@link Operation} will be dispatched to the pipeline of {@link Exchange | Exchanges} when
294294+ * subscribing to the returned {@link Source}, which issues {@link OperationResult | OperationResults}
295295+ * belonging to this `Operation`.
296296+ *
297297+ * Internally, {@link OperationResult | OperationResults} are filtered and deliverd to this source by
298298+ * comparing the {@link Operation.key} on the operation and the {@link OperationResult.operation}.
299299+ * For mutations, the {@link OperationContext._instance | `OperationContext._instance`} will additionally be compared, since two mutations
300300+ * with, even given the same variables, will have two distinct results and will be executed separately.
301301+ *
302302+ * The {@link Client} dispatches the {@link Operation} when we subscribe to the returned {@link Source}
303303+ * and will from then on consider the `Operation` as “active” until we unsubscribe. When all consumers unsubscribe
304304+ * from an `Operation` and it becomes “inactive” a `teardown` signal will be dispatched to the
305305+ * {@link Exchange | Exchanges}.
306306+ *
307307+ * Hint: While bindings will use this method, if you’re executing operations manually, you can use one
308308+ * of the other convenience methods instead, like {@link Client.executeQuery} et al.
309309+ */
95310 executeRequestOperation<
96311 Data = any,
97312 Variables extends AnyVariables = AnyVariables
···99314 operation: Operation<Data, Variables>
100315 ): Source<OperationResult<Data, Variables>>;
101316317317+ /** Creates a `Source` that executes the GraphQL query operation created from the passed parameters.
318318+ *
319319+ * @param query - a GraphQL document containing the query operation that will be executed.
320320+ * @param variables - the variables used to execute the operation.
321321+ * @param opts - {@link OperationContext} options that'll override and be merged with options from the {@link ClientOptions}.
322322+ * @returns A {@link PromisifiedSource} issuing the {@link OperationResult | OperationResults} for the GraphQL operation.
323323+ *
324324+ * @remarks
325325+ * The `Client.query` method is useful to programmatically create and issue a GraphQL query operation.
326326+ * It automatically calls {@link createRequest}, {@link client.createRequestOperation}, and
327327+ * {@link client.executeRequestOperation} for you, and is a convenience method.
328328+ *
329329+ * Since it returns a {@link PromisifiedSource} it may be chained with a `toPromise()` call to only
330330+ * await a single result in an async function.
331331+ *
332332+ * Hint: This is the recommended way to create queries programmatically when not using the bindings,
333333+ * or when you’re trying to get a single, promisified result.
334334+ *
335335+ * @example
336336+ * ```ts
337337+ * const getBookQuery = gql`
338338+ * query GetBook($id: ID!) {
339339+ * book(id: $id) {
340340+ * id
341341+ * name
342342+ * author {
343343+ * name
344344+ * }
345345+ * }
346346+ * }
347347+ * `;
348348+ *
349349+ * async function getBook(id) {
350350+ * const result = await client.query(getBookQuery, { id }).toPromise();
351351+ * if (result.error) {
352352+ * throw result.error;
353353+ * }
354354+ *
355355+ * return result.data.book;
356356+ * }
357357+ * ```
358358+ */
102359 query<Data = any, Variables extends AnyVariables = AnyVariables>(
103360 query: DocumentNode | TypedDocumentNode<Data, Variables> | string,
104361 variables: Variables,
105362 context?: Partial<OperationContext>
106363 ): PromisifiedSource<OperationResult<Data, Variables>>;
107364365365+ /** Returns the first synchronous result a `Client` provides for a given operation.
366366+ *
367367+ * @param query - a GraphQL document containing the query operation that will be executed.
368368+ * @param variables - the variables used to execute the operation.
369369+ * @param opts - {@link OperationContext} options that'll override and be merged with options from the {@link ClientOptions}.
370370+ * @returns An {@link OperationResult} if one became available synchronously or `null`.
371371+ *
372372+ * @remarks
373373+ * The `Client.readQuery` method returns a result synchronously or defaults to `null`. This is useful
374374+ * as it limits the result for a query operation to whatever the cache {@link Exchange} of a {@link Client}
375375+ * had stored and available at that moment.
376376+ *
377377+ * In `urql`, it's expected that cache exchanges return their results synchronously. The bindings
378378+ * and this method exploit this by using synchronous results, like these, to check what data is already
379379+ * in the cache.
380380+ *
381381+ * This method is similar to what all bindings do to synchronously provide the initial state for queries,
382382+ * regardless of whether effects afterwards that subscribe to the query operation update this state synchronously
383383+ * or asynchronously.
384384+ */
108385 readQuery<Data = any, Variables extends AnyVariables = AnyVariables>(
109386 query: DocumentNode | TypedDocumentNode<Data, Variables> | string,
110387 variables: Variables,
111388 context?: Partial<OperationContext>
112389 ): OperationResult<Data, Variables> | null;
113390391391+ /** Creates a `Source` that executes the GraphQL query operation for the passed `GraphQLRequest`.
392392+ *
393393+ * @param query - a {@link GraphQLRequest}
394394+ * @param opts - {@link OperationContext} options that'll override and be merged with options from the {@link ClientOptions}.
395395+ * @returns A {@link PromisifiedSource} issuing the {@link OperationResult | OperationResults} for the GraphQL operation.
396396+ *
397397+ * @remarks
398398+ * The `Client.executeQuery` method is used to programmatically issue a GraphQL query operation.
399399+ * It automatically calls {@link client.createRequestOperation} and {@link client.executeRequestOperation} for you,
400400+ * but requires you to create a {@link GraphQLRequest} using {@link createRequest} yourself first.
401401+ *
402402+ * @see {@link Client.query} for a method that doesn't require calling {@link createRequest} yourself.
403403+ */
114404 executeQuery<Data = any, Variables extends AnyVariables = AnyVariables>(
115405 query: GraphQLRequest<Data, Variables>,
116406 opts?: Partial<OperationContext> | undefined
117407 ): Source<OperationResult<Data, Variables>>;
118408409409+ /** Creates a `Source` that executes the GraphQL subscription operation created from the passed parameters.
410410+ *
411411+ * @param query - a GraphQL document containing the subscription operation that will be executed.
412412+ * @param variables - the variables used to execute the operation.
413413+ * @param opts - {@link OperationContext} options that'll override and be merged with options from the {@link ClientOptions}.
414414+ * @returns A Wonka {@link Source} issuing the {@link OperationResult | OperationResults} for the GraphQL operation.
415415+ *
416416+ * @remarks
417417+ * The `Client.subscription` method is useful to programmatically create and issue a GraphQL subscription operation.
418418+ * It automatically calls {@link createRequest}, {@link client.createRequestOperation}, and
419419+ * {@link client.executeRequestOperation} for you, and is a convenience method.
420420+ *
421421+ * Hint: This is the recommended way to create subscriptions programmatically when not using the bindings.
422422+ *
423423+ * @example
424424+ * ```ts
425425+ * import { pipe, subscribe } from 'wonka';
426426+ *
427427+ * const getNewsSubscription = gql`
428428+ * subscription GetNews {
429429+ * breakingNews {
430430+ * id
431431+ * text
432432+ * createdAt
433433+ * }
434434+ * }
435435+ * `;
436436+ *
437437+ * function subscribeToBreakingNews() {
438438+ * const subscription = pipe(
439439+ * client.subscription(getNewsSubscription, {}),
440440+ * subscribe(result => {
441441+ * if (result.data) {
442442+ * console.log(result.data.breakingNews.text);
443443+ * }
444444+ * })
445445+ * );
446446+ *
447447+ * return subscription.unsubscribe;
448448+ * }
449449+ * ```
450450+ */
119451 subscription<Data = any, Variables extends AnyVariables = AnyVariables>(
120452 query: DocumentNode | TypedDocumentNode<Data, Variables> | string,
121453 variables: Variables,
122454 context?: Partial<OperationContext>
123455 ): Source<OperationResult<Data, Variables>>;
124456457457+ /** Creates a `Source` that executes the GraphQL subscription operation for the passed `GraphQLRequest`.
458458+ *
459459+ * @param query - a {@link GraphQLRequest}
460460+ * @param opts - {@link OperationContext} options that'll override and be merged with options from the {@link ClientOptions}.
461461+ * @returns A {@link PromisifiedSource} issuing the {@link OperationResult | OperationResults} for the GraphQL operation.
462462+ *
463463+ * @remarks
464464+ * The `Client.executeSubscription` method is used to programmatically issue a GraphQL subscription operation.
465465+ * It automatically calls {@link client.createRequestOperation} and {@link client.executeRequestOperation} for you,
466466+ * but requires you to create a {@link GraphQLRequest} using {@link createRequest} yourself first.
467467+ *
468468+ * @see {@link Client.subscription} for a method that doesn't require calling {@link createRequest} yourself.
469469+ */
125470 executeSubscription<
126471 Data = any,
127472 Variables extends AnyVariables = AnyVariables
···130475 opts?: Partial<OperationContext> | undefined
131476 ): Source<OperationResult<Data, Variables>>;
132477478478+ /** Creates a `Source` that executes the GraphQL mutation operation created from the passed parameters.
479479+ *
480480+ * @param query - a GraphQL document containing the mutation operation that will be executed.
481481+ * @param variables - the variables used to execute the operation.
482482+ * @param opts - {@link OperationContext} options that'll override and be merged with options from the {@link ClientOptions}.
483483+ * @returns A {@link PromisifiedSource} issuing the {@link OperationResult | OperationResults} for the GraphQL operation.
484484+ *
485485+ * @remarks
486486+ * The `Client.mutation` method is useful to programmatically create and issue a GraphQL mutation operation.
487487+ * It automatically calls {@link createRequest}, {@link client.createRequestOperation}, and
488488+ * {@link client.executeRequestOperation} for you, and is a convenience method.
489489+ *
490490+ * Since it returns a {@link PromisifiedSource} it may be chained with a `toPromise()` call to only
491491+ * await a single result in an async function. Since mutations will only typically issue one result,
492492+ * using this method is recommended.
493493+ *
494494+ * Hint: This is the recommended way to create mutations programmatically when not using the bindings,
495495+ * or when you’re trying to get a single, promisified result.
496496+ *
497497+ * @example
498498+ * ```ts
499499+ * const createPostMutation = gql`
500500+ * mutation CreatePost($text: String!) {
501501+ * createPost(text: $text) {
502502+ * id
503503+ * text
504504+ * }
505505+ * }
506506+ * `;
507507+ *
508508+ * async function createPost(text) {
509509+ * const result = await client.mutation(createPostMutation, {
510510+ * text,
511511+ * }).toPromise();
512512+ * if (result.error) {
513513+ * throw result.error;
514514+ * }
515515+ *
516516+ * return result.data.createPost;
517517+ * }
518518+ * ```
519519+ */
133520 mutation<Data = any, Variables extends AnyVariables = AnyVariables>(
134521 query: DocumentNode | TypedDocumentNode<Data, Variables> | string,
135522 variables: Variables,
136523 context?: Partial<OperationContext>
137524 ): PromisifiedSource<OperationResult<Data, Variables>>;
138525526526+ /** Creates a `Source` that executes the GraphQL mutation operation for the passed `GraphQLRequest`.
527527+ *
528528+ * @param query - a {@link GraphQLRequest}
529529+ * @param opts - {@link OperationContext} options that'll override and be merged with options from the {@link ClientOptions}.
530530+ * @returns A {@link PromisifiedSource} issuing the {@link OperationResult | OperationResults} for the GraphQL operation.
531531+ *
532532+ * @remarks
533533+ * The `Client.executeMutation` method is used to programmatically issue a GraphQL mutation operation.
534534+ * It automatically calls {@link client.createRequestOperation} and {@link client.executeRequestOperation} for you,
535535+ * but requires you to create a {@link GraphQLRequest} using {@link createRequest} yourself first.
536536+ *
537537+ * @see {@link Client.mutation} for a method that doesn't require calling {@link createRequest} yourself.
538538+ */
139539 executeMutation<Data = any, Variables extends AnyVariables = AnyVariables>(
140540 query: GraphQLRequest<Data, Variables>,
141541 opts?: Partial<OperationContext> | undefined
···278678279679 createRequestOperation(kind, request, opts) {
280680 if (!opts) opts = {};
281281- const requestOperationType = getOperationType(request.query);
681681+682682+ let requestOperationType: string | undefined;
282683 if (
283684 process.env.NODE_ENV !== 'production' &&
284685 kind !== 'teardown' &&
285285- requestOperationType !== kind
686686+ (requestOperationType = getOperationType(request.query)) !== kind
286687 ) {
287688 throw new Error(
288689 `Expected operation of type "${kind}" but found "${requestOperationType}"`
289690 );
290691 }
692692+291693 return makeOperation(kind, request, {
292694 _instance:
293695 kind === 'mutation'
···436838 return client;
437839} as any;
438840841841+/** Accepts `ClientOptions` and creates a `Client`.
842842+ * @param opts - A {@link ClientOptions} objects with options for the `Client`.
843843+ * @returns A {@link Client} instantiated with `opts`.
844844+ */
439845export const createClient = (Client as any) as (opts: ClientOptions) => Client;
+23-1
packages/core/src/exchanges/cache.ts
···1717const shouldSkip = ({ kind }: Operation) =>
1818 kind !== 'mutation' && kind !== 'query';
19192020+/** Default document cache exchange.
2121+ *
2222+ * @remarks
2323+ * The default document cache in `urql` avoids sending the same GraphQL request
2424+ * multiple times by caching it using the {@link Operation.key}. It will invalidate
2525+ * query results automatically whenever it sees a mutation responses with matching
2626+ * `__typename`s in their responses.
2727+ *
2828+ * The document cache will get the introspected `__typename` fields by modifying
2929+ * your GraphQL operation documents using the {@link formatDocument} utility.
3030+ *
3131+ * This automatic invalidation strategy can fail if your query or mutation don’t
3232+ * contain matching typenames, for instance, because the query contained an
3333+ * empty list.
3434+ * You can manually add hints for this exchange by specifying a list of
3535+ * {@link OperationContext.additionalTypenames} for queries and mutations that
3636+ * should invalidate one another.
3737+ *
3838+ * @see {@link https://formidable.com/open-source/urql/docs/basics/document-caching/} for more information on this cache.
3939+ */
2040export const cacheExchange: Exchange = ({ forward, client, dispatchDebug }) => {
2141 const resultCache: ResultCache = new Map();
2242 const operationCache: OperationCache = new Map();
···148168 };
149169};
150170151151-// Reexecutes a given operation with the default requestPolicy
171171+/** Reexecutes an `Operation` with the `network-only` request policy.
172172+ * @internal
173173+ */
152174export const reexecuteOperation = (client: Client, operation: Operation) => {
153175 return client.reexecuteOperation(
154176 makeOperation(operation.kind, operation, {
+17-4
packages/core/src/exchanges/compose.ts
···11-import { Exchange, ExchangeInput } from '../types';
11+import type { ExchangeIO, Exchange, ExchangeInput } from '../types';
2233-/** This composes an array of Exchanges into a single ExchangeIO function */
44-export const composeExchanges = (exchanges: Exchange[]) => ({
33+/** Composes an array of Exchanges into a single one.
44+ *
55+ * @param exchanges - An array of {@link Exchange | Exchanges}.
66+ * @returns - A composed {@link Exchange}.
77+ *
88+ * @remarks
99+ * `composeExchanges` returns an {@link Exchange} that when instantiated
1010+ * composes the array of passed `Exchange`s into one, calling them from
1111+ * right to left, with the prior `Exchange`’s {@link ExchangeIO} function
1212+ * as the {@link ExchangeInput.forward} input.
1313+ *
1414+ * This simply merges all exchanges into one and is used by the {@link Client}
1515+ * to merge the `exchanges` option it receives.
1616+ */
1717+export const composeExchanges = (exchanges: Exchange[]): Exchange => ({
518 client,
619 forward,
720 dispatchDebug,
88-}: ExchangeInput) =>
2121+}: ExchangeInput): ExchangeIO =>
922 exchanges.reduceRight(
1023 (forward, exchange) =>
1124 exchange({
+14
packages/core/src/exchanges/debug.ts
···11import { pipe, tap } from 'wonka';
22import { Exchange } from '../types';
3344+/** Simple log debugger exchange.
55+ *
66+ * @remarks
77+ * An exchange that logs incoming {@link Operation | Operations} and
88+ * {@link OperationResult | OperationResults} in development.
99+ *
1010+ * This exchange is a no-op in production and often used in issue reporting
1111+ * to understand certain usage patterns of `urql` without having access to
1212+ * the original source code.
1313+ *
1414+ * Hint: When you report an issue you’re having with `urql`, adding
1515+ * this as your first exchange and posting its output can speed up
1616+ * issue triaging a lot!
1717+ */
418export const debugExchange: Exchange = ({ forward }) => {
519 if (process.env.NODE_ENV === 'production') {
620 return ops$ => forward(ops$);
+16-1
packages/core/src/exchanges/dedup.ts
···11import { filter, pipe, tap } from 'wonka';
22import { Exchange, Operation, OperationResult } from '../types';
3344-/** A default exchange for debouncing GraphQL requests. */
44+/** Default deduplication exchange.
55+ *
66+ * @remarks
77+ * The `dedupExchange` deduplicates queries and subscriptions that are
88+ * started with identical documents and variables by deduplicating by
99+ * their {@link Operation.key}.
1010+ * This can prevent duplicate requests from being sent to your GraphQL API.
1111+ *
1212+ * Because this is a very safe exchange to add to any GraphQL setup, it’s
1313+ * not only the default, but we also recommend you to always keep this
1414+ * exchange added and included in your setup.
1515+ *
1616+ * Hint: In React and Vue, some common usage patterns can trigger duplicate
1717+ * operations. For instance, in React a single render will actually
1818+ * trigger two phases that execute an {@link Operation}.
1919+ */
520export const dedupExchange: Exchange = ({ forward, dispatchDebug }) => {
621 const inFlightKeys = new Set<number>();
722
+10-7
packages/core/src/exchanges/fallback.ts
···11import { filter, pipe, tap } from 'wonka';
22import { Operation, ExchangeIO, ExchangeInput } from '../types';
33-import { noop } from '../utils';
4355-/** This is always the last exchange in the chain; No operation should ever reach it */
44+/** Used by the `Client` as the last exchange to warn about unhandled operations.
55+ *
66+ * @remarks
77+ * In a normal setup, some operations may go unhandled when a {@link Client} isn’t set up
88+ * with the right exchanges.
99+ * For instance, a `Client` may be missing a fetch exchange, or an exchange handling subscriptions.
1010+ * This {@link Exchange} is added by the `Client` automatically to log warnings about unhandled
1111+ * {@link Operaiton | Operations} in development.
1212+ */
613export const fallbackExchange: ({
714 dispatchDebug,
815}: Pick<ExchangeInput, 'dispatchDebug'>) => ExchangeIO = ({
···2532 console.warn(message);
2633 }
2734 }),
2828- /* All operations that skipped through the entire exchange chain should be filtered from the output */
3535+ // All operations that skipped through the entire exchange chain should be filtered from the output
2936 filter<any>(() => false)
3037 );
3131-3232-export const fallbackExchangeIO: ExchangeIO = fallbackExchange({
3333- dispatchDebug: noop,
3434-});
+17-1
packages/core/src/exchanges/fetch.ts
···99 makeFetchSource,
1010} from '../internal';
11111212-/** A default exchange for fetching GraphQL requests. */
1212+/** Default GraphQL over HTTP fetch exchange.
1313+ *
1414+ * @remarks
1515+ * The default fetch exchange in `urql` supports sending GraphQL over HTTP
1616+ * requests, can optionally send GraphQL queries as GET requests, and
1717+ * handles incremental multipart responses.
1818+ *
1919+ * This exchange does not handle persisted queries or multipart uploads.
2020+ * Support for the former can be added using `@urql/exchange-persisted-fetch`
2121+ * and the latter using `@urql/exchange-multipart-fetch`.
2222+ *
2323+ * Hint: The `fetchExchange` and the two other exchanges all use the built-in fetch
2424+ * utilities in `@urql/core/internal`, which you can also use to implement
2525+ * a customized fetch exchange.
2626+ *
2727+ * @see {@link makeFetchSource} for the shared utility calling the Fetch API.
2828+ */
1329export const fetchExchange: Exchange = ({ forward, dispatchDebug }) => {
1430 return ops$ => {
1531 const sharedOps$ = share(ops$);
+9-1
packages/core/src/exchanges/index.ts
···44export { debugExchange } from './debug';
55export { dedupExchange } from './dedup';
66export { fetchExchange } from './fetch';
77-export { fallbackExchangeIO } from './fallback';
87export { composeExchanges } from './compose';
98109export type {
···2019import { dedupExchange } from './dedup';
2120import { fetchExchange } from './fetch';
22212222+/** The default list of exchanges a `Client` falls back to.
2323+ *
2424+ * @remarks
2525+ * When {@link ClientOptions.exchanges} isn’s passed, a {@link Client} is automatically
2626+ * created using this list of default exchanges.
2727+ *
2828+ * By default, this adds deduplication of operations, a basic document cache,
2929+ * and the built-in fetch exchange for GraphQL over HTTP.
3030+ */
2331export const defaultExchanges = [dedupExchange, cacheExchange, fetchExchange];
+56
packages/core/src/exchanges/map.ts
···22import { Operation, OperationResult, Exchange } from '../types';
33import { CombinedError } from '../utils';
4455+/** Options for the `mapExchange` allowing it to react to incoming operations, results, or errors. */
56export interface MapExchangeOpts {
77+ /** Accepts a callback for incoming `Operation`s.
88+ *
99+ * @param operation - An {@link Operation} that the {@link mapExchange} received.
1010+ * @returns optionally a new {@link Operation} replacing the original.
1111+ *
1212+ * @remarks
1313+ * You may return new {@link Operation | Operations} from this function replacing
1414+ * the original that the {@link mapExchange} received.
1515+ * It’s recommended that you use the {@link makeOperation} utility to create a copy
1616+ * of the original when you do this. (However, this isn’t required)
1717+ *
1818+ * Hint: The callback may also be promisified and return a new {@link Operation} asynchronously,
1919+ * provided you place your {@link mapExchange} after all synchronous {@link Exchange | Exchanges},
2020+ * like after your `cacheExchange`.
2121+ */
622 onOperation?(operation: Operation): Promise<Operation> | Operation | void;
2323+ /** Accepts a callback for incoming `OperationResult`s.
2424+ *
2525+ * @param result - An {@link OperationResult} that the {@link mapExchange} received.
2626+ * @returns optionally a new {@link OperationResult} replacing the original.
2727+ *
2828+ * @remarks
2929+ * This callback may optionally return a new {@link OperationResult} that replaces the original,
3030+ * which you can use to modify incoming API results.
3131+ *
3232+ * Hint: The callback may also be promisified and return a new {@link Operation} asynchronously,
3333+ * provided you place your {@link mapExchange} after all synchronous {@link Exchange | Exchanges},
3434+ * like after your `cacheExchange`.
3535+ */
736 onResult?(
837 result: OperationResult
938 ): Promise<OperationResult> | OperationResult | void;
3939+ /** Accepts a callback for incoming `CombinedError`s.
4040+ *
4141+ * @param error - A {@link CombinedError} that an incoming {@link OperationResult} contained.
4242+ * @param operation - The {@link Operation} of the incoming {@link OperationResult}.
4343+ *
4444+ * @remarks
4545+ * The callback may also be promisified and return a new {@link Operation} asynchronously,
4646+ * provided you place your {@link mapExchange} after all synchronous {@link Exchange | Exchanges},
4747+ * like after your `cacheExchange`.
4848+ */
1049 onError?(error: CombinedError, operation: Operation): void;
1150}
12515252+/** Creates an `Exchange` mapping over incoming operations, results, and/or errors.
5353+ *
5454+ * @param opts - A {@link MapExchangeOpts} configuration object, containing the callbacks the `mapExchange` will use.
5555+ * @returns the created {@link Exchange}
5656+ *
5757+ * @remarks
5858+ * The `mapExchange` may be used to react to or modify incoming {@link Operation | Operations}
5959+ * and {@link OperationResult | OperationResults}. Optionally, it can also modify these
6060+ * asynchronously, when a promise is returned from the callbacks.
6161+ *
6262+ * This is useful to, for instance, add an authentication token to a given request, when
6363+ * the `@urql/exchange-auth` package would be overkill.
6464+ *
6565+ * It can also accept an `onError` callback, which can be used to react to incoming
6666+ * {@link CombinedError | CombinedErrors} on results, and trigger side-effects.
6767+ *
6868+ */
1369export const mapExchange = ({
1470 onOperation,
1571 onResult,
+93-5
packages/core/src/exchanges/ssr.ts
···44import { addMetadata, CombinedError } from '../utils';
55import { reexecuteOperation } from './cache';
6677+/** A serialized version of an {@link OperationResult}.
88+ *
99+ * @remarks
1010+ * All properties are serialized separately as JSON strings, except for the
1111+ * {@link CombinedError} to speed up JS parsing speed, even if a result doesn’t
1212+ * end up being used.
1313+ *
1414+ * @internal
1515+ */
716export interface SerializedResult {
817 hasNext?: boolean;
1818+ /** JSON-serialized version of {@link OperationResult.data}. */
919 data?: string | undefined; // JSON string of data
1010- extensions?: string | undefined; // JSON string of data
2020+ /** JSON-serialized version of {@link OperationResult.extensions}. */
2121+ extensions?: string | undefined;
2222+ /** JSON version of {@link CombinedError}. */
1123 error?: {
1224 graphQLErrors: Array<Partial<GraphQLError> | string>;
1325 networkError?: string;
1426 };
1527}
16282929+/** A dictionary of {@link Operation.key} keys to serializable {@link SerializedResult} objects.
3030+ *
3131+ * @remarks
3232+ * It’s not recommended to modify the serialized data manually, however, multiple payloads of
3333+ * this dictionary may safely be merged and combined.
3434+ */
1735export interface SSRData {
1836 [key: string]: SerializedResult;
1937}
20383939+/** Options for the `ssrExchange` allowing it to either operate on the server- or client-side. */
2140export interface SSRExchangeParams {
4141+ /** Indicates to the {@link SSRExchange} whether it's currently in server-side or client-side mode.
4242+ *
4343+ * @remarks
4444+ * Depending on this option, the {@link SSRExchange} will either capture or replay results.
4545+ * When `true`, it’s in client-side mode and results will be serialized. When `false`, it’ll
4646+ * use its deserialized data and replay results from it.
4747+ */
2248 isClient?: boolean;
4949+ /** May be used on the client-side to pass the {@link SSRExchange} serialized data from the server-side.
5050+ *
5151+ * @remarks
5252+ * Alternatively, {@link SSRExchange.restoreData} may be called to imperatively add serialized data to
5353+ * the exchange.
5454+ *
5555+ * Hint: This method also works on the server-side to add to the initial serialized data, which enables
5656+ * you to combine multiple {@link SSRExchange} results, as needed.
5757+ */
2358 initialState?: SSRData;
5959+ /** Forces a new API request to be sent in the background after replaying the deserialized result.
6060+ *
6161+ * @remarks
6262+ * Similarly to the `cache-and-network` {@link RequestPolicy}, this option tells the {@link SSRExchange}
6363+ * to send a new API request for the {@link Operation} after replaying a serialized result.
6464+ *
6565+ * Hint: This is useful when you're caching SSR results and need the client-side to update itself after
6666+ * rendering the initial serialized SSR results.
6767+ */
2468 staleWhileRevalidate?: boolean;
6969+ /** Forces {@link OperationResult.extensions} to be serialized alongside the rest of a result.
7070+ *
7171+ * @remarks
7272+ * Entries in the `extension` object of a GraphQL result are often non-standard metdata, and many
7373+ * APIs use it for data that changes between every request. As such, the {@link SSRExchange} will
7474+ * not serialize this data by default, unless this flag is set.
7575+ */
2576 includeExtensions?: boolean;
2677}
27787979+/** An `SSRExchange` either in server-side mode, serializing results, or client-side mode, deserializing and replaying results..
8080+ *
8181+ * @remarks
8282+ * This same {@link Exchange} is used in your code both for the client-side and server-side as it’s “universal”
8383+ * and can be put into either client-side or server-side mode using the {@link SSRExchangeParams.isClient} flag.
8484+ *
8585+ * In server-side mode, the `ssrExchange` will “record” results it sees from your API and provide them for you
8686+ * to send to the client-side using the {@link SSRExchange.extractData} method.
8787+ *
8888+ * In client-side mode, the `ssrExchange` will use these serialized results, rehydrated either using
8989+ * {@link SSRExchange.restoreData} or {@link SSRexchangeParams.initialState}, to replay results the
9090+ * server-side has seen and sent before.
9191+ *
9292+ * Each serialized result will only be replayed once, as it’s assumed that your cache exchange will have the
9393+ * results cached afterwards.
9494+ */
2895export interface SSRExchange extends Exchange {
2929- /** Rehydrates cached data */
9696+ /** Client-side method to add serialized results to the {@link SSRExchange}.
9797+ * @param data - {@link SSRData},
9898+ */
3099 restoreData(data: SSRData): void;
3131- /** Extracts cached data */
100100+ /** Server-side method to get all serialized results the {@link SSRExchange} has captured.
101101+ * @returns an {@link SSRData} dictionary.
102102+ */
32103 extractData(): SSRData;
33104}
34105···65136 return result;
66137};
671386868-/** Deserialize plain JSON to an OperationResult */
139139+/** Deserialize plain JSON to an OperationResult
140140+ * @internal
141141+ */
69142const deserializeResult = (
70143 operation: Operation,
71144 result: SerializedResult,
···9016391164const revalidated = new Set<number>();
921659393-/** The ssrExchange can be created to capture data during SSR and also to rehydrate it on the client */
166166+/** Creates a server-side rendering `Exchange` that either captures responses on the server-side or replays them on the client-side.
167167+ *
168168+ * @param params - An {@link SSRExchangeParams} configuration object.
169169+ * @returns the created {@link SSRExchange}
170170+ *
171171+ * @remarks
172172+ * When dealing with server-side rendering, we essentially have two {@link Client | Clients} making requests,
173173+ * the server-side client, and the client-side one. The `ssrExchange` helps implementing a tiny cache on both
174174+ * sides that:
175175+ *
176176+ * - captures results on the server-side which it can serialize,
177177+ * - replays results on the client-side that it deserialized from the server-side.
178178+ *
179179+ * Hint: The `ssrExchange` is basically an exchange that acts like a replacement for any fetch exchange
180180+ * temporarily. As such, you should place it after your cache exchange but in front of any fetch exchange.
181181+ */
94182export const ssrExchange = (params: SSRExchangeParams = {}): SSRExchange => {
95183 const staleWhileRevalidate = !!params.staleWhileRevalidate;
96184 const includeExtensions = !!params.includeExtensions;
+81-4
packages/core/src/exchanges/subscription.ts
···2525 OperationResult,
2626} from '../types';
27272828+/** An abstract observer-like interface.
2929+ *
3030+ * @remarks
3131+ * Observer-like interfaces are passed to {@link ObservableLike.subscribe} to provide them
3232+ * with callbacks for their events.
3333+ *
3434+ * @see {@link https://github.com/tc39/proposal-observable} for the full TC39 Observable proposal.
3535+ */
2836export interface ObserverLike<T> {
3737+ /** Callback for values an {@link ObservableLike} emits. */
2938 next: (value: T) => void;
3939+ /** Callback for an error an {@link ObservableLike} emits, which ends the subscription. */
3040 error: (err: any) => void;
4141+ /** Callback for the completion of an {@link ObservableLike}, which ends the subscription. */
3142 complete: () => void;
3243}
33443434-/** An abstract observable interface conforming to: https://github.com/tc39/proposal-observable */
4545+/** An abstract observable-like interface.
4646+ *
4747+ * @remarks
4848+ * Observable, or Observable-like interfaces, are often used by GraphQL transports to abstract
4949+ * how they send {@link ExecutionResult | ExecutionResults} to consumers. These generally contain
5050+ * a `subscribe` method accepting an {@link ObserverLike} structure.
5151+ *
5252+ * @see {@link https://github.com/tc39/proposal-observable} for the full TC39 Observable proposal.
5353+ */
3554export interface ObservableLike<T> {
5555+ /** Start the Observable-like subscription and returns a subscription handle.
5656+ *
5757+ * @param observer - an {@link ObserverLike} object with result, error, and completion callbacks.
5858+ * @returns a subscription handle providing an `unsubscribe` method to stop the subscription.
5959+ */
3660 subscribe(
3761 observer: ObserverLike<T>
3862 ): {
···4064 };
4165}
42666767+/** A more cross-compatible version of the {@link Operation} structure.
6868+ *
6969+ * @remarks
7070+ * When the `subscriptionExchange` was first created, some transports needed a specific shape
7171+ * of {@link GraphQLRequest} objects to be passed to them. This is a shim that is as compatible
7272+ * with most transports out of the box as possible.
7373+ */
4374export interface SubscriptionOperation {
4475 query: string;
4576 variables: Record<string, unknown> | undefined;
···4778 context: OperationContext;
4879}
49808181+/** A subscription forwarding function, which must accept a {@link SubscriptionOperation}.
8282+ *
8383+ * @param operation - A {@link SubscriptionOperation}
8484+ * @returns An {@link ObservableLike} object issuing {@link ExecutionResult | ExecutionResults}.
8585+ */
5086export type SubscriptionForwarder = (
5187 operation: SubscriptionOperation
5288) => ObservableLike<ExecutionResult>;
53895490/** This is called to create a subscription and needs to be hooked up to a transport client. */
5591export interface SubscriptionExchangeOpts {
5656- // This has been modelled to work with subscription-transport-ws
5757- // See: https://github.com/apollographql/subscriptions-transport-ws#requestoptions--observableexecutionresult-returns-observable-to-execute-the-operation
9292+ /** A subscription forwarding function, which must accept a {@link SubscriptionOperation}.
9393+ *
9494+ * @param operation - A {@link SubscriptionOperation}
9595+ * @returns An {@link ObservableLike} object issuing {@link ExecutionResult | ExecutionResults}.
9696+ *
9797+ * @remarks
9898+ * This callback is called for each {@link Operation} that this `subscriptionExchange` will
9999+ * handle. It receives the {@link SubscriptionOperation}, which is a more compatible version
100100+ * of the raw {@link Operation} objects and must return an {@link ObservableLike} of results.
101101+ */
58102 forwardSubscription: SubscriptionForwarder;
591036060- /** This flag may be turned on to allow your subscriptions-transport to handle all operation types */
104104+ /** Flag to enable this exchange to handle all types of GraphQL operations.
105105+ *
106106+ * @remarks
107107+ * When you aren’t using fetch exchanges and GraphQL over HTTP as a transport for your GraphQL requests,
108108+ * or you have a third-party GraphQL transport implementation, which must also be used for queries and
109109+ * mutations, this flag may be used to allow this exchange to handle all kinds of GraphQL operations.
110110+ *
111111+ * By default, this flag is `false` and the exchange will only handle GraphQL subscription operations.
112112+ */
61113 enableAllOperations?: boolean;
114114+115115+ /** A predicate function that causes an operation to be handled by this `subscriptionExchange` if `true` is returned.
116116+ *
117117+ * @param operation - an {@link Operation}
118118+ * @returns true when the operation is handled by this exchange.
119119+ *
120120+ * @remarks
121121+ * In some cases, a `subscriptionExchange` will be used to only handle some {@link Operation | Operations},
122122+ * e.g. all that contain `@live` directive. For these cases, this function may be passed to precisely
123123+ * determine which `Operation`s this exchange should handle, instead of forwarding.
124124+ *
125125+ * When specified, the {@link SubscriptionExchangeOpts.enableAllOperations} flag is disregarded.
126126+ */
62127 isSubscriptionOperation?: (operation: Operation) => boolean;
63128}
64129130130+/** Generic subscription exchange factory used to either create an exchange handling just subscriptions or all operation kinds.
131131+ *
132132+ * @remarks
133133+ * `subscriptionExchange` can be used to create an {@link Exchange} that either
134134+ * handles just GraphQL subscription operations, or optionally all operations,
135135+ * when the {@link SubscriptionExchangeOpts.enableAllOperations} flag is passed.
136136+ *
137137+ * The {@link SubscriptionExchangeOpts.forwardSubscription} function must
138138+ * be provided and provides a generic input that's based on {@link Operation}
139139+ * but is compatible with many libraries implementing GraphQL request or
140140+ * subscription interfaces.
141141+ */
65142export const subscriptionExchange = ({
66143 forwardSubscription,
67144 enableAllOperations,
+46
packages/core/src/gql.ts
···3434 }
3535};
36363737+/** A GraphQL parse function, which may be called as a tagged template literal, returning a parsed {@link DocumentNode}.
3838+ *
3939+ * @remarks
4040+ * The `gql` tag or function is used to parse a GraphQL query document into a {@link DocumentNode}.
4141+ *
4242+ * When used as a tagged template, `gql` will automatically merge fragment definitions into the resulting
4343+ * document and deduplicate them.
4444+ *
4545+ * It enforces that all fragments have a unique name. When fragments with different definitions share a name,
4646+ * it will log a warning in development.
4747+ *
4848+ * Hint: It’s recommended to use this `gql` function over other GraphQL parse functions, since it puts the parsed
4949+ * results directly into `@urql/core`’s internal caches and prevents further unnecessary work.
5050+ *
5151+ * @example
5252+ * ```ts
5353+ * const AuthorFragment = gql`
5454+ * fragment AuthorDisplayComponent on Author {
5555+ * id
5656+ * name
5757+ * }
5858+ * `;
5959+ *
6060+ * const BookFragment = gql`
6161+ * fragment ListBookComponent on Book {
6262+ * id
6363+ * title
6464+ * author {
6565+ * ...AuthorDisplayComponent
6666+ * }
6767+ * }
6868+ *
6969+ * ${AuthorFragment}
7070+ * `;
7171+ *
7272+ * const BookQuery = gql`
7373+ * query Book($id: ID!) {
7474+ * book(id: $id) {
7575+ * ...BookFragment
7676+ * }
7777+ * }
7878+ *
7979+ * ${BookFragment}
8080+ * `;
8181+ * ```
8282+ */
3783function gql<Data = any, Variables extends AnyVariables = AnyVariables>(
3884 strings: TemplateStringsArray,
3985 ...interpolations: Array<TypedDocumentNode | DocumentNode | string>
+30
packages/core/src/internal/fetchOptions.ts
···55} from '../utils';
66import { AnyVariables, GraphQLRequest, Operation } from '../types';
7788+/** Abstract definition of the JSON data sent during GraphQL HTTP POST requests. */
89export interface FetchBody {
910 query?: string;
1011 operationName: string | undefined;
···1213 extensions: undefined | Record<string, any>;
1314}
14151616+/** Creates a GraphQL over HTTP compliant JSON request body.
1717+ * @param request - An object containing a `query` document and `variables`.
1818+ * @returns A {@link FetchBody}
1919+ * @see {@link https://github.com/graphql/graphql-over-http} for the GraphQL over HTTP spec.
2020+ */
1521export function makeFetchBody<
1622 Data = any,
1723 Variables extends AnyVariables = AnyVariables
···2430 };
2531}
26323333+/** Creates a URL that will be called for a GraphQL HTTP request.
3434+ *
3535+ * @param operation - An {@link Operation} for which to make the request.
3636+ * @param body - A {@link FetchBody} which may be replaced with a URL.
3737+ *
3838+ * @remarks
3939+ * Creates the URL that’ll be called as part of a GraphQL HTTP request.
4040+ * Built-in fetch exchanges support sending GET requests, even for
4141+ * non-persisted full requests, which this function supports by being
4242+ * able to serialize GraphQL requests into the URL.
4343+ */
2744export const makeFetchURL = (
2845 operation: Operation,
2946 body?: FetchBody
···5067 return finalUrl;
5168};
52697070+/** Creates a `RequestInit` object for a given `Operation`.
7171+ *
7272+ * @param operation - An {@link Operation} for which to make the request.
7373+ * @param body - A {@link FetchBody} which is added to the options, if the request isn’t a GET request.
7474+ *
7575+ * @remarks
7676+ * Creates the fetch options {@link RequestInit} object that’ll be passed to the Fetch API
7777+ * as part of a GraphQL over HTTP request. It automatically sets a default `Content-Type`
7878+ * header.
7979+ *
8080+ * @see {@link https://github.com/graphql/graphql-over-http} for the GraphQL over HTTP spec.
8181+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API} for the Fetch API spec.
8282+ */
5383export const makeFetchOptions = (
5484 operation: Operation,
5585 body?: FetchBody
+27
packages/core/src/internal/fetchSource.ts
···1515 ? (input as Buffer).toString()
1616 : decoder!.decode(input as ArrayBuffer);
17171818+/** Makes a GraphQL HTTP request to a given API by wrapping around the Fetch API.
1919+ *
2020+ * @param operation - The {@link Operation} that should be sent via GraphQL over HTTP.
2121+ * @param url - The endpoint URL for the GraphQL HTTP API.
2222+ * @param fetchOptions - The {@link RequestInit} fetch options for the request.
2323+ * @returns A Wonka {@link Source} of {@link OperationResult | OperationResults}.
2424+ *
2525+ * @remarks
2626+ * This utility defines how all built-in fetch exchanges make GraphQL HTTP requests,
2727+ * supporting multipart incremental responses, cancellation and other smaller
2828+ * implementation details.
2929+ *
3030+ * If you’re implementing a modified fetch exchange for a GraphQL over HTTP API
3131+ * it’s recommended you use this utility.
3232+ *
3333+ * Hint: This function does not use the passed `operation` to create or modify the
3434+ * `fetchOptions` and instead expects that the options have already been created
3535+ * using {@link makeFetchOptions} and modified as needed.
3636+ *
3737+ * @throws
3838+ * If the `fetch` polyfill or globally available `fetch` function doesn’t support
3939+ * streamed multipart responses while trying to handle a `multipart/mixed` GraphQL response,
4040+ * the source will throw “Streaming requests unsupported”.
4141+ * This shouldn’t happen in modern browsers and Node.js.
4242+ *
4343+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API} for the Fetch API spec.
4444+ */
1845export const makeFetchSource = (
1946 operation: Operation,
2047 url: string,
+535-39
packages/core/src/types.ts
···33import { Client } from './client';
44import { CombinedError } from './utils/error';
5566-// NOTE: This is mirrored from @graphql-typed-document-node/core and must match this type exactly.
77-// It has been copied here to avoid tooling problems where build systems get confused about the type-only nature of this package.
88-// See for original: https://github.com/dotansimha/graphql-typed-document-node/blob/3711b12/packages/core/src/index.ts#L3-L10
66+/** A GraphQL `DocumentNode` with attached generics for its result data and variables.
77+ *
88+ * @remarks
99+ * A GraphQL {@link DocumentNode} defines both the variables it accepts on request and the `data`
1010+ * shape it delivers on a response in the GraphQL query language.
1111+ *
1212+ * To bridge the gap to TypeScript, tools may be used to generate TypeScript types that define the shape
1313+ * of `data` and `variables` ahead of time. These types are then attached to GraphQL documents using this
1414+ * `TypedDocumentNode` type.
1515+ *
1616+ * Using a `DocumentNode` that is typed like this will cause any `urql` API to type its input `variables`
1717+ * and resulting `data` using the types provided.
1818+ *
1919+ * @privateRemarks
2020+ * For compatibility reasons this type has been copied and internalized from:
2121+ * https://github.com/dotansimha/graphql-typed-document-node/blob/3711b12/packages/core/src/index.ts#L3-L10
2222+ *
2323+ * @see {@link https://github.com/dotansimha/graphql-typed-document-node} for more information.
2424+ */
925export interface TypedDocumentNode<
1026 Result = { [key: string]: any },
1127 Variables = { [key: string]: any }
1228> extends DocumentNode {
1313- /**
1414- * This type is used to ensure that the variables you pass in to the query are assignable to Variables
1515- * and that the Result is assignable to whatever you pass your result to. The method is never actually
1616- * implemented, but the type is valid because we list it as optional
2929+ /** Type to check whether `Variables` and `Result` are assignable types.
3030+ * @internal
1731 */
1832 __apiType?: (variables: Variables) => Result;
1933}
20343535+/** A list of errors on {@link ExecutionResult | ExecutionResults}.
3636+ * @see {@link https://spec.graphql.org/draft/#sec-Errors.Error-Result-Format} for the GraphQL Error Result format spec.
3737+ */
2138type ErrorLike = Partial<GraphQLError> | Error;
3939+/** Extensions which may be placed on {@link ExecutionResult | ExecutionResults}.
4040+ * @see {@link https://spec.graphql.org/draft/#sel-EAPHJCAACCoGu9J} for the GraphQL Error Result format spec.
4141+ */
2242type Extensions = Record<string, any>;
23434444+/** Incremental Payloads sent as part of "Incremental Delivery" patching prior result data.
4545+ *
4646+ * @remarks
4747+ * "Incremental Delivery" works by allowing APIs to stream patches to the client, whih update
4848+ * prior results at the specified `path`.
4949+ *
5050+ * @see {@link https://github.com/graphql/graphql-spec/blob/94363c9/spec/Section%207%20--%20Response.md#incremental} for the incremental payload spec
5151+ */
2452export interface IncrementalPayload {
5353+ /** Optional label for the incremental payload that corresponds to directives' labels.
5454+ *
5555+ * @remarks
5656+ * All incremental payloads are labelled by the label that `@stream` or `@defer` directives
5757+ * specified, to identify which directive they originally belonged to.
5858+ */
2559 label?: string | null;
6060+ /** JSON patch at which to apply the `data` patch or append the `items`.
6161+ *
6262+ * @remarks
6363+ * The `path` indicates the JSON path of a prior result’s `data` structure at which
6464+ * to insert the patch’s data.
6565+ * When `items` is set instead, which represents a list of items to insert, the last
6666+ * entry of the `path` will be an index number at which to start setting the range of
6767+ * items.
6868+ */
2669 path: readonly (string | number)[];
7070+ /** Data to patch into the result data at the given `path`.
7171+ *
7272+ * @remarks
7373+ * This `data`, when set, is merged into the object at the given `path` of the last
7474+ * result that has been delivered.
7575+ * This isn't set when `items` is set.
7676+ */
2777 data?: Record<string, unknown> | null;
7878+ /** List of items to patch into the result data at the given `path`.
7979+ *
8080+ * @remarks
8181+ * The `items`, when provided, is set onto a range in an array, at the given JSON
8282+ * `path`. The start index is the last entry of the `path` and the end index is
8383+ * the length of the `items` list added to this index.
8484+ * This isn't set when `data` is set.
8585+ */
2886 items?: readonly unknown[] | null;
8787+ /** Contains a list of errors raised by incremental payloads.
8888+ *
8989+ * @remarks
9090+ * The list of `errors` on `incremental` payloads is merged into the list of prior
9191+ * results’ errors.
9292+ *
9393+ * @see {@link https://spec.graphql.org/October2021/#sec-Errors} for the GraphQL Errors Response spec
9494+ */
2995 errors?: ErrorLike[] | readonly ErrorLike[];
9696+ /** Additional metadata that a GraphQL API may choose to send that is out of spec.
9797+ * @see {@link https://spec.graphql.org/October2021/#sel-EAPHJCAACCoGu9J} for the GraphQL Response spec
9898+ */
3099 extensions?: Extensions;
31100}
3210133102export interface ExecutionResult {
103103+ /** Incremental patches to be applied to a previous result as part of "Incremental Delivery".
104104+ *
105105+ * @remarks
106106+ * When this is set `data` and `errors` is typically not set on the result. Instead, the incremental payloads
107107+ * are applied as patches to a prior result's `data`.
108108+ *
109109+ * @see {@link https://github.com/graphql/graphql-spec/blob/94363c9/spec/Section%207%20--%20Response.md#incremental} for the incremental payload spec
110110+ */
34111 incremental?: IncrementalPayload[];
112112+ /** The result of the execution of the GraphQL operation.
113113+ * @see {@link https://spec.graphql.org/October2021/#sec-Data} for the GraphQL Data Response spec
114114+ */
35115 data?: null | Record<string, any>;
116116+ /** Contains a list of errors raised by fields or the request itself.
117117+ * @see {@link https://spec.graphql.org/October2021/#sec-Errors} for the GraphQL Errors Response spec
118118+ */
36119 errors?: ErrorLike[] | readonly ErrorLike[];
120120+ /** Additional metadata that a GraphQL API may choose to send that is out of spec.
121121+ * @see {@link https://spec.graphql.org/October2021/#sel-EAPHJCAACCoGu9J} for the GraphQL Response spec
122122+ */
37123 extensions?: Extensions;
124124+ /** Flag indicating whether a future, incremental response may update this response.
125125+ * @see {@link https://github.com/graphql/graphql-wg/blob/main/rfcs/DeferStream.md#payload-format} for the DeferStream spec
126126+ */
38127 hasNext?: boolean;
39128}
40129130130+/** A `Source` with a `PromisifiedSource.toPromise` helper method, to promisify a single result.
131131+ *
132132+ * @remarks
133133+ * The {@link Client} will often return a `PromisifiedSource` to provide the `toPromise` method. When called, this returns
134134+ * a promise of the source that resolves on the first {@link OperationResult} of the `Source` that doesn't have `stale: true`
135135+ * nor `hasNext: true` set, meaning, it'll resolve to the first result that is stable and complete.
136136+ */
41137export type PromisifiedSource<T = any> = Source<T> & {
42138 toPromise: () => Promise<T>;
43139};
441404545-/** The type of GraphQL operation being executed. */
141141+/** A type of Operation, either a GraphQL `query`, `mutation`, or `subscription`; or a `teardown` signal.
142142+ *
143143+ * @remarks
144144+ * Internally, {@link Operation | Operations} instruct the {@link Client} to perform a certain action on its exchanges.
145145+ * Any of the three GraphQL operations tell it to execute these operations, and the `teardown` signal instructs it that
146146+ * the operations are cancelled and/or have ended.
147147+ *
148148+ * The `teardown` signal is sent when nothing is subscribed to an operation anymore and no longer interested in its results
149149+ * or any updates.
150150+ */
46151export type OperationType = 'subscription' | 'query' | 'mutation' | 'teardown';
471524848-/** The strategy that is used to request results from network and/or the cache. */
153153+/** The request and caching strategy that is used by exchanges to retrive cached results.
154154+ *
155155+ * @remarks
156156+ * The `RequestPolicy` is used by cache exchanges to decide how a query operation may be resolved with cached results.h
157157+ * A cache exchange may behave differently depending on which policy is returned.
158158+ *
159159+ * - `cache-first` (the default) prefers cached results and falls back to sending an API request.
160160+ * - `cache-and-network` returns cached results but also always sends an API request in the background.
161161+ * - `network-only` will ignore any cached results and send an API request.
162162+ * - `cache-only` will always return cached results and prevent API requests.
163163+ */
49164export type RequestPolicy =
50165 | 'cache-first'
5151- | 'cache-only'
166166+ | 'cache-and-network'
52167 | 'network-only'
5353- | 'cache-and-network';
168168+ | 'cache-only';
541695555-/** How the operation has */
170170+/** A metadata flag set by cache exchanges to indicate whether a cache miss, a cache hit, or a partial cache hit has occurred.
171171+ *
172172+ * @remarks
173173+ * A cache exchange may update {@link OperationDebugMeta.cacheOutcome} on {@link OperationContext.meta} to indicate whether
174174+ * an operation has been resolved from the cache.
175175+ *
176176+ * A cache hit is considered a result that has fully come from a cache. A partial result is a result that has come from a cache
177177+ * but is incomplete, which may trigger another API request. A cache miss means a result must be requested from the API as no
178178+ * cache result has been delivered.
179179+ */
56180export type CacheOutcome = 'miss' | 'partial' | 'hit';
571815858-/** A default type for variables */
182182+/** A default type for variables.
183183+ *
184184+ * @remarks
185185+ * While {@link TypedDocumentNode} can be used by generators to add TypeScript types for a GraphQL operation’s
186186+ * variables and result, when this isn’t the case this type is used as a fallback for the `Variables` generic.
187187+ */
59188export type AnyVariables = { [prop: string]: any } | void | undefined;
601896161-/** A Graphql query, mutation, or subscription. */
190190+/** A GraphQL request representing a single execution in GraphQL.
191191+ *
192192+ * @remarks
193193+ * A `GraphQLRequest` is a single executable request that may be used by a cache or a GraphQL API to deliver a result.
194194+ * A request contains a `DocumentNode` for the query document of a GraphQL operation and the `variables` for the given
195195+ * request.
196196+ *
197197+ * A unique `key` is generated to identify the request internally by `urql`. Two requests with the same query and
198198+ * variables will share the same `key`.
199199+ *
200200+ * The `Data` and `Variables` generics may be provided by a {@link TypedDocumentNode}, adding TypeScript types for what
201201+ * the result shape and variables shape are.
202202+ *
203203+ * @see {@link https://spec.graphql.org/October2021/#sec-Executing-Requests} for more information on GraphQL reuqests.
204204+ */
62205export interface GraphQLRequest<
63206 Data = any,
64207 Variables extends AnyVariables = AnyVariables
65208> {
6666- /** Unique identifier of the request. */
209209+ /** Unique identifier for the `GraphQLRequest`.
210210+ *
211211+ * @remarks
212212+ * This is a key that combines the unique key of the `query` and the `variables` into a unique
213213+ * `key` for the `GraphQLRequest`. Any request with the same query and variables will have a unique
214214+ * `key` by which results and requests can be identified as identical.
215215+ *
216216+ * Internally, a stable, cached `key` is generated for the `DocumentNode` and for the `variables` and
217217+ * both will be combined into a combined `key` which is set here, based on a DJB2 hash,
218218+ *
219219+ * The `variables` will change the key even if they contain a non-JSON reference. If you pass a custom
220220+ * class instance to `variables` that doesn't contain a `toString` or `toJSON` method, a stable but random
221221+ * identifier will replace this class to generate a key.
222222+ */
67223 key: number;
224224+ /** A GraphQL document to execute against a cache or API.
225225+ *
226226+ * @remarks
227227+ * A `GraphQLRequest` is executed against an operation in a GraphQL document.
228228+ * In `urql`, we expect a document to only contain a single operation that is executed rather than
229229+ * multiple ones by convention.
230230+ */
68231 query: DocumentNode | TypedDocumentNode<Data, Variables>;
232232+ /** Variables used to execute the `query` document.
233233+ *
234234+ * @remarks
235235+ * The `variables`, based either on the {@link AnyVariables} type or the {@link TypedDocumentNode}'s provided
236236+ * generic, are sent to the GraphQL API to execute a request.
237237+ */
69238 variables: Variables;
70239}
712407272-/** Metadata that is only available in development for devtools. */
241241+/** Metadata used to annotate an `Operation` in development for the `urql-devtools`.
242242+ *
243243+ * @remarks
244244+ * The `OperationDebugMeta` is found on {@link OperationContext.meta} only in development,
245245+ * and is used to send additional metadata to the `urql-devtools` about the {@link Operation}.
246246+ *
247247+ * In production, most of this metadata will be missing, and it must not be used outside
248248+ * of development, and should only be used by the `urql-devtools`.
249249+ */
73250export interface OperationDebugMeta {
251251+ /** A label for the source of the `Operation`.
252252+ *
253253+ * @remarks
254254+ * The `source` string indicates a human readable originator for the `Operation`.
255255+ * This may be set to a component name or function name to indicate what originally
256256+ * triggered the `Operation`.
257257+ */
74258 source?: string;
259259+ /** A type of caching outcome set by cache exchanges on `OperationResult`s.
260260+ *
261261+ * @remarks
262262+ * The `cacheOutcome` flag is set to a {@link CacheOutcome} on {@link Operation | Operations}
263263+ * after they passed through the cache exchange. This flag indicates whether a cache hit, miss,
264264+ * or partial cache hit has occurred.
265265+ */
75266 cacheOutcome?: CacheOutcome;
267267+ /** Reserved to indicate the time it took for a GraphQL request to receive a response from a GraphQL API.
268268+ *
269269+ * @remarks
270270+ * The `networkLatency` may be set to the time it took (in ms) for a GraphQL API to respond to a request
271271+ * and deliver a result.
272272+ * @internal
273273+ */
76274 networkLatency?: number;
275275+ /** Reserved to indicate the timestamp at which a GraphQL request was sent to a GraphQL API.
276276+ *
277277+ * @remarks
278278+ * The `startTime` is set to an epoch timestamp (in ms) at which a GraphQL request was started
279279+ * and sent to a GraphQL API.
280280+ * @internal
281281+ */
77282 startTime?: number;
78283}
792848080-/** A unique marker that marks the operation's identity when multiple mutation operations with identical keys are issued. */
8181-export type OperationInstance = number & { readonly _opaque: unique symbol };
285285+/** A unique identity for GraphQL mutations.
286286+ *
287287+ * @remarks
288288+ * GraphQL mutations not only use {@link GraphQLRequest.key} to identify a result, but instead use
289289+ * an identity to mark which result belongs to them.
290290+ *
291291+ * While two GraphQL queries and subscriptions sharing the same variables and the same operation
292292+ * (i.e. `DocumentNode`) are considered identical, two mutations are not.
293293+ * Two GraphQL queries or subscription results with the same {@link GraphQLRequest.key} can be used
294294+ * to resolve any {@link GraphQLRequest} with this same `key`.
295295+ * This is because identical queries and subscriptions are idempotent.
296296+ *
297297+ * However, two mutations with the same variables may receive different results from a GraphQL API,
298298+ * since they may trigger side-effects.
299299+ * This means that `urql` needs an additional identifier to differentiate between two mutations with
300300+ * the same `DocumentNode`s and `variables`.
301301+ */
302302+export type OperationInstance = number & {
303303+ /** Marker to indicate that an `OperationInstance` may not be created by a user.
304304+ *
305305+ * @remarks
306306+ * The {@link Client} creates `OperationInstance` indentities automatically and uses them internally
307307+ * to identify mutations results as belonging to mutation operations. These are just integers (numbers),
308308+ * however, they're used as if they are objects (e.g. `{}`). However, since instances of arrays and
309309+ * objects are not serialisable numbers are used instead.
310310+ *
311311+ * Because these are internal, the TypeScript type is marked using a `unique symbol` because they're
312312+ * created opaquely and privately.
313313+ *
314314+ * @internal
315315+ */
316316+ readonly _opaque: unique symbol;
317317+};
823188383-/** Additional metadata passed to [exchange]{@link Exchange} functions. */
319319+/** Additional metadata for an `Operation` used to execute it.
320320+ *
321321+ * @remarks
322322+ * The `OperationContext` is found on {@link Operation.context} and gives exchanges additional metadata
323323+ * and options used to execute the operation.
324324+ *
325325+ * The context can often be changed on a per-operation basis, meaning, APIs on the {@link Client} or
326326+ * bindings can pass a partial context that alters these options for a single operation.
327327+ *
328328+ * The `OperationContext` is populated mostly from the initial options passed to the `Client` at its
329329+ * time of creation, but may also be modified by exchanges when an {@link Operation} is passed through
330330+ * to the next exchange or when a result is returned.
331331+ */
84332export interface OperationContext {
8585- [key: string]: any;
333333+ /** A unique identity for GraphQL mutations.
334334+ *
335335+ * @remarks
336336+ * This is an internal property set by the `Client` to an identity of type {@link OperationInstance}.
337337+ * An `OperationInstance` is an identifier that's used to tell two mutation operations with identical
338338+ * `query` documents and `variables` apart from one another.
339339+ * @internal
340340+ */
86341 readonly _instance?: OperationInstance | undefined;
342342+ /** Additional cache tags for `@urql/core`'s document `cacheExchange`.
343343+ *
344344+ * @remarks
345345+ * The built-in {@link cacheExchange} in `@urql/core` is a document cache that uses `__typename`s in
346346+ * mutation results to invalidate past, cached queries.
347347+ * The `additionalTypenames` array may be set to the list of custom typenames whenever a result may
348348+ * not deliver `__typename` properties, e.g. when an empty array may be sent.
349349+ *
350350+ * By providing a list of custom typenames you may "tag" a result as containing a certain type, which
351351+ * helps the document cache associate mutations with queries when either don't actually contain a
352352+ * `__typename` in the JSON result.
353353+ */
87354 additionalTypenames?: string[];
355355+ /** The `fetch` function used to make API calls.
356356+ *
357357+ * @remarks
358358+ * This is the fetch polyfill used by any fetch exchange to make an API request. By default, when this
359359+ * option isn't set, any fetch exchange will attempt to use the globally available `fetch` function
360360+ * to make a request instead.
361361+ *
362362+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API} for the Fetch API spec.
363363+ */
88364 fetch?: typeof fetch;
365365+ /** The `url` passed to the `fetch` call on API requests.
366366+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/fetch} for a description of the `fetch` calls.
367367+ */
368368+ url: string;
369369+ /** Additional options passed to the `fetch` call on API requests.
370370+ *
371371+ * @remarks
372372+ * The options in this object or an object returned by a callback function will be merged into the
373373+ * {@link RequestInit} options passed to the `fetch` call.
374374+ *
375375+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/fetch} for a description of this object.
376376+ */
89377 fetchOptions?: RequestInit | (() => RequestInit);
378378+ /** The request and caching strategy instructing cache exchanges how to treat cached results.
379379+ *
380380+ * @remarks
381381+ * The {@link RequestPolicy} instructing cache exchanges how to use and treat their cached results.
382382+ * By default `cache-first` is set and used, which will use cache results, and only make an API request
383383+ * on a cache miss.
384384+ */
90385 requestPolicy: RequestPolicy;
9191- url: string;
386386+ /** Metadata that annotates an `Operation` in development for the `urql-devtools`.
387387+ *
388388+ * @remarks
389389+ * This is metadata that is used by the `urql-devtools` to get more information about `Operation`s and
390390+ * `OperationResult`s and is filled in by exchanges across the codebase in development.
391391+ *
392392+ * This data is not for production use and hence shouldn't be used or relied upon directly.
393393+ */
92394 meta?: OperationDebugMeta;
9393- suspense?: boolean;
94395 /** Instructs fetch exchanges to use a GET request.
9595- * When true or 'within-url-limit' is passed, GET won't be used when the resulting URL exceeds a length of 2048. */
396396+ *
397397+ * @remarks
398398+ * By default, GraphQL over HTTP requests are always sent as POST requests with a JSON body.
399399+ * However, sometimes it's preferable to send a GET request instead, for instance, for caching with or
400400+ * without persisted queries.
401401+ *
402402+ * When set to `true`, the `preferGetMethod` instructs fetch exchanges to instead send a GET request
403403+ * for query operations.
404404+ *
405405+ * Additionally, `urql`'s built-in fetch exchanges will default to `'within-url-limit'` and not send a GET request
406406+ * when the resulting URL would be 2,048 characters or longer. This can be forced and circumvented by setting
407407+ * this option to `'force'`.
408408+ */
96409 preferGetMethod?: boolean | 'force' | 'within-url-limit';
410410+ /** A configuration flag indicating whether this operation may trigger "Suspense".
411411+ *
412412+ * @remarks
413413+ * This configuration flag is reserved for `urql` (`react-urql`) and `@urql/preact` to activate or
414414+ * deactivate support for Suspense, and is ignored in other bindings.
415415+ * When activated here and on {@link `Client.suspense`} it allows the bindings to "suspend" instead
416416+ * of returning a loading state, which will stop updates in a querying component and instead cascade
417417+ * to a higher suspense boundary for a loading state.
418418+ *
419419+ * @see {@link https://beta.reactjs.org/blog/2022/03/29/react-v18#new-suspense-features} for more information on React Suspense.
420420+ */
421421+ suspense?: boolean;
422422+ [key: string]: any;
97423}
984249999-/** A [query]{@link Query} or [mutation]{@link Mutation} with additional metadata for use during transmission. */
425425+/** The inputs to `urql`'s Exchange pipeline to instruct them to execute a GraphQL operation.
426426+ *
427427+ * @remarks
428428+ * An `Operation`, in `urql`, starts a {@link GraphQLRequest} and are events. The `kind` of an `Operation` can
429429+ * be set to any operation kind of GraphQL, namely `query`, `mutation`, or `subscription`. To terminate an
430430+ * operation, once it's cancelled, a `teardown` kind event is sent.
431431+ *
432432+ * The {@link ExchangeIO} type describes how {@link Exchange | Exchanges} receive `Operation`s and return
433433+ * `OperationResults`, using `teardown` `Operation`s to cancel ongoing operations.
434434+ *
435435+ * @see {@link https://formidable.com/open-source/urql/docs/architecture/#the-client-and-exchanges} for more information
436436+ * on the flow of Exchanges.
437437+ */
100438export interface Operation<
101439 Data = any,
102440 Variables extends AnyVariables = AnyVariables
103441> extends GraphQLRequest<Data, Variables> {
442442+ /** The `OperationType` describing the kind of `Operation`.
443443+ *
444444+ * @remarks
445445+ * This is used to describe what to do with the {@link GraphQLRequest} of an {@link Operation} and is set
446446+ * to a GraphQL operation type (`query`, `mutation`, or `subscription`) to start an `Operation`; and to
447447+ * `teardown` to cancel an operation, which either terminates it early or lets exchanges know that no
448448+ * consumer is interested in this operation any longer.
449449+ */
104450 readonly kind: OperationType;
451451+ /** Holds additional metadata for an `Operation` used to execute it.
452452+ *
453453+ * @remarks
454454+ * The {@link OperationContext} is created by the {@link Client} but may also be modified by
455455+ * {@link Exchange | Exchanges} and is used as metadata by them.
456456+ */
105457 context: OperationContext;
106458}
107459108108-/** Resulting data from an [operation]{@link Operation}. */
460460+/** A result for an `Operation` carrying a full GraphQL response.
461461+ *
462462+ * @remarks
463463+ * An `OperationResult` is the result of an {@link Operation} and carry a description of the full response
464464+ * on them. The {@link OperationResult.operation} is set to the `Operation` that this result fulfils.
465465+ *
466466+ * Unlike {@link ExecutionResult}, an `OperationResult` will never be an incremental result and will
467467+ * always match the fully merged type of a GraphQL request. It essentially is a postprocessed version
468468+ * of a GraphQL API response.
469469+ */
109470export interface OperationResult<
110471 Data = any,
111472 Variables extends AnyVariables = AnyVariables
112473> {
113474 /** The [operation]{@link Operation} which has been executed. */
475475+ /** The `Operation` which this `OperationResult` is for.
476476+ *
477477+ * @remarks
478478+ * The `operation` property is set to the {@link Operation} that this result is. At the time the
479479+ * {@link OperationResult} is constructed (either from the cache or an API response) the original
480480+ * `Operation` that the exchange delivering this result has received will be added.
481481+ *
482482+ * The {@link Client} uses this to identify which {@link Operation} this {@link OperationResult} is
483483+ * for and to filter and deliver this result to the right place and consumers.
484484+ */
114485 operation: Operation<Data, Variables>;
115115- /** The data returned from the Graphql server. */
486486+ /** The result of the execution of the GraphQL operation.
487487+ * @see {@link https://spec.graphql.org/October2021/#sec-Data} for the GraphQL Data Response spec
488488+ */
116489 data?: Data;
117117- /** Any errors resulting from the operation. */
490490+ /** Contains a description of errors raised by GraphQL fields or the request itself by the API.
491491+ *
492492+ * @remarks
493493+ * The `error` of an `OperationResult` is set to a {@link CombinedError} if the GraphQL API response
494494+ * contained any GraphQL errors.
495495+ *
496496+ * GraphQL errors occur when either a GraphQL request was prevented from executing entirely
497497+ * (at which point `data: undefined` is set) or when one or more fields of a GraphQL request
498498+ * failed to execute. Due to the latter, you may receive partial data when a GraphQL request
499499+ * partially failed.
500500+ */
118501 error?: CombinedError;
119119- /** Optional extensions return by the Graphql server. */
502502+ /** Additional metadata that a GraphQL API may choose to send that is out of spec.
503503+ * @see {@link https://spec.graphql.org/October2021/#sel-EAPHJCAACCoGu9J} for the GraphQL Response spec
504504+ */
120505 extensions?: Record<string, any>;
121121- /** Optional stale flag added by exchanges that return stale results. */
506506+ /** Indicates that an `OperationResult` is not fresh and a new result will follow.
507507+ *
508508+ * @remarks
509509+ * The `stale` flag indicates whether a result is expected to be superseded by a new result soon.
510510+ * This flag is set whenever a new result is being awaited and will be deliverd as soon as the API responds.
511511+ *
512512+ * It may be set by the {@link Client} when the `Operation` was already active, at which point
513513+ * the {@link Client} asks the {@link Exchange | Exchanges} to request a new API response, or
514514+ * by cache exchanges when a temporary, incomplete, or initial cache result has been deliverd, and
515515+ * a new API request has been started in the background. (For partial cache results)
516516+ *
517517+ * Most commonly, this flag is set for a cached result when the operation is executed using the
518518+ * `cache-and-network` {@link RequestPolicy}.
519519+ */
122520 stale?: boolean;
123123- /** Optional hasNext flag indicating deferred/streamed results are following. */
521521+ /** Indicates that the GraphQL response is streamed and updated results will follow.
522522+ *
523523+ * @remarks
524524+ * Due to incremental delivery, an API may deliver multiple {@link ExecutionResult | ExecutionResults} for a
525525+ * single GraphQL request. This can happen for `@defer`, `@stream`, or `@live` queries, which allow an API
526526+ * to update an initial GraphQL response over time, like a subscription.
527527+ *
528528+ * For GraphQL subscriptions, this flag will always be set to `true`.
529529+ */
124530 hasNext?: boolean;
125531}
126532127127-/** Input parameters for to an Exchange factory function. */
533533+/** The input parameters a `Client` passes to an `Exchange` when it's created.
534534+ *
535535+ * @remarks
536536+ * When instantiated, a {@link Client} passes these inputs parameters to an {@link Exchange}.
537537+ *
538538+ * This input contains the `Client` itself, a `dispatchDebug` function for the `urql-devtools`, and
539539+ * `forward`, which is set to the next exchange's {@link ExchangeIO} function in the exchange pipeline.
540540+ */
128541export interface ExchangeInput {
542542+ /** The `Client` that is using this `Exchange`.
543543+ *
544544+ * @remarks
545545+ * The {@link Client} instantiating the {@link Exchange} will call it with the `ExchangeInput` object,
546546+ * while setting `client` to itself.
547547+ *
548548+ * Exchanges use methods like {@link Client.reexecuteOperation} to issue {@link Operation | Operations}
549549+ * themselves, and communicate with the exchange pipeline as a whole.
550550+ */
129551 client: Client;
552552+ /** The next `Exchange`'s {@link ExchangeIO} function in the pipeline.
553553+ *
554554+ * @remarks
555555+ * `Exchange`s are like middleware function, and are henced composed like a recursive pipeline.
556556+ * Each `Exchange` will receive the next `Exchange`'s {@link ExchangeIO} function which they
557557+ * then call to compose each other.
558558+ *
559559+ * Since each `Exchange` calls the next, this creates a pipeline where operations are forwarded
560560+ * in sequence and `OperationResult`s from the next `Exchange` are combined with the current.
561561+ */
130562 forward: ExchangeIO;
131131- dispatchDebug: <T extends keyof DebugEventTypes | string>(
563563+ /** Issues a debug event to the `urql-devtools`.
564564+ *
565565+ * @remarks
566566+ * If `@urql/devtools` are set up, this dispatch function issues events to the `urql-devtools`.
567567+ * These events give the devtools more granular insights on what's going on in exchanges asynchronously,
568568+ * since `Operation`s and `OperationResult`s only signify the “start” and “end” of a request.
569569+ */
570570+ dispatchDebug<T extends keyof DebugEventTypes | string>(
132571 t: DebugEventArg<T>
133133- ) => void;
572572+ ): void;
134573}
135574136136-/** Function responsible for listening for streamed [operations]{@link Operation}. */
575575+/** `Exchange`s are both extensions for a `Client` and part of the control-flow executing `Operation`s.
576576+ *
577577+ * @remarks
578578+ * `Exchange`s are responsible for the pipeline in `urql` that accepts {@link Operation | Operations} and
579579+ * returns {@link OperationResult | OperationResults}. They take care of adding functionality to a {@link Client},
580580+ * like deduplication, caching, and fetching (i.e. making GraphQL requests).
581581+ *
582582+ * When passed to the `Client`, they're instantiated with the {@link ExchangeInput} object and return an {@link ExchangeIO}
583583+ * function, which is a mapping function that receives a stream of `Operation`s and returns a stream of `OperationResult`s.
584584+ *
585585+ * Like middleware, exchanges are composed, calling each other in a pipeline-like fashion, which is facilitated by exchanges
586586+ * calling {@link ExchangeInput.forward}, which is set to the next exchange's {@link ExchangeIO} function in the pipeline.
587587+ *
588588+ * @see {@link https://formidable.com/open-source/urql/docs/architecture/#the-client-and-exchanges} for more information on Exchanges.
589589+ * @see {@link https://formidable.com/open-source/urql/docs/advanced/authoring-exchanges/} on how Exchanges are authored.
590590+ */
137591export type Exchange = (input: ExchangeInput) => ExchangeIO;
138592139139-/** Function responsible for receiving an observable [operation]{@link Operation} and returning a [result]{@link OperationResult}. */
593593+/** Returned by `Exchange`s, the `ExchangeIO` function are the composed pipeline functions.
594594+ *
595595+ * @remarks
596596+ * An {@link Exchange} must return an `ExchangeIO` function, which accepts a stream of {@link Operation | Operations} which
597597+ * this exchange handles and returns a stream of {@link OperationResult | OperationResults}. These streams are Wonka {@link Source | Sources}.
598598+ *
599599+ * An exchange may enhance the incoming stream of `Operation`s to add, filter, map (change), or remove `Operation`s, before
600600+ * forwarding those to {@link ExchangeInput.forward}, using Wonka's operators, and may add or remove `OperationResult`s from
601601+ * the returned stream.
602602+ *
603603+ * Generally, the stream of `OperationResult` returned by {@link ExchangeInput.forward} is always merged and combined with
604604+ * the `Exchange`'s own stream of results if the `Exchange` creates and delivers results of its own.
605605+ *
606606+ * @see {@link https://formidable.com/open-source/urql/docs/advanced/authoring-exchanges/} on how Exchanges are authored.
607607+ */
140608export type ExchangeIO = (ops$: Source<Operation>) => Source<OperationResult>;
141609142142-/** Debug event types (interfaced for declaration merging). */
610610+/** A mapping type of debug event types to their payloads.
611611+ *
612612+ * @remarks
613613+ * These are the debug events that {@link ExchangeInput.dispatchDebug} accepts mapped to the payloads these events carry.
614614+ * Debug events are only used in development and only consumed by the `urql-devtools`.
615615+ */
143616export interface DebugEventTypes {
144144- // Cache exchange
617617+ /** Signals to the devtools that a cache exchange will deliver a cached result. */
145618 cacheHit: { value: any };
619619+ /** Signals to the devtools that a cache exchange will invalidate a cached result. */
146620 cacheInvalidation: {
147621 typenames: string[];
148622 response: OperationResult;
149623 };
150150- // Fetch exchange
624624+ /** Signals to the devtools that a fetch exchange will make a GraphQL API request. */
151625 fetchRequest: {
152626 url: string;
153627 fetchOptions: RequestInit;
154628 };
629629+ /** Signals to the devtools that a fetch exchange has received a GraphQL API response successfully. */
155630 fetchSuccess: {
156631 url: string;
157632 fetchOptions: RequestInit;
158633 value: object;
159634 };
635635+ /** Signals to the devtools that a fetch exchange has failed to execute a GraphQL API request. */
160636 fetchError: {
161637 url: string;
162638 fetchOptions: RequestInit;
163639 value: Error;
164640 };
165165- // Retry exchange
641641+ /** Signals to the devtools that a retry exchange will retry an Operation. */
166642 retryRetrying: {
167643 retryCount: number;
168644 };
169645}
170646647647+/** Utility type that maps a debug event type to its payload.
648648+ *
649649+ * @remarks
650650+ * This is a utility type that determines the required payload for a given debug event, which is
651651+ * sent to the `urql-devtools`.
652652+ *
653653+ * The payloads for known debug events are defined by the {@link DebugEventTypes} type, and
654654+ * each event additionally carries a human readable `message` with it, and the {@link Operation}
655655+ * for which the event is.
656656+ *
657657+ * @internal
658658+ */
171659export type DebugEventArg<T extends keyof DebugEventTypes | string> = {
172660 type: T;
173661 message: string;
···176664 ? { data: DebugEventTypes[T] }
177665 : { data?: any });
178666667667+/** Utility type of the full payload that is sent to the `urql-devtools`.
668668+ *
669669+ * @remarks
670670+ * While the {@link DebugEventArg} defines the payload that {@link ExchangeInput.dispatchDebug}
671671+ * accepts, each debug event then receives additional properties which are sent to the `urql-devtools`,
672672+ * which this type defines.
673673+ * @internal
674674+ */
179675export type DebugEvent<
180676 T extends keyof DebugEventTypes | string = string
181677> = DebugEventArg<T> & {
+47-1
packages/core/src/utils/error.ts
···3333 }
3434};
35353636-/** An error which can consist of GraphQL errors and Network errors. */
3636+/** An abstracted `Error` that provides either a `networkError` or `graphQLErrors`.
3737+ *
3838+ * @remarks
3939+ * During a GraphQL request, either the request can fail entirely, causing a network error,
4040+ * or the GraphQL execution or fields can fail, which will cause an {@link ExecutionResult}
4141+ * to contain an array of GraphQL errors.
4242+ *
4343+ * The `CombinedError` abstracts and normalizes both failure cases. When {@link OperationResult.error}
4444+ * is set to this error, the `CombinedError` abstracts all errors, making it easier to handle only
4545+ * a subset of error cases.
4646+ *
4747+ * @see {@link https://formidable.com/open-source/urql/docs/basics/errors/} for more information on handling
4848+ * GraphQL errors and the `CombinedError`.
4949+ */
3750export class CombinedError extends Error {
3851 public name: string;
3952 public message: string;
5353+5454+ /** A list of GraphQL errors rehydrated from a {@link ExecutionResult}.
5555+ *
5656+ * @remarks
5757+ * If an {@link ExecutionResult} received from the API contains a list of errors,
5858+ * the `CombinedError` will rehydrate them, normalize them to
5959+ * {@link GraphQLError | GraphQLErrors} and list them here.
6060+ * An empty list indicates that no GraphQL error has been sent by the API.
6161+ */
4062 public graphQLErrors: GraphQLError[];
6363+6464+ /** Set to an error, if a GraphQL request has failed outright.
6565+ *
6666+ * @remarks
6767+ * A GraphQL over HTTP request may fail and not reach the API. Any error that
6868+ * prevents a GraphQl request outright, will be considered a “network error” and
6969+ * set here.
7070+ */
4171 public networkError?: Error;
7272+7373+ /** Set to the {@link Response} object a fetch exchange received.
7474+ *
7575+ * @remarks
7676+ * If a built-in fetch {@link Exchange} is used in `urql`, this may
7777+ * be set to the {@link Response} object of the Fetch API response.
7878+ * However, since `urql` doesn’t assume that all users will use HTTP
7979+ * as the only or exclusive transport for GraphQL this property is
8080+ * neither typed nor guaranteed and may be re-used for other purposes
8181+ * by non-fetch exchanges.
8282+ *
8383+ * Hint: It can be useful to use `response.status` here, however, if
8484+ * you plan on relying on this being a {@link Response} in your app,
8585+ * which it is by default, then make sure you add some extra checks
8686+ * before blindly assuming so!
8787+ */
4288 public response?: any;
43894490 constructor(input: {
+30-4
packages/core/src/utils/hash.ts
···11-export type HashValue = number & { readonly _opaque: unique symbol };
11+/** A hash value as computed by {@link phash}.
22+ *
33+ * @remarks
44+ * Typically `HashValue`s are used as hashes and keys of GraphQL documents,
55+ * variables, and combined, for GraphQL requests.
66+ */
77+export type HashValue = number & {
88+ /** Marker to indicate that a `HashValue` may not be created by a user.
99+ *
1010+ * @remarks
1111+ * `HashValue`s are created by {@link phash} and are marked as such to not mix them
1212+ * up with other numbers and prevent them from being created or used outside of this
1313+ * hashing function.
1414+ *
1515+ * @internal
1616+ */
1717+ readonly _opaque: unique symbol;
1818+};
21933-// When we have separate strings it's useful to run a progressive
44-// version of djb2 where we pretend that we're still looping over
55-// the same string
2020+/** Computes a djb2 hash of the given string.
2121+ *
2222+ * @param x - the string to be hashed
2323+ * @param seed - optionally a prior hash for progressive hashing
2424+ * @returns a hash value, i.e. a number
2525+ *
2626+ * @remark
2727+ * This is the hashing function used throughout `urql`, primarily to compute
2828+ * {@link Operation.key}.
2929+ *
3030+ * @see {@link http://www.cse.yorku.ca/~oz/hash.html#djb2} for a further description of djb2.
3131+ */
632export const phash = (x: string, seed?: HashValue): HashValue => {
733 let h = typeof seed === 'number' ? seed | 0 : 5381;
834 for (let i = 0, l = x.length | 0; i < l; i++)
+12
packages/core/src/utils/maskTypename.ts
···11+/** Used to recursively mark `__typename` fields in data as non-enumerable.
22+ *
33+ * @remarks
44+ * This utility can be used to recursively copy GraphQl response data and hide
55+ * all `__typename` fields present on it.
66+ *
77+ * Hint: It’s not recommended to do this, unless it's absolutely necessary as
88+ * cloning and modifying all data of a response can be unnecessarily slow, when
99+ * a manual and more specific copy/mask is more efficient.
1010+ *
1111+ * @see {@link ClientOptions.maskTypename} for a description of how the `Client` uses this utility.
1212+ */
113export const maskTypename = (data: any, isRoot?: boolean): any => {
214 if (!data || typeof data !== 'object') {
315 return data;
+26-1
packages/core/src/utils/operation.ts
···66 OperationType,
77} from '../types';
8899+/** Creates a {@link Operation} from the given parameters.
1010+ *
1111+ * @param kind - The {@link OperationType} of GraphQL operation, i.e. `query`, `mutation`, or `subscription`.
1212+ * @param request - The {@link GraphQLRequest} used as a template for the `Operation`.
1313+ * @param context - The {@link OperationContext} `context` data for the `Operation`.
1414+ * @returns An {@link Operation}.
1515+ *
1616+ * @remarks
1717+ * This method is both used to create new {@link Operation | Operations} as well as copy and modify existing
1818+ * operations. While it’s not required to use this function to copy an `Operation`, it is recommended, in case
1919+ * additional dynamic logic is added to them in the future.
2020+ *
2121+ * @example
2222+ * An example of copying an existing `Operation` to modify its `context`:
2323+ *
2424+ * ```ts
2525+ * makeOperation(
2626+ * operation.kind,
2727+ * operation,
2828+ * { ...operation.context, requestPolicy: 'cache-first' },
2929+ * );
3030+ * ```
3131+ */
932function makeOperation<
1033 Data = any,
1134 Variables extends AnyVariables = AnyVariables
···38613962export { makeOperation };
40634141-/** Spreads the provided metadata to the source operation's meta property in context. */
6464+/** Adds additional metadata to an `Operation`'s `context.meta` property while copying it.
6565+ * @see {@link OperationDebugMeta} for more information on the {@link OperationContext.meta} property.
6666+ */
4267export const addMetadata = (
4368 operation: Operation,
4469 meta: OperationContext['meta']
+62-4
packages/core/src/utils/request.ts
···1515 loc: Location | undefined;
1616}
17171818+/** A `DocumentNode` annotated with its hashed key.
1919+ * @internal
2020+ */
1821export interface KeyedDocumentNode extends DocumentNode {
1922 __key: HashValue;
2023}
···2629const replaceOutsideStrings = (str: string, idx: number) =>
2730 idx % 2 === 0 ? str.replace(REPLACE_CHAR_RE, '\n') : str;
28313232+/** Sanitizes a GraphQL document string by replacing comments and redundant newlines in it. */
2933const sanitizeDocument = (node: string): string =>
3034 node.split(GRAPHQL_STRING_RE).map(replaceOutsideStrings).join('').trim();
31353236const prints = new Map<DocumentNode | DefinitionNode, string>();
3337const docs = new Map<HashValue, KeyedDocumentNode>();
34383939+/** A cached printing function for GraphQL documents.
4040+ *
4141+ * @param node - A string of a document or a {@link DocumentNode}
4242+ * @returns A normalized printed string of the passed GraphQL document.
4343+ *
4444+ * @remarks
4545+ * This function accepts a GraphQL query string or {@link DocumentNode},
4646+ * then prints and sanitizes it. The sanitizer takes care of removing
4747+ * comments, which otherwise alter the key of the document although the
4848+ * document is otherwise equivalent to another.
4949+ *
5050+ * When a {@link DocumentNode} is passed to this function, it caches its
5151+ * output by modifying the `loc.source.body` property on the GraphQL node.
5252+ */
3553export const stringifyDocument = (
3654 node: string | DefinitionNode | DocumentNode
3755): string => {
···6078 return printed;
6179};
62808181+/** Computes the hash for a document's string using {@link stringifyDocument}'s output.
8282+ *
8383+ * @param node - A string of a document or a {@link DocumentNode}
8484+ * @returns A {@link HashValue}
8585+ *
8686+ * @privateRemarks
8787+ * This function adds the operation name of the document to the hash, since sometimes
8888+ * a merged document with multiple operations may be used. Although `urql` requires a
8989+ * `DocumentNode` to only contain a single operation, when the cached `loc.source.body`
9090+ * of a `DocumentNode` is used, this string may still contain multiple operations and
9191+ * the resulting hash should account for only one at a time.
9292+ */
6393const hashDocument = (
6494 node: string | DefinitionNode | DocumentNode
6595): HashValue => {
···72102 return key;
73103};
74104105105+/** Returns a canonical version of the passed `DocumentNode` with an added hash key.
106106+ *
107107+ * @param node - A string of a document or a {@link DocumentNode}
108108+ * @returns A {@link KeyedDocumentNode}
109109+ *
110110+ * @remarks
111111+ * `urql` will always avoid unnecessary work, no matter whether a user passes `DocumentNode`s
112112+ * or strings of GraphQL documents to its APIs.
113113+ *
114114+ * This function will return a canonical version of a {@link KeyedDocumentNode} no matter
115115+ * which kind of input is passed, avoiding parsing or hashing of passed data as needed.
116116+ */
75117export const keyDocument = (node: string | DocumentNode): KeyedDocumentNode => {
76118 let key: HashValue;
77119 let query: DocumentNode;
···91133 return query as KeyedDocumentNode;
92134};
93135136136+/** Creates a `GraphQLRequest` from the passed parameters.
137137+ *
138138+ * @param q - A string of a document or a {@link DocumentNode}
139139+ * @param variables - A variables object for the defined GraphQL operation.
140140+ * @returns A {@link GraphQLRequest}
141141+ *
142142+ * @remarks
143143+ * `createRequest` creates a {@link GraphQLRequest} from the passed parameters,
144144+ * while replacing the document as needed with a canonical version of itself,
145145+ * to avoid parsing, printing, or hashing the same input multiple times.
146146+ *
147147+ * If no variables are passed, canonically it'll default to an empty object,
148148+ * which is removed from the resulting hash key.
149149+ */
94150export const createRequest = <
95151 Data = any,
96152 Variables extends AnyVariables = AnyVariables
···106162 return { key, query, variables };
107163};
108164109109-/**
110110- * Finds the Name value from the OperationDefinition of a Document
165165+/** Returns the name of the `DocumentNode`'s operation, if any.
166166+ * @param query - A {@link DocumentNode}
167167+ * @returns the operation's name contained within the document, or `undefined`
111168 */
112169export const getOperationName = (query: DocumentNode): string | undefined => {
113170 for (const node of query.definitions) {
···117174 }
118175};
119176120120-/**
121121- * Finds the operation-type
177177+/** Returns the type of the `DocumentNode`'s operation, if any.
178178+ * @param query - A {@link DocumentNode}
179179+ * @returns the operation's type contained within the document, or `undefined`
122180 */
123181export const getOperationType = (query: DocumentNode): string | undefined => {
124182 for (const node of query.definitions) {
+48
packages/core/src/utils/result.ts
···66} from '../types';
77import { CombinedError } from './error';
8899+/** Converts the `ExecutionResult` received for a given `Operation` to an `OperationResult`.
1010+ *
1111+ * @param operation - The {@link Operation} for which the API’s result is for.
1212+ * @param result - The GraphQL API’s {@link ExecutionResult}.
1313+ * @param response - Optionally, a raw object representing the API’s result (Typically a {@link Response}).
1414+ * @returns An {@link OperationResult}.
1515+ *
1616+ * @remarks
1717+ * This utility can be used to create {@link OperationResult | OperationResults} in the shape
1818+ * that `urql` expects and defines, and should be used rather than creating the results manually.
1919+ *
2020+ * @throws
2121+ * If no data, or errors are contained within the result, or the result is instead an incremental
2222+ * response containing a `path` property, a “No Content” error is thrown.
2323+ *
2424+ * @see {@link ExecutionResult} for the type definition of GraphQL API results.
2525+ */
926export const makeResult = (
1027 operation: Operation,
1128 result: ExecutionResult,
···3451 };
3552};
36535454+/** Merges an incrementally delivered `ExecutionResult` into a previous `OperationResult`.
5555+ *
5656+ * @param prevResult - The {@link OperationResult} that preceded this result.
5757+ * @param path - The GraphQL API’s {@link ExecutionResult} that should be patching the `prevResult`.
5858+ * @param response - Optionally, a raw object representing the API’s result (Typically a {@link Response}).
5959+ * @returns A new {@link OperationResult} patched with the incremental result.
6060+ *
6161+ * @remarks
6262+ * This utility should be used to merge subsequent {@link ExecutionResult | ExecutionResults} of
6363+ * incremental responses into a prior {@link OperationResult}.
6464+ *
6565+ * When directives like `@defer`, `@stream`, and `@live` are used, GraphQL may deliver new
6666+ * results that modify previous results. In these cases, it'll set a `path` property to modify
6767+ * the result it sent last. This utility is built to handle these cases and merge these payloads
6868+ * into existing {@link OperationResult | OperationResults}.
6969+ *
7070+ * @see {@link ExecutionResult} for the type definition of GraphQL API results.
7171+ */
3772export const mergeResultPatch = (
3873 prevResult: OperationResult,
3974 nextResult: ExecutionResult,
···102137 };
103138};
104139140140+/** Creates an `OperationResult` containing a network error for requests that encountered unexpected errors.
141141+ *
142142+ * @param operation - The {@link Operation} for which the API’s result is for.
143143+ * @param error - The network-like error that prevented an API result from being delivered.
144144+ * @param response - Optionally, a raw object representing the API’s result (Typically a {@link Response}).
145145+ * @returns An {@link OperationResult} containing only a {@link CombinedError}.
146146+ *
147147+ * @remarks
148148+ * This utility can be used to create {@link OperationResult | OperationResults} in the shape
149149+ * that `urql` expects and defines, and should be used rather than creating the results manually.
150150+ * This function should be used for when the {@link CombinedError.networkError} property is
151151+ * populated and no GraphQL execution actually occurred.
152152+ */
105153export const makeErrorResult = (
106154 operation: Operation,
107155 error: Error,
+5
packages/core/src/utils/streamUtils.ts
···11import { Source, subscribe, pipe } from 'wonka';
22import { OperationResult, PromisifiedSource } from '../types';
3344+/** Patches a `toPromise` method onto the `Source` passed to it.
55+ * @param source$ - the Wonka {@link Source} to patch.
66+ * @returns The passed `source$` with a patched `toPromise` method as a {@link PromisifiedSource}.
77+ * @internal
88+ */
49export function withPromise<T extends OperationResult>(
510 source$: Source<T>
611): PromisifiedSource<T> {
+14
packages/core/src/utils/stringifyVariables.ts
···4242 return out;
4343};
44444545+/** A stable stringifier for GraphQL variables objects.
4646+ *
4747+ * @param x - any JSON-like data.
4848+ * @return A JSON string.
4949+ *
5050+ * @remarks
5151+ * This utility creates a stable JSON string from any passed data,
5252+ * and protects itself from throwing.
5353+ *
5454+ * The JSON string is stable insofar as objects’ keys are sorted,
5555+ * and instances of non-plain objects are replaced with random keys
5656+ * replacing their values, which remain stable for the objects’
5757+ * instance.
5858+ */
4559export const stringifyVariables = (x: any): string => {
4660 seen.clear();
4761 return stringify(x);
+24
packages/core/src/utils/typenames.ts
···2929 return types;
3030};
31313232+/** Finds and returns a list of `__typename` fields found in response data.
3333+ *
3434+ * @privateRemarks
3535+ * This is used by `@urql/core`’s document `cacheExchange` to find typenames
3636+ * in a given GraphQL response’s data.
3737+ */
3238export const collectTypesFromResponse = (response: object): string[] => [
3339 ...collectTypes(response as EntityLike, new Set()),
3440];
···63696470const formattedDocs = new Map<number, KeyedDocumentNode>();
65717272+/** Adds `__typename` fields to a GraphQL `DocumentNode`.
7373+ *
7474+ * @param node - a {@link DocumentNode}.
7575+ * @returns a copy of the passed {@link DocumentNode} with added `__typename` introspection fields.
7676+ *
7777+ * @remarks
7878+ * Cache {@link Exchange | Exchanges} will require typename introspection to
7979+ * recognize types in a GraphQL response. To retrieve these typenames,
8080+ * this function is used to add the `__typename` fields to non-root
8181+ * selection sets of a GraphQL document.
8282+ *
8383+ * This utility also preserves the internally computed key of the
8484+ * document as created by {@link createRequest} to avoid any
8585+ * formatting from being duplicated.
8686+ *
8787+ * @see {@link https://spec.graphql.org/October2021/#sec-Type-Name-Introspection} for more information
8888+ * on typename introspection via the `__typename` field.
8989+ */
6690export const formatDocument = <T extends DocumentNode>(node: T): T => {
6791 const query = keyDocument(node);
6892