import { share } from 'wonka'; import type { ExchangeIO, Exchange, ExchangeInput } from '../types'; /** Composes an array of Exchanges into a single one. * * @param exchanges - An array of {@link Exchange | Exchanges}. * @returns - A composed {@link Exchange}. * * @remarks * `composeExchanges` returns an {@link Exchange} that when instantiated * composes the array of passed `Exchange`s into one, calling them from * right to left, with the prior `Exchange`’s {@link ExchangeIO} function * as the {@link ExchangeInput.forward} input. * * This simply merges all exchanges into one and is used by the {@link Client} * to merge the `exchanges` option it receives. * * @throws * In development, if {@link ExchangeInput.forward} is called repeatedly * by an {@link Exchange} an error is thrown, since `forward()` must only * be called once per `Exchange`. */ export const composeExchanges = (exchanges: Exchange[]): Exchange => ({ client, forward, dispatchDebug }: ExchangeInput): ExchangeIO => exchanges.reduceRight((forward, exchange) => { let forwarded = false; return exchange({ client, forward(operations$) { if (process.env.NODE_ENV !== 'production') { if (forwarded) throw new Error( 'forward() must only be called once in each Exchange.' ); forwarded = true; } return share(forward(share(operations$))); }, dispatchDebug(event) { dispatchDebug({ timestamp: Date.now(), source: exchange.name, ...event, }); }, }); }, forward);