@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.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +578 -0
  3. package/esm/_dnt.polyfills.d.ts +20 -0
  4. package/esm/_dnt.polyfills.d.ts.map +1 -0
  5. package/esm/_dnt.polyfills.js +12 -0
  6. package/esm/_spec.d.ts +260 -0
  7. package/esm/_spec.d.ts.map +1 -0
  8. package/esm/_spec.js +1 -0
  9. package/esm/_types.d.ts +141 -0
  10. package/esm/_types.d.ts.map +1 -0
  11. package/esm/_types.js +20 -0
  12. package/esm/error.d.ts +331 -0
  13. package/esm/error.d.ts.map +1 -0
  14. package/esm/error.js +408 -0
  15. package/esm/events.d.ts +320 -0
  16. package/esm/events.d.ts.map +1 -0
  17. package/esm/events.js +451 -0
  18. package/esm/helpers/_types.d.ts +188 -0
  19. package/esm/helpers/_types.d.ts.map +1 -0
  20. package/esm/helpers/_types.js +1 -0
  21. package/esm/helpers/mod.d.ts +90 -0
  22. package/esm/helpers/mod.d.ts.map +1 -0
  23. package/esm/helpers/mod.js +90 -0
  24. package/esm/helpers/operations/batch.d.ts +109 -0
  25. package/esm/helpers/operations/batch.d.ts.map +1 -0
  26. package/esm/helpers/operations/batch.js +140 -0
  27. package/esm/helpers/operations/combination.d.ts +162 -0
  28. package/esm/helpers/operations/combination.d.ts.map +1 -0
  29. package/esm/helpers/operations/combination.js +350 -0
  30. package/esm/helpers/operations/conditional.d.ts +211 -0
  31. package/esm/helpers/operations/conditional.d.ts.map +1 -0
  32. package/esm/helpers/operations/conditional.js +280 -0
  33. package/esm/helpers/operations/core.d.ts +198 -0
  34. package/esm/helpers/operations/core.d.ts.map +1 -0
  35. package/esm/helpers/operations/core.js +264 -0
  36. package/esm/helpers/operations/errors.d.ts +277 -0
  37. package/esm/helpers/operations/errors.d.ts.map +1 -0
  38. package/esm/helpers/operations/errors.js +378 -0
  39. package/esm/helpers/operations/mod.d.ts +26 -0
  40. package/esm/helpers/operations/mod.d.ts.map +1 -0
  41. package/esm/helpers/operations/mod.js +25 -0
  42. package/esm/helpers/operations/timing.d.ts +206 -0
  43. package/esm/helpers/operations/timing.d.ts.map +1 -0
  44. package/esm/helpers/operations/timing.js +457 -0
  45. package/esm/helpers/operators.d.ts +520 -0
  46. package/esm/helpers/operators.d.ts.map +1 -0
  47. package/esm/helpers/operators.js +563 -0
  48. package/esm/helpers/pipe.d.ts +118 -0
  49. package/esm/helpers/pipe.d.ts.map +1 -0
  50. package/esm/helpers/pipe.js +129 -0
  51. package/esm/helpers/utils.d.ts +142 -0
  52. package/esm/helpers/utils.d.ts.map +1 -0
  53. package/esm/helpers/utils.js +193 -0
  54. package/esm/mod.d.ts +863 -0
  55. package/esm/mod.d.ts.map +1 -0
  56. package/esm/mod.js +861 -0
  57. package/esm/observable.d.ts +1610 -0
  58. package/esm/observable.d.ts.map +1 -0
  59. package/esm/observable.js +1970 -0
  60. package/esm/package.json +3 -0
  61. package/esm/queue.d.ts +201 -0
  62. package/esm/queue.d.ts.map +1 -0
  63. package/esm/queue.js +273 -0
  64. package/esm/symbol.d.ts +60 -0
  65. package/esm/symbol.d.ts.map +1 -0
  66. package/esm/symbol.js +132 -0
  67. package/package.json +96 -0
  68. package/script/_dnt.polyfills.d.ts +20 -0
  69. package/script/_dnt.polyfills.d.ts.map +1 -0
  70. package/script/_dnt.polyfills.js +13 -0
  71. package/script/_spec.d.ts +260 -0
  72. package/script/_spec.d.ts.map +1 -0
  73. package/script/_spec.js +2 -0
  74. package/script/_types.d.ts +141 -0
  75. package/script/_types.d.ts.map +1 -0
  76. package/script/_types.js +22 -0
  77. package/script/error.d.ts +331 -0
  78. package/script/error.d.ts.map +1 -0
  79. package/script/error.js +414 -0
  80. package/script/events.d.ts +320 -0
  81. package/script/events.d.ts.map +1 -0
  82. package/script/events.js +458 -0
  83. package/script/helpers/_types.d.ts +188 -0
  84. package/script/helpers/_types.d.ts.map +1 -0
  85. package/script/helpers/_types.js +2 -0
  86. package/script/helpers/mod.d.ts +90 -0
  87. package/script/helpers/mod.d.ts.map +1 -0
  88. package/script/helpers/mod.js +106 -0
  89. package/script/helpers/operations/batch.d.ts +109 -0
  90. package/script/helpers/operations/batch.d.ts.map +1 -0
  91. package/script/helpers/operations/batch.js +144 -0
  92. package/script/helpers/operations/combination.d.ts +162 -0
  93. package/script/helpers/operations/combination.d.ts.map +1 -0
  94. package/script/helpers/operations/combination.js +355 -0
  95. package/script/helpers/operations/conditional.d.ts +211 -0
  96. package/script/helpers/operations/conditional.d.ts.map +1 -0
  97. package/script/helpers/operations/conditional.js +286 -0
  98. package/script/helpers/operations/core.d.ts +198 -0
  99. package/script/helpers/operations/core.d.ts.map +1 -0
  100. package/script/helpers/operations/core.js +272 -0
  101. package/script/helpers/operations/errors.d.ts +277 -0
  102. package/script/helpers/operations/errors.d.ts.map +1 -0
  103. package/script/helpers/operations/errors.js +387 -0
  104. package/script/helpers/operations/mod.d.ts +26 -0
  105. package/script/helpers/operations/mod.d.ts.map +1 -0
  106. package/script/helpers/operations/mod.js +41 -0
  107. package/script/helpers/operations/timing.d.ts +206 -0
  108. package/script/helpers/operations/timing.d.ts.map +1 -0
  109. package/script/helpers/operations/timing.js +464 -0
  110. package/script/helpers/operators.d.ts +520 -0
  111. package/script/helpers/operators.d.ts.map +1 -0
  112. package/script/helpers/operators.js +570 -0
  113. package/script/helpers/pipe.d.ts +118 -0
  114. package/script/helpers/pipe.d.ts.map +1 -0
  115. package/script/helpers/pipe.js +132 -0
  116. package/script/helpers/utils.d.ts +142 -0
  117. package/script/helpers/utils.d.ts.map +1 -0
  118. package/script/helpers/utils.js +200 -0
  119. package/script/mod.d.ts +863 -0
  120. package/script/mod.d.ts.map +1 -0
  121. package/script/mod.js +877 -0
  122. package/script/observable.d.ts +1610 -0
  123. package/script/observable.d.ts.map +1 -0
  124. package/script/observable.js +1984 -0
  125. package/script/package.json +3 -0
  126. package/script/queue.d.ts +201 -0
  127. package/script/queue.d.ts.map +1 -0
  128. package/script/queue.js +286 -0
  129. package/script/symbol.d.ts +60 -0
  130. package/script/symbol.d.ts.map +1 -0
  131. package/script/symbol.js +135 -0
