Skip to content

Commit 6d3d939

Browse files
feat(exchanges): add binding for @urql/multipart-fetch-exchange (#242)
1 parent 527ea8e commit 6d3d939

File tree

7 files changed

+121
-302
lines changed

7 files changed

+121
-302
lines changed

__tests__/Client_test.res

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,4 +208,21 @@ describe("Client", () => {
208208
open Expect
209209
expect(client) |> toMatchSnapshot
210210
}))
211+
212+
describe("Ecosystem exchanges", () => {
213+
it("should support passing the multipartFetchExchange", () => {
214+
let client = Client.make(
215+
~url="https://localhost:3000",
216+
~exchanges=[
217+
Client.Exchanges.dedupExchange,
218+
Client.Exchanges.cacheExchange,
219+
Client.Exchanges.multipartFetchExchange,
220+
],
221+
(),
222+
)
223+
224+
open Expect
225+
expect(client) |> toMatchSnapshot
226+
})
227+
})
211228
})

__tests__/__snapshots__/Client_test.bs.js.snap

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,30 @@ Client {
151151
}
152152
`;
153153

154+
exports[`Client Ecosystem exchanges should support passing the multipartFetchExchange 1`] = `
155+
Client {
156+
"activeOperations": Object {},
157+
"createOperationContext": [Function],
158+
"createRequestOperation": [Function],
159+
"dispatchOperation": [Function],
160+
"executeMutation": [Function],
161+
"executeQuery": [Function],
162+
"executeSubscription": [Function],
163+
"fetch": undefined,
164+
"fetchOptions": undefined,
165+
"maskTypename": false,
166+
"operations$": [Function],
167+
"preferGetMethod": false,
168+
"queue": Array [],
169+
"reexecuteOperation": [Function],
170+
"requestPolicy": "cache-first",
171+
"results$": [Function],
172+
"subscribeToDebugTarget": [Function],
173+
"suspense": false,
174+
"url": "https://localhost:3000",
175+
}
176+
`;
177+
154178
exports[`Client ssrExchange should exist and be callable 1`] = `[Function]`;
155179

156180
exports[`Client with custom fetch implementation should accept a custom fetch implementation 1`] = `

docs/exchanges.md

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,23 @@ Exchanges are the mechanism by which `reason-urql` modifies requests before they
44

55
The `Exchanges` `module` is a submodule of the `Client` module and can be referenced at `ReasonUrql.Client.Exchanges`. The following exchanges are provided out of the box with `reason-urql`.
66

7-
#### `cacheExchange`
7+
## Core Exchanges
8+
9+
`urql` ships with a set of core exchanges that are baked right into `@urql/core` and can be referenced safely in `reason-urql` without installing any additional packages. These are detailed below.
10+
11+
### `cacheExchange`
812

913
The `cacheExchange` provides basic caching support for your GraphQL operations. It is of type `Exchanges.t`.
1014

11-
#### `dedupExchange`
15+
### `dedupExchange`
1216

1317
The `dedupExchange` will deduplicate pending operations waiting for a response. For example, if a user attempts to execute the same query by clicking a button in rapid succession, the `dedupExchange` will filter these events to a single request. It is of type `Exchanges.t`.
1418

15-
#### `fetchExchange`
19+
### `fetchExchange`
1620

1721
The `fetchExchange` is responsible for actually sending your request to your GraphQL API and handling the response. It is of type `Exchanges.t`.
1822

19-
#### `defaultExchanges`
23+
### `defaultExchanges`
2024

2125
The above three exchanges make up `urql`'s `defaultExchanges`. When you create a client in `reason-urql` these exchanges are already applied by default. If you specify an `exchanges` array, be sure to include the specific exchanges you need. You almost always want the `defaultExchanges`, so make sure to include them using `Array.concat` or `Array.append`.
2226

@@ -37,11 +41,11 @@ let client = Client.(
3741
);
3842
```
3943

40-
#### `debugExchange`
44+
### `debugExchange`
4145

4246
The `debugExchange` is useful for tracking how operations are passing through the exchanges pipeline. It simply logs all incoming and outgoing operations to the console. Be sure to remove this in production! It is of type `Exchanges.t`.
4347

44-
#### `subscriptionExchange`
48+
### `subscriptionExchange`
4549

4650
The `subscriptionExchange` should be used in the event that you intend to support GraphQL subscriptions in your application through use of `useSubscription` or the client's `executeSubscription` method.
4751

@@ -79,7 +83,7 @@ let client = Client.(
7983
);
8084
```
8185

