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

major(core|graphcache): remove deprected options/methods (#3520)

+5
.changeset/giant-cheetahs-join.md
···
+
---
+
'@urql/core': major
+
---
+
+
Remove deprecated `dedupExchange`
+5
.changeset/strange-steaks-grow.md
···
+
---
+
'@urql/exchange-graphcache': major
+
---
+
+
Remove deprecated `resolveFieldByKey`, use `cache.resolve` instead
+5
.changeset/stupid-mice-judge.md
···
+
---
+
'@urql/core': major
+
---
+
+
Remove deprecated `maskTypename`
+1 -2
docs/advanced/authentication.md
···
The order is very important here:
```js
-
import { createClient, dedupExchange, cacheExchange, fetchExchange, errorExchange, mapExchange } from 'urql';
+
import { createClient, cacheExchange, fetchExchange, mapExchange } from 'urql';
import { authExchange } from '@urql/exchange-auth';
const client = createClient({
url: 'http://localhost:3000/graphql',
exchanges: [
-
dedupExchange,
cacheExchange,
mapExchange({
onError(error, _operation) {
+8 -10
docs/advanced/server-side-rendering.md
···
you'll need to instead provide them in the `exchanges` property of the returned client object.
```js
-
import { dedupExchange, cacheExchange, fetchExchange } from '@urql/core';
+
import { cacheExchange, fetchExchange } from '@urql/core';
import { withUrqlClient } from 'next-urql';
export default withUrqlClient(ssrExchange => ({
url: 'http://localhost:3000/graphql',
-
exchanges: [dedupExchange, cacheExchange, ssrExchange, fetchExchange],
+
exchanges: [cacheExchange, ssrExchange, fetchExchange],
}))(Index);
```
···
argument to `withUrqlClient`:
```js
-
import { dedupExchange, cacheExchange, fetchExchange } from '@urql/core';
+
import { cacheExchange, fetchExchange } from '@urql/core';
import { withUrqlClient } from 'next-urql';
export default withUrqlClient(
ssrExchange => ({
url: 'http://localhost:3000/graphql',
-
exchanges: [dedupExchange, cacheExchange, ssrExchange, fetchExchange],
+
exchanges: [cacheExchange, ssrExchange, fetchExchange],
}),
{ ssr: true } // Enables server-side rendering using `getInitialProps`
)(Index);
···
```js
import { withUrqlClient, initUrqlClient } from 'next-urql';
-
import { ssrExchange, dedupExchange, cacheExchange, fetchExchange, useQuery } from 'urql';
+
import { ssrExchange, cacheExchange, fetchExchange, useQuery } from 'urql';
const TODOS_QUERY = `
query { todos { id text } }
···
const client = initUrqlClient(
{
url: 'your-url',
-
exchanges: [dedupExchange, cacheExchange, ssrCache, fetchExchange],
+
exchanges: [cacheExchange, ssrCache, fetchExchange],
},
false
);
···
```js
import { withUrqlClient, initUrqlClient } from 'next-urql';
-
import { ssrExchange, dedupExchange, cacheExchange, fetchExchange, useQuery } from 'urql';
+
import { ssrExchange, cacheExchange, fetchExchange, useQuery } from 'urql';
import { executeExchange } from '@urql/exchange-execute';
import { schema } from '@/server/graphql'; // our GraphQL server's executable schema
···
{
url: '', // not needed without `fetchExchange`
exchanges: [
-
dedupExchange,
cacheExchange,
ssrCache,
executeExchange({ schema }), // replaces `fetchExchange`
···
import urql, {
createClient,
-
dedupExchange,
cacheExchange,
fetchExchange,
ssrExchange
···
// NOTE: All we care about here is that the SSR Exchange is included
const ssr = ssrExchange({ isClient: false });
app.use(urql, {
-
exchanges: [dedupExchange, cacheExchange, ssr, fetchExchange]
+
exchanges: [cacheExchange, ssr, fetchExchange]
});
const markup = await renderToString(app);
+1 -2
docs/api/auth-exchange.md
···
but after all other synchronous exchanges, like the `cacheExchange`.
```js
-
import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql';
+
import { createClient, cacheExchange, fetchExchange } from 'urql';
import { authExchange } from '@urql/exchange-auth';
const client = createClient({
url: 'http://localhost:3000/graphql',
exchanges: [
-
dedupExchange,
cacheExchange,
authExchange(async utils => {
return {
+1 -21
docs/api/core.md
···
| `suspense` | `?boolean` | Activates the experimental React suspense mode, which can be used during server-side rendering to prefetch data |
| `requestPolicy` | `?RequestPolicy` | Changes the default request policy that will be used. By default, this will be `cache-first`. |
| `preferGetMethod` | `?boolean \| 'force' \| 'within-url-limit'` | This is picked up by the `fetchExchange` and will force all queries (not mutations) to be sent using the HTTP GET method instead of POST if the length of the resulting URL doesn't exceed 2048 characters. When `'force'` is passed a GET request is always sent regardless of how long the resulting URL is. |
-
| `maskTypename` | `?boolean` | Enables the `Client` to automatically apply the `maskTypename` utility to all `data` on [`OperationResult`s](#operationresult). This makes the `__typename` properties non-enumerable. |
### client.executeQuery
···
An exchange is defined to be a function that receives [`ExchangeInput`](#exchangeinput) and returns
an `ExchangeIO` function. The `ExchangeIO` function in turn will receive a stream of operations, and
must return a stream of results. If the exchange is purely transforming data, like the
-
`dedupExchange` for instance, it'll call `forward`, which is the next Exchange's `ExchangeIO`
+
`mapExchange` for instance, it'll call `forward`, which is the next Exchange's `ExchangeIO`
function to get a stream of results.
```js
···
This exchange is disabled in production and is based on the `mapExchange`.
If you'd like to customise it, you can replace it with a custom `mapExchange`.
-
### dedupExchange
-
-
An exchange that keeps track of ongoing `Operation`s that haven't returned had
-
a corresponding `OperationResult` yet. Any duplicate `Operation` that it
-
receives is filtered out if the same `Operation` has already been received
-
and is still waiting for a result.
-
### fetchExchange
The `fetchExchange` of type `Exchange` is responsible for sending operations of type `'query'` and
···
This utility is used by the [`cacheExchange`](#cacheexchange) and by
[Graphcache](../graphcache/README.md) to add `__typename` fields to GraphQL `DocumentNode`s.
-
-
### maskTypename
-
-
This utility accepts a GraphQL `data` object, like `data` on [`OperationResult`s](#operationresult)
-
and marks every `__typename` property as non-enumerable.
-
-
The [`formatDocument`](#formatdocument) is often used by `urql` automatically and adds `__typename`
-
fields to all results. However, this means that data often cannot be passed back into variables or
-
inputs on mutations, which is a common use-case. This utility hides these fields, which can solve
-
this problem.
-
-
It's used by the [`Client`](#client) when the `maskTypename` option is enabled.
### composeExchanges
+1 -2
docs/api/execute-exchange.md
···
since it'll handle operations and return results.
```js
-
import { createClient, dedupExchange, cacheExchange } from 'urql';
+
import { createClient, cacheExchange } from 'urql';
import { executeExchange } from '@urql/exchange-execute';
const client = createClient({
url: 'http://localhost:3000/graphql',
exchanges: [
-
dedupExchange,
cacheExchange,
executeExchange({
/* config */
+1 -3
docs/api/graphcache.md
···
```
This specialized case is likely only going to be useful in combination with
-
[`cache.inspectFields`](#inspectfields). Previously a specialised method existed for this
-
case specifically and was called `cache.resolveFieldByKey`, which is now deprecated, since
-
`cache.resolve` may be called with a field key and no extra arguments.
+
[`cache.inspectFields`](#inspectfields).
### inspectFields
+3 -4
docs/api/refocus-exchange.md
···
npm install --save @urql/exchange-refocus
```
-
Then add it to your `Client`, preferably after the `dedupExchange` but in front of any asynchronous
-
exchanges, like the `fetchExchange`:
+
Then add it to your `Client`, preferably in front of your `cacheExchange`
```js
-
import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql';
+
import { createClient, cacheExchange, fetchExchange } from 'urql';
import { refocusExchange } from '@urql/exchange-refocus';
const client = createClient({
url: 'http://localhost:3000/graphql',
-
exchanges: [dedupExchange, refocusExchange(), cacheExchange, fetchExchange],
+
exchanges: [refocusExchange(), cacheExchange, fetchExchange],
});
```
+2 -3
docs/api/request-policy-exchange.md
···
npm install --save @urql/exchange-request-policy
```
-
Then add it to your `Client`, preferably after the `dedupExchange` but in front of any asynchronous
+
Then add it to your `Client`, preferably in front of the `cacheExchange` and in front of any asynchronous
exchanges, like the `fetchExchange`:
```js
-
import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql';
+
import { createClient, cacheExchange, fetchExchange } from 'urql';
import { requestPolicyExchange } from '@urql/exchange-request-policy';
const client = createClient({
url: 'http://localhost:3000/graphql',
exchanges: [
-
dedupExchange,
requestPolicyExchange({
/* config */
}),
+1 -2
exchanges/auth/README.md
···
You'll then need to add the `authExchange`, that this package exposes to your `urql` Client
```js
-
import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql';
+
import { createClient, cacheExchange, fetchExchange } from 'urql';
import { makeOperation } from '@urql/core';
import { authExchange } from '@urql/exchange-auth';
const client = createClient({
url: 'http://localhost:1234/graphql',
exchanges: [
-
dedupExchange,
cacheExchange,
authExchange(async utils => {
// called on initial launch,
+1 -2
exchanges/context/README.md
···
You'll then need to add the `contextExchange`, that this package exposes, to your `urql` Client, the positioning of this exchange depends on whether you set an async setter or not. If you set an async context-setter it's best placed after all the synchronous exchanges (in front of the fetchExchange).
```js
-
import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql';
+
import { createClient, cacheExchange, fetchExchange } from 'urql';
import { contextExchange } from '@urql/exchange-context';
const client = createClient({
url: 'http://localhost:1234/graphql',
exchanges: [
-
dedupExchange,
cacheExchange,
contextExchange({
getContext: async operation => {
+1 -2
exchanges/execute/README.md
···
by replacing the default fetch exchange with it:
```js
-
import { createClient, dedupExchange, cacheExchange } from 'urql';
+
import { createClient, cacheExchange } from 'urql';
import { executeExchange } from '@urql/exchange-execute';
const client = createClient({
url: 'http://localhost:1234/graphql',
exchanges: [
-
dedupExchange,
cacheExchange,
// Replace the default fetchExchange with the new one.
executeExchange({
+1 -2
exchanges/graphcache/README.md
···
by replacing the default cache exchange with it:
```js
-
import { createClient, dedupExchange, fetchExchange } from 'urql';
+
import { createClient, fetchExchange } from 'urql';
import { cacheExchange } from '@urql/exchange-graphcache';
const client = createClient({
url: 'http://localhost:1234/graphql',
exchanges: [
-
dedupExchange,
// Replace the default cacheExchange with the new one
cacheExchange({
/* optional config */
+5 -6
exchanges/graphcache/benchmarks/urqlClient.js
···
-
import { createClient, dedupExchange } from '@urql/core';
+
import { createClient } from '@urql/core';
import { cacheExchange } from '@urql/exchange-graphcache';
import { executeExchange } from '@urql/exchange-execute';
import { buildSchema } from 'graphql';
···
input NewTodosInput {
todos: [NewTodo]!
}
-
+
input NewWriter {
id: ID!
name: String
···
book: NewBook!
}
-
+
input NewAuthorsInput {
authors: [NewAuthor]!
}
-
+
input NewReview {
id: ID!
score: Int!
···
employees: [Employee]!
authors: [Author]!
}
-
+
type Mutation {
addTodo( text: String!, complete: Boolean! ): Todo!
updateTodo( id: ID!, complete: Boolean! ): Todo!
···
const client = createClient({
url: 'http://localhost:3000/graphql',
exchanges: [
-
dedupExchange,
cache,
// cacheExchange({}),
executeExchange({ schema, rootValue }),
+1 -9
exchanges/graphcache/e2e-tests/query.spec.tsx
···
import * as React from 'react';
import { mount } from '@cypress/react';
-
import {
-
Provider,
-
createClient,
-
useQuery,
-
dedupExchange,
-
debugExchange,
-
} from 'urql';
+
import { Provider, createClient, useQuery, debugExchange } from 'urql';
import { executeExchange } from '@urql/exchange-execute';
import { buildSchema, introspectionFromSchema } from 'graphql';
···
const client = createClient({
url: 'https://trygql.formidable.dev/graphql/basic-pokedex',
exchanges: [
-
dedupExchange,
cacheExchange({}),
debugExchange,
executeExchange({ schema, rootValue }),
···
const client = createClient({
url: 'https://trygql.formidable.dev/graphql/basic-pokedex',
exchanges: [
-
dedupExchange,
cacheExchange({ schema: introspectionFromSchema(schema) }),
debugExchange,
executeExchange({ schema, rootValue }),
-2
exchanges/graphcache/e2e-tests/updates.spec.tsx
···
gql,
useQuery,
useMutation,
-
dedupExchange,
debugExchange,
} from 'urql';
···
client = createClient({
url: 'https://trygql.formidable.dev/graphql/basic-pokedex',
exchanges: [
-
dedupExchange,
cacheExchange({}),
debugExchange,
executeExchange({ schema, rootValue }),
+21 -2
exchanges/graphcache/src/store/store.test.ts
···
/* eslint-disable @typescript-eslint/no-var-requires */
import { minifyIntrospectionQuery } from '@urql/introspection';
-
import { formatDocument, gql, maskTypename } from '@urql/core';
+
import { formatDocument, gql } from '@urql/core';
import { vi, expect, it, beforeEach, describe } from 'vitest';
import {
···
write(store, { query: TodosWithoutTypename }, todosData);
const result = query(store, { query: TodosWithoutTypename });
expect(result.data).toEqual({
-
...maskTypename(todosData),
+
todos: [
+
{
+
id: '0',
+
text: 'Go to the shops',
+
complete: false,
+
author: { id: '0', name: 'Jovi' },
+
},
+
{
+
id: '1',
+
text: 'Pick up the kids',
+
complete: true,
+
author: { id: '1', name: 'Phil' },
+
},
+
{
+
id: '2',
+
text: 'Install urql',
+
complete: false,
+
author: { id: '0', name: 'Jovi' },
+
},
+
],
__typename: 'Query',
});
});
-4
exchanges/graphcache/src/store/store.ts
···
}
}
-
resolveFieldByKey(entity: Entity, field: string, args?: FieldArgs) {
-
return this.resolve(entity, field, args);
-
}
-
invalidate(entity: Entity, field?: string, args?: FieldArgs) {
const entityKey = this.keyOfEntity(entity);
const shouldInvalidateType =
-10
exchanges/graphcache/src/types.ts
···
args?: FieldArgs
): DataField | undefined;
-
/** Returns a cached value on a given entity’s field by its field key.
-
*
-
* @deprecated
-
* Use {@link cache.resolve} instead.
-
*/
-
resolveFieldByKey(
-
entity: Entity | undefined,
-
fieldKey: string
-
): DataField | undefined;
-
/** Returns a list of cached fields for a given GraphQL object (“entity”).
*
* @param entity - a GraphQL object (“entity”) or an entity key.
+2 -4
exchanges/persisted/README.md
···
to your `exchanges`.
```js
-
import { createClient, dedupExchange, fetchExchange, cacheExchange } from 'urql';
+
import { createClient, fetchExchange, cacheExchange } from 'urql';
import { persistedExchange } from '@urql/exchange-persisted';
const client = createClient({
url: 'http://localhost:1234/graphql',
exchanges: [
-
dedupExchange,
cacheExchange,
persistedExchange({
/* optional config */
···
when using this all you need to do in this exchange is the following:
```js
-
import { createClient, dedupExchange, fetchExchange, cacheExchange } from 'urql';
+
import { createClient, fetchExchange, cacheExchange } from 'urql';
import { persistedExchange } from '@urql/exchange-persisted';
const client = createClient({
url: 'http://localhost:1234/graphql',
exchanges: [
-
dedupExchange,
cacheExchange,
persistedExchange({
generateHash: (_, document) => document.documentId,
+2 -2
exchanges/populate/README.md
···
You'll then need to add the `populateExchange`, that this package exposes.
```js
-
import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql';
+
import { createClient, cacheExchange, fetchExchange } from 'urql';
import { populateExchange } from '@urql/exchange-populate';
const client = createClient({
url: 'http://localhost:1234/graphql',
-
exchanges: [dedupExchange, populateExchange({ schema }), cacheExchange, fetchExchange],
+
exchanges: [populateExchange({ schema }), cacheExchange, fetchExchange],
});
```
+3 -3
exchanges/refocus/README.md
···
npm install --save @urql/exchange-refocus
```
-
Then add it to your `Client`, preferably after the `dedupExchange` but in front of any asynchronous
+
Then add it to your `Client`, preferably before the `cacheExchange` and in front of any asynchronous
exchanges, like the `fetchExchange`:
```js
-
import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql';
+
import { createClient, cacheExchange, fetchExchange } from 'urql';
import { refocusExchange } from '@urql/exchange-refocus';
const client = createClient({
url: 'http://localhost:3000/graphql',
-
exchanges: [dedupExchange, refocusExchange(), cacheExchange, fetchExchange],
+
exchanges: [refocusExchange(), cacheExchange, fetchExchange],
});
```
+1 -2
exchanges/request-policy/README.md
···
Then add it to your client.
```js
-
import { createClient, dedupExchange, cacheExchange, fetchExchange } from 'urql';
+
import { createClient, cacheExchange, fetchExchange } from 'urql';
import { requestPolicyExchange } from '@urql/exchange-request-policy';
const client = createClient({
url: 'http://localhost:1234/graphql',
exchanges: [
-
dedupExchange,
requestPolicyExchange({
// The amount of time in ms that has to go by before upgrading, default is 5 minutes.
ttl: 60 * 1000, // 1 minute.
+1 -32
packages/core/src/client.ts
···
import {
createRequest,
withPromise,
-
maskTypename,
noop,
makeOperation,
getOperationType,
···
* This is the basis for how `urql` handles GraphQL operations, and exchanges handle the creation, execution,
* and control flow of exchanges for the `Client`.
*
-
* To easily get started you should consider using the {@link dedupExchange}, {@link cacheExchange} and {@link fetchExchange}
+
* To easily get started you should consider using the {@link cacheExchange} and {@link fetchExchange}
* these are all exported from the core package.
*
* @see {@link https://urql.dev/goto/docs/architecture/#the-client-and-exchanges} for more information
···
* requests for queries.
*/
preferGetMethod?: boolean | 'force' | 'within-url-limit';
-
/** Instructs the `Client` to remove `__typename` properties on all results.
-
*
-
* @deprecated Not recommended over modelling inputs manually (See #3299)
-
*
-
* @remarks
-
* By default, cache exchanges will alter your GraphQL documents to request `__typename` fields
-
* for all selections. However, this means that your GraphQL data will now contain `__typename` fields you
-
* didn't ask for. This is why the {@link Client} supports “masking” this field by marking it
-
* as non-enumerable via this option.
-
*
-
* Only use this option if you absolutely have to. It's popular to model mutation inputs in
-
* GraphQL schemas after the object types they modify, and if you're using this option to make
-
* it possible to directly pass objects from results as inputs to your mutation variables, it's
-
* more performant and idomatic to instead create a new input object.
-
*
-
* Hint: With `@urql/exchange-graphcache` you will never need this option, as it selects fields on
-
* the client-side according to which fields you specified, rather than the fields it modified.
-
*
-
* @see {@link https://spec.graphql.org/October2021/#sec-Type-Name-Introspection} for more information
-
* on typename introspection via the `__typename` field.
-
*/
-
maskTypename?: boolean;
}
/** The `Client` is the central hub for your GraphQL operations and holds `urql`'s state.
···
)
)
);
-
-
// Mask typename properties if the option for it is turned on
-
if (opts.maskTypename) {
-
result$ = pipe(
-
result$,
-
map(res => ({ ...res, data: maskTypename(res.data, true) }))
-
);
-
}
if (operation.kind !== 'query') {
// Interrupt subscriptions and mutations when they have no more results
-10
packages/core/src/exchanges/dedup.ts
···
-
import type { Exchange } from '../types';
-
-
/** Default deduplication exchange.
-
* @deprecated
-
* This exchange's functionality is now built into the {@link Client}.
-
*/
-
export const dedupExchange: Exchange =
-
({ forward }) =>
-
ops$ =>
-
forward(ops$);
-1
packages/core/src/exchanges/index.ts
···
export { cacheExchange } from './cache';
export { subscriptionExchange } from './subscription';
export { debugExchange } from './debug';
-
export { dedupExchange } from './dedup';
export { fetchExchange } from './fetch';
export { composeExchanges } from './compose';
-1
packages/core/src/index.ts
···
makeErrorResult,
mergeResultPatch,
formatDocument,
-
maskTypename,
makeOperation,
} from './utils';
-1
packages/core/src/utils/index.ts
···
export * from './variables';
export * from './collectTypenames';
export * from './formatDocument';
-
export * from './maskTypename';
export * from './streamUtils';
export * from './operation';
-86
packages/core/src/utils/maskTypename.test.ts
···
-
import { it, expect } from 'vitest';
-
import { maskTypename } from './maskTypename';
-
-
it('strips typename from flat objects', () => {
-
expect(maskTypename({ __typename: 'Todo', id: 1 })).toEqual({ id: 1 });
-
});
-
-
it('strips typename from flat objects containing dates', () => {
-
const date = new Date();
-
expect(maskTypename({ __typename: 'Todo', id: 1, date })).toEqual({
-
id: 1,
-
date,
-
});
-
});
-
-
it('strips typename from nested objects', () => {
-
expect(
-
maskTypename({
-
__typename: 'Todo',
-
id: 1,
-
author: {
-
id: 2,
-
__typename: 'Author',
-
},
-
})
-
).toEqual({ id: 1, author: { id: 2 } });
-
});
-
-
it('works with nested arrays', () => {
-
expect(
-
maskTypename({
-
__typename: 'Todo',
-
id: 1,
-
nodes: [[4, 5]],
-
author: {
-
id: 2,
-
__typename: 'Author',
-
},
-
})
-
).toEqual({ id: 1, nodes: [[4, 5]], author: { id: 2 } });
-
});
-
-
it('strips typename from nested objects with arrays', () => {
-
expect(
-
maskTypename({
-
__typename: 'Todo',
-
id: 1,
-
author: {
-
id: 2,
-
__typename: 'Author',
-
books: [
-
{
-
id: 3,
-
__typename: 'Book',
-
review: { id: 8, __typename: 'Review' },
-
},
-
{ id: 4, __typename: 'Book' },
-
{ id: 5, __typename: 'Book' },
-
],
-
},
-
})
-
).toEqual({
-
id: 1,
-
author: {
-
id: 2,
-
books: [{ id: 3, review: { id: 8 } }, { id: 4 }, { id: 5 }],
-
},
-
});
-
});
-
-
it('strips typename in nested object from root', () => {
-
expect(maskTypename({ root: { __typename: 'Todo', id: 1 } }, true)).toEqual({
-
root: {
-
id: 1,
-
},
-
});
-
});
-
-
it('doesn’t strip typename in sub-object when there is no __typename field', () => {
-
expect(maskTypename({ subObject: { __typename: 'Todo', id: 1 } })).toEqual({
-
subObject: {
-
__typename: 'Todo',
-
id: 1,
-
},
-
});
-
});
-40
packages/core/src/utils/maskTypename.ts
···
-
/** Used to recursively mark `__typename` fields in data as non-enumerable.
-
*
-
* @deprecated Not recommended over modelling inputs manually (See #3299)
-
*
-
* @remarks
-
* This utility can be used to recursively copy GraphQl response data and hide
-
* all `__typename` fields present on it.
-
*
-
* Hint: It’s not recommended to do this, unless it's absolutely necessary as
-
* cloning and modifying all data of a response can be unnecessarily slow, when
-
* a manual and more specific copy/mask is more efficient.
-
*
-
* @see {@link ClientOptions.maskTypename} for a description of how the `Client` uses this utility.
-
*/
-
export const maskTypename = (data: any, isRoot?: boolean): any => {
-
if (!data || typeof data !== 'object') {
-
return data;
-
} else if (Array.isArray(data)) {
-
return data.map(d => maskTypename(d));
-
} else if (
-
data &&
-
typeof data === 'object' &&
-
(isRoot || '__typename' in data)
-
) {
-
const acc = {};
-
for (const key in data) {
-
if (key === '__typename') {
-
Object.defineProperty(acc, '__typename', {
-
enumerable: false,
-
value: data.__typename,
-
});
-
} else {
-
acc[key] = maskTypename(data[key]);
-
}
-
}
-
return acc;
-
} else {
-
return data;
-
}
-
};
+2 -2
packages/preact-urql/README.md
···
small example:
```jsx
-
import { createClient, dedupExchange, cacheExchange, fetchExchange, Provider, useQuery } from '@urql/preact';
+
import { createClient, cacheExchange, fetchExchange, Provider, useQuery } from '@urql/preact';
const client = createClient({
url: 'https://myHost/graphql',
-
exchanges: [dedupExchange, cacheExchange, fetchExchange],
+
exchanges: [cacheExchange, fetchExchange],
});
const App = () => (
+2 -3
packages/react-urql/e2e-tests/useQuery.spec.tsx
···
createClient,
gql,
useQuery,
-
dedupExchange,
cacheExchange,
fetchExchange,
Exchange,
···
const client = createClient({
url: 'https://trygql.formidable.dev/graphql/basic-pokedex',
suspense: true,
-
exchanges: [dedupExchange, cacheExchange, delayExchange, fetchExchange],
+
exchanges: [cacheExchange, delayExchange, fetchExchange],
});
// eslint-disable-next-line
···
const client = createClient({
url: 'https://trygql.formidable.dev/graphql/basic-pokedex',
suspense: false,
-
exchanges: [dedupExchange, cacheExchange, delayExchange, fetchExchange],
+
exchanges: [cacheExchange, delayExchange, fetchExchange],
});
// eslint-disable-next-line
+2 -3
packages/react-urql/src/test-utils/ssr.test.tsx
···
gql,
Client,
Exchange,
-
dedupExchange,
cacheExchange,
ssrExchange,
OperationContext,
···
client = new Client({
url,
// We include the SSR exchange after the cache
-
exchanges: [dedupExchange, cacheExchange, ssr, fetchExchange],
+
exchanges: [cacheExchange, ssr, fetchExchange],
suspense: true,
});
});
···
client = new Client({
url,
// We include the SSR exchange after the cache
-
exchanges: [dedupExchange, cacheExchange, ssr, fetchExchange],
+
exchanges: [cacheExchange, ssr, fetchExchange],
suspense: false,
});
});
+2 -2
packages/storage-rn/README.md
···
Then add it to the offline exchange:
```js
-
import { createClient, dedupExchange, fetchExchange } from 'urql';
+
import { createClient, fetchExchange } from 'urql';
import { offlineExchange } from '@urql/exchange-graphcache';
import { makeAsyncStorage } from '@urql/storage-rn';
···
const client = createClient({
url: 'http://localhost:3000/graphql',
-
exchanges: [dedupExchange, cache, fetchExchange],
+
exchanges: [cache, fetchExchange],
});
```