fix(core): update getLastValueFromAsyncIterableIterator to support AsyncIterables returned from executors (#23229)

When an executor returns an `AsyncIterable` Nx fails because it cannot
read the value using `getLastValueFromAsyncIterableIterator` (which only
supports `AsyncIterableIterator`. This PR updates it to support both so
executors like `@nx/rollup:rollup` will work.


<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

## Current Behavior
Running Nx command fails if executor returns `AsyncIterable` e.g. by
calling `createAsyncIterable`.

## Expected Behavior
Nx command succeeds when executor returns `AsyncIterable`.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #23028
This commit is contained in:
Jack Hsu 2024-05-08 18:07:14 -04:00 committed by GitHub
parent 078dd06dd9
commit 4106691d33
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 18 additions and 2 deletions

View File

@ -1,4 +1,5 @@
import { createAsyncIterable } from './create-async-iterable';
import { getLastValueFromAsyncIterableIterator } from 'nx/src/utils/async-iterator';
describe(createAsyncIterable.name, () => {
test('simple callback', async () => {
@ -55,4 +56,15 @@ describe(createAsyncIterable.name, () => {
expect(results).toEqual(['first', 'second', 'third', 'fourth']);
});
test('works with getLastValueFromAsyncIterableIterator', async () => {
const it = createAsyncIterable<string>(({ next, done }) => {
setTimeout(() => {
next('foo');
done();
});
});
const result = await getLastValueFromAsyncIterableIterator(it);
expect(result).toEqual('foo');
});
});

View File

@ -3,13 +3,17 @@ export function isAsyncIterator<T>(v: any): v is AsyncIterableIterator<T> {
}
export async function getLastValueFromAsyncIterableIterator<T>(
i: AsyncIterableIterator<T>
i: AsyncIterable<T> | AsyncIterableIterator<T>
): Promise<T> {
let prev: IteratorResult<T, T>;
let current: IteratorResult<T, T>;
const generator = i[Symbol.asyncIterator] || i[Symbol.iterator];
const iterator = generator.call(i);
do {
prev = current;
current = await i.next();
current = await iterator.next();
} while (!current.done);
return current.value !== undefined || !prev ? current.value : prev.value;