1import { Source, Sink, Operator } from './types';
2
3interface UnaryFn<T, R> {
4 (source: T): R;
5}
6
7/** Chain calls operators on a given source and returns the last result.
8 * @param args - A source, then a variable number of transform functions
9 *
10 * @remarks
11 * The `pipe` utility can be called with a {@link Source} then one or more unary transform functions.
12 * Each transform function will be called in turn with the last function's return value, starting
13 * with the source passed as the first argument to `pipe`.
14 *
15 * It's used to transform a source with a list of {@link Operator | Operators}. The last argument may
16 * also be a {@link Sink} that returns something else than a Source.
17 *
18 * @example
19 *
20 * ```ts
21 * pipe(
22 * fromArray([1, 2, 3]),
23 * map(x => x * 2),
24 * subscribe(console.log)
25 * );
26 * ```
27 *
28 * @see {@link https://github.com/tc39/proposal-pipeline-operator} for the JS Pipeline Operator spec, for which this is a replacement utility for.
29 */
30interface pipe {
31 /* pipe definitions for source + operators composition */
32
33 <T, A>(source: Source<T>, op1: UnaryFn<Source<T>, Source<A>>): Source<A>;
34
35 <T, A, B>(
36 source: Source<T>,
37 op1: UnaryFn<Source<T>, Source<A>>,
38 op2: UnaryFn<Source<A>, Source<B>>
39 ): Source<B>;
40
41 <T, A, B, C>(
42 source: Source<T>,
43 op1: UnaryFn<Source<T>, Source<A>>,
44 op2: UnaryFn<Source<A>, Source<B>>,
45 op3: UnaryFn<Source<B>, Source<C>>
46 ): Source<C>;
47
48 <T, A, B, C, D>(
49 source: Source<T>,
50 op1: UnaryFn<Source<T>, Source<A>>,
51 op2: UnaryFn<Source<A>, Source<B>>,
52 op3: UnaryFn<Source<B>, Source<C>>,
53 op4: UnaryFn<Source<C>, Source<D>>
54 ): Source<D>;
55
56 <T, A, B, C, D, E>(
57 source: Source<T>,
58 op1: UnaryFn<Source<T>, Source<A>>,
59 op2: UnaryFn<Source<A>, Source<B>>,
60 op3: UnaryFn<Source<B>, Source<C>>,
61 op4: UnaryFn<Source<C>, Source<D>>,
62 op5: UnaryFn<Source<D>, Source<E>>
63 ): Source<E>;
64
65 <T, A, B, C, D, E, F>(
66 source: Source<T>,
67 op1: UnaryFn<Source<T>, Source<A>>,
68 op2: UnaryFn<Source<A>, Source<B>>,
69 op3: UnaryFn<Source<B>, Source<C>>,
70 op4: UnaryFn<Source<C>, Source<D>>,
71 op5: UnaryFn<Source<D>, Source<E>>,
72 op6: UnaryFn<Source<E>, Source<F>>
73 ): Source<F>;
74
75 <T, A, B, C, D, E, F, G>(
76 source: Source<T>,
77 op1: UnaryFn<Source<T>, Source<A>>,
78 op2: UnaryFn<Source<A>, Source<B>>,
79 op3: UnaryFn<Source<B>, Source<C>>,
80 op4: UnaryFn<Source<C>, Source<D>>,
81 op5: UnaryFn<Source<D>, Source<E>>,
82 op6: UnaryFn<Source<E>, Source<F>>,
83 op7: UnaryFn<Source<F>, Source<G>>
84 ): Source<G>;
85
86 <T, A, B, C, D, E, F, G, H>(
87 source: Source<T>,
88 op1: UnaryFn<Source<T>, Source<A>>,
89 op2: UnaryFn<Source<A>, Source<B>>,
90 op3: UnaryFn<Source<B>, Source<C>>,
91 op4: UnaryFn<Source<C>, Source<D>>,
92 op5: UnaryFn<Source<D>, Source<E>>,
93 op6: UnaryFn<Source<E>, Source<F>>,
94 op7: UnaryFn<Source<F>, Source<G>>,
95 op8: UnaryFn<Source<G>, Source<H>>
96 ): Source<H>;
97
98 /* pipe definitions for source + operators + consumer composition */
99
100 <T, R>(source: Source<T>, consumer: UnaryFn<Source<T>, R>): R;
101
102 <T, A, R>(
103 source: Source<T>,
104 op1: UnaryFn<Source<T>, Source<A>>,
105 consumer: UnaryFn<Source<A>, R>
106 ): R;
107
108 <T, A, B, R>(
109 source: Source<T>,
110 op1: UnaryFn<Source<T>, Source<A>>,
111 op2: UnaryFn<Source<A>, Source<B>>,
112 consumer: UnaryFn<Source<B>, R>
113 ): R;
114
115 <T, A, B, C, R>(
116 source: Source<T>,
117 op1: UnaryFn<Source<T>, Source<A>>,
118 op2: UnaryFn<Source<A>, Source<B>>,
119 op3: UnaryFn<Source<B>, Source<C>>,
120 consumer: UnaryFn<Source<C>, R>
121 ): R;
122
123 <T, A, B, C, D, R>(
124 source: Source<T>,
125 op1: UnaryFn<Source<T>, Source<A>>,
126 op2: UnaryFn<Source<A>, Source<B>>,
127 op3: UnaryFn<Source<B>, Source<C>>,
128 op4: UnaryFn<Source<C>, Source<D>>,
129 consumer: UnaryFn<Source<D>, R>
130 ): R;
131
132 <T, A, B, C, D, E, R>(
133 source: Source<T>,
134 op1: UnaryFn<Source<T>, Source<A>>,
135 op2: UnaryFn<Source<A>, Source<B>>,
136 op3: UnaryFn<Source<B>, Source<C>>,
137 op4: UnaryFn<Source<C>, Source<D>>,
138 op5: UnaryFn<Source<D>, Source<E>>,
139 consumer: UnaryFn<Source<E>, R>
140 ): R;
141
142 <T, A, B, C, D, E, F, R>(
143 source: Source<T>,
144 op1: UnaryFn<Source<T>, Source<A>>,
145 op2: UnaryFn<Source<A>, Source<B>>,
146 op3: UnaryFn<Source<B>, Source<C>>,
147 op4: UnaryFn<Source<C>, Source<D>>,
148 op5: UnaryFn<Source<D>, Source<E>>,
149 op6: UnaryFn<Source<E>, Source<F>>,
150 consumer: UnaryFn<Source<F>, R>
151 ): R;
152
153 <T, A, B, C, D, E, F, G, R>(
154 source: Source<T>,
155 op1: UnaryFn<Source<T>, Source<A>>,
156 op2: UnaryFn<Source<A>, Source<B>>,
157 op3: UnaryFn<Source<B>, Source<C>>,
158 op4: UnaryFn<Source<C>, Source<D>>,
159 op5: UnaryFn<Source<D>, Source<E>>,
160 op6: UnaryFn<Source<E>, Source<F>>,
161 op7: UnaryFn<Source<F>, Source<G>>,
162 consumer: UnaryFn<Source<G>, R>
163 ): R;
164
165 <T, A, B, C, D, E, F, G, H, R>(
166 source: Source<T>,
167 op1: UnaryFn<Source<T>, Source<A>>,
168 op2: UnaryFn<Source<A>, Source<B>>,
169 op3: UnaryFn<Source<B>, Source<C>>,
170 op4: UnaryFn<Source<C>, Source<D>>,
171 op5: UnaryFn<Source<D>, Source<E>>,
172 op6: UnaryFn<Source<E>, Source<F>>,
173 op7: UnaryFn<Source<F>, Source<G>>,
174 op8: UnaryFn<Source<G>, Source<H>>,
175 consumer: UnaryFn<Source<H>, R>
176 ): R;
177}
178
179const pipe: pipe = (...args: Function[]): any => {
180 let x = args[0];
181 for (let i = 1, l = args.length; i < l; i++) x = args[i](x);
182 return x;
183};
184
185export { pipe };