@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,520 @@
|
|
|
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 type { ExcludeError, Operator, OperatorErrorMode, StatefulTransformFunctionOptions, TransformFunctionOptions, TransformHandlerContext, TransformStreamOptions } from "./_types.js";
|
|
222
|
+
import { ObservableError } from "../error.js";
|
|
223
|
+
/**
|
|
224
|
+
* Creates optimized stream operators with consistent error handling
|
|
225
|
+
*
|
|
226
|
+
* The Web Streams API's TransformStream is powerful but requires boilerplate for
|
|
227
|
+
* error handling, lifecycle management, and memory optimization. This function
|
|
228
|
+
* eliminates that complexity while providing four error handling strategies:
|
|
229
|
+
*
|
|
230
|
+
* - **pass-through**: Errors become observable values in the stream (default)
|
|
231
|
+
* - **ignore**: Silently skip errors and continue processing
|
|
232
|
+
* - **throw**: Stop stream immediately on first error
|
|
233
|
+
* - **manual**: No automatic error handling - you're in full control
|
|
234
|
+
*
|
|
235
|
+
* Performance: Pre-compiles error handling logic to avoid runtime checks on every chunk.
|
|
236
|
+
* Memory: Extracts only needed functions from options to enable garbage collection.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ```ts
|
|
240
|
+
* // Stream continues even if mapping fails for some items
|
|
241
|
+
* const safeMap = <T, R>(fn: (x: T) => R) => createOperator({
|
|
242
|
+
* name: 'safeMap',
|
|
243
|
+
* errorMode: 'pass-through', // Errors become ObservableError values
|
|
244
|
+
* transform(chunk, controller) {
|
|
245
|
+
* controller.enqueue(fn(chunk)); // If fn() throws, error gets enqueued
|
|
246
|
+
* }
|
|
247
|
+
* });
|
|
248
|
+
*
|
|
249
|
+
* // Stream stops immediately on any error
|
|
250
|
+
* const strictMap = <T, R>(fn: (x: T) => R) => createOperator({
|
|
251
|
+
* name: 'strictMap',
|
|
252
|
+
* errorMode: 'throw', // Stream terminates on first error
|
|
253
|
+
* transform(chunk, controller) {
|
|
254
|
+
* controller.enqueue(fn(chunk));
|
|
255
|
+
* }
|
|
256
|
+
* });
|
|
257
|
+
*
|
|
258
|
+
* // You handle all errors manually
|
|
259
|
+
* const customMap = <T, R>(fn: (x: T) => R) => createOperator({
|
|
260
|
+
* name: 'customMap',
|
|
261
|
+
* errorMode: 'manual',
|
|
262
|
+
* transform(chunk, controller) {
|
|
263
|
+
* try {
|
|
264
|
+
* controller.enqueue(fn(chunk));
|
|
265
|
+
* } catch (err) {
|
|
266
|
+
* // Your custom error logic here
|
|
267
|
+
* controller.enqueue(err.message);
|
|
268
|
+
* }
|
|
269
|
+
* }
|
|
270
|
+
* });
|
|
271
|
+
* ```
|
|
272
|
+
*/
|
|
273
|
+
export declare function createOperator<T, R, O extends R | ObservableError = R | ObservableError>(options: TransformFunctionOptions<T, O> & {
|
|
274
|
+
errorMode?: "pass-through";
|
|
275
|
+
}): Operator<T, O>;
|
|
276
|
+
/**
|
|
277
|
+
* Creates a pass-through operator from a pre-built TransformStream factory.
|
|
278
|
+
*/
|
|
279
|
+
export declare function createOperator<T, R, O extends R | ObservableError = R | ObservableError>(options: TransformStreamOptions<T, O> & {
|
|
280
|
+
errorMode?: "pass-through";
|
|
281
|
+
}): Operator<T, O>;
|
|
282
|
+
/**
|
|
283
|
+
* Creates an ignore-mode operator from a transform callback.
|
|
284
|
+
*/
|
|
285
|
+
export declare function createOperator<T, R, O extends ExcludeError<R> = ExcludeError<R>>(options: TransformFunctionOptions<T, O> & {
|
|
286
|
+
errorMode: "ignore";
|
|
287
|
+
}): Operator<T, O>;
|
|
288
|
+
/**
|
|
289
|
+
* Creates an ignore-mode operator from a TransformStream factory.
|
|
290
|
+
*/
|
|
291
|
+
export declare function createOperator<T, R, O extends ExcludeError<R> = ExcludeError<R>>(options: TransformStreamOptions<T, O> & {
|
|
292
|
+
errorMode: "ignore";
|
|
293
|
+
}): Operator<T, O>;
|
|
294
|
+
/**
|
|
295
|
+
* Creates a throw-mode operator from a transform callback.
|
|
296
|
+
*/
|
|
297
|
+
export declare function createOperator<T, R, O extends ExcludeError<R> = ExcludeError<R>>(options: TransformFunctionOptions<T, O> & {
|
|
298
|
+
errorMode: "throw";
|
|
299
|
+
}): Operator<T, O>;
|
|
300
|
+
/**
|
|
301
|
+
* Creates a throw-mode operator from a TransformStream factory.
|
|
302
|
+
*/
|
|
303
|
+
export declare function createOperator<T, R, O extends ExcludeError<R> = ExcludeError<R>>(options: TransformStreamOptions<T, O> & {
|
|
304
|
+
errorMode: "throw";
|
|
305
|
+
}): Operator<T, O>;
|
|
306
|
+
/**
|
|
307
|
+
* Creates a manual-mode operator from a transform callback.
|
|
308
|
+
*/
|
|
309
|
+
export declare function createOperator<T, R, O = R>(options: TransformFunctionOptions<T, O> & {
|
|
310
|
+
errorMode: "manual";
|
|
311
|
+
}): Operator<T, O>;
|
|
312
|
+
/**
|
|
313
|
+
* Creates a manual-mode operator from a TransformStream factory.
|
|
314
|
+
*/
|
|
315
|
+
export declare function createOperator<T, R, O = R>(options: TransformStreamOptions<T, O> & {
|
|
316
|
+
errorMode: "manual";
|
|
317
|
+
}): Operator<T, O>;
|
|
318
|
+
/**
|
|
319
|
+
* Hot-path optimized error handling for transform functions
|
|
320
|
+
*
|
|
321
|
+
* Problem: Transform functions are called for EVERY chunk in a stream. Doing
|
|
322
|
+
* error mode checks and type checks on every call kills performance.
|
|
323
|
+
*
|
|
324
|
+
* Solution: Pre-compile the error handling logic into optimized functions.
|
|
325
|
+
* Each error mode gets its own specialized function with zero runtime overhead.
|
|
326
|
+
*
|
|
327
|
+
* Memory optimization: Only references the specific transform function and state,
|
|
328
|
+
* not the entire options object, enabling garbage collection of unused properties.
|
|
329
|
+
*
|
|
330
|
+
* @example
|
|
331
|
+
* ```ts
|
|
332
|
+
* // Instead of this slow approach:
|
|
333
|
+
* function slowTransform(chunk, controller) {
|
|
334
|
+
* if (errorMode === 'ignore' && isObservableError(chunk)) return;
|
|
335
|
+
* if (errorMode === 'pass-through' && isObservableError(chunk)) {
|
|
336
|
+
* controller.enqueue(chunk);
|
|
337
|
+
* return;
|
|
338
|
+
* }
|
|
339
|
+
* // ... more runtime checks
|
|
340
|
+
* }
|
|
341
|
+
*
|
|
342
|
+
* // handleTransform pre-compiles to this:
|
|
343
|
+
* function fastIgnoreTransform(chunk, controller) {
|
|
344
|
+
* if (isObservableError(chunk)) return; // Only one check needed
|
|
345
|
+
* try {
|
|
346
|
+
* userTransform(chunk, controller);
|
|
347
|
+
* } catch (_) { return; } // Pre-compiled error handling
|
|
348
|
+
* }
|
|
349
|
+
* ```
|
|
350
|
+
*
|
|
351
|
+
* @typeParam T - Input chunk type
|
|
352
|
+
* @typeParam O - Output chunk type
|
|
353
|
+
* @typeParam S - State type (for stateful operators)
|
|
354
|
+
* @param errorMode - How to handle errors ("pass-through", "ignore", "throw", "manual")
|
|
355
|
+
* @param transform - Your transform function (stateless or stateful)
|
|
356
|
+
* @param context - Info about the operator, including name and state
|
|
357
|
+
* @returns A function suitable for TransformStream's `transform` property
|
|
358
|
+
*/
|
|
359
|
+
export declare function handleTransform<T, O, S = never>(errorMode: OperatorErrorMode, transform: TransformFunctionOptions<T, O>["transform"] | StatefulTransformFunctionOptions<T, O, S>["transform"], context?: TransformHandlerContext<S>): Transformer<T, O>["transform"];
|
|
360
|
+
/**
|
|
361
|
+
* Lifecycle error handling for the start of the stream
|
|
362
|
+
*
|
|
363
|
+
* The start() lifecycle method runs once when a TransformStream is created.
|
|
364
|
+
* Unlike transform(), performance isn't critical here, but error handling
|
|
365
|
+
* consistency is. This wrapper ensures start() failures are handled the
|
|
366
|
+
* same way across all error modes.
|
|
367
|
+
*
|
|
368
|
+
* Key difference: Start errors often indicate setup failures that should
|
|
369
|
+
* terminate the stream immediately (unlike transform errors which might
|
|
370
|
+
* be recoverable).
|
|
371
|
+
*
|
|
372
|
+
* @example
|
|
373
|
+
* ```ts
|
|
374
|
+
* // Database connection setup that might fail
|
|
375
|
+
* createOperator({
|
|
376
|
+
* errorMode: 'pass-through',
|
|
377
|
+
* start(controller) {
|
|
378
|
+
* // If this throws, it becomes an ObservableError in the stream
|
|
379
|
+
* this.db = connectToDatabase();
|
|
380
|
+
* },
|
|
381
|
+
* transform(chunk, controller) {
|
|
382
|
+
* const result = this.db.process(chunk);
|
|
383
|
+
* controller.enqueue(result);
|
|
384
|
+
* }
|
|
385
|
+
* });
|
|
386
|
+
* ```
|
|
387
|
+
*
|
|
388
|
+
* @typeParam T - Input chunk type
|
|
389
|
+
* @typeParam O - Output chunk type
|
|
390
|
+
* @typeParam S - State type (for stateful operators)
|
|
391
|
+
* @param errorMode - How to handle errors ("pass-through", "ignore", "throw", "manual")
|
|
392
|
+
* @param start - Your start function (stateless or stateful, optional)
|
|
393
|
+
* @param context - Info about the operator, including name and state
|
|
394
|
+
* @returns A function suitable for TransformStream's `start` property, or undefined
|
|
395
|
+
*/
|
|
396
|
+
export declare function handleStart<T, O, S extends unknown = undefined>(errorMode: OperatorErrorMode, start?: TransformFunctionOptions<T, O>["start"] | StatefulTransformFunctionOptions<T, O, S>["start"], context?: TransformHandlerContext<S>): Transformer<T, O>["start"];
|
|
397
|
+
/**
|
|
398
|
+
* Lifecycle error handling for stream cleanup
|
|
399
|
+
*
|
|
400
|
+
* The flush() method runs once when the input stream ends. This is your
|
|
401
|
+
* last chance to emit final values or clean up resources. Flush errors
|
|
402
|
+
* should typically terminate the stream since there's no more input to process.
|
|
403
|
+
*
|
|
404
|
+
* Common use cases: Emitting buffered data, closing file handles,
|
|
405
|
+
* sending final aggregated results.
|
|
406
|
+
*
|
|
407
|
+
* @example
|
|
408
|
+
* ```ts
|
|
409
|
+
* // Buffer that flushes remaining items on stream end
|
|
410
|
+
* createOperator({
|
|
411
|
+
* errorMode: 'throw', // Any flush error should fail the stream
|
|
412
|
+
* transform(chunk, controller) {
|
|
413
|
+
* this.buffer.push(chunk);
|
|
414
|
+
* if (this.buffer.length >= 10) {
|
|
415
|
+
* controller.enqueue([...this.buffer]);
|
|
416
|
+
* this.buffer.length = 0;
|
|
417
|
+
* }
|
|
418
|
+
* },
|
|
419
|
+
* flush(controller) {
|
|
420
|
+
* // Emit any remaining buffered items
|
|
421
|
+
* if (this.buffer.length > 0) {
|
|
422
|
+
* controller.enqueue([...this.buffer]);
|
|
423
|
+
* }
|
|
424
|
+
* // If this throws, stream fails (as intended)
|
|
425
|
+
* this.cleanup();
|
|
426
|
+
* }
|
|
427
|
+
* });
|
|
428
|
+
* ```
|
|
429
|
+
*
|
|
430
|
+
* @typeParam T - Input chunk type
|
|
431
|
+
* @typeParam O - Output chunk type
|
|
432
|
+
* @typeParam S - State type (for stateful operators)
|
|
433
|
+
* @param errorMode - How to handle errors ("pass-through", "ignore", "throw", "manual")
|
|
434
|
+
* @param flush - Your flush function (stateless or stateful, optional)
|
|
435
|
+
* @param context - Info about the operator, including name and state
|
|
436
|
+
* @returns A function suitable for TransformStream's `flush` property, or undefined
|
|
437
|
+
*/
|
|
438
|
+
export declare function handleFlush<T, O, S extends unknown = undefined>(errorMode: OperatorErrorMode, flush?: TransformFunctionOptions<T, O>["flush"] | StatefulTransformFunctionOptions<T, O, S>["flush"], context?: TransformHandlerContext<S>): Transformer<T, O>["flush"];
|
|
439
|
+
/**
|
|
440
|
+
* Creates operators that maintain state across stream chunks
|
|
441
|
+
*
|
|
442
|
+
* Problem: Many stream operations need memory (scanning, buffering, counting, etc.)
|
|
443
|
+
* but TransformStream doesn't provide built-in state management.
|
|
444
|
+
*
|
|
445
|
+
* Solution: This function handles state creation, lifecycle integration, and
|
|
446
|
+
* memory cleanup automatically. State is created once per stream and passed
|
|
447
|
+
* to all lifecycle methods.
|
|
448
|
+
*
|
|
449
|
+
* Memory safety: State is held in closure only for the stream's lifetime.
|
|
450
|
+
* When the stream ends, state becomes eligible for garbage collection.
|
|
451
|
+
*
|
|
452
|
+
* Performance: State access is direct (no lookups), and error handling
|
|
453
|
+
* is pre-compiled just like createOperator().
|
|
454
|
+
*
|
|
455
|
+
* @example
|
|
456
|
+
* ```ts
|
|
457
|
+
* // Running average that needs to remember previous values
|
|
458
|
+
* const runningAverage = () => createStatefulOperator({
|
|
459
|
+
* name: 'runningAverage',
|
|
460
|
+
* createState: () => ({ sum: 0, count: 0 }),
|
|
461
|
+
*
|
|
462
|
+
* transform(chunk, state, controller) {
|
|
463
|
+
* state.sum += chunk;
|
|
464
|
+
* state.count++;
|
|
465
|
+
* controller.enqueue(state.sum / state.count);
|
|
466
|
+
* },
|
|
467
|
+
*
|
|
468
|
+
* // State automatically cleaned up when stream ends
|
|
469
|
+
* });
|
|
470
|
+
*
|
|
471
|
+
* // Time-based window that needs periodic cleanup
|
|
472
|
+
* const timeWindow = (ms) => createStatefulOperator({
|
|
473
|
+
* name: 'timeWindow',
|
|
474
|
+
* createState: () => ({ items: [], timer: null }),
|
|
475
|
+
*
|
|
476
|
+
* start(state, controller) {
|
|
477
|
+
* // Set up timer using state
|
|
478
|
+
* state.timer = setInterval(() => {
|
|
479
|
+
* if (state.items.length > 0) {
|
|
480
|
+
* controller.enqueue([...state.items]);
|
|
481
|
+
* state.items.length = 0;
|
|
482
|
+
* }
|
|
483
|
+
* }, ms);
|
|
484
|
+
* },
|
|
485
|
+
*
|
|
486
|
+
* transform(chunk, state, controller) {
|
|
487
|
+
* state.items.push(chunk);
|
|
488
|
+
* },
|
|
489
|
+
*
|
|
490
|
+
* flush(state, controller) {
|
|
491
|
+
* clearInterval(state.timer); // Cleanup
|
|
492
|
+
* if (state.items.length > 0) {
|
|
493
|
+
* controller.enqueue([...state.items]);
|
|
494
|
+
* }
|
|
495
|
+
* }
|
|
496
|
+
* });
|
|
497
|
+
* ```
|
|
498
|
+
*/
|
|
499
|
+
export declare function createStatefulOperator<T, R, S, O extends R | ObservableError = R | ObservableError>(options: StatefulTransformFunctionOptions<T, O, S> & {
|
|
500
|
+
errorMode?: "pass-through";
|
|
501
|
+
}): Operator<T, O>;
|
|
502
|
+
/**
|
|
503
|
+
* Creates an ignore-mode stateful operator.
|
|
504
|
+
*/
|
|
505
|
+
export declare function createStatefulOperator<T, R, S, O extends ExcludeError<R> = ExcludeError<R>>(options: StatefulTransformFunctionOptions<T, O, S> & {
|
|
506
|
+
errorMode: "ignore";
|
|
507
|
+
}): Operator<T, O>;
|
|
508
|
+
/**
|
|
509
|
+
* Creates a throw-mode stateful operator.
|
|
510
|
+
*/
|
|
511
|
+
export declare function createStatefulOperator<T, R, S, O extends ExcludeError<R> = ExcludeError<R>>(options: StatefulTransformFunctionOptions<T, O, S> & {
|
|
512
|
+
errorMode: "throw";
|
|
513
|
+
}): Operator<T, O>;
|
|
514
|
+
/**
|
|
515
|
+
* Creates a manual-mode stateful operator.
|
|
516
|
+
*/
|
|
517
|
+
export declare function createStatefulOperator<T, R, S, O = R>(options: StatefulTransformFunctionOptions<T, O, S> & {
|
|
518
|
+
errorMode: "manual";
|
|
519
|
+
}): Operator<T, O>;
|
|
520
|
+
//# sourceMappingURL=operators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operators.d.ts","sourceRoot":"","sources":["../../src/helpers/operators.ts"],"names":[],"mappings":"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"}
|