Mirror: The small sibling of the graphql package, slimmed down for client-side libraries.
at v16.1.1000 2.7 kB view raw
1import { 2 getEnterLeaveForKind, 3 getVisitFn, 4 visitInParallel, 5 BREAK, 6} from 'graphql/language/visitor'; 7 8export { getEnterLeaveForKind, getVisitFn, visitInParallel, BREAK }; 9 10export function visit(node, visitor) { 11 const path = []; 12 const ancestors = []; 13 14 function traverse(node, key, parent) { 15 let hasEdited = false; 16 17 const enter = getVisitFn(visitor, node.kind, false); 18 const resultEnter = 19 enter && enter.call(visitor, node, key, parent, path, ancestors); 20 if (resultEnter === false) { 21 return node; 22 } else if (resultEnter === null) { 23 return null; 24 } else if (resultEnter === BREAK) { 25 throw BREAK; 26 } else if (resultEnter && typeof resultEnter.kind === 'string') { 27 hasEdited = resultEnter !== node; 28 node = resultEnter; 29 } 30 31 if (parent) ancestors.push(parent); 32 33 let result; 34 const copy = { ...node }; 35 for (const nodeKey in node) { 36 path.push(nodeKey); 37 let value = node[nodeKey]; 38 if (Array.isArray(value)) { 39 const newValue = []; 40 for (let index = 0; index < value.length; index++) { 41 if (value[index] != null && typeof value[index].kind === 'string') { 42 ancestors.push(node); 43 path.push(index); 44 result = traverse(value[index], index, value); 45 path.pop(); 46 ancestors.pop(); 47 if (result === undefined) { 48 newValue.push(value[index]); 49 } else if (result === null) { 50 hasEdited = true; 51 } else { 52 hasEdited = hasEdited || result !== value[index]; 53 newValue.push(result); 54 } 55 } 56 } 57 value = newValue; 58 } else if (value != null && typeof value.kind === 'string') { 59 result = traverse(value, nodeKey, node); 60 if (result !== undefined) { 61 hasEdited = hasEdited || value !== result; 62 value = result; 63 } 64 } 65 66 path.pop(); 67 if (hasEdited) copy[nodeKey] = value; 68 } 69 70 if (parent) ancestors.pop(); 71 const leave = getVisitFn(visitor, node.kind, true); 72 const resultLeave = 73 leave && leave.call(visitor, node, key, parent, path, ancestors); 74 if (resultLeave === BREAK) { 75 throw BREAK; 76 } else if (resultLeave !== undefined) { 77 return resultLeave; 78 } else if (resultEnter !== undefined) { 79 return hasEdited ? copy : resultEnter; 80 } else { 81 return hasEdited ? copy : node; 82 } 83 } 84 85 try { 86 const result = traverse(node); 87 return result !== undefined && result !== false ? result : node; 88 } catch (error) { 89 if (error !== BREAK) throw error; 90 return node; 91 } 92}