You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
88 lines
2.7 KiB
88 lines
2.7 KiB
'use strict'; |
|
|
|
Object.defineProperty(exports, '__esModule', { |
|
value: true, |
|
}); |
|
exports.separateOperations = separateOperations; |
|
|
|
var _kinds = require('../language/kinds.js'); |
|
|
|
var _visitor = require('../language/visitor.js'); |
|
|
|
/** |
|
* separateOperations accepts a single AST document which may contain many |
|
* operations and fragments and returns a collection of AST documents each of |
|
* which contains a single operation as well the fragment definitions it |
|
* refers to. |
|
*/ |
|
function separateOperations(documentAST) { |
|
const operations = []; |
|
const depGraph = Object.create(null); // Populate metadata and build a dependency graph. |
|
|
|
for (const definitionNode of documentAST.definitions) { |
|
switch (definitionNode.kind) { |
|
case _kinds.Kind.OPERATION_DEFINITION: |
|
operations.push(definitionNode); |
|
break; |
|
|
|
case _kinds.Kind.FRAGMENT_DEFINITION: |
|
depGraph[definitionNode.name.value] = collectDependencies( |
|
definitionNode.selectionSet, |
|
); |
|
break; |
|
|
|
default: // ignore non-executable definitions |
|
} |
|
} // For each operation, produce a new synthesized AST which includes only what |
|
// is necessary for completing that operation. |
|
|
|
const separatedDocumentASTs = Object.create(null); |
|
|
|
for (const operation of operations) { |
|
const dependencies = new Set(); |
|
|
|
for (const fragmentName of collectDependencies(operation.selectionSet)) { |
|
collectTransitiveDependencies(dependencies, depGraph, fragmentName); |
|
} // Provides the empty string for anonymous operations. |
|
|
|
const operationName = operation.name ? operation.name.value : ''; // The list of definition nodes to be included for this operation, sorted |
|
// to retain the same order as the original document. |
|
|
|
separatedDocumentASTs[operationName] = { |
|
kind: _kinds.Kind.DOCUMENT, |
|
definitions: documentAST.definitions.filter( |
|
(node) => |
|
node === operation || |
|
(node.kind === _kinds.Kind.FRAGMENT_DEFINITION && |
|
dependencies.has(node.name.value)), |
|
), |
|
}; |
|
} |
|
|
|
return separatedDocumentASTs; |
|
} |
|
|
|
// From a dependency graph, collects a list of transitive dependencies by |
|
// recursing through a dependency graph. |
|
function collectTransitiveDependencies(collected, depGraph, fromName) { |
|
if (!collected.has(fromName)) { |
|
collected.add(fromName); |
|
const immediateDeps = depGraph[fromName]; |
|
|
|
if (immediateDeps !== undefined) { |
|
for (const toName of immediateDeps) { |
|
collectTransitiveDependencies(collected, depGraph, toName); |
|
} |
|
} |
|
} |
|
} |
|
|
|
function collectDependencies(selectionSet) { |
|
const dependencies = []; |
|
(0, _visitor.visit)(selectionSet, { |
|
FragmentSpread(node) { |
|
dependencies.push(node.name.value); |
|
}, |
|
}); |
|
return dependencies; |
|
}
|
|
|