Skip to content

Commit

Permalink
refactor to rely on mapSchema (#1767)
Browse files Browse the repository at this point in the history
= TransformCompositeFields and TransformInputObjectFields can use mapSchema via MapperKind.COMPOSITE_FIELD and MapperKind.INPUT_OBJECT_FIELD.

= field utility functions can use rebuildAstNode and rebuildExtensionAstNodes from mapSchema
  • Loading branch information
yaacovCR committed Jul 14, 2020
1 parent 63644bd commit 3b5fef8
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 267 deletions.
51 changes: 2 additions & 49 deletions packages/utils/src/fields.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import {
GraphQLFieldConfigMap,
GraphQLObjectType,
GraphQLFieldConfig,
GraphQLSchema,
ObjectTypeDefinitionNode,
ObjectTypeExtensionNode,
FieldDefinitionNode,
} from 'graphql';
import { GraphQLFieldConfigMap, GraphQLObjectType, GraphQLFieldConfig, GraphQLSchema } from 'graphql';
import { MapperKind } from './Interfaces';
import { mapSchema } from './mapSchema';
import { mapSchema, rebuildAstNode, rebuildExtensionAstNodes } from './mapSchema';
import { addTypes } from './addTypes';

export function appendObjectFields(
Expand Down Expand Up @@ -152,42 +144,3 @@ export function modifyObjectFields(

return [newSchema, removedFields];
}

function rebuildAstNode(
astNode: ObjectTypeDefinitionNode,
fieldConfigMap: Record<string, GraphQLFieldConfig<any, any>>
): ObjectTypeDefinitionNode {
if (astNode == null) {
return undefined;
}

const newAstNode: ObjectTypeDefinitionNode = {
...astNode,
fields: undefined,
};

const fields: Array<FieldDefinitionNode> = [];
Object.values(fieldConfigMap).forEach(fieldConfig => {
if (fieldConfig.astNode != null) {
fields.push(fieldConfig.astNode);
}
});

return {
...newAstNode,
fields,
};
}

function rebuildExtensionAstNodes(
extensionASTNodes: ReadonlyArray<ObjectTypeExtensionNode>
): Array<ObjectTypeExtensionNode> {
if (!extensionASTNodes?.length) {
return [];
}

return extensionASTNodes.map(node => ({
...node,
fields: undefined,
}));
}
4 changes: 2 additions & 2 deletions packages/utils/src/mapSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ function getEnumValueMapper(schemaMapper: SchemaMapper): EnumValueMapper | null
return enumValueMapper != null ? enumValueMapper : null;
}

function rebuildAstNode<
export function rebuildAstNode<
TypeDefinitionNode extends ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode | InputObjectTypeDefinitionNode
>(
astNode: TypeDefinitionNode,
Expand Down Expand Up @@ -530,7 +530,7 @@ function rebuildAstNode<
};
}

