Skip to content

Commit

Permalink
feat: add bindings for @urql/exchange-persisted-fetch and @urql/excha…
Browse files Browse the repository at this point in the history
…nge-refocus (#251)
  • Loading branch information
parkerziegler authored Jan 19, 2021
1 parent 1463301 commit 6d9365d
Show file tree
Hide file tree
Showing 6 changed files with 256 additions and 160 deletions.
66 changes: 47 additions & 19 deletions __tests__/Client_test.res
Original file line number Diff line number Diff line change
Expand Up @@ -210,34 +210,30 @@ describe("Client", () => {
}))

describe("Ecosystem exchanges", () => {
describe("retryExchange", () => {
it("should apply the default retryExchange options from urql if none are applied", () => {
let retryExchangeOptions = Client.Exchanges.makeRetryExchangeOptions()
describe("persistedFetchExchange", () => {
it("should return None for all persistedFetchExchange options if unspecified", () => {
let persistedFetchExchangeOptions = Client.Exchanges.makePersistedFetchExchangeOptions()

open Expect
expect(retryExchangeOptions) |> toEqual({
Client.Exchanges.initialDelayMs: None,
maxDelayMs: None,
maxNumberAttempts: None,
randomDelay: None,
retryIf: None,
expect(persistedFetchExchangeOptions) |> toEqual({
Client.Exchanges.preferGetForPersistedQueries: None,
generateHash: None,
})
})

it("should apply any specified options to the retryExchange", () => {
let retryExchangeOptions = Client.Exchanges.makeRetryExchangeOptions(
~initialDelayMs=200,
~randomDelay=false,
it("should apply any specified options to the persistedFetchExchange", () => {
let hashFn = (query, _) => Js.Promise.resolve(Js.String.normalize(query))

let persistedFetchExchangeOptions = Client.Exchanges.makePersistedFetchExchangeOptions(
~preferGetForPersistedQueries=true,
~generateHash=hashFn,
(),
)

open Expect
expect(retryExchangeOptions) |> toEqual({
Client.Exchanges.initialDelayMs: Some(200),
maxDelayMs: None,
maxNumberAttempts: None,
randomDelay: Some(false),
retryIf: None,
expect(persistedFetchExchangeOptions) |> toEqual({
Client.Exchanges.preferGetForPersistedQueries: Some(true),
generateHash: Some(hashFn),
})
})
})
Expand Down Expand Up @@ -270,5 +266,37 @@ describe("Client", () => {
})
})
})

describe("retryExchange", () => {
it("should apply the default retryExchange options from urql if none are applied", () => {
let retryExchangeOptions = Client.Exchanges.makeRetryExchangeOptions()

open Expect
expect(retryExchangeOptions) |> toEqual({
Client.Exchanges.initialDelayMs: None,
maxDelayMs: None,
maxNumberAttempts: None,
randomDelay: None,
retryIf: None,
})
})

it("should apply any specified options to the retryExchange", () => {
let retryExchangeOptions = Client.Exchanges.makeRetryExchangeOptions(
~initialDelayMs=200,
~randomDelay=false,
(),
)

open Expect
expect(retryExchangeOptions) |> toEqual({
Client.Exchanges.initialDelayMs: Some(200),
maxDelayMs: None,
maxNumberAttempts: None,
randomDelay: Some(false),
retryIf: None,
})
})
})
})
})
119 changes: 91 additions & 28 deletions docs/exchanges.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,78 +165,77 @@ let client = Client.make(
~exchanges=[
Client.Exchanges.dedupExchange,
Client.Exchanges.cacheExchange,
Client.Exchanges.multipartFetchExchange
Client.Exchanges.multipartFetchExchange,
],
()
)
```

Read more on the `multipartFetchExchange` [here](https://github.com/FormidableLabs/urql/tree/main/exchanges/multipart-fetch).

### `retryExchange`
### `persistedFetchExchange`

The `retryExchange` is useful for retrying particular operations. By default, adding this exchange with the base options will retry any operations that failed due to network errors. However, we can customize the exchange to catch more specific error cases as well.
The `persistedFetchExchange` adds support for [persisted queries](https://www.onegraph.com/docs/persisted_queries.html), building off of the standard `fetchExchange`.

To use the `retryExchange`, add the package to your dependencies:
To use the `persistedFetchExchange`, add the package to your dependencies:

```sh
yarn add @urql/exchange-retry
yarn add @urql/exchange-persisted-fetch
```

Then, add the exchange to your array of `exchanges`, specifying the options you want to configure:
Then, add the exchange to your array of `exchanges`, sepcifying the options you want to configure:

```rescript
open ReasonUrql
let retryExchangeOptions =
Client.Exchanges.makeRetryExchangeOptions(~initialDelayMs=2000, ~randomDelay=false, ())
let persistedFetchExchangeOptions = Client.Exchanges.makePersistedFetchExchangeOptions(
~preferGetForPersistedQueries=true,
(),
)
let client = Client.make(
~url="http://localhost:3000",
~exchanges=[
Client.Exchanges.dedupExchange,
Client.Exchanges.cacheExchange,
Client.Exchanges.retryExchange(retryExchangeOptions),
Client.Exchanges.fetchExchange
Client.Exchanges.persistedFetchExchange(persistedFetchExchangeOptions),
// Keep the fetchExchange to handle mutations.
// The persistedFetchExchange only handles queries.
Client.Exchanges.fetchExchange,
],
()
)
```

By default, `urql` will apply the following configuration for you:
Read more about the `persistedFetchExchange` [here](https://github.com/FormidableLabs/urql/tree/main/exchanges/persisted-fetch).

```typescript
{
initialDelayMs: 1000,
maxDelayMs: 15000,
randomDelay: true,
maxNumberAttempts: 2,
retryIf: err => err && err.networkError,
}
### `refocusExchange`

The `refocusExchange` allows `reason-urql` to redispatch active operations when the window regains focus.

To use the `refocusExchange`, add the package to your dependencies:

```sh
yarn add @urql/exchange-refocus
```

If you want to use the defaults from `urql`, call `makeRetryExchangeOptions` with just a `unit` parameter.
Then, add the exchange to your array of `exchanges`. The `refocusExchange` should be added _after_ the `dedupeExchange`, to prevent doing additional work on requests that are later deduplicated, and _before_ the `fetchExchange`:

```rescript
open ReasonUrql
let retryExchangeOptions =
Client.Exchanges.makeRetryExchangeOptions()
let client = Client.make(
~url="http://localhost:3000",
~exchanges=[
Client.Exchanges.dedupExchange,
Client.Exchanges.refocusExchange(),
Client.Exchanges.cacheExchange,
Client.Exchanges.retryExchange(retryExchangeOptions),
Client.Exchanges.fetchExchange
Client.Exchanges.fetchExchange,
],
()
)
```

Read more on the `retryExchange` [here](https://formidable.com/open-source/urql/docs/advanced/retry-operations/).

### `requestPolicyExchange`

The `requestPolicyExchange` allows `reason-urql` to automatically upgrade an operation's `requestPolicy` on a time-to-live basis. When the specified TTL has elapsed, `reason-urql` will either:
Expand Down Expand Up @@ -270,14 +269,78 @@ let client = Client.make(
Client.Exchanges.dedupExchange,
Client.Exchanges.cacheExchange,
Client.Exchanges.requestPolicyExchange(requestPolicyExchangeOptions),
Client.Exchanges.fetchExchange
Client.Exchanges.fetchExchange,
],
()
)
```

Read more about the `requestPolicyExchange` [here](https://github.com/FormidableLabs/urql/tree/main/exchanges/request-policy).

### `retryExchange`

The `retryExchange` is useful for retrying particular operations. By default, adding this exchange with the base options will retry any operations that failed due to network errors. However, we can customize the exchange to catch more specific error cases as well.

To use the `retryExchange`, add the package to your dependencies:

```sh
yarn add @urql/exchange-retry
```

Then, add the exchange to your array of `exchanges`, specifying the options you want to configure:

```rescript
open ReasonUrql
let retryExchangeOptions =
Client.Exchanges.makeRetryExchangeOptions(~initialDelayMs=2000, ~randomDelay=false, ())
let client = Client.make(
~url="http://localhost:3000",
~exchanges=[
Client.Exchanges.dedupExchange,
Client.Exchanges.cacheExchange,
Client.Exchanges.retryExchange(retryExchangeOptions),
Client.Exchanges.fetchExchange,
],
()
)
```

By default, `urql` will apply the following configuration for you:

```typescript
{
initialDelayMs: 1000,
maxDelayMs: 15000,
randomDelay: true,
maxNumberAttempts: 2,
retryIf: err => err && err.networkError,
}
```

If you want to use the defaults from `urql`, call `makeRetryExchangeOptions` with just a `unit` parameter.

```rescript
open ReasonUrql
let retryExchangeOptions =
Client.Exchanges.makeRetryExchangeOptions()
let client = Client.make(
~url="http://localhost:3000",
~exchanges=[
Client.Exchanges.dedupExchange,
Client.Exchanges.cacheExchange,
Client.Exchanges.retryExchange(retryExchangeOptions),
Client.Exchanges.fetchExchange,
],
()
)
```

Read more on the `retryExchange` [here](https://formidable.com/open-source/urql/docs/advanced/retry-operations/).

## Custom Exchanges

`reason-urql` also allows you to write your own exchanges to modify outgoing GraphQL requests and incoming responses. To read up on the basics of exchanges, check out the excellent [`urql` documentation](https://formidable.com/open-source/urql/docs/concepts/exchanges/).
Expand Down
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@
"@babel/plugin-transform-modules-commonjs": "^7.12.1",
"@glennsl/bs-jest": "^0.6.0",
"@reasonml-community/graphql-ppx": "^1.0.1",
"@urql/exchange-multipart-fetch": "^0.1.11",
"@urql/exchange-retry": "^0.2.0",
"all-contributors-cli": "^6.19.0",
"babel-jest": "^26.6.3",
"bs-platform": "^8.3.2",
Expand Down
Loading

0 comments on commit 6d9365d

Please sign in to comment.