1import { share } from 'wonka';
2import type { ExchangeIO, Exchange, ExchangeInput } from '../types';
3
4/** Composes an array of Exchanges into a single one.
5 *
6 * @param exchanges - An array of {@link Exchange | Exchanges}.
7 * @returns - A composed {@link Exchange}.
8 *
9 * @remarks
10 * `composeExchanges` returns an {@link Exchange} that when instantiated
11 * composes the array of passed `Exchange`s into one, calling them from
12 * right to left, with the prior `Exchange`’s {@link ExchangeIO} function
13 * as the {@link ExchangeInput.forward} input.
14 *
15 * This simply merges all exchanges into one and is used by the {@link Client}
16 * to merge the `exchanges` option it receives.
17 *
18 * @throws
19 * In development, if {@link ExchangeInput.forward} is called repeatedly
20 * by an {@link Exchange} an error is thrown, since `forward()` must only
21 * be called once per `Exchange`.
22 */
23export const composeExchanges =
24 (exchanges: Exchange[]): Exchange =>
25 ({ client, forward, dispatchDebug }: ExchangeInput): ExchangeIO =>
26 exchanges.reduceRight((forward, exchange) => {
27 let forwarded = false;
28 return exchange({
29 client,
30 forward(operations$) {
31 if (process.env.NODE_ENV !== 'production') {
32 if (forwarded)
33 throw new Error(
34 'forward() must only be called once in each Exchange.'
35 );
36 forwarded = true;
37 }
38 return share(forward(share(operations$)));
39 },
40 dispatchDebug(event) {
41 dispatchDebug({
42 timestamp: Date.now(),
43 source: exchange.name,
44 ...event,
45 });
46 },
47 });
48 }, forward);