Skip to content

Commit

Permalink
introduce TransformEnumValues and MapLeafValues (#1769)
Browse files Browse the repository at this point in the history
  • Loading branch information
yaacovCR committed Jul 16, 2020
1 parent 24101f9 commit 1f3b14a
Show file tree
Hide file tree
Showing 8 changed files with 593 additions and 97 deletions.
5 changes: 3 additions & 2 deletions packages/utils/src/Interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -471,9 +471,10 @@ export type ScalarTypeMapper = (type: GraphQLScalarType, schema: GraphQLSchema)
export type EnumTypeMapper = (type: GraphQLEnumType, schema: GraphQLSchema) => GraphQLEnumType | null | undefined;

export type EnumValueMapper = (
value: GraphQLEnumValueConfig,
valueConfig: GraphQLEnumValueConfig,
typeName: string,
schema: GraphQLSchema
schema: GraphQLSchema,
externalValue: string
) => GraphQLEnumValueConfig | [string, GraphQLEnumValueConfig] | null | undefined;

export type CompositeTypeMapper = (
Expand Down
38 changes: 19 additions & 19 deletions packages/utils/src/fields.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GraphQLFieldConfigMap, GraphQLObjectType, GraphQLFieldConfig, GraphQLSchema } from 'graphql';
import { MapperKind } from './Interfaces';
import { mapSchema, rebuildAstNode, rebuildExtensionAstNodes } from './mapSchema';
import { mapSchema, correctASTNodes } from './mapSchema';
import { addTypes } from './addTypes';

export function appendObjectFields(
Expand Down Expand Up @@ -31,12 +31,12 @@ export function appendObjectFields(
newFieldConfigMap[fieldName] = additionalFields[fieldName];
});

return new GraphQLObjectType({
...config,
fields: newFieldConfigMap,
astNode: rebuildAstNode(config.astNode, newFieldConfigMap),
extensionASTNodes: rebuildExtensionAstNodes(config.extensionASTNodes),
});
return correctASTNodes(
new GraphQLObjectType({
...config,
fields: newFieldConfigMap,
})
);
}
},
});
Expand Down Expand Up @@ -64,12 +64,12 @@ export function removeObjectFields(
}
});

return new GraphQLObjectType({
...config,
fields: newFieldConfigMap,
astNode: rebuildAstNode(config.astNode, newFieldConfigMap),
extensionASTNodes: rebuildExtensionAstNodes(config.extensionASTNodes),
});
return correctASTNodes(
new GraphQLObjectType({
...config,
fields: newFieldConfigMap,
})
);
}
},
});
Expand Down Expand Up @@ -132,12 +132,12 @@ export function modifyObjectFields(
newFieldConfigMap[fieldName] = fieldConfig;
});

return new GraphQLObjectType({
...config,
fields: newFieldConfigMap,
astNode: rebuildAstNode(config.astNode, newFieldConfigMap),
extensionASTNodes: rebuildExtensionAstNodes(config.extensionASTNodes),
});
return correctASTNodes(
new GraphQLObjectType({
...config,
fields: newFieldConfigMap,
})
);
}
},
});
Expand Down
211 changes: 135 additions & 76 deletions packages/utils/src/mapSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,10 @@ import {
GraphQLList,
GraphQLNonNull,
GraphQLEnumType,
ObjectTypeDefinitionNode,
InterfaceTypeDefinitionNode,
InputObjectTypeDefinitionNode,
InputObjectTypeExtensionNode,
InterfaceTypeExtensionNode,
ObjectTypeExtensionNode,
InputValueDefinitionNode,
FieldDefinitionNode,
Kind,
EnumValueDefinitionNode,
} from 'graphql';

