Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* rewrite attachDirectiveResolvers to be immutable * add mapping by arguments * add schema transforms schema transform functions take a schema as an argument and return a schema, possibly modifying it a schema transform function can be templated, i.e. one can create a function that takes certain arguments, such as the names of directives that annotate fields of interest, and return a schema transform function that modifies the schema based on the specified annotating directives this allows one to reuse a schema transform function across projects, allowing for the customization of the schema transform function on a per use basis schema transform functionc can be called directly on a schema to modify it before use -- makeExecutableSchema can now also be passed an array of schema transform functions, with makeExecutableSchema responsible for performing all schema transformations prior to returning. Eventually, all schema visitor examples can be rewritten using the schema transform functional API addresses #1234 * add generic field mapper to SchemaMapper to allow indiscriminate mapping of all fields and input fields * add enum directive extraction and value mapping * add tests demonstrating templated schema transforms * update docs for schemaTransforms include deprecated example in tests reorder some types
- Loading branch information
Showing
15 changed files
with
2,727 additions
and
553 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,111 @@ | ||
import { getDirectiveValues, GraphQLDirective, GraphQLSchema } from 'graphql'; | ||
import { | ||
GraphQLDirective, | ||
GraphQLSchema, | ||
SchemaDefinitionNode, | ||
TypeDefinitionNode, | ||
SchemaExtensionNode, | ||
TypeExtensionNode, | ||
GraphQLNamedType, | ||
GraphQLField, | ||
GraphQLInputField, | ||
FieldDefinitionNode, | ||
InputValueDefinitionNode, | ||
GraphQLFieldConfig, | ||
GraphQLInputFieldConfig, | ||
GraphQLSchemaConfig, | ||
GraphQLObjectTypeConfig, | ||
GraphQLInterfaceTypeConfig, | ||
GraphQLUnionTypeConfig, | ||
GraphQLScalarTypeConfig, | ||
GraphQLEnumTypeConfig, | ||
GraphQLInputObjectTypeConfig, | ||
GraphQLEnumValue, | ||
GraphQLEnumValueConfig, | ||
EnumValueDefinitionNode, | ||
} from 'graphql'; | ||
|
||
import { getArgumentValues } from './getArgumentValues'; | ||
|
||
export type DirectiveUseMap = { [key: string]: any }; | ||
|
||
export function getDirectives(schema: GraphQLSchema, node: any): DirectiveUseMap { | ||
type SchemaOrTypeNode = | ||
| SchemaDefinitionNode | ||
| SchemaExtensionNode | ||
| TypeDefinitionNode | ||
| TypeExtensionNode | ||
| EnumValueDefinitionNode | ||
| FieldDefinitionNode | ||
| InputValueDefinitionNode; | ||
|
||
type DirectableGraphQLObject = | ||
| GraphQLSchema | ||
| GraphQLSchemaConfig | ||
| GraphQLNamedType | ||
| GraphQLObjectTypeConfig<any, any> | ||
| GraphQLInterfaceTypeConfig<any, any> | ||
| GraphQLUnionTypeConfig<any, any> | ||
| GraphQLScalarTypeConfig<any, any> | ||
| GraphQLEnumTypeConfig | ||
| GraphQLEnumValue | ||
| GraphQLEnumValueConfig | ||
| GraphQLInputObjectTypeConfig | ||
| GraphQLField<any, any> | ||
| GraphQLInputField | ||
| GraphQLFieldConfig<any, any> | ||
| GraphQLInputFieldConfig; | ||
|
||
export function getDirectives(schema: GraphQLSchema, node: DirectableGraphQLObject): DirectiveUseMap { | ||
const schemaDirectives: ReadonlyArray<GraphQLDirective> = | ||
schema && schema.getDirectives ? schema.getDirectives() : []; | ||
const astNode = node && node.astNode; | ||
|
||
const schemaDirectiveMap = schemaDirectives.reduce((schemaDirectiveMap, schemaDirective) => { | ||
schemaDirectiveMap[schemaDirective.name] = schemaDirective; | ||
return schemaDirectiveMap; | ||
}, {}); | ||
|
||
let astNodes: Array<SchemaOrTypeNode> = []; | ||
if (node.astNode) { | ||
astNodes.push(node.astNode); | ||
} | ||
if ('extensionASTNodes' in node && node.extensionASTNodes) { | ||
astNodes = [...astNodes, ...node.extensionASTNodes]; | ||
} | ||
|
||
const result: DirectiveUseMap = {}; | ||
|
||
if (astNode) { | ||
schemaDirectives.forEach((directive: GraphQLDirective) => { | ||
const directiveValue = getDirectiveValues(directive, astNode); | ||
astNodes.forEach(astNode => { | ||
astNode.directives.forEach(directive => { | ||
const schemaDirective = schemaDirectiveMap[directive.name.value]; | ||
if (schemaDirective) { | ||
const directiveValue = getDirectiveValues(schemaDirective, astNode); | ||
|
||
if (directiveValue !== undefined) { | ||
result[directive.name] = directiveValue || {}; | ||
if (schemaDirective.isRepeatable) { | ||
if (result[schemaDirective.name]) { | ||
result[schemaDirective.name] = result[schemaDirective.name].concat([directiveValue]); | ||
} else { | ||
result[schemaDirective.name] = [directiveValue]; | ||
} | ||
} else { | ||
result[schemaDirective.name] = directiveValue; | ||
} | ||
} | ||
}); | ||
} | ||
}); | ||
|
||
return result; | ||
} | ||
|
||
// graphql-js getDirectiveValues does not handle repeatable directives | ||
function getDirectiveValues(directiveDef: GraphQLDirective, node: SchemaOrTypeNode): any { | ||
if (node.directives) { | ||
if (directiveDef.isRepeatable) { | ||
const directiveNodes = node.directives.filter(directive => directive.name.value === directiveDef.name); | ||
|
||
return directiveNodes.map(directiveNode => getArgumentValues(directiveDef, directiveNode)); | ||
} | ||
|
||
const directiveNode = node.directives.find(directive => directive.name.value === directiveDef.name); | ||
|
||
return getArgumentValues(directiveDef, directiveNode); | ||
} | ||
} |
Oops, something went wrong.