| 254 | * @param evaluator - The evaluate function that decides when to stop |
| 255 | */ |
| 256 | export function resolveUntil<T, V>( |
| 257 | source: Iterator<T>, |
| 258 | resolver: (sourceVal: T) => ValueOrPromise<V | undefined>, |
| 259 | evaluator: (sourceVal: T, targetVal: V | undefined) => boolean, |
| 260 | ): ValueOrPromise<V | undefined> { |
| 261 | // Do iteration in loop for synchronous values to avoid stack overflow |
| 262 | // eslint-disable-next-line no-constant-condition |
| 263 | while (true) { |
| 264 | const next = source.next(); |
| 265 | if (next.done) return undefined; // End of the iterator |
| 266 | const sourceVal = next.value; |
| 267 | const valueOrPromise = resolver(sourceVal); |
| 268 | if (isPromiseLike(valueOrPromise)) { |
| 269 | return valueOrPromise.then(v => { |
| 270 | if (evaluator(sourceVal, v)) { |
| 271 | return v; |
| 272 | } else { |
| 273 | return resolveUntil(source, resolver, evaluator); |
| 274 | } |
| 275 | }); |
| 276 | } else { |
| 277 | if (evaluator(sourceVal, valueOrPromise)) { |
| 278 | return valueOrPromise; |
| 279 | } |
| 280 | // Continue with the while loop |
| 281 | } |
| 282 | } |
| 283 | } |
| 284 | |
| 285 | /** |
| 286 | * Transform a value or promise with a function that produces a new value or |