216 lines
5.8 KiB
JavaScript
216 lines
5.8 KiB
JavaScript
"use strict";
|
|
|
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
|
|
exports.__esModule = true;
|
|
exports.multipleRootQueriesError = multipleRootQueriesError;
|
|
exports.graphqlValidationError = graphqlValidationError;
|
|
exports.graphqlError = graphqlError;
|
|
|
|
var _graphql = require("graphql");
|
|
|
|
var _codeFrame = require("@babel/code-frame");
|
|
|
|
var _lodash = _interopRequireDefault(require("lodash"));
|
|
|
|
var _reporter = _interopRequireDefault(require("gatsby-cli/lib/reporter"));
|
|
|
|
// These handle specific errors throw by RelayParser. If an error matches
|
|
// you get a pointer to the location in the query that is broken, otherwise
|
|
// we show the error and the query.
|
|
const handlers = [[/Unknown field `(.+)` on type `(.+)`/i, ([name], node) => {
|
|
if (node.kind === `Field` && node.name.value === name) {
|
|
return node.name.loc;
|
|
}
|
|
|
|
return null;
|
|
}], [/Unknown argument `(.+)`/i, ([name], node) => {
|
|
if (node.kind === `Argument` && node.name.value === name) {
|
|
return node.name.loc;
|
|
}
|
|
|
|
return null;
|
|
}], [/Unknown directive `@(.+)`/i, ([name], node) => {
|
|
if (node.kind === `Directive` && node.name.value === name) {
|
|
return node.name.loc;
|
|
}
|
|
|
|
return null;
|
|
}]];
|
|
|
|
function formatFilePath(filePath) {
|
|
return `${_reporter.default.format.bold(`file:`)} ${_reporter.default.format.blue(filePath)}`;
|
|
}
|
|
|
|
function formatError(message, filePath, codeFrame) {
|
|
return _reporter.default.stripIndent`
|
|
${message}
|
|
|
|
${formatFilePath(filePath)}
|
|
` + `\n\n${codeFrame}\n`;
|
|
}
|
|
|
|
function extractError(error) {
|
|
const docRegex = /Error:[\0-\uFFFF](RelayParser|GraphQLParser):([\0-\uFFFF]*)Source: document[\0-\uFFFF]`([\0-\uFFFF]*)`[\0-\uFFFF]file[\0-\uFFFF]*(GraphQL[\0-\uFFFF]request[\0-\uFFFF]*^[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]*$)/gm;
|
|
let matches;
|
|
let message = ``;
|
|
let docName = ``;
|
|
let codeBlock = ``;
|
|
|
|
while ((matches = docRegex.exec(error.toString())) !== null) {
|
|
// This is necessary to avoid infinite loops with zero-width matches
|
|
if (matches.index === docRegex.lastIndex) docRegex.lastIndex++;
|
|
[,, message, docName, codeBlock] = matches;
|
|
}
|
|
|
|
if (!message) {
|
|
message = error.toString();
|
|
}
|
|
|
|
message = message.trim();
|
|
return {
|
|
message,
|
|
codeBlock,
|
|
docName
|
|
};
|
|
}
|
|
|
|
function findLocation(extractedMessage, def) {
|
|
let location = null;
|
|
(0, _graphql.visit)(def, {
|
|
enter(node) {
|
|
if (location) return;
|
|
|
|
for (let [regex, handler] of handlers) {
|
|
let match = extractedMessage.match(regex);
|
|
if (!match) continue;
|
|
if (location = handler(match.slice(1), node)) break;
|
|
}
|
|
}
|
|
|
|
});
|
|
return location;
|
|
}
|
|
|
|
function getCodeFrame(query, line, column) {
|
|
return (0, _codeFrame.codeFrameColumns)(query, {
|
|
start: {
|
|
line,
|
|
column
|
|
}
|
|
}, {
|
|
linesAbove: 10,
|
|
linesBelow: 10
|
|
});
|
|
}
|
|
|
|
function getCodeFrameFromRelayError(def, extractedMessage, error) {
|
|
let {
|
|
start,
|
|
source
|
|
} = findLocation(extractedMessage, def) || {};
|
|
let query = source ? source.body : (0, _graphql.print)(def); // we can't reliably get a location without the location source, since
|
|
// the printed query may differ from the original.
|
|
|
|
let {
|
|
line,
|
|
column
|
|
} = source && (0, _graphql.getLocation)(source, start) || {};
|
|
return getCodeFrame(query, line, column);
|
|
}
|
|
|
|
function multipleRootQueriesError(filePath, def, otherDef) {
|
|
let name = def.name.value;
|
|
let otherName = otherDef.name.value;
|
|
let unifiedName = `${_lodash.default.camelCase(name)}And${_lodash.default.upperFirst(_lodash.default.camelCase(otherName))}`;
|
|
return formatError(`Multiple "root" queries found in file: "${name}" and "${otherName}". ` + `Only the first ("${otherName}") will be registered.`, filePath, ` ${_reporter.default.format.yellow(`Instead of:`)} \n\n` + (0, _codeFrame.codeFrameColumns)(_reporter.default.stripIndent`
|
|
query ${otherName} {
|
|
bar {
|
|
#...
|
|
}
|
|
}
|
|
|
|
query ${name} {
|
|
foo {
|
|
#...
|
|
}
|
|
}
|
|
`, {
|
|
start: {
|
|
column: 0,
|
|
line: 0
|
|
}
|
|
}, {
|
|
linesBelow: Number.MAX_SAFE_INTEGER
|
|
}) + `\n\n ${_reporter.default.format.green(`Do:`)} \n\n` + (0, _codeFrame.codeFrameColumns)(_reporter.default.stripIndent`
|
|
query ${unifiedName} {
|
|
bar {
|
|
#...
|
|
}
|
|
foo {
|
|
#...
|
|
}
|
|
}
|
|
`, {
|
|
start: {
|
|
column: 0,
|
|
line: 0
|
|
}
|
|
}, {
|
|
linesBelow: Number.MAX_SAFE_INTEGER
|
|
}));
|
|
}
|
|
|
|
function graphqlValidationError(errors, filePath, doc) {
|
|
if (!errors || !errors.length) return ``;
|
|
let error = errors[0];
|
|
let {
|
|
source,
|
|
locations: [{
|
|
line,
|
|
column
|
|
}] = [{}]
|
|
} = error;
|
|
let query = source ? source.body : (0, _graphql.print)(doc);
|
|
return formatError(error.message, filePath, getCodeFrame(query, line, column));
|
|
}
|
|
|
|
function graphqlError(namePathMap, nameDefMap, error) {
|
|
let codeBlock;
|
|
let {
|
|
message,
|
|
docName
|
|
} = extractError(error);
|
|
let filePath = namePathMap.get(docName);
|
|
|
|
if (filePath && docName) {
|
|
codeBlock = getCodeFrameFromRelayError(nameDefMap.get(docName), message, error);
|
|
const formattedMessage = formatError(message, filePath, codeBlock);
|
|
return {
|
|
formattedMessage,
|
|
docName,
|
|
message,
|
|
codeBlock
|
|
};
|
|
}
|
|
|
|
let reportedMessage = `There was an error while compiling your site's GraphQL queries.
|
|
${message || error.message}
|
|
`;
|
|
|
|
if (error.message.match(/must be an instance of/)) {
|
|
reportedMessage += `This usually means that more than one instance of 'graphql' is installed ` + `in your node_modules. Remove all but the top level one or run \`npm dedupe\` to fix it.`;
|
|
}
|
|
|
|
if (error.message.match(/Duplicate document/)) {
|
|
reportedMessage += `${error.message.slice(21)}\n`;
|
|
}
|
|
|
|
return {
|
|
formattedMessage: reportedMessage,
|
|
docName,
|
|
message,
|
|
codeBlock
|
|
};
|
|
}
|
|
//# sourceMappingURL=graphql-errors.js.map
|