function rebuildExtensionAstNodes<
export function rebuildExtensionAstNodes<
TypeExtensionNode extends ObjectTypeExtensionNode | InterfaceTypeExtensionNode | InputObjectTypeExtensionNode
>(extensionASTNodes: ReadonlyArray<TypeExtensionNode>): Array<TypeExtensionNode> {
if (!extensionASTNodes?.length) {
Expand Down
132 changes: 14 additions & 118 deletions packages/wrap/src/transforms/TransformCompositeFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,6 @@ import {
SelectionSetNode,
SelectionNode,
FragmentDefinitionNode,
GraphQLInterfaceType,
isObjectType,
isInterfaceType,
GraphQLObjectType,
GraphQLFieldConfig,
FieldDefinitionNode,
ObjectTypeDefinitionNode,
InterfaceTypeDefinitionNode,
ObjectTypeExtensionNode,
InterfaceTypeExtensionNode,
} from 'graphql';

import { Transform, Request, MapperKind, mapSchema, visitData, ExecutionResult } from '@graphql-tools/utils';
Expand Down Expand Up @@ -48,8 +38,20 @@ export default class TransformCompositeFields implements Transform {

public transformSchema(originalSchema: GraphQLSchema): GraphQLSchema {
this.transformedSchema = mapSchema(originalSchema, {
[MapperKind.OBJECT_TYPE]: (type: GraphQLObjectType) => this.transformFields(type, this.fieldTransformer),
[MapperKind.INTERFACE_TYPE]: (type: GraphQLInterfaceType) => this.transformFields(type, this.fieldTransformer),
[MapperKind.COMPOSITE_FIELD]: (fieldConfig, fieldName, typeName) => {
const transformedField = this.fieldTransformer(typeName, fieldName, fieldConfig);
if (Array.isArray(transformedField)) {
const newFieldName = transformedField[0];

if (newFieldName !== fieldName) {
if (!(typeName in this.mapping)) {
this.mapping[typeName] = {};
}
this.mapping[typeName][newFieldName] = fieldName;
}
}
return transformedField;
},
});
this.typeInfo = new TypeInfo(this.transformedSchema);

Expand Down Expand Up @@ -88,73 +90,6 @@ export default class TransformCompositeFields implements Transform {
return result;
}

private transformFields(type: GraphQLObjectType, fieldTransformer: FieldTransformer): GraphQLObjectType;

private transformFields(type: GraphQLInterfaceType, fieldTransformer: FieldTransformer): GraphQLInterfaceType;

private transformFields(type: GraphQLObjectType | GraphQLInterfaceType, fieldTransformer: FieldTransformer): any {
const config = type.toConfig();

const originalFieldConfigMap = config.fields;
const newFieldConfigMap = {};

Object.keys(originalFieldConfigMap).forEach(fieldName => {
const originalfieldConfig = originalFieldConfigMap[fieldName];
const transformedField = fieldTransformer(type.name, fieldName, originalfieldConfig);

if (transformedField === undefined) {
newFieldConfigMap[fieldName] = originalfieldConfig;
} else if (Array.isArray(transformedField)) {
const newFieldName = transformedField[0];
const newFieldConfig = transformedField[1];

if (newFieldName !== fieldName) {
const typeName = type.name;
if (!(typeName in this.mapping)) {
this.mapping[typeName] = {};
}
this.mapping[typeName][newFieldName] = fieldName;

if (newFieldConfig.astNode != null) {
newFieldConfig.astNode = {
...newFieldConfig.astNode,
name: {
...newFieldConfig.astNode.name,
value: newFieldName,
},
};
}
}

newFieldConfigMap[newFieldName] = newFieldConfig;
} else if (transformedField != null) {
newFieldConfigMap[fieldName] = transformedField;
}
});

if (!Object.keys(newFieldConfigMap).length) {
return null;
}

if (isObjectType(type)) {
const oldConfig = type.toConfig();
return new GraphQLObjectType({
...oldConfig,
fields: newFieldConfigMap,
astNode: rebuildAstNode(oldConfig.astNode, newFieldConfigMap),
extensionASTNodes: rebuildExtensionAstNodes(oldConfig.extensionASTNodes),
});
} else if (isInterfaceType(type)) {
const oldConfig = type.toConfig();
return new GraphQLInterfaceType({
...type.toConfig(),
fields: newFieldConfigMap,
astNode: rebuildAstNode(oldConfig.astNode, newFieldConfigMap),
extensionASTNodes: rebuildExtensionAstNodes(oldConfig.extensionASTNodes),
});
}
}

private transformDocument(
document: DocumentNode,
fragments: Record<string, FragmentDefinitionNode>,
Expand Down Expand Up @@ -258,42 +193,3 @@ export default class TransformCompositeFields implements Transform {
};
}
}

function rebuildAstNode<TypeDefinitionNode extends ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode>(
astNode: TypeDefinitionNode,
fieldConfigMap: Record<string, GraphQLFieldConfig<any, any>>
): TypeDefinitionNode {
if (astNode == null) {
return undefined;
}

const newAstNode: TypeDefinitionNode = {
...astNode,
fields: undefined,
};

const fields: Array<FieldDefinitionNode> = [];
Object.values(fieldConfigMap).forEach(fieldConfig => {
if (fieldConfig.astNode != null) {
fields.push(fieldConfig.astNode);
}
});

return {
...newAstNode,
fields,
};
}

function rebuildExtensionAstNodes<TypeExtensionNode extends ObjectTypeExtensionNode | InterfaceTypeExtensionNode>(
extensionASTNodes: ReadonlyArray<TypeExtensionNode>
): Array<TypeExtensionNode> {
if (!extensionASTNodes?.length) {
return [];
}

return extensionASTNodes.map(node => ({
...node,
fields: undefined,
}));
}
112 changes: 14 additions & 98 deletions packages/wrap/src/transforms/TransformInputObjectFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ import {
GraphQLInputObjectType,
ObjectValueNode,
ObjectFieldNode,
InputObjectTypeDefinitionNode,
InputObjectTypeExtensionNode,
GraphQLInputFieldConfig,
InputValueDefinitionNode,
} from 'graphql';

import { Transform, Request, MapperKind, mapSchema } from '@graphql-tools/utils';
Expand All @@ -40,8 +36,20 @@ export default class TransformInputObjectFields implements Transform {

public transformSchema(originalSchema: GraphQLSchema): GraphQLSchema {
this.transformedSchema = mapSchema(originalSchema, {
[MapperKind.INPUT_OBJECT_TYPE]: (type: GraphQLInputObjectType) =>
this.transformFields(type, this.inputFieldTransformer),
[MapperKind.INPUT_OBJECT_FIELD]: (inputFieldConfig, fieldName, typeName) => {
const transformedInputField = this.inputFieldTransformer(typeName, fieldName, inputFieldConfig);
if (Array.isArray(transformedInputField)) {
const newFieldName = transformedInputField[0];

if (newFieldName !== fieldName) {
if (!(typeName in this.mapping)) {
this.mapping[typeName] = {};
}
this.mapping[typeName][newFieldName] = fieldName;
}
}
return transformedInputField;
},
});

return this.transformedSchema;
Expand Down Expand Up @@ -69,59 +77,6 @@ export default class TransformInputObjectFields implements Transform {
};
}

private transformFields(type: GraphQLInputObjectType, inputFieldTransformer: InputFieldTransformer): any {
const config = type.toConfig();

const originalInputFieldConfigMap = config.fields;
const newInputFieldConfigMap = {};

Object.keys(originalInputFieldConfigMap).forEach(fieldName => {
const originalInputFieldConfig = originalInputFieldConfigMap[fieldName];
const transformedField = inputFieldTransformer(type.name, fieldName, originalInputFieldConfig);

if (transformedField === undefined) {
newInputFieldConfigMap[fieldName] = originalInputFieldConfig;
} else if (Array.isArray(transformedField)) {
const newFieldName = transformedField[0];
const newFieldConfig = transformedField[1];

if (newFieldName !== fieldName) {
const typeName = type.name;
if (!(typeName in this.mapping)) {
this.mapping[typeName] = {};
}
this.mapping[typeName][newFieldName] = fieldName;

if (newFieldConfig.astNode != null) {
newFieldConfig.astNode = {
...newFieldConfig.astNode,
name: {
...newFieldConfig.astNode.name,
value: newFieldName,
},
};
}
}

newInputFieldConfigMap[newFieldName] = newFieldConfig;
} else if (transformedField != null) {
newInputFieldConfigMap[fieldName] = transformedField;
}
});

if (!Object.keys(newInputFieldConfigMap).length) {
return null;
}

const oldConfig = type.toConfig();
return new GraphQLInputObjectType({
...oldConfig,
fields: newInputFieldConfigMap,
astNode: rebuildAstNode(oldConfig.astNode, newInputFieldConfigMap),
extensionASTNodes: rebuildExtensionAstNodes(oldConfig.extensionASTNodes),
});
}

private transformDocument(
document: DocumentNode,
mapping: Record<string, Record<string, string>>,
Expand Down Expand Up @@ -211,42 +166,3 @@ export default class TransformInputObjectFields implements Transform {
return newDocument;
}
}

function rebuildAstNode(
astNode: InputObjectTypeDefinitionNode,
inputFieldConfigMap: Record<string, GraphQLInputFieldConfig>
): InputObjectTypeDefinitionNode {
if (astNode == null) {
return undefined;
}

const newAstNode: InputObjectTypeDefinitionNode = {
...astNode,
fields: undefined,
};

const fields: Array<InputValueDefinitionNode> = [];
Object.values(inputFieldConfigMap).forEach(inputFieldConfig => {
if (inputFieldConfig.astNode != null) {
fields.push(inputFieldConfig.astNode);
}
});

return {
...newAstNode,
fields,
};
}

function rebuildExtensionAstNodes(
extensionASTNodes: ReadonlyArray<InputObjectTypeExtensionNode>
): Array<InputObjectTypeExtensionNode> {
if (!extensionASTNodes?.length) {
return [];
}

return extensionASTNodes.map(node => ({
...node,
fields: undefined,
}));
}

0 comments on commit 3b5fef8

Please sign in to comment.