Mirror: The small sibling of the graphql package, slimmed down for client-side libraries.
1import { BREAK, Kind } from '@0no-co/graphql.web';
2export { BREAK, visit, Kind } from '@0no-co/graphql.web';
3
4export function getEnterLeaveForKind(visitor, kind) {
5 if (typeof visitor[kind] === 'object') {
6 return visitor[kind];
7 }
8 return {
9 enter: visitor[kind] || visitor.enter,
10 leave: visitor.leave,
11 };
12}
13
14export function getVisitFn(visitor, kind, isLeaving) {
15 const { enter, leave } = getEnterLeaveForKind(visitor, kind);
16 return isLeaving ? leave : enter;
17}
18
19export function visitInParallel(visitors) {
20 const skipping = new Array(visitors.length).fill(null);
21 const mergedVisitor = {};
22
23 for (const kindName in Kind) {
24 const kind = Kind[kindName];
25 let hasVisitor = false;
26 const enterList = new Array(visitors.length).fill();
27 const leaveList = new Array(visitors.length).fill();
28
29 for (let i = 0; i < visitors.length; ++i) {
30 const { enter, leave } = getEnterLeaveForKind(visitors[i], kind);
31 hasVisitor = hasVisitor || enter != null || leave != null;
32 enterList[i] = enter;
33 leaveList[i] = leave;
34 }
35
36 if (hasVisitor) {
37 mergedVisitor[kind] = {
38 enter(...args) {
39 const node = args[0];
40 for (let i = 0; i < visitors.length; i++) {
41 if (!skipping[i]) {
42 const result = enterList[i] && enterList[i].apply(visitors[i], args);
43 if (result === false) {
44 skipping[i] = node;
45 } else if (result === BREAK) {
46 skipping[i] = BREAK;
47 } else if (result !== undefined) {
48 return result;
49 }
50 }
51 }
52 },
53 leave(...args) {
54 const node = args[0];
55 for (let i = 0; i < visitors.length; i++) {
56 if (!skipping[i]) {
57 const result = leaveList[i] && leaveList[i].apply(visitors[i], args);
58 if (result === BREAK) {
59 skipping[i] = BREAK;
60 } else if (result !== undefined && result !== false) {
61 return result;
62 }
63 } else if (skipping[i] === node) {
64 skipping[i] = null;
65 }
66 }
67 },
68 };
69 }
70 }
71
72 return mergedVisitor;
73}