Spaces:
Running
Running
; | |
Object.defineProperty(exports, '__esModule', { | |
value: true, | |
}); | |
exports.print = print; | |
var _blockString = require('./blockString.js'); | |
var _printString = require('./printString.js'); | |
var _visitor = require('./visitor.js'); | |
/** | |
* Converts an AST into a string, using one set of reasonable | |
* formatting rules. | |
*/ | |
function print(ast) { | |
return (0, _visitor.visit)(ast, printDocASTReducer); | |
} | |
const MAX_LINE_LENGTH = 80; | |
const printDocASTReducer = { | |
Name: { | |
leave: (node) => node.value, | |
}, | |
Variable: { | |
leave: (node) => '$' + node.name, | |
}, | |
// Document | |
Document: { | |
leave: (node) => join(node.definitions, '\n\n'), | |
}, | |
OperationDefinition: { | |
leave(node) { | |
const varDefs = wrap('(', join(node.variableDefinitions, ', '), ')'); | |
const prefix = join( | |
[ | |
node.operation, | |
join([node.name, varDefs]), | |
join(node.directives, ' '), | |
], | |
' ', | |
); // Anonymous queries with no directives or variable definitions can use | |
// the query short form. | |
return (prefix === 'query' ? '' : prefix + ' ') + node.selectionSet; | |
}, | |
}, | |
VariableDefinition: { | |
leave: ({ variable, type, defaultValue, directives }) => | |
variable + | |
': ' + | |
type + | |
wrap(' = ', defaultValue) + | |
wrap(' ', join(directives, ' ')), | |
}, | |
SelectionSet: { | |
leave: ({ selections }) => block(selections), | |
}, | |
Field: { | |
leave({ alias, name, arguments: args, directives, selectionSet }) { | |
const prefix = wrap('', alias, ': ') + name; | |
let argsLine = prefix + wrap('(', join(args, ', '), ')'); | |
if (argsLine.length > MAX_LINE_LENGTH) { | |
argsLine = prefix + wrap('(\n', indent(join(args, '\n')), '\n)'); | |
} | |
return join([argsLine, join(directives, ' '), selectionSet], ' '); | |
}, | |
}, | |
Argument: { | |
leave: ({ name, value }) => name + ': ' + value, | |
}, | |
// Fragments | |
FragmentSpread: { | |
leave: ({ name, directives }) => | |
'...' + name + wrap(' ', join(directives, ' ')), | |
}, | |
InlineFragment: { | |
leave: ({ typeCondition, directives, selectionSet }) => | |
join( | |
[ | |
'...', | |
wrap('on ', typeCondition), | |
join(directives, ' '), | |
selectionSet, | |
], | |
' ', | |
), | |
}, | |
FragmentDefinition: { | |
leave: ( | |
{ name, typeCondition, variableDefinitions, directives, selectionSet }, // Note: fragment variable definitions are experimental and may be changed | |
) => | |
// or removed in the future. | |
`fragment ${name}${wrap('(', join(variableDefinitions, ', '), ')')} ` + | |
`on ${typeCondition} ${wrap('', join(directives, ' '), ' ')}` + | |
selectionSet, | |
}, | |
// Value | |
IntValue: { | |
leave: ({ value }) => value, | |
}, | |
FloatValue: { | |
leave: ({ value }) => value, | |
}, | |
StringValue: { | |
leave: ({ value, block: isBlockString }) => | |
isBlockString | |
? (0, _blockString.printBlockString)(value) | |
: (0, _printString.printString)(value), | |
}, | |
BooleanValue: { | |
leave: ({ value }) => (value ? 'true' : 'false'), | |
}, | |
NullValue: { | |
leave: () => 'null', | |
}, | |
EnumValue: { | |
leave: ({ value }) => value, | |
}, | |
ListValue: { | |
leave: ({ values }) => '[' + join(values, ', ') + ']', | |
}, | |
ObjectValue: { | |
leave: ({ fields }) => '{' + join(fields, ', ') + '}', | |
}, | |
ObjectField: { | |
leave: ({ name, value }) => name + ': ' + value, | |
}, | |
// Directive | |
Directive: { | |
leave: ({ name, arguments: args }) => | |
'@' + name + wrap('(', join(args, ', '), ')'), | |
}, | |
// Type | |
NamedType: { | |
leave: ({ name }) => name, | |
}, | |
ListType: { | |
leave: ({ type }) => '[' + type + ']', | |
}, | |
NonNullType: { | |
leave: ({ type }) => type + '!', | |
}, | |
// Type System Definitions | |
SchemaDefinition: { | |
leave: ({ description, directives, operationTypes }) => | |
wrap('', description, '\n') + | |
join(['schema', join(directives, ' '), block(operationTypes)], ' '), | |
}, | |
OperationTypeDefinition: { | |
leave: ({ operation, type }) => operation + ': ' + type, | |
}, | |
ScalarTypeDefinition: { | |
leave: ({ description, name, directives }) => | |
wrap('', description, '\n') + | |
join(['scalar', name, join(directives, ' ')], ' '), | |
}, | |
ObjectTypeDefinition: { | |
leave: ({ description, name, interfaces, directives, fields }) => | |
wrap('', description, '\n') + | |
join( | |
[ | |
'type', | |
name, | |
wrap('implements ', join(interfaces, ' & ')), | |
join(directives, ' '), | |
block(fields), | |
], | |
' ', | |
), | |
}, | |
FieldDefinition: { | |
leave: ({ description, name, arguments: args, type, directives }) => | |
wrap('', description, '\n') + | |
name + | |
(hasMultilineItems(args) | |
? wrap('(\n', indent(join(args, '\n')), '\n)') | |
: wrap('(', join(args, ', '), ')')) + | |
': ' + | |
type + | |
wrap(' ', join(directives, ' ')), | |
}, | |
InputValueDefinition: { | |
leave: ({ description, name, type, defaultValue, directives }) => | |
wrap('', description, '\n') + | |
join( | |
[name + ': ' + type, wrap('= ', defaultValue), join(directives, ' ')], | |
' ', | |
), | |
}, | |
InterfaceTypeDefinition: { | |
leave: ({ description, name, interfaces, directives, fields }) => | |
wrap('', description, '\n') + | |
join( | |
[ | |
'interface', | |
name, | |
wrap('implements ', join(interfaces, ' & ')), | |
join(directives, ' '), | |
block(fields), | |
], | |
' ', | |
), | |
}, | |
UnionTypeDefinition: { | |
leave: ({ description, name, directives, types }) => | |
wrap('', description, '\n') + | |
join( | |
['union', name, join(directives, ' '), wrap('= ', join(types, ' | '))], | |
' ', | |
), | |
}, | |
EnumTypeDefinition: { | |
leave: ({ description, name, directives, values }) => | |
wrap('', description, '\n') + | |
join(['enum', name, join(directives, ' '), block(values)], ' '), | |
}, | |
EnumValueDefinition: { | |
leave: ({ description, name, directives }) => | |
wrap('', description, '\n') + join([name, join(directives, ' ')], ' '), | |
}, | |
InputObjectTypeDefinition: { | |
leave: ({ description, name, directives, fields }) => | |
wrap('', description, '\n') + | |
join(['input', name, join(directives, ' '), block(fields)], ' '), | |
}, | |
DirectiveDefinition: { | |
leave: ({ description, name, arguments: args, repeatable, locations }) => | |
wrap('', description, '\n') + | |
'directive @' + | |
name + | |
(hasMultilineItems(args) | |
? wrap('(\n', indent(join(args, '\n')), '\n)') | |
: wrap('(', join(args, ', '), ')')) + | |
(repeatable ? ' repeatable' : '') + | |
' on ' + | |
join(locations, ' | '), | |
}, | |
SchemaExtension: { | |
leave: ({ directives, operationTypes }) => | |
join( | |
['extend schema', join(directives, ' '), block(operationTypes)], | |
' ', | |
), | |
}, | |
ScalarTypeExtension: { | |
leave: ({ name, directives }) => | |
join(['extend scalar', name, join(directives, ' ')], ' '), | |
}, | |
ObjectTypeExtension: { | |
leave: ({ name, interfaces, directives, fields }) => | |
join( | |
[ | |
'extend type', | |
name, | |
wrap('implements ', join(interfaces, ' & ')), | |
join(directives, ' '), | |
block(fields), | |
], | |
' ', | |
), | |
}, | |
InterfaceTypeExtension: { | |
leave: ({ name, interfaces, directives, fields }) => | |
join( | |
[ | |
'extend interface', | |
name, | |
wrap('implements ', join(interfaces, ' & ')), | |
join(directives, ' '), | |
block(fields), | |
], | |
' ', | |
), | |
}, | |
UnionTypeExtension: { | |
leave: ({ name, directives, types }) => | |
join( | |
[ | |
'extend union', | |
name, | |
join(directives, ' '), | |
wrap('= ', join(types, ' | ')), | |
], | |
' ', | |
), | |
}, | |
EnumTypeExtension: { | |
leave: ({ name, directives, values }) => | |
join(['extend enum', name, join(directives, ' '), block(values)], ' '), | |
}, | |
InputObjectTypeExtension: { | |
leave: ({ name, directives, fields }) => | |
join(['extend input', name, join(directives, ' '), block(fields)], ' '), | |
}, | |
}; | |
/** | |
* Given maybeArray, print an empty string if it is null or empty, otherwise | |
* print all items together separated by separator if provided | |
*/ | |
function join(maybeArray, separator = '') { | |
var _maybeArray$filter$jo; | |
return (_maybeArray$filter$jo = | |
maybeArray === null || maybeArray === void 0 | |
? void 0 | |
: maybeArray.filter((x) => x).join(separator)) !== null && | |
_maybeArray$filter$jo !== void 0 | |
? _maybeArray$filter$jo | |
: ''; | |
} | |
/** | |
* Given array, print each item on its own line, wrapped in an indented `{ }` block. | |
*/ | |
function block(array) { | |
return wrap('{\n', indent(join(array, '\n')), '\n}'); | |
} | |
/** | |
* If maybeString is not null or empty, then wrap with start and end, otherwise print an empty string. | |
*/ | |
function wrap(start, maybeString, end = '') { | |
return maybeString != null && maybeString !== '' | |
? start + maybeString + end | |
: ''; | |
} | |
function indent(str) { | |
return wrap(' ', str.replace(/\n/g, '\n ')); | |
} | |
function hasMultilineItems(maybeArray) { | |
var _maybeArray$some; | |
// FIXME: https://github.com/graphql/graphql-js/issues/2203 | |
/* c8 ignore next */ | |
return (_maybeArray$some = | |
maybeArray === null || maybeArray === void 0 | |
? void 0 | |
: maybeArray.some((str) => str.includes('\n'))) !== null && | |
_maybeArray$some !== void 0 | |
? _maybeArray$some | |
: false; | |
} | |