@graphql-tools/utils
Version:
Common package containing utils and types for GraphQL tools
73 lines (72 loc) • 2.5 kB
JavaScript
import { fakePromise, fakeRejectPromise } from './fakePromise.js';
import { mapMaybePromise } from './map-maybe-promise.js';
/**
* Given an AsyncIterable and a callback function, return an AsyncIterator
* which produces values mapped via calling the callback function.
*/
export function mapAsyncIterator(iterator, onNext, onError, onEnd) {
if (Symbol.asyncIterator in iterator) {
iterator = iterator[Symbol.asyncIterator]();
}
let $return;
let abruptClose;
let onEndWithValue;
if (onEnd) {
let onEndWithValueResult /** R in onEndWithValue */;
onEndWithValue = value => {
onEndWithValueResult ||= mapMaybePromise(onEnd(), () => value);
return onEndWithValueResult;
};
}
if (typeof iterator.return === 'function') {
$return = iterator.return;
abruptClose = (error) => {
const rethrow = () => {
throw error;
};
return $return.call(iterator).then(rethrow, rethrow);
};
}
function mapResult(result) {
if (result.done) {
return onEndWithValue ? onEndWithValue(result) : result;
}
return mapMaybePromise(result.value, value => mapMaybePromise(onNext(value), iteratorResult, abruptClose));
}
let mapReject;
if (onError) {
let onErrorResult;
// Capture rejectCallback to ensure it cannot be null.
const reject = onError;
mapReject = (error) => {
onErrorResult ||= mapMaybePromise(error, error => mapMaybePromise(reject(error), iteratorResult, abruptClose));
return onErrorResult;
};
}
return {
next() {
return iterator.next().then(mapResult, mapReject);
},
return() {
const res$ = $return
? $return.call(iterator).then(mapResult, mapReject)
: fakePromise({ value: undefined, done: true });
return onEndWithValue ? res$.then(onEndWithValue) : res$;
},
throw(error) {
if (typeof iterator.throw === 'function') {
return iterator.throw(error).then(mapResult, mapReject);
}
if (abruptClose) {
return abruptClose(error);
}
return fakeRejectPromise(error);
},
[Symbol.asyncIterator]() {
return this;
},
};
}
function iteratorResult(value) {
return { value, done: false };
}