apollo-codegen-core
Version:
Core generator APIs for Apollo Codegen
200 lines (199 loc) • 7.77 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.combineOperationsAndFragments = exports.extractOperationsAndFragments = exports.loadAndMergeQueryDocuments = exports.loadQueryDocuments = exports.extractDocumentFromJavascript = exports.loadSchema = void 0;
require("apollo-env");
const localfs_1 = require("./localfs");
const common_tags_1 = require("common-tags");
const astTypes = require("ast-types");
const recast = require("recast");
const graphql_1 = require("graphql");
const apollo_language_server_1 = require("apollo-language-server");
function loadSchema(schemaPath) {
if (!localfs_1.fs.existsSync(schemaPath)) {
throw new apollo_language_server_1.ToolError(`Cannot find GraphQL schema file: ${schemaPath}`);
}
const schemaData = require(schemaPath);
if (!schemaData.data && !schemaData.__schema) {
throw new apollo_language_server_1.ToolError("GraphQL schema file should contain a valid GraphQL introspection query result");
}
return (0, graphql_1.buildClientSchema)(schemaData.data ? schemaData.data : schemaData);
}
exports.loadSchema = loadSchema;
function maybeCommentedOut(content) {
return ((content.indexOf("/*") > -1 && content.indexOf("*/") > -1) ||
content.split("//").length > 1);
}
function filterValidDocuments(documents) {
return documents.filter((document) => {
const source = new graphql_1.Source(document);
try {
(0, graphql_1.parse)(source);
return true;
}
catch (e) {
if (!maybeCommentedOut(document)) {
console.warn((0, common_tags_1.stripIndents) `
Failed to parse:
${document.trim().split("\n")[0]}...
`);
}
return false;
}
});
}
function extractDocumentsWithAST(content, options) {
let tagName = options.tagName || "gql";
const ast = recast.parse(content, {
parser: options.parser || require("recast/parsers/babylon"),
});
const finished = [];
astTypes.visit(ast, {
visitTaggedTemplateExpression(path) {
const tag = path.value.tag;
if (tag.name === tagName) {
finished.push(path.value.quasi.quasis
.map(({ value }) => value.cooked)
.join(""));
}
return this.traverse(path);
},
});
return finished;
}
function extractDocumentFromJavascript(content, options = {}) {
let matches = [];
try {
matches = extractDocumentsWithAST(content, options);
}
catch (e) {
e.message =
"Operation extraction " +
(options.inputPath ? "from file " + options.inputPath + " " : "") +
"failed with \n" +
e.message;
throw e;
}
matches = filterValidDocuments(matches);
const doc = matches.join("\n");
return doc.length ? doc : null;
}
exports.extractDocumentFromJavascript = extractDocumentFromJavascript;
function loadQueryDocuments(inputPaths, tagName = "gql") {
const sources = inputPaths
.map((inputPath) => {
if (localfs_1.fs.lstatSync(inputPath).isDirectory()) {
return null;
}
const body = localfs_1.fs.readFileSync(inputPath, "utf8");
if (!body) {
return null;
}
if (inputPath.endsWith(".jsx") ||
inputPath.endsWith(".js") ||
inputPath.endsWith(".tsx") ||
inputPath.endsWith(".ts")) {
let parser;
if (inputPath.endsWith(".ts")) {
parser = require("recast/parsers/typescript");
}
else if (inputPath.endsWith(".tsx")) {
parser = {
parse: (source, options) => {
const babelParser = require("@babel/parser");
options = require("recast/parsers/_babylon_options.js")(options);
options.plugins.push("jsx", "typescript");
return babelParser.parse(source, options);
},
};
}
else {
parser = require("recast/parsers/babylon");
}
const doc = extractDocumentFromJavascript(body.toString(), {
tagName,
parser,
inputPath,
});
return doc ? new graphql_1.Source(doc, inputPath) : null;
}
if (inputPath.endsWith(".graphql") ||
inputPath.endsWith(".graphqls") ||
inputPath.endsWith(".gql")) {
return new graphql_1.Source(body, inputPath);
}
return null;
})
.filter((source) => source)
.map((source) => {
try {
return (0, graphql_1.parse)(source);
}
catch (e) {
const name = (source && source.name) || "";
console.warn((0, common_tags_1.stripIndents) `
Warning: error parsing GraphQL file ${name}
${e.stack}`);
return null;
}
})
.filter((source) => source);
return sources;
}
exports.loadQueryDocuments = loadQueryDocuments;
function loadAndMergeQueryDocuments(inputPaths, tagName = "gql") {
return (0, graphql_1.concatAST)(loadQueryDocuments(inputPaths, tagName));
}
exports.loadAndMergeQueryDocuments = loadAndMergeQueryDocuments;
function extractOperationsAndFragments(documents, errorLogger) {
const fragments = {};
const operations = [];
documents.forEach((operation) => {
(0, graphql_1.visit)(operation, {
[graphql_1.Kind.FRAGMENT_DEFINITION]: (node) => {
if (!node.name || node.name.kind !== "Name") {
(errorLogger || console.warn)(`Fragment Definition must have a name ${node}`);
}
if (fragments[node.name.value]) {
(errorLogger || console.warn)(`Duplicate definition of fragment ${node.name.value}. Please rename one of them or use the same fragment`);
}
fragments[node.name.value] = node;
},
[graphql_1.Kind.OPERATION_DEFINITION]: (node) => {
operations.push(node);
},
});
});
return { fragments, operations };
}
exports.extractOperationsAndFragments = extractOperationsAndFragments;
function combineOperationsAndFragments(operations, fragments, errorLogger) {
const fullOperations = [];
operations.forEach((operation) => {
const completeOperation = [
operation,
...Object.values(getNestedFragments(operation, fragments, errorLogger)),
];
fullOperations.push({
kind: "Document",
definitions: completeOperation,
});
});
return fullOperations;
}
exports.combineOperationsAndFragments = combineOperationsAndFragments;
function getNestedFragments(operation, fragments, errorLogger) {
const combination = {};
(0, graphql_1.visit)(operation, {
[graphql_1.Kind.FRAGMENT_SPREAD]: (node) => {
if (!node.name || node.name.kind !== "Name") {
(errorLogger || console.warn)(`Fragment Spread must have a name ${node}`);
}
if (!fragments[node.name.value]) {
(errorLogger || console.warn)(`Fragment ${node.name.value} is not defined. Please add the file containing the fragment to the set of included paths`);
}
Object.assign(combination, getNestedFragments(fragments[node.name.value], fragments, errorLogger), { [node.name.value]: fragments[node.name.value] });
},
});
return combination;
}
//# sourceMappingURL=loading.js.map
;