82-
#### `ssrExchange`
86+
### `ssrExchange`
8387

8488
The `ssrExchange` accepts a single optional argument, `~ssrExchangeParams`, a record with two fields:
8589

@@ -133,11 +137,43 @@ let extractedData = Client.Exchanges.restoreData(~exchange=ssrCache, ~restore=ur
133137

134138
This part of the API is still quite experimental, as server-side rendering in Reason with Next.js is still in its infancy. Use with caution. For more information, read `urql`'s server-side rendering guide [here](https://github.com/FormidableLabs/urql/blob/master/docs/basics.md#server-side-rendering). To see an example of server-side rendering with `reason-urql`, check out our [`reason-urql-ssr` example](https://github.com/parkerziegler/reason-urql-ssr).
135139

136-
#### `composeExchanges`
140+
### `composeExchanges`
137141

138142
`composeExchanges` is a helper function that will compose a single exchange function from an array of exchanges. Operations will be run through the provided exchanges in the order that they were provided to `composeExchanges`.
139143

140-
### Custom Exchanges
144+
## Ecosystem Exchanges
145+
146+
In addition to the core exchanges exposed by `@urql/core`, `urql` also supports more abstracted exchanges that meet particular needs that may or may not be critical to your use case. In contrast to the core exchanges, these ecosystem exchanges should be used when you have a specific use case that warrants them. Many of these exchanges require additional packages to be installed. `reason-urql` is in the process of adding bindings for these exchanges; if the ecosystem exchange you're interested in isn't outlined below, the bindings may not have yet been implemented. Community contributions are very welcome in this space!
147+
148+
### `multipartFetchExchange`
149+
150+
The `multipartFetchExchange` builds on the `fetchExchange` but adds additional functionality for multipart file uploads. It should replace the use of the `fetchExchange` if you need to support traditional fetches and multipart file uploads.
151+
152+
To use the `multipartFetchExchange`, add the package to your dependencies:
153+
154+
```sh
155+
yarn add @urql/exchange-multipart-fetch
156+
```
157+
158+
Then, substitute the `fetchExchange` with the `multipartFetchExchange`:
159+
160+
```res
161+
open ReasonUrql
162+
163+
let client = Client.make(
164+
~url="http://localhost:3000",
165+
~exchanges=[|
166+
Client.Exchanges.dedupExchange,
167+
Client.Exchanges.cacheExchange,
168+
Client.Exchanges.multipartFetchExchange
169+
|],
170+
()
171+
)
172+
```
173+
174+
Read more on the `multipartFetchExchange` [here](https://github.com/FormidableLabs/urql/tree/main/exchanges/multipart-fetch).
175+
176+
## Custom Exchanges
141177

142178
`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/).
143179

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"@babel/plugin-transform-modules-commonjs": "^7.12.1",
3535
"@glennsl/bs-jest": "^0.6.0",
3636
"@reasonml-community/graphql-ppx": "^1.0.1",
37+
"@urql/exchange-multipart-fetch": "^0.1.11",
3738
"all-contributors-cli": "^6.19.0",
3839
"babel-jest": "^26.6.3",
3940
"bs-platform": "^8.3.2",

src/Client.res

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ module Exchanges = {
7070
@module("urql")
7171
external defaultExchanges: array<t> = "defaultExchanges"
7272

73+
/* Ecosystem exchanges. */
74+
@module("@urql/exchange-multipart-fetch")
75+
external multipartFetchExchange: t = "multipartFetchExchange"
76+
7377
/* Specific types for the subscriptionExchange. */
7478
type observerLike<'value> = {
7579
next: 'value => unit,

src/Client.resi

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ module Exchanges: {
5252
@module("urql")
5353
external defaultExchanges: array<t> = "defaultExchanges"
5454

55+
/* Ecosystem exchanges. */
56+
@module("@urql/exchange-multipart-fetch")
57+
external multipartFetchExchange: t = "multipartFetchExchange"
58+
5559
/* Specific types for the subscriptionExchange. */
5660
type observerLike<'value> = {
5761
next: 'value => unit,

0 commit comments

Comments
 (0)