UNPKG

spectaql

Version:

A powerful library for autogenerating static GraphQL API documentation

477 lines (360 loc) 11.2 kB
"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.addQuoteTags = addQuoteTags;exports.addSpecialTags = addSpecialTags;exports.enumToJsonFriendly = enumToJsonFriendly;exports.generateIntrospectionTypeExample = generateIntrospectionTypeExample;exports.getExampleForScalarDefinition = getExampleForScalarDefinition;exports.introspectionArgsToVariables = introspectionArgsToVariables;exports.introspectionQueryOrMutationToResponse = introspectionQueryOrMutationToResponse;exports.markdown = markdown;exports.printSchema = printSchema;var _json = _interopRequireDefault(require("json5")); var _jsonStringifyPrettyCompact = _interopRequireDefault(require("json-stringify-pretty-compact")); var _cheerio = require("cheerio"); var _marked = require("marked"); var _highlight = _interopRequireDefault(require("highlight.js")); var _graphqlHl = require("../spectaql/graphql-hl"); var _typeHelpers = require("../spectaql/type-helpers"); var _utils = require("../spectaql/utils"); var _microfiber = require("microfiber"); var _graphqlScalars = require("../themes/default/helpers/graphql-scalars");function _interopRequireDefault(e) {return e && e.__esModule ? e : { default: e };} _highlight.default.configure({ }); _highlight.default.registerLanguage('graphql', _graphqlHl.ourFunction); const mdRenderer = new _marked.marked.Renderer(); mdRenderer.code = highlight; _marked.marked.setOptions({ renderer: mdRenderer }); const SPECIAL_TAG = 'SPECIALTAG'; const SPECIAL_TAG_REGEX = new RegExp(`"?${SPECIAL_TAG}"?`, 'g'); const QUOTE_TAG = 'QUOTETAG'; const QUOTE_TAG_REGEX = new RegExp(QUOTE_TAG, 'g'); const QUOTE_HTML = '&quot;'; const QUOTE_HTML_REGEX = new RegExp(QUOTE_HTML, 'g'); const SCALAR_TO_EXAMPLE = { String: ['abc123', 'xyz789'], Int: [123, 987], Float: [123.45, 987.65], Boolean: [true, false], Date: [ new Date(), new Date(new Date().setMonth(new Date().getMonth() - 6).valueOf())]. map((date) => date.toISOString()), DateTime: [ new Date(), new Date(new Date().setMonth(new Date().getMonth() - 6).valueOf())]. map((date) => date.toISOString()), JSON: SPECIAL_TAG + '{}' + SPECIAL_TAG, ID: [4, '4'] }; function unwindTags(str) { if (typeof str !== 'string') { return str; } return replaceQuoteTags(removeSpecialTags(str)); } function jsonReplacer(name, value) { return value; } function enumToJsonFriendly(str) { return ( str. replace( /(:\s*)([a-zA-Z]\w*)/g, (match, keyPart, enumValue) => keyPart + '"' + enumValue + '"' ). replace(/\[(([a-zA-Z]\w*)[,\s]*)*\]/g, (match) => { return ( '[' + match. substr(1, match.length - 2). split(','). map((enumValue) => '"' + enumValue.trim() + '"'). join(', ') + ']'); })); } function addSpecialTags(value) { if (typeof value !== 'string' || value.includes(SPECIAL_TAG)) return value; return `${SPECIAL_TAG}${value}${SPECIAL_TAG}`; } function removeSpecialTags(value) { if (typeof value !== 'string') return value; return value.replace(SPECIAL_TAG_REGEX, ''); } function addQuoteTags(value) { if (!value || typeof value !== 'string' || value.includes(QUOTE_TAG)) { return value; } return `${QUOTE_TAG}${value}${QUOTE_TAG}`; } function replaceQuoteTags(value) { if (typeof value !== 'string') { return value; } return value.replace(QUOTE_TAG_REGEX, QUOTE_HTML); } function replaceHtmlQuotesWithQuotes(value) { if (typeof value !== 'string') return value; return value.replace(QUOTE_HTML_REGEX, '"'); } function markdown( value, { stripParagraph = false, addClass = false } = {}) { if (!value) { return value; } let html = _marked.marked.parse(value); if (stripParagraph) { let $ = (0, _cheerio.load)('<root>' + html + '</root>')('root'); if ($.children().length === 1 && $.children('p').length === 1) { html = $.children('p').html(); } } if (addClass) { let $ = (0, _cheerio.load)('<root>' + html + '</root>')('root'); if ($.children().length === 1) { $.children().first().addClass(addClass); html = $.html(); } } return html; } function highlight(code, language) { let highlighted; if (language) { try { highlighted = _highlight.default.highlight(code, { language }).value; } catch (e) { console.error(e); } } if (!highlighted) { highlighted = _highlight.default.highlightAuto(code).value; } return ( '<pre><code' + ( language ? ' class="hljs ' + this.options.langPrefix + language + '"' : ' class="hljs"') + '>' + highlighted + '\n</code></pre>\n'); } function getExampleForScalarDefinition(scalarDefinition, otherOptions) {var _otherOptions$extensi; const { name, kind } = scalarDefinition; if (kind !== 'SCALAR') { return; } let replacement; let wasFromGraphQLScalar = false; const useGraphqlScalarExamples = otherOptions === null || otherOptions === void 0 || (_otherOptions$extensi = otherOptions.extensions) === null || _otherOptions$extensi === void 0 ? void 0 : _otherOptions$extensi.graphqlScalarExamples; if (useGraphqlScalarExamples) { replacement = (0, _graphqlScalars.getExampleForGraphQLScalar)(name); if (typeof replacement !== 'undefined') { wasFromGraphQLScalar = true; } } if (typeof replacement === 'undefined') { replacement = SCALAR_TO_EXAMPLE[name]; } if (typeof replacement === 'undefined') { return; } replacement = !wasFromGraphQLScalar && Array.isArray(replacement) ? replacement[Math.floor(Math.random() * replacement.length)] : replacement; if (typeof replacement === 'string') { replacement = addSpecialTags(addQuoteTags(replacement)); } return replacement; } function introspectionArgsToVariables({ args, introspectionResponse, introspectionManipulator, extensions }) { if (!(args && args.length)) { return null; } return args.reduce((acc, arg) => { acc[arg.name] = introspectionArgToVariable({ arg, introspectionResponse, introspectionManipulator, extensions }); return acc; }, {}); } function introspectionArgToVariable({ arg, introspectionResponse, introspectionManipulator, extensions }) { if (!arg) { return null; } if (!(0, _utils.isUndef)(arg.example)) { return arg.example; } if (arg.defaultValue) { const { underlyingType, isArray } = (0, _typeHelpers.analyzeTypeIntrospection)(arg.type); if (typeof arg.defaultValue === 'string') { if (underlyingType.kind !== 'ENUM') { return _json.default.parse(enumToJsonFriendly(arg.defaultValue)); } if (!isArray) { return arg.defaultValue; } return arg.defaultValue. substr(1, arg.defaultValue.length - 2). split(','). map((val) => val.trim()); } } introspectionManipulator = introspectionManipulator || new _microfiber.Microfiber(introspectionResponse); const underlyingTypeDefinition = introspectionManipulator.getType( _microfiber.Microfiber.digUnderlyingType(arg.type) ); const otherOptions = { extensions }; return generateIntrospectionReturnTypeExample( { thing: arg, underlyingTypeDefinition, originalType: arg.type }, otherOptions ); } function introspectionQueryOrMutationToResponse({ field, introspectionResponse, introspectionManipulator, extensions }) { introspectionManipulator = introspectionManipulator || new _microfiber.Microfiber(introspectionResponse); const { isArray } = (0, _typeHelpers.analyzeTypeIntrospection)(field.type); const underlyingTypeDefinition = introspectionManipulator.getType( _microfiber.Microfiber.digUnderlyingType(field.type) ); const otherOptions = { extensions }; if (!underlyingTypeDefinition.fields) { return generateIntrospectionReturnTypeExample( { thing: field, underlyingTypeDefinition, originalType: field.type }, otherOptions ); } const exampleObject = underlyingTypeDefinition.fields.reduce((acc, field) => { const underlyingTypeDefinition = introspectionManipulator.getType( _microfiber.Microfiber.digUnderlyingType(field.type) ); acc[field.name] = generateIntrospectionReturnTypeExample( { thing: field, underlyingTypeDefinition, originalType: field.type }, otherOptions ); return acc; }, {}); return isArray ? [exampleObject] : exampleObject; } function generateIntrospectionReturnTypeExample( { thing, underlyingTypeDefinition, originalType, quoteEnum = false }, otherOptions) { let example = (0, _utils.firstNonUndef)([ thing.example, originalType.example, underlyingTypeDefinition.example] ); if ((0, _utils.isUndef)(example)) { example = underlyingTypeDefinition.kind === 'ENUM' && underlyingTypeDefinition.enumValues.length && ( quoteEnum ? addQuoteTags(underlyingTypeDefinition.enumValues[0].name) : underlyingTypeDefinition.enumValues[0].name) || underlyingTypeDefinition.kind === 'UNION' && underlyingTypeDefinition.possibleTypes.length && addSpecialTags(underlyingTypeDefinition.possibleTypes[0].name) || getExampleForScalarDefinition(underlyingTypeDefinition, otherOptions); } if (typeof example !== 'undefined') { } else { example = addSpecialTags(underlyingTypeDefinition.name); } const { isArray } = (0, _typeHelpers.analyzeTypeIntrospection)(originalType); return isArray && !Array.isArray(example) ? [example] : example; } function generateIntrospectionTypeExample({ type, introspectionResponse, introspectionManipulator, extensions }) { introspectionManipulator = introspectionManipulator || new _microfiber.Microfiber(introspectionResponse); const otherOptions = { extensions }; const fields = type.fields || type.inputFields; if (!fields) { return generateIntrospectionReturnTypeExample( { thing: type, underlyingTypeDefinition: type, originalType: type, quoteEnum: true }, otherOptions ); } return fields.reduce((acc, field) => { const underlyingTypeDefinition = introspectionManipulator.getType( _microfiber.Microfiber.digUnderlyingType(field.type) ); acc[field.name] = generateIntrospectionReturnTypeExample( { thing: field, underlyingTypeDefinition, originalType: field.type }, otherOptions ); return acc; }, {}); } function printSchema(value, _root) { if (!value) { return ''; } let markedDown; if (typeof value == 'string') { markedDown = _marked.marked.parse('```gql\r\n' + value + '\n```'); } else { const stringified = (0, _jsonStringifyPrettyCompact.default)(value, { indent: 2, replacer: jsonReplacer }); markedDown = _marked.marked.parse('```json\r\n' + stringified + '\n```'); } const quoted = replaceHtmlQuotesWithQuotes(markedDown); return (0, _cheerio.load)(unwindTags(quoted), null, false).html(); }