import {
Expand Down Expand Up @@ -147,22 +143,25 @@ function mapEnumValues(originalTypeMap: TypeMap, schema: GraphQLSchema, schemaMa
const config = type.toConfig();
const originalEnumValueConfigMap = config.values;
const newEnumValueConfigMap = {};
Object.keys(originalEnumValueConfigMap).forEach(enumValueName => {
const originalEnumValueConfig = originalEnumValueConfigMap[enumValueName];
const mappedEnumValue = enumValueMapper(originalEnumValueConfig, type.name, schema);
Object.keys(originalEnumValueConfigMap).forEach(externalValue => {
const originalEnumValueConfig = originalEnumValueConfigMap[externalValue];
const mappedEnumValue = enumValueMapper(originalEnumValueConfig, type.name, schema, externalValue);
if (mappedEnumValue === undefined) {
newEnumValueConfigMap[enumValueName] = originalEnumValueConfig;
newEnumValueConfigMap[externalValue] = originalEnumValueConfig;
} else if (Array.isArray(mappedEnumValue)) {
const [newEnumValueName, newEnumValueConfig] = mappedEnumValue;
newEnumValueConfigMap[newEnumValueName] = newEnumValueConfig;
const [newExternalValue, newEnumValueConfig] = mappedEnumValue;
newEnumValueConfigMap[newExternalValue] =
newEnumValueConfig === undefined ? originalEnumValueConfig : newEnumValueConfig;
} else if (mappedEnumValue !== null) {
newEnumValueConfigMap[enumValueName] = mappedEnumValue;
newEnumValueConfigMap[externalValue] = mappedEnumValue;
}
});
return new GraphQLEnumType({
...config,
values: newEnumValueConfigMap,
});
return correctASTNodes(
new GraphQLEnumType({
...config,
values: newEnumValueConfigMap,
})
);
},
},
type => isEnumType(type)
Expand Down Expand Up @@ -256,35 +255,33 @@ function mapFields(originalTypeMap: TypeMap, schema: GraphQLSchema, schemaMapper
},
};
}
newFieldConfigMap[newFieldName] = newFieldConfig;
newFieldConfigMap[newFieldName] = newFieldConfig === undefined ? originalFieldConfig : newFieldConfig;
} else if (mappedField !== null) {
newFieldConfigMap[fieldName] = mappedField;
}
});

if (isObjectType(originalType)) {
newTypeMap[typeName] = new GraphQLObjectType({
...(config as GraphQLObjectTypeConfig<any, any>),
fields: newFieldConfigMap,
astNode: rebuildAstNode((config as GraphQLObjectTypeConfig<any, any>).astNode, newFieldConfigMap),
extensionASTNodes: rebuildExtensionAstNodes((config as GraphQLObjectTypeConfig<any, any>).extensionASTNodes),
});
newTypeMap[typeName] = correctASTNodes(
new GraphQLObjectType({
...(config as GraphQLObjectTypeConfig<any, any>),
fields: newFieldConfigMap,
})
);
} else if (isInterfaceType(originalType)) {
newTypeMap[typeName] = new GraphQLInterfaceType({
...(config as GraphQLInterfaceTypeConfig<any, any>),
fields: newFieldConfigMap,
astNode: rebuildAstNode((config as GraphQLInterfaceTypeConfig<any, any>).astNode, newFieldConfigMap),
extensionASTNodes: rebuildExtensionAstNodes(
(config as GraphQLInterfaceTypeConfig<any, any>).extensionASTNodes
),
});
newTypeMap[typeName] = correctASTNodes(
new GraphQLInterfaceType({
...(config as GraphQLInterfaceTypeConfig<any, any>),
fields: newFieldConfigMap,
})
);
} else {
newTypeMap[typeName] = new GraphQLInputObjectType({
...(config as GraphQLInputObjectTypeConfig),
fields: newFieldConfigMap,
astNode: rebuildAstNode((config as GraphQLInputObjectTypeConfig).astNode, newFieldConfigMap),
extensionASTNodes: rebuildExtensionAstNodes((config as GraphQLInputObjectTypeConfig).extensionASTNodes),
});
newTypeMap[typeName] = correctASTNodes(
new GraphQLInputObjectType({
...(config as GraphQLInputObjectTypeConfig),
fields: newFieldConfigMap,
})
);
}
}
});
Expand Down Expand Up @@ -497,48 +494,110 @@ function getEnumValueMapper(schemaMapper: SchemaMapper): EnumValueMapper | null
return enumValueMapper != null ? enumValueMapper : null;
}

