Mirror: The spec-compliant minimum of client-side GraphQL.
1import { Kind } from './kind'; 2import { ASTNode } from './ast'; 3 4export function printString(string: string) { 5 return JSON.stringify(string); 6} 7 8export function printBlockString(string: string) { 9 return '"""\n' + string.replace(/"""/g, '\\"""') + '\n"""'; 10} 11 12const hasItems = <T>( 13 array: ReadonlyArray<T> | undefined | null 14): array is ReadonlyArray<T> => !!(array && array.length); 15 16export function print(node: ASTNode): string { 17 let out: string; 18 switch (node.kind) { 19 case Kind.OPERATION_DEFINITION: 20 if (node.operation === 'query' && !node.name && !hasItems(node.variableDefinitions) && !hasItems(node.directives)) { 21 return print(node.selectionSet); 22 } 23 out = node.operation; 24 if (node.name) 25 out += ' ' + node.name.value; 26 if (hasItems(node.variableDefinitions)) { 27 if (!node.name) out += ' '; 28 out += '(' + node.variableDefinitions.map(print).join(', ') + ')'; 29 } 30 if (hasItems(node.directives)) 31 out += ' ' + node.directives.map(print).join(' '); 32 return out + ' ' + print(node.selectionSet); 33 34 case Kind.VARIABLE_DEFINITION: 35 out = print(node.variable) + 36 ': ' + 37 print(node.type); 38 if (node.defaultValue) 39 out += ' = ' + print(node.defaultValue); 40 if (hasItems(node.directives)) 41 out += ' ' + node.directives.map(print).join(' '); 42 return out; 43 44 case Kind.FIELD: 45 out = (node.alias ? print(node.alias) + ': ' : '') + node.name.value 46 if (hasItems(node.arguments)) 47 out += '(' + node.arguments.map(print).join(', ') + ')'; 48 if (hasItems(node.directives)) 49 out += ' ' + node.directives.map(print).join(' '); 50 return node.selectionSet 51 ? out + ' ' + print(node.selectionSet) 52 : out; 53 54 case Kind.STRING: 55 return node.block 56 ? printBlockString(node.value) 57 : printString(node.value); 58 59 case Kind.BOOLEAN: 60 return '' + node.value; 61 62 case Kind.NULL: 63 return 'null'; 64 65 case Kind.INT: 66 case Kind.FLOAT: 67 case Kind.ENUM: 68 case Kind.NAME: 69 return node.value; 70 71 case Kind.LIST: 72 return '[' + node.values.map(print).join(', ') + ']'; 73 74 case Kind.OBJECT: 75 return '{' + node.fields.map(print).join(', ') + '}'; 76 77 case Kind.OBJECT_FIELD: 78 return node.name.value + ': ' + print(node.value); 79 80 case Kind.VARIABLE: 81 return '$' + node.name.value; 82 83 case Kind.DOCUMENT: 84 return hasItems(node.definitions) 85 ? node.definitions.map(print).join('\n\n') 86 : ''; 87 88 case Kind.SELECTION_SET: 89 return '{\n ' + 90 node.selections.map(print).join('\n').replace(/\n/g, '\n ') + 91 '\n}'; 92 93 case Kind.ARGUMENT: 94 return node.name.value + ': ' + print(node.value); 95 96 case Kind.FRAGMENT_SPREAD: 97 out = '...' + node.name.value; 98 if (hasItems(node.directives)) 99 out += ' ' + node.directives.map(print).join(' '); 100 return out; 101 102 case Kind.INLINE_FRAGMENT: 103 out = '...'; 104 if (node.typeCondition) 105 out += ' on ' + node.typeCondition.name.value; 106 if (hasItems(node.directives)) 107 out += ' ' + node.directives.map(print).join(' '); 108 return out + ' ' + print(node.selectionSet); 109 110 case Kind.FRAGMENT_DEFINITION: 111 out = 'fragment ' + node.name.value; 112 out += ' on ' + node.typeCondition.name.value; 113 if (hasItems(node.directives)) 114 out += ' ' + node.directives.map(print).join(' '); 115 return out + ' ' + print(node.selectionSet); 116 117 case Kind.DIRECTIVE: 118 out = '@' + node.name.value; 119 if (hasItems(node.arguments)) 120 out += '(' + node.arguments.map(print).join(', ') + ')'; 121 return out; 122 123 case Kind.NAMED_TYPE: 124 return node.name.value; 125 126 case Kind.LIST_TYPE: 127 return '[' + print(node.type) + ']'; 128 129 case Kind.NON_NULL_TYPE: 130 return print(node.type) + '!'; 131 } 132}