import { BREAK, Kind } from '@0no-co/graphql.web'; import { getEnterLeaveForKind } from 'graphql/language/visitor'; export { getEnterLeaveForKind, getVisitFn } from 'graphql/language/visitor'; export { BREAK, visit, Kind } from '@0no-co/graphql.web'; export function visitInParallel(visitors) { const skipping = new Array(visitors.length).fill(null); const mergedVisitor = Object.create(null); for (const kind of Object.values(Kind)) { let hasVisitor = false; const enterList = new Array(visitors.length).fill(undefined); const leaveList = new Array(visitors.length).fill(undefined); for (let i = 0; i < visitors.length; ++i) { const { enter, leave } = getEnterLeaveForKind(visitors[i], kind); hasVisitor = hasVisitor || enter != null || leave != null; enterList[i] = enter; leaveList[i] = leave; } if (!hasVisitor) { continue; } const mergedEnterLeave = { enter(...args) { const node = args[0]; for (let i = 0; i < visitors.length; i++) { if (skipping[i] === null) { const result = enterList[i] && enterList[i].apply(visitors[i], args); if (result === false) { skipping[i] = node; } else if (result === BREAK) { skipping[i] = BREAK; } else if (result !== undefined) { return result; } } } }, leave(...args) { const node = args[0]; for (let i = 0; i < visitors.length; i++) { if (skipping[i] === null) { const result = leaveList[i] && leaveList[i].apply(visitors[i], args); if (result === BREAK) { skipping[i] = BREAK; } else if (result !== undefined && result !== false) { return result; } } else if (skipping[i] === node) { skipping[i] = null; } } }, }; mergedVisitor[kind] = mergedEnterLeave; } return mergedVisitor; }