export function rebuildAstNode<
TypeDefinitionNode extends ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode | InputObjectTypeDefinitionNode
>(
astNode: TypeDefinitionNode,
fieldOrInputFieldConfigMap: Record<
string,
TypeDefinitionNode extends ObjectTypeDefinitionNode | InterfaceTypeDefinitionNode
? GraphQLFieldConfig<any, any>
: GraphQLInputFieldConfig
>
): TypeDefinitionNode {
if (astNode == null) {
return undefined;
}
export function correctASTNodes(type: GraphQLObjectType): GraphQLObjectType;
export function correctASTNodes(type: GraphQLInterfaceType): GraphQLInterfaceType;
export function correctASTNodes(type: GraphQLInputObjectType): GraphQLInputObjectType;
export function correctASTNodes(type: GraphQLEnumType): GraphQLEnumType;
export function correctASTNodes(type: GraphQLNamedType): GraphQLNamedType {
if (isObjectType(type)) {
const config = (type as GraphQLObjectType).toConfig();
if (config.astNode != null) {
const fields: Array<FieldDefinitionNode> = [];
Object.values(config.fields).forEach(fieldConfig => {
if (fieldConfig.astNode != null) {
fields.push(fieldConfig.astNode);
}
});
config.astNode = {
...config.astNode,
kind: Kind.OBJECT_TYPE_DEFINITION,
fields,
};
}

const newAstNode: TypeDefinitionNode = {
...astNode,
fields: undefined,
};
if (config.extensionASTNodes != null) {
config.extensionASTNodes = config.extensionASTNodes.map(node => ({
...node,
kind: Kind.OBJECT_TYPE_EXTENSION,
fields: undefined,
}));
}

const fields: Array<FieldDefinitionNode | InputValueDefinitionNode> = [];
Object.values(fieldOrInputFieldConfigMap).forEach(fieldOrInputFieldConfig => {
if (fieldOrInputFieldConfig.astNode != null) {
fields.push(fieldOrInputFieldConfig.astNode);
return new GraphQLObjectType(config);
} else if (isInterfaceType(type)) {
const config = (type as GraphQLInterfaceType).toConfig();
if (config.astNode != null) {
const fields: Array<FieldDefinitionNode> = [];
Object.values(config.fields).forEach(fieldConfig => {
if (fieldConfig.astNode != null) {
fields.push(fieldConfig.astNode);
}
});
config.astNode = {
...config.astNode,
kind: Kind.INTERFACE_TYPE_DEFINITION,
fields,
};
}
});

return {
...newAstNode,
fields,
};
}
if (config.extensionASTNodes != null) {
config.extensionASTNodes = config.extensionASTNodes.map(node => ({
...node,
kind: Kind.INTERFACE_TYPE_EXTENSION,
fields: undefined,
}));
}

export function rebuildExtensionAstNodes<
TypeExtensionNode extends ObjectTypeExtensionNode | InterfaceTypeExtensionNode | InputObjectTypeExtensionNode
>(extensionASTNodes: ReadonlyArray<TypeExtensionNode>): Array<TypeExtensionNode> {
if (!extensionASTNodes?.length) {
return [];
}
return new GraphQLInterfaceType(config);
} else if (isInputObjectType(type)) {
const config = (type as GraphQLInputObjectType).toConfig();
if (config.astNode != null) {
const fields: Array<InputValueDefinitionNode> = [];
Object.values(config.fields).forEach(fieldConfig => {
if (fieldConfig.astNode != null) {
fields.push(fieldConfig.astNode);
}
});
config.astNode = {
...config.astNode,
kind: Kind.INPUT_OBJECT_TYPE_DEFINITION,
fields,
};
}

if (config.extensionASTNodes != null) {
config.extensionASTNodes = config.extensionASTNodes.map(node => ({
...node,
kind: Kind.INPUT_OBJECT_TYPE_EXTENSION,
fields: undefined,
}));
}

return extensionASTNodes.map(node => ({
...node,
fields: undefined,
}));
return new GraphQLInputObjectType(config);
} else if (isEnumType(type)) {
const config = (type as GraphQLEnumType).toConfig();
if (config.astNode != null) {
const values: Array<EnumValueDefinitionNode> = [];
Object.values(config.values).forEach(enumValueConfig => {
if (enumValueConfig.astNode != null) {
values.push(enumValueConfig.astNode);
}
});
config.astNode = {
...config.astNode,
values,
};
}

if (config.extensionASTNodes != null) {
config.extensionASTNodes = config.extensionASTNodes.map(node => ({
...node,
values: undefined,
}));
}

return new GraphQLEnumType(config);
} else {
return type;
}
}

0 comments on commit 1f3b14a

Please sign in to comment.