@@ -0,0 +1,350 @@
1
+ /**
2
+ * Operators that turn each source value into another stream and combine the
3
+ * results.
4
+ *
5
+ * This entrypoint covers the "flattening" family of operators such as
6
+ * `mergeMap`, `concatMap`, and `switchMap`. Use it when one input value needs
7
+ * to start follow-up async work, for example fetching related records, reading
8
+ * files, or switching to the latest search request.
9
+ *
10
+ * The operators in this module mainly differ in concurrency and cancellation
11
+ * behavior. `mergeMap` keeps multiple inner streams alive at once, `concatMap`
12
+ * preserves order by running one at a time, and `switchMap` cancels older work
13
+ * when a newer source value arrives.
14
+ *
15
+ * @module
16
+ */
17
+ import "../../_dnt.polyfills.js";
18
+ import { createStatefulOperator } from "../operators.js";
19
+ import { isObservableError, ObservableError } from "../../error.js";
20
+ import { pull } from "../../observable.js";
21
+ /**
22
+ * Transforms each item into a new stream and merges their outputs, running
23
+ * them in parallel.
24
+ *
25
+ * Like `Promise.all(items.map(project))` but for streams, with control over
26
+ * concurrency. It's designed for high-throughput parallel processing.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * import { pipe, mergeMap, from } from "./helpers/mod.ts";
31
+ * import { of } from "../../observable.ts";
32
+ *
33
+ * // Promise.all behavior
34
+ * const ids = [1, 2, 3];
35
+ * const promises = ids.map(id => Promise.resolve(`User ${id}`));
36
+ * const users = await Promise.all(promises); // ["User 1", "User 2", "User 3"]
37
+ *
38
+ * // Stream behavior
39
+ * const idStream = from(ids);
40
+ * const userStream = pipe(
41
+ * idStream,
42
+ * mergeMap(id => of(`User ${id}`), 2) // Process 2 at a time
43
+ * );
44
+ *
45
+ * // Results may arrive in any order, e.g., "User 2", "User 1", "User 3"
46
+ * ```
47
+ *
48
+ * ## Practical Use Case
49
+ *
50
+ * Use `mergeMap` to fetch data for multiple items concurrently. For example,
51
+ * given a stream of user IDs, you can fetch each user's profile in parallel.
52
+ * This is much faster than fetching them one by one.
53
+ *
54
+ * ## Key Insight
55
+ *
56
+ * `mergeMap` is for parallel, high-throughput operations where the order of
57
+ * results doesn't matter. It's the go-to for maximizing concurrency.
58
+ *
59
+ * @typeParam T - Type of values from the source Observable
60
+ * @typeParam R - Type of values in the result Observable
61
+ * @param project - Function that maps a source value to an Observable
62
+ * @param concurrent - Maximum number of inner Observables being subscribed
63
+ * to concurrently. Default is Infinity.
64
+ * @returns An operator function that maps and flattens values
65
+ */
66
+ export function mergeMap(project, concurrent = Infinity) {
67
+ return createStatefulOperator({
68
+ name: "mergeMap",
69
+ // Initialize state
70
+ createState: () => ({
71
+ activeSubscriptions: new Map(),
72
+ buffer: [],
73
+ sourceCompleted: false,
74
+ index: 0,
75
+ activeCount: 0,
76
+ }),
77
+ // Process each incoming chunk
78
+ async transform(chunk, state, controller) {
79
+ // If we're under the concurrency limit, process immediately
80
+ if (state.activeCount < concurrent) {
81
+ await subscribeToProjection(chunk, state.index++);
82
+ }
83
+ else {
84
+ // Otherwise, buffer for later
85
+ state.buffer.push([chunk, state.index++]);
86
+ }
87
+ // Helper function to subscribe to inner Observable
88
+ async function subscribeToProjection(value, innerIndex) {
89
+ let innerObservable;
90
+ try {
91
+ // Apply projection function to get inner Observable
92
+ innerObservable = project(value, innerIndex);
93
+ }
94
+ catch (err) {
95
+ // Forward any errors from the projection function
96
+ controller.enqueue(ObservableError.from(err, "operator:stateful:mergeMap:project", value));
97
+ return;
98
+ }
99
+ state.activeCount++;
100
+ // Use pull to iterate asynchronously
101
+ try {
102
+ for await (const innerValue of pull(innerObservable, { throwError: false })) {
103
+ controller.enqueue(innerValue);
104
+ }
105
+ }
106
+ catch (err) {
107
+ controller.enqueue(ObservableError.from(err, "operator:stateful:mergeMap:innerObservable", value));
108
+ }
109
+ finally {
110
+ // Clean up after inner Observable completes
111
+ state.activeSubscriptions.delete(innerIndex);
112
+ state.activeCount--;
113
+ // Process the buffer if we have space
114
+ processBuffer();
115
+ }
116
+ }
117
+ // Helper function to process the buffer
118
+ async function processBuffer() {
119
+ // While we have room for more inner Observables and
120
+ // there are items in the buffer, subscribe to inner Observables
121
+ while (state.activeCount < concurrent && state.buffer.length > 0) {
122
+ const [value, bufferIndex] = state.buffer.shift();
123
+ await subscribeToProjection(value, bufferIndex);
124
+ }
125
+ // If the source is completed and we have no active inner
126
+ // subscriptions, complete the output stream
127
+ // Nothing more to do, transformation is complete
128
+ }
129
+ },
130
+ // Handle the end of the source stream
131
+ flush(state) {
132
+ // Mark the source as completed
133
+ state.sourceCompleted = true;
134
+ // If no active inner subscriptions, we're done
135
+ // Stream will close naturally
136
+ // Otherwise, let the active subscriptions complete
137
+ },
138
+ // Handle cancellation
139
+ cancel(state) {
140
+ // Clean up all inner subscriptions
141
+ for (const subscription of state.activeSubscriptions.values()) {
142
+ subscription.unsubscribe();
143
+ }
144
+ // Clear the buffer and state
145
+ state.buffer.length = 0;
146
+ state.activeSubscriptions.clear();
147
+ state.activeCount = 0;
148
+ },
149
+ });
150
+ }
151
+ /**
152
+ * Transforms each item into a new stream and runs them one after another, in
153
+ * strict order.
154
+ *
155
+ * Like a series of `await` calls in a `for...of` loop, this ensures that each
156
+ * new stream completes before the next one begins.
157
+ *
158
+ * @example
159
+ * ```ts
160
+ * import { pipe, concatMap, from } from "./helpers/mod.ts";
161
+ * import { of } from "../../observable.ts";
162
+ *
163
+ * // Sequential awaits in a loop
164
+ * async function processSequentially() {
165
+ * const results = [];
166
+ * for (const id of [1, 2, 3]) {
167
+ * const result = await Promise.resolve(`Step ${id}`);
168
+ * results.push(result);
169
+ * }
170
+ * return results; // ["Step 1", "Step 2", "Step 3"]
171
+ * }
172
+ *
173
+ * // Stream behavior
174
+ * const idStream = from([1, 2, 3]);
175
+ * const processStream = pipe(
176
+ * idStream,
177
+ * concatMap(id => of(`Step ${id}`))
178
+ * );
179
+ *
180
+ * // Results are guaranteed to be in order: "Step 1", "Step 2", "Step 3"
181
+ * ```
182
+ *
183
+ * ## Practical Use Case
184
+ *
185
+ * Use `concatMap` for sequential operations where order matters, such as a
186
+ * multi-step process where each step depends on the previous one (e.g., create
187
+ * user, then create their profile, then send a welcome email).
188
+ *
189
+ * ## Key Insight
190
+ *
191
+ * `concatMap` guarantees order by waiting for each inner stream to complete
192
+ * before starting the next. It's perfect for sequential tasks but is slower
193
+ * than `mergeMap` because it doesn't run in parallel.
194
+ *
195
+ * @typeParam T - Type of values from the source Observable
196
+ * @typeParam R - Type of values in the result Observable
197
+ * @param project - Function that maps a source value to an Observable
198
+ * @returns An operator function that maps and concatenates values
199
+ */
200
+ export function concatMap(project) {
201
+ // concatMap is just mergeMap with concurrency = 1
202
+ return mergeMap(project, 1);
203
+ }
204
+ /**
205
+ * Transforms items into new streams, but cancels the previous stream when a new
206
+ * item arrives.
207
+ *
208
+ * Like an auto-cancelling search input, it only cares about the latest value
209
+ * and discards any pending work from previous values.
210
+ *
211
+ * @example
212
+ * ```ts
213
+ * import { pipe, switchMap, from } from "./helpers/mod.ts";
214
+ * import { of } from "../../observable.ts";
215
+ *
216
+ * // No direct Array equivalent, as it's about handling events over time.
217
+ *
218
+ * // Stream behavior for a search input
219
+ * const queryStream = from(["cat", "cats", "cats rul"]);
220
+ *
221
+ * const searchResultStream = pipe(
222
+ * queryStream,
223
+ * switchMap(query => of(`Results for "${query}"`))
224
+ * );
225
+ *
226
+ * // Assuming each query arrives before the last one "completes":
227
+ * // The first two searches for "cat" and "cats" would be cancelled.
228
+ * // The final output would only be: 'Results for "cats rul"'
229
+ * ```
230
+ *
231
+ * ## Practical Use Case
232
+ *
233
+ * `switchMap` is essential for live search bars or any UI element that
234
+ * triggers frequent events. It ensures that only the results for the most
235
+ * recent event are processed, preventing outdated or out-of-order results.
236
+ *
237
+ * ## Key Insight
238
+ *
239
+ * `switchMap` is the operator of choice for handling rapid-fire events where
240
+ * only the latest matters. It prevents race conditions and keeps your UI
241
+ * responsive by cancelling stale, in-flight operations.
242
+ *
243
+ * @typeParam T - Type of values from the source Observable
244
+ * @typeParam R - Type of values in the result Observable
245
+ * @param project - Function that maps a source value to an Observable
246
+ * @returns An operator function that maps and switches between values
247
+ */
248
+ export function switchMap(project) {
249
+ return createStatefulOperator({
250
+ name: "switchMap",
251
+ // Initialize state
252
+ createState: () => ({
253
+ currentController: null,
254
+ currentTask: null,
255
+ currentTaskToken: null,
256
+ sourceCompleted: false,
257
+ index: 0,
258
+ }),
259
+ // Process each incoming chunk
260
+ transform(chunk, state, controller) {
261
+ if (isObservableError(chunk)) {
262
+ // If the chunk is an error, we can immediately enqueue it
263
+ controller.enqueue(chunk);
264
+ return;
265
+ }
266
+ // Cancel any existing inner subscription
267
+ if (state.currentController) {
268
+ state.currentController.abort();
269
+ state.currentController = null;
270
+ }
271
+ let innerObservable;
272
+ try {
273
+ // Apply projection function to get inner Observable
274
+ innerObservable = project(chunk, state.index++);
275
+ }
276
+ catch (err) {
277
+ // Forward any errors from the projection function
278
+ controller.enqueue(ObservableError.from(err, "operator:stateful:switchMap:project", chunk));
279
+ return;
280
+ }
281
+ // Create a new abort controller for this inner subscription
282
+ const abortController = new AbortController();
283
+ state.currentController = abortController;
284
+ // Subscribe to the new inner Observable
285
+ const currentTaskToken = {};
286
+ const currentTask = (async () => {
287
+ const enqueueIfActive = (value) => {
288
+ if (abortController.signal.aborted ||
289
+ state.currentController !== abortController) {
290
+ return;
291
+ }
292
+ try {
293
+ controller.enqueue(value);
294
+ }
295
+ catch {
296
+ abortController.abort();
297
+ }
298
+ };
299
+ try {
300
+ const iterator = pull(innerObservable, { throwError: false })[Symbol.asyncIterator]();
301
+ while (!abortController.signal.aborted) {
302
+ const { value, done } = await iterator.next();
303
+ // If the controller is aborted or we're done, exit the loop
304
+ if (abortController.signal.aborted || done)
305
+ break;
306
+ // Forward the value
307
+ enqueueIfActive(value);
308
+ }
309
+ }
310
+ catch (err) {
311
+ if (!abortController.signal.aborted) {
312
+ enqueueIfActive(ObservableError.from(err, "operator:stateful:switchMap:innerObservable", chunk));
313
+ }
314
+ }
315
+ finally {
316
+ if (state.currentTaskToken === currentTaskToken) {
317
+ state.currentTask = null;
318
+ state.currentTaskToken = null;
319
+ }
320
+ // Only handle completion if this is still the current controller
321
+ if (state.currentController === abortController) {
322
+ state.currentController = null;
323
+ // If source is completed and we have no active inner, we're done
324
+ // Stream will close naturally
325
+ }
326
+ }
327
+ })();
328
+ state.currentTask = currentTask;
329
+ state.currentTaskToken = currentTaskToken;
330
+ },
331
+ // Handle the end of the source stream
332
+ async flush(state) {
333
+ // Mark the source as completed
334
+ state.sourceCompleted = true;
335
+ if (state.currentTask) {
336
+ await state.currentTask;
337
+ }
338
+ },
339
+ // Handle cancellation
340
+ cancel(state) {
341
+ // Cancel the current inner subscription
342
+ if (state.currentController) {
343
+ state.currentController.abort();
344
+ state.currentController = null;
345
+ }
346
+ state.currentTask = null;
347
+ state.currentTaskToken = null;
348
+ },
349
+ });
350
+ }
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Predicate and decision-oriented operators for Observable streams.
3
+ *
4
+ * This entrypoint exports the operators that answer questions about a stream or
5
+ * gate values based on a condition. These are the Observable equivalents of
6
+ * array helpers such as `every()`, `some()`, and `find()`, plus utilities that
7
+ * stop early once a decision has been reached.
8
+ *
9
+ * Reach for this module when you care about whether a stream contains a match,
10
+ * whether every value passes a rule, or when processing should stop as soon as
11
+ * the answer is known.
12
+ *
13
+ * @module
14
+ */
15
+ import "../../_dnt.polyfills.js";
16
+ import type { ExcludeError, Operator } from "../_types.js";
17
+ import type { ObservableError } from "../../error.js";
18
+ /**
19
+ * Checks if every item in the stream passes a test.
20
+ *
21
+ * Like `Array.prototype.every()`, it stops and returns `false` on the first
22
+ * failure. If the stream completes without any failures, it returns `true`.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import { pipe, every, from } from "./helpers/mod.ts";
27
+ *
28
+ * // Array behavior
29
+ * const allEven = [2, 4, 6].every(n => n % 2 === 0); // true
30
+ * const someOdd = [2, 4, 5].every(n => n % 2 === 0); // false
31
+ *
32
+ * // Stream behavior
33
+ * const allEvenStream = from([2, 4, 6]);
34
+ * const result1 = await pipe(allEvenStream, every(n => n % 2 === 0)).toPromise(); // true
35
+ *
36
+ * const someOddStream = from([2, 4, 5]);
37
+ * const result2 = await pipe(someOddStream, every(n => n % 2 === 0)).toPromise(); // false
38
+ * ```
39
+ *
40
+ * ## Practical Use Case
41
+ *
42
+ * Use `every` to verify that all items in a stream meet a certain condition,
43
+ * such as ensuring all uploaded files are of the correct type or that all
44
+ * API responses were successful.
45
+ *
46
+ * ## Key Insight
47
+ *
48
+ * `every` provides a definitive boolean answer for the entire stream, making
49
+ * it a final, summary operation.
50
+ *
51
+ * @typeParam T - Type of values from the source stream
52
+ * @param predicate - Function to test each value
53
+ * @returns A stream operator that tests all values
54
+ */
55
+ export declare function every<T>(predicate: (value: ExcludeError<T>, index: number) => boolean): Operator<T | ObservableError, boolean | ObservableError>;
56
+ /**
57
+ * Checks if at least one item in the stream passes a test.
58
+ *
59
+ * Like `Array.prototype.some()`, it stops and returns `true` on the first
60
+ * success. If the stream completes without any successes, it returns `false`.
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * import { pipe, some, from } from "./helpers/mod.ts";
65
+ *
66
+ * // Array behavior
67
+ * const hasEven = [1, 3, 4].some(n => n % 2 === 0); // true
68
+ * const noEven = [1, 3, 5].some(n => n % 2 === 0); // false
69
+ *
70
+ * // Stream behavior
71
+ * const hasEvenStream = from([1, 3, 4]);
72
+ * const result1 = await pipe(hasEvenStream, some(n => n % 2 === 0)).toPromise(); // true
73
+ *
74
+ * const noEvenStream = from([1, 3, 5]);
75
+ * const result2 = await pipe(noEvenStream, some(n => n % 2 === 0)).toPromise(); // false
76
+ * ```
77
+ *
78
+ * ## Practical Use Case
79
+ *
80
+ * Use `some` to quickly determine if a condition is met by any item in a
81
+ * stream, such as checking for the existence of a specific user permission or
82
+ * detecting if any item in a batch has an error.
83
+ *
84
+ * ## Key Insight
85
+ *
86
+ * `some` is an efficient way to get a "yes" or "no" answer from a stream
87
+ * without processing all the items.
88
+ *
89
+ * @typeParam T - Type of values from the source stream
90
+ * @param predicate - Function to test each value
91
+ * @returns A stream operator that tests for any matching value
92
+ */
93
+ export declare function some<T>(predicate: (value: ExcludeError<T>, index: number) => boolean): Operator<T | ObservableError, boolean | ObservableError>;
94
+ /**
95
+ * Finds the first item in the stream that passes a test.
96
+ *
97
+ * Like `Array.prototype.find()`, it stops and emits the first matching item,
98
+ * then immediately completes the stream.
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * import { pipe, find, from } from "./helpers/mod.ts";
103
+ *
104
+ * // Array behavior
105
+ * const firstEven = [1, 3, 4, 6].find(n => n % 2 === 0); // 4
106
+ *
107
+ * // Stream behavior
108
+ * const numberStream = from([1, 3, 4, 6]);
109
+ * const result = await pipe(numberStream, find(n => n % 2 === 0)).toPromise(); // 4
110
+ * ```
111
+ *
112
+ * ## Practical Use Case
113
+ *
114
+ * Use `find` to locate a specific record or event in a stream without needing
115
+ * to process the entire dataset, such as finding the first available time slot
116
+ * or the first user to log in.
117
+ *
118
+ * ## Key Insight
119
+ *
120
+ * `find` is an efficient shortcut to get the first item you care about from a
121
+ * potentially long stream.
122
+ *
123
+ * @typeParam T - Type of values from the source stream
124
+ * @param predicate - Function to test each value
125
+ * @returns A stream operator that finds the first matching value
126
+ */
127
+ export declare function find<T>(predicate: (value: ExcludeError<T>, index: number) => boolean): Operator<T | ObservableError, T | ObservableError>;
128
+ /**
129
+ * Removes duplicate values from the stream, keeping only the first occurrence.
130
+ *
131
+ * Like creating a `new Set()` from an array, but for async streams. You can
132
+ * provide a `keySelector` to determine uniqueness based on an object property.
133
+ *
134
+ * @example
135
+ * ```ts
136
+ * import { pipe, unique, from } from "./helpers/mod.ts";
137
+ *
138
+ * // Array behavior
139
+ * const uniqueNumbers = [...new Set([1, 2, 2, 3, 1])]; // [1, 2, 3]
140
+ *
141
+ * // Stream behavior
142
+ * const numberStream = from([1, 2, 2, 3, 1]);
143
+ * const uniqueStream = pipe(numberStream, unique()); // Emits 1, 2, 3
144
+ *
145
+ * // With a key selector
146
+ * const users = [{ id: 1, name: 'A' }, { id: 2, name: 'B' }, { id: 1, name: 'C' }];
147
+ * const userStream = from(users);
148
+ * const uniqueUserStream = pipe(userStream, unique(user => user.id)); // Emits { id: 1, name: 'A' }, { id: 2, name: 'B' }
149
+ * ```
150
+ *
151
+ * ## Practical Use Case
152
+ *
153
+ * Use `unique` to de-duplicate a stream of events or data, such as processing
154
+ * a list of user IDs where some may appear multiple times, or handling event
155
+ * streams that might emit the same event more than once.
156
+ *
157
+ * ## Key Insight
158
+ *
159
+ * `unique` simplifies de-duplication in asynchronous pipelines, ensuring that
160
+ * downstream operations only run once for each unique item.
161
+ *
162
+ * @typeParam T The type of items in the stream.
163
+ * @typeParam K The type of the key used for uniqueness checks.
164
+ * @param keySelector An optional function to extract a key for uniqueness comparison.
165
+ * @returns An operator that filters out duplicate values.
166
+ */
167
+ export declare function unique<T, K = T>(keySelector?: (value: ExcludeError<T>) => K): Operator<T | ObservableError, ExcludeError<T> | ObservableError>;
168
+ /**
169
+ * Emits an item only if it is different from the previous one.
170
+ *
171
+ * This is useful for streams where values can be emitted repeatedly, but you
172
+ * only care about the changes.
173
+ *
174
+ * @example
175
+ * ```ts
176
+ * import { pipe, changed, from } from "./helpers/mod.ts";
177
+ *
178
+ * // No direct Array equivalent, as it depends on sequence.
179
+ *
180
+ * // Stream behavior
181
+ * const valueStream = from([1, 1, 2, 2, 2, 1, 3]);
182
+ * const changedStream = pipe(valueStream, changed()); // Emits 1, 2, 1, 3
183
+ *
184
+ * // With a key selector
185
+ * const userStream = from([
186
+ * { id: 1, status: 'active' },
187
+ * { id: 1, status: 'active' },
188
+ * { id: 1, status: 'inactive' }
189
+ * ]);
190
+ * const statusChangeStream = pipe(userStream, changed(user => user.status));
191
+ * // Emits { id: 1, status: 'active' }, { id: 1, status: 'inactive' }
192
+ * ```
193
+ *
194
+ * ## Practical Use Case
195
+ *
196
+ * Use `changed` to monitor a stream of state updates and only react when the
197
+ * state actually changes. This is common in UI programming for tracking user
198
+ * input or state management.
199
+ *
200
+ * ## Key Insight
201
+ *
202
+ * `changed` filters out noise from repetitive values, allowing you to focus
203
+ * on the moments when something actually changes.
204
+ *
205
+ * @typeParam T The type of items in the stream.
206
+ * @typeParam K The type of the key used for comparison.
207
+ * @param keySelector An optional function to extract a key for comparison.
208
+ * @param compare An optional function to compare two keys for equality.
209
+ * @returns An operator that filters out consecutive duplicate values.
210
+ */
211
+ //# sourceMappingURL=conditional.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conditional.d.ts","sourceRoot":"","sources":["../../../src/helpers/operations/conditional.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAItD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,KAAK,CAAC,CAAC,EACrB,SAAS,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,GAC5D,QAAQ,CAAC,CAAC,GAAG,eAAe,EAAE,OAAO,GAAG,eAAe,CAAC,CA2B1D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,IAAI,CAAC,CAAC,EACpB,SAAS,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,GAC5D,QAAQ,CAAC,CAAC,GAAG,eAAe,EAAE,OAAO,GAAG,eAAe,CAAC,CA2B1D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,IAAI,CAAC,CAAC,EACpB,SAAS,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,GAC5D,QAAQ,CAAC,CAAC,GAAG,eAAe,EAAE,CAAC,GAAG,eAAe,CAAC,CAcpD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAC7B,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,GAC1C,QAAQ,CAAC,CAAC,GAAG,eAAe,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,eAAe,CAAC,CAqBlE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG"}