UNPKG

@netlify/content-engine

Version:
342 lines 13.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.printTypeDefinitions = exports.printDirectives = void 0; const fs = __importStar(require("fs-extra")); const graphql_compose_1 = require("graphql-compose"); const reporter_1 = __importDefault(require("../reporter")); const graphql_1 = require("graphql"); const blockString_1 = require("graphql/language/blockString"); const extensions_1 = require("./extensions"); const lodash_omit_1 = __importDefault(require("lodash.omit")); const built_in_types_1 = require("./types/built-in-types"); const breakLine = (line, maxLen) => { const parts = line.split(new RegExp(`((?: |^).{15,${maxLen - 40}}(?= |$))`)); if (parts.length < 4) { return [line]; } const sublines = [parts[0] + parts[1] + parts[2]]; for (let i = 3; i < parts.length; i += 2) { sublines.push(parts[i].slice(1) + parts[i + 1]); } return sublines; }; const descriptionLines = (description, maxLen) => { const rawLines = description.split(`\n`); return rawLines?.flatMap((line) => { if (line.length < maxLen + 5) { return line; } // For > 120 character long lines, cut at space boundaries into sublines // of ~80 chars. return breakLine(line, maxLen); }); }; const printBlock = (items) => items.length !== 0 ? ` {\n` + items.join(`\n`) + `\n}` : ``; const printDeprecated = (fieldOrEnumVal) => { const reason = fieldOrEnumVal.deprecationReason; if (!reason) { return ``; } const reasonAST = (0, graphql_1.astFromValue)(reason, graphql_1.GraphQLString); if (reasonAST && reason !== `` && reason !== graphql_1.DEFAULT_DEPRECATION_REASON) { return ` @deprecated(reason: ` + (0, graphql_1.print)(reasonAST) + `)`; } return ` @deprecated`; }; const printDescription = (def, indentation = ``, firstInBlock = true) => { const description = (0, graphql_compose_1.isNamedTypeComposer)(def) ? def.getDescription() : def.description; if (!description) { return ``; } const lines = descriptionLines(description, 120 - indentation.length); const text = lines.join(`\n`); const isMultiline = text.length > 70; const blockString = (0, blockString_1.printBlockString)(text, { minimize: !isMultiline }); const prefix = indentation && !firstInBlock ? `\n` + indentation : indentation; return prefix + blockString.replace(/\n/g, `\n` + indentation) + `\n`; }; const printDirectiveArgs = (args, directive) => { if (!args || !directive) { return ``; } const directiveArgs = Object.entries(args); if (directiveArgs.length === 0) { return ``; } return (`(` + directiveArgs .map(([name, value]) => { const arg = directive.args && directive.args.find((arg) => arg.name === name); return arg && `${name}: ${(0, graphql_1.print)((0, graphql_1.astFromValue)(value, arg.type))}`; }) .join(`, `) + `)`); }; const printDirectives = (extensions, directives) => Object.entries(extensions) .map(([name, args]) => { if ([...extensions_1.internalExtensionNames, `deprecated`].includes(name)) return ``; return (` @${name}` + printDirectiveArgs(args, directives.find((directive) => directive.name === name))); }) .join(``); exports.printDirectives = printDirectives; const printInputValue = ([name, inputTC]) => { let argDecl = name + `: ` + inputTC.type.getTypeName(); if (inputTC.defaultValue) { const defaultAST = (0, graphql_1.astFromValue)(inputTC.defaultValue, inputTC.type.getType()); if (defaultAST) { argDecl += ` = ${(0, graphql_1.print)(defaultAST)}`; } } return argDecl; }; const printArgs = (args, indentation = ``) => { if (!args) { return ``; } const argsArray = Object.entries(args); if (argsArray.length === 0) { return ``; } // If all args have no description, print them on one line if (argsArray.every(([_name, argTC]) => !argTC.description)) { return `(` + argsArray.map(printInputValue).join(`, `) + `)`; } return (`(\n` + argsArray .map(([_name, argTC], i) => printDescription(argTC, ` ` + indentation, !i) + ` ` + indentation + printInputValue([_name, argTC])) .join(`\n`) + `\n` + indentation + `)`); }; const printFields = (fields, directives) => { const printedFields = Object.entries(fields).map(([fieldName, fieldTC], i) => printDescription(fieldTC, ` `, !i) + ` ` + fieldName + printArgs(fieldTC.args, ` `) + `: ` + String(fieldTC.type.getTypeName()) + (0, exports.printDirectives)(fieldTC.extensions || {}, directives) + printDeprecated(fieldTC)); return printBlock(printedFields); }; const printScalarType = (tc) => printDescription(tc) + `scalar ${tc.getTypeName()}`; const printObjectType = (tc) => { const interfaces = tc.getInterfaces(); const implementedInterfaces = interfaces.length ? ` implements ` + interfaces.map((i) => i.getTypeName()).join(` & `) : ``; const extensions = tc.getExtensions(); let fields = tc.getFields(); if (tc.hasInterface(`Node`)) { extensions.dontInfer = null; fields = (0, lodash_omit_1.default)(fields, [`id`, `parent`, `children`, `internal`]); } const directives = tc.schemaComposer.getDirectives(); const printedDirectives = (0, exports.printDirectives)(extensions, directives); return (printDescription(tc) + `type ${tc.getTypeName()}${implementedInterfaces}${printedDirectives}` + printFields(fields, directives)); }; const printInterfaceType = (tc) => { const interfaces = tc.getInterfaces(); const implementedInterfaces = interfaces.length ? ` implements ` + interfaces.map((i) => i.getTypeName()).join(` & `) : ``; const extensions = tc.getExtensions(); const directives = tc.schemaComposer.getDirectives(); const printedDirectives = (0, exports.printDirectives)(extensions, directives); return (printDescription(tc) + `interface ${tc.getTypeName()}${implementedInterfaces}${printedDirectives}` + printFields(tc.getFields(), directives)); }; const printUnionType = (tc) => { const types = tc.getTypeNames(); const possibleTypes = types.length ? ` = ` + types.join(` | `) : ``; return printDescription(tc) + `union ` + tc.getTypeName() + possibleTypes; }; const printEnumType = (tc) => { const values = Object.entries(tc.getFields()).map(([name, valueTC], i) => printDescription(valueTC, ` `, !i) + ` ` + name + printDeprecated(valueTC)); return printDescription(tc) + `enum ${tc.getTypeName()}` + printBlock(values); }; const printInputObjectType = (tc) => { const fields = Object.entries(tc.getFields()).map(([fieldName, fieldTC], i) => printDescription(fieldTC, ` `, !i) + ` ` + printInputValue([fieldName, fieldTC])); return (printDescription(tc) + `input ${tc.getTypeName()}` + printBlock(fields)); }; const printType = (tc) => { if (tc instanceof graphql_compose_1.ObjectTypeComposer) { return printObjectType(tc); } else if (tc instanceof graphql_compose_1.InterfaceTypeComposer) { return printInterfaceType(tc); } else if (tc instanceof graphql_compose_1.UnionTypeComposer) { return printUnionType(tc); } else if (tc instanceof graphql_compose_1.EnumTypeComposer) { return printEnumType(tc); } else if (tc instanceof graphql_compose_1.ScalarTypeComposer) { return printScalarType(tc); } else if (tc instanceof graphql_compose_1.InputTypeComposer) { return printInputObjectType(tc); } return ``; }; const printTypeDefinitions = ({ config, schemaComposer, }) => { if (!config) return Promise.resolve(); const { path, include, exclude, withFieldTypes, rewrite = false, } = config || {}; if (!path) { reporter_1.default.error(`Printing type definitions aborted. Please provide a file path.`); return Promise.resolve(); } if (!rewrite && fs.existsSync(path)) { reporter_1.default.error(`Printing type definitions aborted. The file \`${path}\` already exists.`); return Promise.resolve(); } const internalPlugins = [`internal-data-bridge`]; const typesToExclude = exclude?.types || []; const pluginsToExclude = exclude?.plugins || []; const getName = (tc) => tc.getTypeName(); const isInternalType = (tc) => { const typeName = getName(tc); if (built_in_types_1.internalTypeNames.includes(typeName)) { return true; } const plugin = tc.getExtension(`plugin`); if (typeof plugin === `string` && internalPlugins.includes(plugin)) { return true; } return false; }; const shouldIncludeType = (tc) => { const typeName = getName(tc); if (typesToExclude.includes(typeName)) { return false; } if (include?.types && !include.types.includes(typeName)) { return false; } const plugin = tc.getExtension(`plugin`); if (typeof plugin === `string` && pluginsToExclude.includes(plugin)) { return false; } if (include?.plugins && (!plugin || (typeof plugin === `string` && !include.plugins.includes(plugin)))) { return false; } return true; }; // Save processed type names, not references to the type composers, // because of how graphql-compose, at least in v6, processes // inline types const processedTypes = new Set(); const typeDefs = new Set(); const addType = (tc) => { const typeName = getName(tc); if (!processedTypes.has(typeName) && !isInternalType(tc)) { processedTypes.add(typeName); return typeDefs.add(tc); } processedTypes.add(typeName); return null; }; const addWithFieldTypes = (tc) => { if (addType(tc) && (tc instanceof graphql_compose_1.ObjectTypeComposer || tc instanceof graphql_compose_1.InterfaceTypeComposer || tc instanceof graphql_compose_1.InputTypeComposer)) { if (tc instanceof graphql_compose_1.ObjectTypeComposer) { const interfaces = tc.getInterfaces(); interfaces.forEach((iface) => { const ifaceName = iface.getTypeName(); if (ifaceName !== `Node`) { addWithFieldTypes(schemaComposer.getAnyTC(ifaceName)); } }); } tc.getFieldNames().forEach((fieldName) => { const fieldType = tc.getFieldTC(fieldName); addWithFieldTypes(fieldType); if (!(tc instanceof graphql_compose_1.InputTypeComposer)) { const fieldArgs = tc.getFieldArgs(fieldName); Object.keys(fieldArgs).forEach((argName) => { try { addWithFieldTypes(tc.getFieldArgTC(fieldName, argName)); } catch { // this type might not exist yet. If it won't be created by the end // of schema creation then building schema will fail and fact that we // skip it here won't matter } }); } }); } }; schemaComposer.forEach((tc) => { if (!isInternalType(tc) && shouldIncludeType(tc)) { if (withFieldTypes) { addWithFieldTypes(tc); } else { addType(tc); } } }); const printedTypeDefs = [ `### Type definitions saved at ${new Date().toISOString()} ###`, ]; try { typeDefs.forEach((tc) => printedTypeDefs.push(printType(tc))); reporter_1.default.info(`Writing GraphQL type definitions to ${path}`); return fs.writeFile(path, printedTypeDefs.join(`\n\n`)); } catch (error) { reporter_1.default.error(`Failed writing type definitions to \`${path}\`.`, error); return Promise.resolve(); } }; exports.printTypeDefinitions = printTypeDefinitions; //# sourceMappingURL=print.js.map