@netlify/content-engine
Version:
342 lines • 13.8 kB
JavaScript
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
;