You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
351 lines
9.3 KiB
351 lines
9.3 KiB
'use strict'; |
|
|
|
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; |
|
}
|
|
|