@okikio/observables 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +578 -0
- package/esm/_dnt.polyfills.d.ts +20 -0
- package/esm/_dnt.polyfills.d.ts.map +1 -0
- package/esm/_dnt.polyfills.js +12 -0
- package/esm/_spec.d.ts +260 -0
- package/esm/_spec.d.ts.map +1 -0
- package/esm/_spec.js +1 -0
- package/esm/_types.d.ts +141 -0
- package/esm/_types.d.ts.map +1 -0
- package/esm/_types.js +20 -0
- package/esm/error.d.ts +331 -0
- package/esm/error.d.ts.map +1 -0
- package/esm/error.js +408 -0
- package/esm/events.d.ts +320 -0
- package/esm/events.d.ts.map +1 -0
- package/esm/events.js +451 -0
- package/esm/helpers/_types.d.ts +188 -0
- package/esm/helpers/_types.d.ts.map +1 -0
- package/esm/helpers/_types.js +1 -0
- package/esm/helpers/mod.d.ts +90 -0
- package/esm/helpers/mod.d.ts.map +1 -0
- package/esm/helpers/mod.js +90 -0
- package/esm/helpers/operations/batch.d.ts +109 -0
- package/esm/helpers/operations/batch.d.ts.map +1 -0
- package/esm/helpers/operations/batch.js +140 -0
- package/esm/helpers/operations/combination.d.ts +162 -0
- package/esm/helpers/operations/combination.d.ts.map +1 -0
- package/esm/helpers/operations/combination.js +350 -0
- package/esm/helpers/operations/conditional.d.ts +211 -0
- package/esm/helpers/operations/conditional.d.ts.map +1 -0
- package/esm/helpers/operations/conditional.js +280 -0
- package/esm/helpers/operations/core.d.ts +198 -0
- package/esm/helpers/operations/core.d.ts.map +1 -0
- package/esm/helpers/operations/core.js +264 -0
- package/esm/helpers/operations/errors.d.ts +277 -0
- package/esm/helpers/operations/errors.d.ts.map +1 -0
- package/esm/helpers/operations/errors.js +378 -0
- package/esm/helpers/operations/mod.d.ts +26 -0
- package/esm/helpers/operations/mod.d.ts.map +1 -0
- package/esm/helpers/operations/mod.js +25 -0
- package/esm/helpers/operations/timing.d.ts +206 -0
- package/esm/helpers/operations/timing.d.ts.map +1 -0
- package/esm/helpers/operations/timing.js +457 -0
- package/esm/helpers/operators.d.ts +520 -0
- package/esm/helpers/operators.d.ts.map +1 -0
- package/esm/helpers/operators.js +563 -0
- package/esm/helpers/pipe.d.ts +118 -0
- package/esm/helpers/pipe.d.ts.map +1 -0
- package/esm/helpers/pipe.js +129 -0
- package/esm/helpers/utils.d.ts +142 -0
- package/esm/helpers/utils.d.ts.map +1 -0
- package/esm/helpers/utils.js +193 -0
- package/esm/mod.d.ts +863 -0
- package/esm/mod.d.ts.map +1 -0
- package/esm/mod.js +861 -0
- package/esm/observable.d.ts +1610 -0
- package/esm/observable.d.ts.map +1 -0
- package/esm/observable.js +1970 -0
- package/esm/package.json +3 -0
- package/esm/queue.d.ts +201 -0
- package/esm/queue.d.ts.map +1 -0
- package/esm/queue.js +273 -0
- package/esm/symbol.d.ts +60 -0
- package/esm/symbol.d.ts.map +1 -0
- package/esm/symbol.js +132 -0
- package/package.json +96 -0
- package/script/_dnt.polyfills.d.ts +20 -0
- package/script/_dnt.polyfills.d.ts.map +1 -0
- package/script/_dnt.polyfills.js +13 -0
- package/script/_spec.d.ts +260 -0
- package/script/_spec.d.ts.map +1 -0
- package/script/_spec.js +2 -0
- package/script/_types.d.ts +141 -0
- package/script/_types.d.ts.map +1 -0
- package/script/_types.js +22 -0
- package/script/error.d.ts +331 -0
- package/script/error.d.ts.map +1 -0
- package/script/error.js +414 -0
- package/script/events.d.ts +320 -0
- package/script/events.d.ts.map +1 -0
- package/script/events.js +458 -0
- package/script/helpers/_types.d.ts +188 -0
- package/script/helpers/_types.d.ts.map +1 -0
- package/script/helpers/_types.js +2 -0
- package/script/helpers/mod.d.ts +90 -0
- package/script/helpers/mod.d.ts.map +1 -0
- package/script/helpers/mod.js +106 -0
- package/script/helpers/operations/batch.d.ts +109 -0
- package/script/helpers/operations/batch.d.ts.map +1 -0
- package/script/helpers/operations/batch.js +144 -0
- package/script/helpers/operations/combination.d.ts +162 -0
- package/script/helpers/operations/combination.d.ts.map +1 -0
- package/script/helpers/operations/combination.js +355 -0
- package/script/helpers/operations/conditional.d.ts +211 -0
- package/script/helpers/operations/conditional.d.ts.map +1 -0
- package/script/helpers/operations/conditional.js +286 -0
- package/script/helpers/operations/core.d.ts +198 -0
- package/script/helpers/operations/core.d.ts.map +1 -0
- package/script/helpers/operations/core.js +272 -0
- package/script/helpers/operations/errors.d.ts +277 -0
- package/script/helpers/operations/errors.d.ts.map +1 -0
- package/script/helpers/operations/errors.js +387 -0
- package/script/helpers/operations/mod.d.ts +26 -0
- package/script/helpers/operations/mod.d.ts.map +1 -0
- package/script/helpers/operations/mod.js +41 -0
- package/script/helpers/operations/timing.d.ts +206 -0
- package/script/helpers/operations/timing.d.ts.map +1 -0
- package/script/helpers/operations/timing.js +464 -0
- package/script/helpers/operators.d.ts +520 -0
- package/script/helpers/operators.d.ts.map +1 -0
- package/script/helpers/operators.js +570 -0
- package/script/helpers/pipe.d.ts +118 -0
- package/script/helpers/pipe.d.ts.map +1 -0
- package/script/helpers/pipe.js +132 -0
- package/script/helpers/utils.d.ts +142 -0
- package/script/helpers/utils.d.ts.map +1 -0
- package/script/helpers/utils.js +200 -0
- package/script/mod.d.ts +863 -0
- package/script/mod.d.ts.map +1 -0
- package/script/mod.js +877 -0
- package/script/observable.d.ts +1610 -0
- package/script/observable.d.ts.map +1 -0
- package/script/observable.js +1984 -0
- package/script/package.json +3 -0
- package/script/queue.d.ts +201 -0
- package/script/queue.d.ts.map +1 -0
- package/script/queue.js +286 -0
- package/script/symbol.d.ts +60 -0
- package/script/symbol.d.ts.map +1 -0
- package/script/symbol.js +135 -0
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Operators are the building blocks of Observable pipelines.
|
|
3
|
+
*
|
|
4
|
+
* If you've ever used `Array.map` or `Array.filter`, you already know the core idea:
|
|
5
|
+
* an **operator** takes a sequence of values and transforms, filters, or combines them
|
|
6
|
+
* into a new sequence. Operators let you build data pipelines, think of them as the
|
|
7
|
+
* Lego bricks for working with streams of data.
|
|
8
|
+
*
|
|
9
|
+
* Think of an operator as a function that takes a stream of values and returns a new stream,
|
|
10
|
+
* transforming, filtering, or combining the data as it flows through.
|
|
11
|
+
*
|
|
12
|
+
* For example, to double every number in an array:
|
|
13
|
+
* ```ts
|
|
14
|
+
* [1, 2, 3].map(x => x * 2); // [2, 4, 6]
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* With Observables, you want to do the same thing, but for values that arrive over time:
|
|
18
|
+
* ```ts
|
|
19
|
+
* // Double every number in a stream
|
|
20
|
+
* const double = createOperator({
|
|
21
|
+
* transform(chunk, controller) {
|
|
22
|
+
* controller.enqueue(chunk * 2);
|
|
23
|
+
* }
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* // Only allow even numbers through
|
|
27
|
+
* const evens = createOperator({
|
|
28
|
+
* transform(chunk, controller) {
|
|
29
|
+
* if (chunk % 2 === 0) controller.enqueue(chunk);
|
|
30
|
+
* }
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Use them together in a pipeline
|
|
34
|
+
* pipe(
|
|
35
|
+
* Observable.from([1, 2, 3, 4]),
|
|
36
|
+
* double,
|
|
37
|
+
* evens
|
|
38
|
+
* ).subscribe(console.log); // Output: 4, 8
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* This module lets you build your own operators using the Web Streams API under the hood.
|
|
42
|
+
* Why streams? Because they're fast, memory-efficient, and let you process data as it arrives,
|
|
43
|
+
* not just after everything is loaded. This is especially useful for things like file processing,
|
|
44
|
+
* network requests, or any situation where you want to handle data piece-by-piece.
|
|
45
|
+
*
|
|
46
|
+
* ## Why Streams? Why Not Just Arrays?
|
|
47
|
+
*
|
|
48
|
+
* Arrays are great for data you already have. But what about data that arrives slowly,
|
|
49
|
+
* or is too big to fit in memory? Think files, network responses, or user events.
|
|
50
|
+
* That's where **streams** shine: they let you process data piece-by-piece, as it arrives,
|
|
51
|
+
* without waiting for everything or loading it all at once.
|
|
52
|
+
*
|
|
53
|
+
* The Web Streams API (and Node.js streams) are the standard way to do this in modern JavaScript.
|
|
54
|
+
* But using them directly is verbose and error-prone:
|
|
55
|
+
* ```ts
|
|
56
|
+
* // Native TransformStream: double every number
|
|
57
|
+
* const stream = new TransformStream({
|
|
58
|
+
* transform(chunk, controller) {
|
|
59
|
+
* controller.enqueue(chunk * 2);
|
|
60
|
+
* }
|
|
61
|
+
* });
|
|
62
|
+
* ```
|
|
63
|
+
* Your operator helpers let you write the same thing, but with less boilerplate and
|
|
64
|
+
* built-in error handling:
|
|
65
|
+
* ```ts
|
|
66
|
+
* const double = createOperator({
|
|
67
|
+
* transform(chunk, controller) {
|
|
68
|
+
* controller.enqueue(chunk * 2);
|
|
69
|
+
* }
|
|
70
|
+
* });
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* By building operators on top of streams, you get:
|
|
74
|
+
* - **Backpressure**: Slow consumers don't overwhelm fast producers.
|
|
75
|
+
* - **Low memory usage**: Process data chunk-by-chunk, not all at once.
|
|
76
|
+
* - **Composable pipelines**: Easily chain transformations.
|
|
77
|
+
*
|
|
78
|
+
* ## Connecting Operators: Pipelines
|
|
79
|
+
*
|
|
80
|
+
* Operators are most powerful when you chain them together. This is called a pipeline.
|
|
81
|
+
*
|
|
82
|
+
* It's just like chaining `map` and `filter` on arrays, but for streams:
|
|
83
|
+
* ```ts
|
|
84
|
+
* pipe(
|
|
85
|
+
* Observable.from([1, 2, 3, 4]),
|
|
86
|
+
* createOperator({
|
|
87
|
+
* transform(chunk, controller) {
|
|
88
|
+
* controller.enqueue(chunk * 2);
|
|
89
|
+
* }
|
|
90
|
+
* }),
|
|
91
|
+
* createOperator({
|
|
92
|
+
* transform(chunk, controller) {
|
|
93
|
+
* if (chunk % 3 === 0) controller.enqueue(chunk);
|
|
94
|
+
* }
|
|
95
|
+
* })
|
|
96
|
+
* ).subscribe(console.log); // Output: 6
|
|
97
|
+
* ```
|
|
98
|
+
*
|
|
99
|
+
* Compare to arrays:
|
|
100
|
+
* ```ts
|
|
101
|
+
* [1, 2, 3, 4]
|
|
102
|
+
* .map(x => x * 2)
|
|
103
|
+
* .filter(x => x % 3 === 0)
|
|
104
|
+
* .forEach(console.log); // [2, 4, 8]
|
|
105
|
+
* ```
|
|
106
|
+
*
|
|
107
|
+
* Of course, no one wants to write operators from scratch every time.
|
|
108
|
+
* So we provide some core operations via basic familiar operators,
|
|
109
|
+
* plus error handling utilities to make your pipelines robust.
|
|
110
|
+
*
|
|
111
|
+
* Aka, `map`, `filter`, `reduce`, `batch`, `catchErrors`, `ignoreErrors`, and more.
|
|
112
|
+
* So really the example above becomes:
|
|
113
|
+
* ```ts
|
|
114
|
+
* pipe(
|
|
115
|
+
* Observable.from([1, 2, 3, 4]),
|
|
116
|
+
* map(x => x * 2),
|
|
117
|
+
* filter(x => x % 3 === 0)
|
|
118
|
+
* ).subscribe(console.log); // Output: 2, 4, 8
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
121
|
+
* The example is not ideal given arrays have functions for this already,
|
|
122
|
+
* but you get the idea. It's meant more for streams of data that arrive over time.
|
|
123
|
+
*
|
|
124
|
+
* ## Error Handling: Real-World Data is Messy
|
|
125
|
+
*
|
|
126
|
+
* Real-world data is messy. Sometimes things go wrong aka, maybe a chunk is malformed, or a network
|
|
127
|
+
* request fails. Our operators let you choose how to handle errors, with four modes:
|
|
128
|
+
*
|
|
129
|
+
* - `"pass-through"` (default): Errors become special values in the stream, so you can handle them downstream. Imagine almost like bubble wrap over error since they are dangerous allowing us to make sure we don't break the flow.
|
|
130
|
+
* - `"ignore"`: Errors are silently skipped. The stream keeps going as if nothing happened. Imagine that we're basically just remove any errors from the stream while it's flowing (pretty stressful ngl).
|
|
131
|
+
* - `"throw"`: The stream stops immediately on the first error. Basically start screaming bloody murder, an error has occured so everything must stop.
|
|
132
|
+
* - `"manual"`: You handle all errors yourself. If you don't catch them, the stream will error. This is primarily for operators who have special error handling requirements.
|
|
133
|
+
*
|
|
134
|
+
* Example: parsing JSON safely
|
|
135
|
+
* ```ts
|
|
136
|
+
* // Pass-through: errors become ObservableError values (
|
|
137
|
+
* // we basically package errors in bubble wrap which we call a ObservableError
|
|
138
|
+
* const safeParse = createOperator({
|
|
139
|
+
* errorMode: "pass-through",
|
|
140
|
+
* transform(chunk, controller) {
|
|
141
|
+
* controller.enqueue(JSON.parse(chunk));
|
|
142
|
+
* }
|
|
143
|
+
* });
|
|
144
|
+
*
|
|
145
|
+
* // Ignore: errors are dropped
|
|
146
|
+
* const ignoreParse = createOperator({
|
|
147
|
+
* errorMode: "ignore",
|
|
148
|
+
* transform(chunk, controller) {
|
|
149
|
+
* controller.enqueue(JSON.parse(chunk));
|
|
150
|
+
* }
|
|
151
|
+
* });
|
|
152
|
+
*
|
|
153
|
+
* // Throw: stream stops on first error
|
|
154
|
+
* const strictParse = createOperator({
|
|
155
|
+
* errorMode: "throw",
|
|
156
|
+
* transform(chunk, controller) {
|
|
157
|
+
* controller.enqueue(JSON.parse(chunk));
|
|
158
|
+
* }
|
|
159
|
+
* });
|
|
160
|
+
* ```
|
|
161
|
+
*
|
|
162
|
+
* Compare to native TransformStream error handling:
|
|
163
|
+
* ```ts
|
|
164
|
+
* // Native: you must handle errors yourself
|
|
165
|
+
* const stream = new TransformStream({
|
|
166
|
+
* transform(chunk, controller) {
|
|
167
|
+
* try {
|
|
168
|
+
* controller.enqueue(JSON.parse(chunk));
|
|
169
|
+
* } catch (err) {
|
|
170
|
+
* controller.error(err); // This kills the stream
|
|
171
|
+
* }
|
|
172
|
+
* }
|
|
173
|
+
* });
|
|
174
|
+
* ```
|
|
175
|
+
*
|
|
176
|
+
* ## Stateful Operators: Remembering Across Chunks
|
|
177
|
+
*
|
|
178
|
+
* Sometimes you need to keep track of things as data flows through, like running totals,
|
|
179
|
+
* buffers, or windows. Your `createStatefulOperator` lets you do this easily:
|
|
180
|
+
*
|
|
181
|
+
* ```ts
|
|
182
|
+
* // Running sum
|
|
183
|
+
* const runningSum = createStatefulOperator({
|
|
184
|
+
* createState: () => ({ sum: 0 }),
|
|
185
|
+
* transform(chunk, state, controller) {
|
|
186
|
+
* state.sum += chunk;
|
|
187
|
+
* controller.enqueue(state.sum);
|
|
188
|
+
* }
|
|
189
|
+
* });
|
|
190
|
+
*
|
|
191
|
+
* pipe(
|
|
192
|
+
* Observable.from([1, 2, 3]),
|
|
193
|
+
* runningSum
|
|
194
|
+
* ).subscribe(console.log); // Output: 1, 3, 6
|
|
195
|
+
* ```
|
|
196
|
+
*
|
|
197
|
+
* Native TransformStream can't do this as cleanly, you'd have to manage state outside the stream,
|
|
198
|
+
* which gets messy, error-prone and annoying real quick.
|
|
199
|
+
*
|
|
200
|
+
* ## Performance and Memory
|
|
201
|
+
*
|
|
202
|
+
* - **Hot path optimization**: The error handling logic is generated for each operator,
|
|
203
|
+
* so there are no runtime branches inside your data processing loop.
|
|
204
|
+
* - **Memory safety**: Only the functions and state you need are kept alive; everything else
|
|
205
|
+
* can be garbage collected.
|
|
206
|
+
* - **Streams scale**: You can process gigabytes of data with minimal RAM, and your operators
|
|
207
|
+
* work just as well for infinite streams as for arrays (though arrays have better performance through
|
|
208
|
+
* their built-in `filter`, `map`, `forEach`, etc..., methods).
|
|
209
|
+
*
|
|
210
|
+
* ## Summary
|
|
211
|
+
*
|
|
212
|
+
* - Operators are like `Array.map`/`filter`, but for async streams of data.
|
|
213
|
+
* - You can build pipelines that transform, filter, buffer, or combine data.
|
|
214
|
+
* - Error handling is flexible and explicit.
|
|
215
|
+
* - Streams make your code scalable and memory-efficient.
|
|
216
|
+
* - State is easy to manage for advanced use cases.
|
|
217
|
+
* - The helpers make working with streams as easy as working with arrays.
|
|
218
|
+
*
|
|
219
|
+
* @module
|
|
220
|
+
*/
|
|
221
|
+
import { injectError, isTransformStreamOptions } from "./utils.js";
|
|
222
|
+
import { isObservableError, ObservableError } from "../error.js";
|
|
223
|
+
// Default case
|
|
224
|
+
export function createOperator(options) {
|
|
225
|
+
// Extract operator name from options or the function name for better error reporting
|
|
226
|
+
const operatorName = `operator:${options.name || "unknown"}`;
|
|
227
|
+
const errorMode = options?.errorMode ??
|
|
228
|
+
"pass-through";
|
|
229
|
+
// Extract only what we need to avoid retaining the full options object
|
|
230
|
+
const transform = options?.transform;
|
|
231
|
+
const start = options?.start;
|
|
232
|
+
const flush = options?.flush;
|
|
233
|
+
return (source) => {
|
|
234
|
+
try {
|
|
235
|
+
// Create a transform stream with the provided options
|
|
236
|
+
const transformStream = isTransformStreamOptions(options)
|
|
237
|
+
? options.stream(options)
|
|
238
|
+
: new TransformStream({
|
|
239
|
+
// Transform function to process each chunk
|
|
240
|
+
transform: handleTransform(errorMode, transform, { operatorName }),
|
|
241
|
+
// Start function called when the stream is initialized
|
|
242
|
+
start: handleStart(errorMode, start, { operatorName }),
|
|
243
|
+
// Flush function called when the input is done
|
|
244
|
+
flush: handleFlush(errorMode, flush, { operatorName }),
|
|
245
|
+
}, { highWaterMark: 1 }, { highWaterMark: 0 });
|
|
246
|
+
// Pipe the source through the transform
|
|
247
|
+
return source.pipeThrough(transformStream);
|
|
248
|
+
}
|
|
249
|
+
catch (err) {
|
|
250
|
+
// If setup fails, return a stream that errors immediately
|
|
251
|
+
return source.pipeThrough(injectError(err, `${operatorName}:setup`, options));
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Hot-path optimized error handling for transform functions
|
|
257
|
+
*
|
|
258
|
+
* Problem: Transform functions are called for EVERY chunk in a stream. Doing
|
|
259
|
+
* error mode checks and type checks on every call kills performance.
|
|
260
|
+
*
|
|
261
|
+
* Solution: Pre-compile the error handling logic into optimized functions.
|
|
262
|
+
* Each error mode gets its own specialized function with zero runtime overhead.
|
|
263
|
+
*
|
|
264
|
+
* Memory optimization: Only references the specific transform function and state,
|
|
265
|
+
* not the entire options object, enabling garbage collection of unused properties.
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* ```ts
|
|
269
|
+
* // Instead of this slow approach:
|
|
270
|
+
* function slowTransform(chunk, controller) {
|
|
271
|
+
* if (errorMode === 'ignore' && isObservableError(chunk)) return;
|
|
272
|
+
* if (errorMode === 'pass-through' && isObservableError(chunk)) {
|
|
273
|
+
* controller.enqueue(chunk);
|
|
274
|
+
* return;
|
|
275
|
+
* }
|
|
276
|
+
* // ... more runtime checks
|
|
277
|
+
* }
|
|
278
|
+
*
|
|
279
|
+
* // handleTransform pre-compiles to this:
|
|
280
|
+
* function fastIgnoreTransform(chunk, controller) {
|
|
281
|
+
* if (isObservableError(chunk)) return; // Only one check needed
|
|
282
|
+
* try {
|
|
283
|
+
* userTransform(chunk, controller);
|
|
284
|
+
* } catch (_) { return; } // Pre-compiled error handling
|
|
285
|
+
* }
|
|
286
|
+
* ```
|
|
287
|
+
*
|
|
288
|
+
* @typeParam T - Input chunk type
|
|
289
|
+
* @typeParam O - Output chunk type
|
|
290
|
+
* @typeParam S - State type (for stateful operators)
|
|
291
|
+
* @param errorMode - How to handle errors ("pass-through", "ignore", "throw", "manual")
|
|
292
|
+
* @param transform - Your transform function (stateless or stateful)
|
|
293
|
+
* @param context - Info about the operator, including name and state
|
|
294
|
+
* @returns A function suitable for TransformStream's `transform` property
|
|
295
|
+
*/
|
|
296
|
+
export function handleTransform(errorMode, transform, context = {}) {
|
|
297
|
+
const operatorName = context.operatorName || `operator:unknown`;
|
|
298
|
+
const isStateful = context.isStateful || false;
|
|
299
|
+
const state = context.state;
|
|
300
|
+
switch (errorMode) {
|
|
301
|
+
case "pass-through":
|
|
302
|
+
return async function (chunk, controller) {
|
|
303
|
+
if (isObservableError(chunk)) {
|
|
304
|
+
controller.enqueue(chunk);
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
try {
|
|
308
|
+
if (isStateful) {
|
|
309
|
+
// If stateful, pass the state along
|
|
310
|
+
return await transform(chunk, state, controller);
|
|
311
|
+
}
|
|
312
|
+
await transform(chunk, controller);
|
|
313
|
+
}
|
|
314
|
+
catch (err) {
|
|
315
|
+
controller.enqueue(ObservableError.from(err, operatorName, chunk));
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
case "ignore":
|
|
319
|
+
return async function (chunk, controller) {
|
|
320
|
+
if (isObservableError(chunk))
|
|
321
|
+
return;
|
|
322
|
+
try {
|
|
323
|
+
if (isStateful) {
|
|
324
|
+
// If stateful, pass the state along
|
|
325
|
+
return await transform(chunk, state, controller);
|
|
326
|
+
}
|
|
327
|
+
await transform(chunk, controller);
|
|
328
|
+
}
|
|
329
|
+
catch (_) {
|
|
330
|
+
// Silently ignore errors
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
case "throw":
|
|
335
|
+
return async function (chunk, controller) {
|
|
336
|
+
if (isObservableError(chunk)) {
|
|
337
|
+
return controller.error(ObservableError.from(chunk, operatorName, chunk));
|
|
338
|
+
}
|
|
339
|
+
try {
|
|
340
|
+
if (isStateful) {
|
|
341
|
+
// If stateful, pass the state along
|
|
342
|
+
return await transform(chunk, state, controller);
|
|
343
|
+
}
|
|
344
|
+
await transform(chunk, controller);
|
|
345
|
+
}
|
|
346
|
+
catch (err) {
|
|
347
|
+
return controller.error(ObservableError.from(err, operatorName, chunk));
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
case "manual":
|
|
351
|
+
default:
|
|
352
|
+
return async function (chunk, controller) {
|
|
353
|
+
// In manual mode, user is expected to handle ALL errors
|
|
354
|
+
// If they don't catch something, let it bubble up and error the stream
|
|
355
|
+
if (isStateful) {
|
|
356
|
+
// If stateful, pass the state along
|
|
357
|
+
return await transform(chunk, state, controller);
|
|
358
|
+
}
|
|
359
|
+
await transform(chunk, controller);
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Lifecycle error handling for the start of the stream
|
|
365
|
+
*
|
|
366
|
+
* The start() lifecycle method runs once when a TransformStream is created.
|
|
367
|
+
* Unlike transform(), performance isn't critical here, but error handling
|
|
368
|
+
* consistency is. This wrapper ensures start() failures are handled the
|
|
369
|
+
* same way across all error modes.
|
|
370
|
+
*
|
|
371
|
+
* Key difference: Start errors often indicate setup failures that should
|
|
372
|
+
* terminate the stream immediately (unlike transform errors which might
|
|
373
|
+
* be recoverable).
|
|
374
|
+
*
|
|
375
|
+
* @example
|
|
376
|
+
* ```ts
|
|
377
|
+
* // Database connection setup that might fail
|
|
378
|
+
* createOperator({
|
|
379
|
+
* errorMode: 'pass-through',
|
|
380
|
+
* start(controller) {
|
|
381
|
+
* // If this throws, it becomes an ObservableError in the stream
|
|
382
|
+
* this.db = connectToDatabase();
|
|
383
|
+
* },
|
|
384
|
+
* transform(chunk, controller) {
|
|
385
|
+
* const result = this.db.process(chunk);
|
|
386
|
+
* controller.enqueue(result);
|
|
387
|
+
* }
|
|
388
|
+
* });
|
|
389
|
+
* ```
|
|
390
|
+
*
|
|
391
|
+
* @typeParam T - Input chunk type
|
|
392
|
+
* @typeParam O - Output chunk type
|
|
393
|
+
* @typeParam S - State type (for stateful operators)
|
|
394
|
+
* @param errorMode - How to handle errors ("pass-through", "ignore", "throw", "manual")
|
|
395
|
+
* @param start - Your start function (stateless or stateful, optional)
|
|
396
|
+
* @param context - Info about the operator, including name and state
|
|
397
|
+
* @returns A function suitable for TransformStream's `start` property, or undefined
|
|
398
|
+
*/
|
|
399
|
+
export function handleStart(errorMode, start, context = {}) {
|
|
400
|
+
if (!start)
|
|
401
|
+
return;
|
|
402
|
+
const operatorName = context.operatorName || `operator:unknown`;
|
|
403
|
+
const isStateful = context.isStateful || false;
|
|
404
|
+
const state = context.state;
|
|
405
|
+
return async function (controller) {
|
|
406
|
+
try {
|
|
407
|
+
if (isStateful) {
|
|
408
|
+
// If stateful, pass the state along
|
|
409
|
+
return await start(state, controller);
|
|
410
|
+
}
|
|
411
|
+
return await start(controller);
|
|
412
|
+
}
|
|
413
|
+
catch (err) {
|
|
414
|
+
switch (errorMode) {
|
|
415
|
+
case "ignore":
|
|
416
|
+
controller.terminate();
|
|
417
|
+
break;
|
|
418
|
+
case "throw":
|
|
419
|
+
return controller.error(ObservableError.from(err, `${operatorName}:start`));
|
|
420
|
+
case "pass-through":
|
|
421
|
+
controller.enqueue(ObservableError.from(err, `${operatorName}:start`));
|
|
422
|
+
controller.terminate();
|
|
423
|
+
break;
|
|
424
|
+
case "manual":
|
|
425
|
+
default:
|
|
426
|
+
throw err;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Lifecycle error handling for stream cleanup
|
|
433
|
+
*
|
|
434
|
+
* The flush() method runs once when the input stream ends. This is your
|
|
435
|
+
* last chance to emit final values or clean up resources. Flush errors
|
|
436
|
+
* should typically terminate the stream since there's no more input to process.
|
|
437
|
+
*
|
|
438
|
+
* Common use cases: Emitting buffered data, closing file handles,
|
|
439
|
+
* sending final aggregated results.
|
|
440
|
+
*
|
|
441
|
+
* @example
|
|
442
|
+
* ```ts
|
|
443
|
+
* // Buffer that flushes remaining items on stream end
|
|
444
|
+
* createOperator({
|
|
445
|
+
* errorMode: 'throw', // Any flush error should fail the stream
|
|
446
|
+
* transform(chunk, controller) {
|
|
447
|
+
* this.buffer.push(chunk);
|
|
448
|
+
* if (this.buffer.length >= 10) {
|
|
449
|
+
* controller.enqueue([...this.buffer]);
|
|
450
|
+
* this.buffer.length = 0;
|
|
451
|
+
* }
|
|
452
|
+
* },
|
|
453
|
+
* flush(controller) {
|
|
454
|
+
* // Emit any remaining buffered items
|
|
455
|
+
* if (this.buffer.length > 0) {
|
|
456
|
+
* controller.enqueue([...this.buffer]);
|
|
457
|
+
* }
|
|
458
|
+
* // If this throws, stream fails (as intended)
|
|
459
|
+
* this.cleanup();
|
|
460
|
+
* }
|
|
461
|
+
* });
|
|
462
|
+
* ```
|
|
463
|
+
*
|
|
464
|
+
* @typeParam T - Input chunk type
|
|
465
|
+
* @typeParam O - Output chunk type
|
|
466
|
+
* @typeParam S - State type (for stateful operators)
|
|
467
|
+
* @param errorMode - How to handle errors ("pass-through", "ignore", "throw", "manual")
|
|
468
|
+
* @param flush - Your flush function (stateless or stateful, optional)
|
|
469
|
+
* @param context - Info about the operator, including name and state
|
|
470
|
+
* @returns A function suitable for TransformStream's `flush` property, or undefined
|
|
471
|
+
*/
|
|
472
|
+
export function handleFlush(errorMode, flush, context = {}) {
|
|
473
|
+
if (!flush)
|
|
474
|
+
return;
|
|
475
|
+
const operatorName = context.operatorName || `operator:unknown`;
|
|
476
|
+
const isStateful = context.isStateful || false;
|
|
477
|
+
const state = context.state;
|
|
478
|
+
return async function (controller) {
|
|
479
|
+
try {
|
|
480
|
+
if (isStateful) {
|
|
481
|
+
// If stateful, pass the state along
|
|
482
|
+
return await flush(state, controller);
|
|
483
|
+
}
|
|
484
|
+
return await flush(controller);
|
|
485
|
+
}
|
|
486
|
+
catch (err) {
|
|
487
|
+
switch (errorMode) {
|
|
488
|
+
case "ignore":
|
|
489
|
+
controller.terminate();
|
|
490
|
+
break;
|
|
491
|
+
case "throw":
|
|
492
|
+
return controller.error(ObservableError.from(err, `${operatorName}:flush`));
|
|
493
|
+
case "pass-through":
|
|
494
|
+
controller.enqueue(ObservableError.from(err, `${operatorName}:flush`));
|
|
495
|
+
controller.terminate();
|
|
496
|
+
break;
|
|
497
|
+
case "manual":
|
|
498
|
+
default:
|
|
499
|
+
throw err;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
// Default case
|
|
505
|
+
export function createStatefulOperator(options) {
|
|
506
|
+
// Extract operator name from options or the function name for better error reporting
|
|
507
|
+
const operatorName = `operator:stateful:${options.name || "unknown"}`;
|
|
508
|
+
const errorMode = options?.errorMode ??
|
|
509
|
+
"pass-through";
|
|
510
|
+
// Extract only what we need to avoid retaining the full options object
|
|
511
|
+
const transform = options
|
|
512
|
+
?.transform;
|
|
513
|
+
const start = options?.start;
|
|
514
|
+
const flush = options?.flush;
|
|
515
|
+
return (source) => {
|
|
516
|
+
try {
|
|
517
|
+
// Create state only when the stream is used
|
|
518
|
+
let state;
|
|
519
|
+
try {
|
|
520
|
+
// Initialize the state
|
|
521
|
+
state = options.createState();
|
|
522
|
+
}
|
|
523
|
+
catch (err) {
|
|
524
|
+
switch (errorMode) {
|
|
525
|
+
case "ignore":
|
|
526
|
+
return source;
|
|
527
|
+
case "manual":
|
|
528
|
+
case "throw":
|
|
529
|
+
throw err;
|
|
530
|
+
}
|
|
531
|
+
// If state creation fails, return a stream that errors immediately
|
|
532
|
+
return source.pipeThrough(injectError(err, `${operatorName}:create:state`, options));
|
|
533
|
+
}
|
|
534
|
+
// Create a transform stream with the provided options
|
|
535
|
+
const transformStream = new TransformStream({
|
|
536
|
+
// Transform function to process each chunk
|
|
537
|
+
start: handleStart(errorMode, start, {
|
|
538
|
+
operatorName,
|
|
539
|
+
isStateful: true,
|
|
540
|
+
state,
|
|
541
|
+
}),
|
|
542
|
+
// Start function called when the stream is initialized
|
|
543
|
+
transform: handleTransform(errorMode, transform, {
|
|
544
|
+
operatorName,
|
|
545
|
+
isStateful: true,
|
|
546
|
+
state,
|
|
547
|
+
}),
|
|
548
|
+
// Flush function called when the input is done
|
|
549
|
+
flush: handleFlush(errorMode, flush, {
|
|
550
|
+
operatorName,
|
|
551
|
+
isStateful: true,
|
|
552
|
+
state,
|
|
553
|
+
}),
|
|
554
|
+
}, { highWaterMark: 1 }, { highWaterMark: 0 });
|
|
555
|
+
// Pipe the source through the transform
|
|
556
|
+
return source.pipeThrough(transformStream);
|
|
557
|
+
}
|
|
558
|
+
catch (err) {
|
|
559
|
+
// If setup fails, return a stream that errors immediately
|
|
560
|
+
return source.pipeThrough(injectError(err, `${operatorName}:setup`, options));
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { ObservableError } from "../error.js";
|
|
2
|
+
import type { SpecObservable } from "../_spec.js";
|
|
3
|
+
import type { Operator } from "./_types.js";
|
|
4
|
+
import { Observable } from "../observable.js";
|
|
5
|
+
/**
|
|
6
|
+
* Pipe function with 19 overloads to handle up to 19 operators with proper typing.
|
|
7
|
+
* Takes an Observable as input and returns an Observable as output, but uses
|
|
8
|
+
* streams internally for efficiency.
|
|
9
|
+
*
|
|
10
|
+
* This function takes an Observable as input and applies a series of operators
|
|
11
|
+
* to transform it. It supports up to 19 operators with full type safety.
|
|
12
|
+
*
|
|
13
|
+
* Internally, this function converts the Observable to a ReadableStream,
|
|
14
|
+
* applies the stream operators, then converts back to an Observable.
|
|
15
|
+
*
|
|
16
|
+
* @returns A new Observable with all transforms applied
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* // Basic pipeline with 3 operators
|
|
21
|
+
* const result = pipe(
|
|
22
|
+
* sourceObservable,
|
|
23
|
+
* mapValue(x => x * 2),
|
|
24
|
+
* filterValue(x => x > 10),
|
|
25
|
+
* takeValue(5)
|
|
26
|
+
* );
|
|
27
|
+
*
|
|
28
|
+
* // Complex pipeline with many operators
|
|
29
|
+
* const result = pipe(
|
|
30
|
+
* sourceObservable,
|
|
31
|
+
* mapValue(x => x * 2),
|
|
32
|
+
* filterValue(x => x > 10),
|
|
33
|
+
* takeValue(5),
|
|
34
|
+
* mapValue(x => x.toString()),
|
|
35
|
+
* filterValue(x => x.length > 1),
|
|
36
|
+
* mapValue(x => x.toUpperCase()),
|
|
37
|
+
* // ... up to 19 operators total
|
|
38
|
+
* );
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function pipe<T>(source: SpecObservable<T>): Observable<T>;
|
|
42
|
+
/**
|
|
43
|
+
* Pipes a source through an operator chain with one applied operator.
|
|
44
|
+
*/
|
|
45
|
+
export declare function pipe<T, A>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>): Observable<A>;
|
|
46
|
+
/**
|
|
47
|
+
* Pipes a source through an operator chain with two applied operators.
|
|
48
|
+
*/
|
|
49
|
+
export declare function pipe<T, A, B>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>): Observable<B>;
|
|
50
|
+
/**
|
|
51
|
+
* Pipes a source through an operator chain with three applied operators.
|
|
52
|
+
*/
|
|
53
|
+
export declare function pipe<T, A, B, C>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>, op3: Operator<B, C>): Observable<C>;
|
|
54
|
+
/**
|
|
55
|
+
* Pipes a source through an operator chain with four applied operators.
|
|
56
|
+
*/
|
|
57
|
+
export declare function pipe<T, A, B, C, D>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>, op3: Operator<B, C>, op4: Operator<C, D>): Observable<D>;
|
|
58
|
+
/**
|
|
59
|
+
* Pipes a source through an operator chain with five applied operators.
|
|
60
|
+
*/
|
|
61
|
+
export declare function pipe<T, A, B, C, D, E>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>, op3: Operator<B, C>, op4: Operator<C, D>, op5: Operator<D, E>): Observable<E>;
|
|
62
|
+
/**
|
|
63
|
+
* Pipes a source through an operator chain with six applied operators.
|
|
64
|
+
*/
|
|
65
|
+
export declare function pipe<T, A, B, C, D, E, F>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>, op3: Operator<B, C>, op4: Operator<C, D>, op5: Operator<D, E>, op6: Operator<E, F>): Observable<F>;
|
|
66
|
+
/**
|
|
67
|
+
* Pipes a source through an operator chain with seven applied operators.
|
|
68
|
+
*/
|
|
69
|
+
export declare function pipe<T, A, B, C, D, E, F, G>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>, op3: Operator<B, C>, op4: Operator<C, D>, op5: Operator<D, E>, op6: Operator<E, F>, op7: Operator<F, G>): Observable<G>;
|
|
70
|
+
/**
|
|
71
|
+
* Pipes a source through an operator chain with eight applied operators.
|
|
72
|
+
*/
|
|
73
|
+
export declare function pipe<T, A, B, C, D, E, F, G, H>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>, op3: Operator<B, C>, op4: Operator<C, D>, op5: Operator<D, E>, op6: Operator<E, F>, op7: Operator<F, G>, op8: Operator<G, H>): Observable<H>;
|
|
74
|
+
/**
|
|
75
|
+
* Pipes a source through an operator chain with nine applied operators.
|
|
76
|
+
*/
|
|
77
|
+
export declare function pipe<T, A, B, C, D, E, F, G, H, I>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>, op3: Operator<B, C>, op4: Operator<C, D>, op5: Operator<D, E>, op6: Operator<E, F>, op7: Operator<F, G>, op8: Operator<G, H>, op9: Operator<H, I>): Observable<I>;
|
|
78
|
+
/**
|
|
79
|
+
* Pipes a source through an operator chain with ten applied operators.
|
|
80
|
+
*/
|
|
81
|
+
export declare function pipe<T, A, B, C, D, E, F, G, H, I, J>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>, op3: Operator<B, C>, op4: Operator<C, D>, op5: Operator<D, E>, op6: Operator<E, F>, op7: Operator<F, G>, op8: Operator<G, H>, op9: Operator<H, I>, op10: Operator<I, J>): Observable<J>;
|
|
82
|
+
/**
|
|
83
|
+
* Pipes a source through an operator chain with eleven applied operators.
|
|
84
|
+
*/
|
|
85
|
+
export declare function pipe<T, A, B, C, D, E, F, G, H, I, J, K>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>, op3: Operator<B, C>, op4: Operator<C, D>, op5: Operator<D, E>, op6: Operator<E, F>, op7: Operator<F, G>, op8: Operator<G, H>, op9: Operator<H, I>, op10: Operator<I, J>, op11: Operator<J, K>): Observable<K>;
|
|
86
|
+
/**
|
|
87
|
+
* Pipes a source through an operator chain with twelve applied operators.
|
|
88
|
+
*/
|
|
89
|
+
export declare function pipe<T, A, B, C, D, E, F, G, H, I, J, K, L>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>, op3: Operator<B, C>, op4: Operator<C, D>, op5: Operator<D, E>, op6: Operator<E, F>, op7: Operator<F, G>, op8: Operator<G, H>, op9: Operator<H, I>, op10: Operator<I, J>, op11: Operator<J, K>, op12: Operator<K, L>): Observable<L>;
|
|
90
|
+
/**
|
|
91
|
+
* Pipes a source through an operator chain with thirteen applied operators.
|
|
92
|
+
*/
|
|
93
|
+
export declare function pipe<T, A, B, C, D, E, F, G, H, I, J, K, L, M>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>, op3: Operator<B, C>, op4: Operator<C, D>, op5: Operator<D, E>, op6: Operator<E, F>, op7: Operator<F, G>, op8: Operator<G, H>, op9: Operator<H, I>, op10: Operator<I, J>, op11: Operator<J, K>, op12: Operator<K, L>, op13: Operator<L, M>): Observable<M>;
|
|
94
|
+
/**
|
|
95
|
+
* Pipes a source through an operator chain with fourteen applied operators.
|
|
96
|
+
*/
|
|
97
|
+
export declare function pipe<T, A, B, C, D, E, F, G, H, I, J, K, L, M, N>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>, op3: Operator<B, C>, op4: Operator<C, D>, op5: Operator<D, E>, op6: Operator<E, F>, op7: Operator<F, G>, op8: Operator<G, H>, op9: Operator<H, I>, op10: Operator<I, J>, op11: Operator<J, K>, op12: Operator<K, L>, op13: Operator<L, M>, op14: Operator<M, N>): Observable<N>;
|
|
98
|
+
/**
|
|
99
|
+
* Pipes a source through an operator chain with fifteen applied operators.
|
|
100
|
+
*/
|
|
101
|
+
export declare function pipe<T, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>, op3: Operator<B, C>, op4: Operator<C, D>, op5: Operator<D, E>, op6: Operator<E, F>, op7: Operator<F, G>, op8: Operator<G, H>, op9: Operator<H, I>, op10: Operator<I, J>, op11: Operator<J, K>, op12: Operator<K, L>, op13: Operator<L, M>, op14: Operator<M, N>, op15: Operator<N, O>): Observable<O>;
|
|
102
|
+
/**
|
|
103
|
+
* Pipes a source through an operator chain with sixteen applied operators.
|
|
104
|
+
*/
|
|
105
|
+
export declare function pipe<T, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>, op3: Operator<B, C>, op4: Operator<C, D>, op5: Operator<D, E>, op6: Operator<E, F>, op7: Operator<F, G>, op8: Operator<G, H>, op9: Operator<H, I>, op10: Operator<I, J>, op11: Operator<J, K>, op12: Operator<K, L>, op13: Operator<L, M>, op14: Operator<M, N>, op15: Operator<N, O>, op16: Operator<O, P>): Observable<P>;
|
|
106
|
+
/**
|
|
107
|
+
* Pipes a source through an operator chain with seventeen applied operators.
|
|
108
|
+
*/
|
|
109
|
+
export declare function pipe<T, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>, op3: Operator<B, C>, op4: Operator<C, D>, op5: Operator<D, E>, op6: Operator<E, F>, op7: Operator<F, G>, op8: Operator<G, H>, op9: Operator<H, I>, op10: Operator<I, J>, op11: Operator<J, K>, op12: Operator<K, L>, op13: Operator<L, M>, op14: Operator<M, N>, op15: Operator<N, O>, op16: Operator<O, P>, op17: Operator<P, Q>): Observable<Q>;
|
|
110
|
+
/**
|
|
111
|
+
* Pipes a source through an operator chain with eighteen applied operators.
|
|
112
|
+
*/
|
|
113
|
+
export declare function pipe<T, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>, op3: Operator<B, C>, op4: Operator<C, D>, op5: Operator<D, E>, op6: Operator<E, F>, op7: Operator<F, G>, op8: Operator<G, H>, op9: Operator<H, I>, op10: Operator<I, J>, op11: Operator<J, K>, op12: Operator<K, L>, op13: Operator<L, M>, op14: Operator<M, N>, op15: Operator<N, O>, op16: Operator<O, P>, op17: Operator<P, Q>, op18: Operator<Q, R>): Observable<R>;
|
|
114
|
+
/**
|
|
115
|
+
* Pipes a source through an operator chain with nineteen applied operators.
|
|
116
|
+
*/
|
|
117
|
+
export declare function pipe<T, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S>(source: SpecObservable<T>, op1: Operator<T | ObservableError, A>, op2: Operator<A, B>, op3: Operator<B, C>, op4: Operator<C, D>, op5: Operator<D, E>, op6: Operator<E, F>, op7: Operator<F, G>, op8: Operator<G, H>, op9: Operator<H, I>, op10: Operator<I, J>, op11: Operator<J, K>, op12: Operator<K, L>, op13: Operator<L, M>, op14: Operator<M, N>, op15: Operator<N, O>, op16: Operator<O, P>, op17: Operator<P, Q>, op18: Operator<Q, R>, op19: Operator<R, S>): Observable<S>;
|
|
118
|
+
//# sourceMappingURL=pipe.d.ts.map
|