'use strict'; Object.defineProperty(exports, '__esModule', { value: true, }); exports.printIntrospectionSchema = printIntrospectionSchema; exports.printSchema = printSchema; exports.printType = printType; var _inspect = require('../jsutils/inspect.js'); var _invariant = require('../jsutils/invariant.js'); var _blockString = require('../language/blockString.js'); var _kinds = require('../language/kinds.js'); var _printer = require('../language/printer.js'); var _definition = require('../type/definition.js'); var _directives = require('../type/directives.js'); var _introspection = require('../type/introspection.js'); var _scalars = require('../type/scalars.js'); var _astFromValue = require('./astFromValue.js'); function printSchema(schema) { return printFilteredSchema( schema, (n) => !(0, _directives.isSpecifiedDirective)(n), isDefinedType, ); } function printIntrospectionSchema(schema) { return printFilteredSchema( schema, _directives.isSpecifiedDirective, _introspection.isIntrospectionType, ); } function isDefinedType(type) { return ( !(0, _scalars.isSpecifiedScalarType)(type) && !(0, _introspection.isIntrospectionType)(type) ); } function printFilteredSchema(schema, directiveFilter, typeFilter) { const directives = schema.getDirectives().filter(directiveFilter); const types = Object.values(schema.getTypeMap()).filter(typeFilter); return [ printSchemaDefinition(schema), ...directives.map((directive) => printDirective(directive)), ...types.map((type) => printType(type)), ] .filter(Boolean) .join('\n\n'); } function printSchemaDefinition(schema) { if (schema.description == null && isSchemaOfCommonNames(schema)) { return; } const operationTypes = []; const queryType = schema.getQueryType(); if (queryType) { operationTypes.push(` query: ${queryType.name}`); } const mutationType = schema.getMutationType(); if (mutationType) { operationTypes.push(` mutation: ${mutationType.name}`); } const subscriptionType = schema.getSubscriptionType(); if (subscriptionType) { operationTypes.push(` subscription: ${subscriptionType.name}`); } return printDescription(schema) + `schema {\n${operationTypes.join('\n')}\n}`; } /** * GraphQL schema define root types for each type of operation. These types are * the same as any other type and can be named in any manner, however there is * a common naming convention: * * ```graphql * schema { * query: Query * mutation: Mutation * subscription: Subscription * } * ``` * * When using this naming convention, the schema description can be omitted. */ function isSchemaOfCommonNames(schema) { const queryType = schema.getQueryType(); if (queryType && queryType.name !== 'Query') { return false; } const mutationType = schema.getMutationType(); if (mutationType && mutationType.name !== 'Mutation') { return false; } const subscriptionType = schema.getSubscriptionType(); if (subscriptionType && subscriptionType.name !== 'Subscription') { return false; } return true; } function printType(type) { if ((0, _definition.isScalarType)(type)) { return printScalar(type); } if ((0, _definition.isObjectType)(type)) { return printObject(type); } if ((0, _definition.isInterfaceType)(type)) { return printInterface(type); } if ((0, _definition.isUnionType)(type)) { return printUnion(type); } if ((0, _definition.isEnumType)(type)) { return printEnum(type); } if ((0, _definition.isInputObjectType)(type)) { return printInputObject(type); } /* c8 ignore next 3 */ // Not reachable, all possible types have been considered. false || (0, _invariant.invariant)( false, 'Unexpected type: ' + (0, _inspect.inspect)(type), ); } function printScalar(type) { return ( printDescription(type) + `scalar ${type.name}` + printSpecifiedByURL(type) ); } function printImplementedInterfaces(type) { const interfaces = type.getInterfaces(); return interfaces.length ? ' implements ' + interfaces.map((i) => i.name).join(' & ') : ''; } function printObject(type) { return ( printDescription(type) + `type ${type.name}` + printImplementedInterfaces(type) + printFields(type) ); } function printInterface(type) { return ( printDescription(type) + `interface ${type.name}` + printImplementedInterfaces(type) + printFields(type) ); } function printUnion(type) { const types = type.getTypes(); const possibleTypes = types.length ? ' = ' + types.join(' | ') : ''; return printDescription(type) + 'union ' + type.name + possibleTypes; } function printEnum(type) { const values = type .getValues() .map( (value, i) => printDescription(value, ' ', !i) + ' ' + value.name + printDeprecated(value.deprecationReason), ); return printDescription(type) + `enum ${type.name}` + printBlock(values); } function printInputObject(type) { const fields = Object.values(type.getFields()).map( (f, i) => printDescription(f, ' ', !i) + ' ' + printInputValue(f), ); return printDescription(type) + `input ${type.name}` + printBlock(fields); } function printFields(type) { const fields = Object.values(type.getFields()).map( (f, i) => printDescription(f, ' ', !i) + ' ' + f.name + printArgs(f.args, ' ') + ': ' + String(f.type) + printDeprecated(f.deprecationReason), ); return printBlock(fields); } function printBlock(items) { return items.length !== 0 ? ' {\n' + items.join('\n') + '\n}' : ''; } function printArgs(args, indentation = '') { if (args.length === 0) { return ''; } // If every arg does not have a description, print them on one line. if (args.every((arg) => !arg.description)) { return '(' + args.map(printInputValue).join(', ') + ')'; } return ( '(\n' + args .map( (arg, i) => printDescription(arg, ' ' + indentation, !i) + ' ' + indentation + printInputValue(arg), ) .join('\n') + '\n' + indentation + ')' ); } function printInputValue(arg) { const defaultAST = (0, _astFromValue.astFromValue)( arg.defaultValue, arg.type, ); let argDecl = arg.name + ': ' + String(arg.type); if (defaultAST) { argDecl += ` = ${(0, _printer.print)(defaultAST)}`; } return argDecl + printDeprecated(arg.deprecationReason); } function printDirective(directive) { return ( printDescription(directive) + 'directive @' + directive.name + printArgs(directive.args) + (directive.isRepeatable ? ' repeatable' : '') + ' on ' + directive.locations.join(' | ') ); } function printDeprecated(reason) { if (reason == null) { return ''; } if (reason !== _directives.DEFAULT_DEPRECATION_REASON) { const astValue = (0, _printer.print)({ kind: _kinds.Kind.STRING, value: reason, }); return ` @deprecated(reason: ${astValue})`; } return ' @deprecated'; } function printSpecifiedByURL(scalar) { if (scalar.specifiedByURL == null) { return ''; } const astValue = (0, _printer.print)({ kind: _kinds.Kind.STRING, value: scalar.specifiedByURL, }); return ` @specifiedBy(url: ${astValue})`; } function printDescription(def, indentation = '', firstInBlock = true) { const { description } = def; if (description == null) { return ''; } const blockString = (0, _printer.print)({ kind: _kinds.Kind.STRING, value: description, block: (0, _blockString.isPrintableAsBlockString)(description), }); const prefix = indentation && !firstInBlock ? '\n' + indentation : indentation; return prefix + blockString.replace(/\n/g, '\n' + indentation) + '\n'; }