Files
30-seconds-of-code/node_modules/@gatsbyjs/relay-compiler/lib/ASTConvert.js
2019-08-20 15:52:05 +02:00

205 lines
5.9 KiB
JavaScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*
* @format
*/
'use strict';
var GraphQLValidator = require("./GraphQLValidator");
var Profiler = require("./GraphQLCompilerProfiler");
var _require = require("./GraphQLSchemaUtils"),
isExecutableDefinitionAST = _require.isExecutableDefinitionAST,
isSchemaDefinitionAST = _require.isSchemaDefinitionAST;
var _require2 = require("graphql"),
extendSchema = _require2.extendSchema,
parse = _require2.parse,
print = _require2.print,
visit = _require2.visit;
function convertASTDocuments(schema, documents, validationRules, transform) {
return Profiler.run('ASTConvert.convertASTDocuments', function () {
var definitions = definitionsFromDocuments(documents);
var astDefinitions = [];
documents.forEach(function (doc) {
doc.definitions.forEach(function (definition) {
if (isExecutableDefinitionAST(definition)) {
astDefinitions.push(definition);
}
});
});
return convertASTDefinitions(schema, definitions, validationRules, transform);
});
}
function convertASTDocumentsWithBase(schema, baseDocuments, documents, validationRules, transform) {
return Profiler.run('ASTConvert.convertASTDocumentsWithBase', function () {
var baseDefinitions = definitionsFromDocuments(baseDocuments);
var definitions = definitionsFromDocuments(documents);
var requiredDefinitions = new Map();
var baseMap = new Map();
baseDefinitions.forEach(function (definition) {
if (isExecutableDefinitionAST(definition)) {
var definitionName = definition.name && definition.name.value; // If there's no name, no reason to put in the map
if (definitionName) {
if (baseMap.has(definitionName)) {
throw new Error("Duplicate definition of '".concat(definitionName, "'."));
}
baseMap.set(definitionName, definition);
}
}
});
var definitionsToVisit = [];
definitions.forEach(function (definition) {
if (isExecutableDefinitionAST(definition)) {
definitionsToVisit.push(definition);
}
});
while (definitionsToVisit.length > 0) {
var definition = definitionsToVisit.pop();
var name = definition.name && definition.name.value;
if (!name) {
continue;
}
if (requiredDefinitions.has(name)) {
if (requiredDefinitions.get(name) !== definition) {
throw new Error("Duplicate definition of '".concat(name, "'."));
}
continue;
}
requiredDefinitions.set(name, definition);
visit(definition, {
FragmentSpread: function FragmentSpread(spread) {
var baseDefinition = baseMap.get(spread.name.value);
if (baseDefinition) {
// We only need to add those definitions not already included
// in definitions
definitionsToVisit.push(baseDefinition);
}
}
});
}
var definitionsToConvert = [];
requiredDefinitions.forEach(function (definition) {
return definitionsToConvert.push(definition);
});
return convertASTDefinitions(schema, definitionsToConvert, validationRules, transform);
});
}
function convertASTDefinitions(schema, definitions, validationRules, transform) {
var operationDefinitions = [];
definitions.forEach(function (definition) {
if (isExecutableDefinitionAST(definition)) {
operationDefinitions.push(definition);
}
});
var validationAST = {
kind: 'Document',
definitions: operationDefinitions
}; // Will throw an error if there are validation issues
GraphQLValidator.validate(validationAST, schema, validationRules);
return transform(schema, operationDefinitions);
}
function definitionsFromDocuments(documents) {
var definitions = [];
documents.forEach(function (doc) {
doc.definitions.forEach(function (definition) {
return definitions.push(definition);
});
});
return definitions;
}
/**
* Extends a GraphQLSchema with a list of schema extensions in string form.
*/
function transformASTSchema(schema, schemaExtensions) {
return Profiler.run('ASTConvert.transformASTSchema', function () {
if (schemaExtensions.length === 0) {
return schema;
}
var extension = schemaExtensions.join('\n');
return cachedExtend(schema, extension, function () {
return extendSchema(schema, parse(extension));
});
});
}
/**
* Extends a GraphQLSchema with a list of schema extensions in AST form.
*/
function extendASTSchema(baseSchema, documents) {
return Profiler.run('ASTConvert.extendASTSchema', function () {
var schemaExtensions = [];
documents.forEach(function (doc) {
doc.definitions.forEach(function (definition) {
if (isSchemaDefinitionAST(definition)) {
schemaExtensions.push(definition);
}
});
});
if (schemaExtensions.length === 0) {
return baseSchema;
}
var key = schemaExtensions.map(print).join('\n');
return cachedExtend(baseSchema, key, function () {
return extendSchema(baseSchema, {
kind: 'Document',
definitions: schemaExtensions
}, // TODO T24511737 figure out if this is dangerous
{
assumeValid: true
});
});
});
}
var extendedSchemas = new Map();
function cachedExtend(schema, key, compute) {
var cache = extendedSchemas.get(schema);
if (!cache) {
cache = {};
extendedSchemas.set(schema, cache);
}
var extendedSchema = cache[key];
if (!extendedSchema) {
extendedSchema = compute();
cache[key] = extendedSchema;
}
return extendedSchema;
}
module.exports = {
convertASTDocuments: convertASTDocuments,
convertASTDocumentsWithBase: convertASTDocumentsWithBase,
extendASTSchema: extendASTSchema,
transformASTSchema: transformASTSchema
};