Skip to content

Commit

Permalink
Use result transforming within bundled transforming
Browse files Browse the repository at this point in the history
Adds result transforming to the following transformers:
= TransformCompositeFields
= TransformInterfaceFields and = TransformObjectFields
= TransformRootFields
= MapFields
= WrapFields
= WrapType

** Still to do: HoistField
  • Loading branch information
yaacovCR committed Jul 2, 2020
1 parent 9473e11 commit 2894c66
Show file tree
Hide file tree
Showing 10 changed files with 284 additions and 60 deletions.
7 changes: 4 additions & 3 deletions packages/delegate/src/defaultMergedResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@ export function defaultMergedResolver(
context: Record<string, any>,
info: GraphQLResolveInfo
) {
// if parent is nullish, cannot be a proxied result
if (!parent) {
return null;
return defaultFieldResolver(parent, args, context, info);
}

const responseKey = getResponseKeyFromInfo(info);
const errors = getErrors(parent, responseKey);

// check to see if parent is not a proxied result, i.e. if parent resolver was manually overwritten
// See https://github.com/apollographql/graphql-tools/issues/967
// all proxied results have an associated array of errors, possibly empty, but always defined
// if errors is nullish, cannot be a proxied result
if (!errors) {
return defaultFieldResolver(parent, args, context, info);
}
Expand Down
3 changes: 2 additions & 1 deletion packages/utils/src/Interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ export interface Transform {

export type FieldNodeMapper = (
fieldNode: FieldNode,
fragments: Record<string, FragmentDefinitionNode>
fragments: Record<string, FragmentDefinitionNode>,
context: Record<string, any>
) => SelectionNode | Array<SelectionNode>;

export type FieldNodeMappers = Record<string, Record<string, FieldNodeMapper>>;
Expand Down
52 changes: 44 additions & 8 deletions packages/wrap/src/transforms/MapFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,69 @@ import { Transform, Request, FieldNodeMappers, ExecutionResult } from '@graphql-

import TransformCompositeFields from './TransformCompositeFields';

import { ObjectValueTransformerMap, ErrorsTransformer } from '../types';

export default class MapFields implements Transform {
private readonly transformer: TransformCompositeFields;

constructor(fieldNodeTransformerMap: FieldNodeMappers) {
constructor(
fieldNodeTransformerMap: FieldNodeMappers,
objectValueTransformerMap?: ObjectValueTransformerMap,
errorsTransformer?: ErrorsTransformer
) {
this.transformer = new TransformCompositeFields(
(_typeName, _fieldName, fieldConfig) => fieldConfig,
(typeName, fieldName, fieldNode, fragments) => {
(typeName, fieldName, fieldNode, fragments, context) => {
const typeTransformers = fieldNodeTransformerMap[typeName];
if (typeTransformers == null) {
return fieldNode;
return undefined;
}

const fieldNodeTransformer = typeTransformers[fieldName];
if (fieldNodeTransformer == null) {
return fieldNode;
return undefined;
}

return fieldNodeTransformer(fieldNode, fragments, context);
},
data => {
if (data == null) {
return data;
}

const typeName = data.__typename;
if (typeName == null) {
return data;
}

return fieldNodeTransformer(fieldNode, fragments);
}
const transformer = objectValueTransformerMap[typeName];
if (transformer == null) {
return data;
}

return transformer(data);
},
errorsTransformer
);
}

public transformSchema(schema: GraphQLSchema): GraphQLSchema {
return this.transformer.transformSchema(schema);
}

public transformRequest(request: Request): Request {
return this.transformer.transformRequest(request);
public transformRequest(
originalRequest: Request,
delegationContext?: Record<string, any>,
transformationContext?: Record<string, any>
): Request {
return this.transformer.transformRequest(originalRequest, delegationContext, transformationContext);
}

public transformResult(
originalResult: ExecutionResult,
delegationContext?: Record<string, any>,
transformationContext?: Record<string, any>
): ExecutionResult {
return this.transformer.transformResult(originalResult, delegationContext, transformationContext);
}
}
84 changes: 67 additions & 17 deletions packages/wrap/src/transforms/TransformCompositeFields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,28 @@ import {
GraphQLObjectType,
} from 'graphql';

import { Transform, Request, MapperKind, mapSchema } from '@graphql-tools/utils';
import { FieldTransformer, FieldNodeTransformer } from '../types';
import { Transform, Request, MapperKind, mapSchema, visitData, ExecutionResult } from '@graphql-tools/utils';
import { FieldTransformer, FieldNodeTransformer, DataTransformer, ErrorsTransformer } from '../types';

export default class TransformCompositeFields implements Transform {
private readonly fieldTransformer: FieldTransformer;
private readonly fieldNodeTransformer: FieldNodeTransformer;
private readonly dataTransformer: DataTransformer;
private readonly errorsTransformer: ErrorsTransformer;
private transformedSchema: GraphQLSchema;
private typeInfo: TypeInfo;
private mapping: Record<string, Record<string, string>>;

constructor(fieldTransformer: FieldTransformer, fieldNodeTransformer?: FieldNodeTransformer) {
constructor(
fieldTransformer: FieldTransformer,
fieldNodeTransformer?: FieldNodeTransformer,
dataTransformer?: DataTransformer,
errorsTransformer?: ErrorsTransformer
) {
this.fieldTransformer = fieldTransformer;
this.fieldNodeTransformer = fieldNodeTransformer;
this.dataTransformer = dataTransformer;
this.errorsTransformer = errorsTransformer;
this.mapping = {};
}

Expand All @@ -35,23 +45,43 @@ export default class TransformCompositeFields implements Transform {
[MapperKind.OBJECT_TYPE]: (type: GraphQLObjectType) => this.transformFields(type, this.fieldTransformer),
[MapperKind.INTERFACE_TYPE]: (type: GraphQLInterfaceType) => this.transformFields(type, this.fieldTransformer),
});
this.typeInfo = new TypeInfo(this.transformedSchema);

return this.transformedSchema;
}

public transformRequest(originalRequest: Request): Request {
public transformRequest(
originalRequest: Request,
_delegationContext?: Record<string, any>,
transformationContext?: Record<string, any>
): Request {
const document = originalRequest.document;
const fragments = Object.create(null);
originalRequest.document.definitions.forEach(def => {
document.definitions.forEach(def => {
if (def.kind === Kind.FRAGMENT_DEFINITION) {
fragments[def.name.value] = def;
}
});
return {
...originalRequest,
document: this.transformDocument(originalRequest.document, fragments),
document: this.transformDocument(document, fragments, transformationContext),
};
}

public transformResult(
result: ExecutionResult,
_delegationContext?: Record<string, any>,
transformationContext?: Record<string, any>
) {
if (this.dataTransformer != null) {
result.data = visitData(result.data, value => this.dataTransformer(value, transformationContext));
}
if (this.errorsTransformer != null) {
result.errors = this.errorsTransformer(result.errors, transformationContext);
}
return result;
}

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

private transformFields(type: GraphQLInterfaceType, fieldTransformer: FieldTransformer): GraphQLInterfaceType;
Expand Down Expand Up @@ -104,24 +134,25 @@ export default class TransformCompositeFields implements Transform {

private transformDocument(
document: DocumentNode,
fragments: Record<string, FragmentDefinitionNode> = {}
fragments: Record<string, FragmentDefinitionNode>,
transformationContext: Record<string, any>
): DocumentNode {
const typeInfo = new TypeInfo(this.transformedSchema);
const newDocument: DocumentNode = visit(
return visit(
document,
visitWithTypeInfo(typeInfo, {
visitWithTypeInfo(this.typeInfo, {
leave: {
[Kind.SELECTION_SET]: node => this.transformSelectionSet(node, typeInfo, fragments),
[Kind.SELECTION_SET]: node =>
this.transformSelectionSet(node, this.typeInfo, fragments, transformationContext),
},
})
);
return newDocument;
}

private transformSelectionSet(
node: SelectionSetNode,
typeInfo: TypeInfo,
fragments: Record<string, FragmentDefinitionNode> = {}
fragments: Record<string, FragmentDefinitionNode>,
transformationContext: Record<string, any>
): SelectionSetNode {
const parentType: GraphQLType = typeInfo.getParentType();
if (parentType == null) {
Expand All @@ -139,10 +170,29 @@ export default class TransformCompositeFields implements Transform {

const newName = selection.name.value;

const transformedSelection =
this.fieldNodeTransformer != null
? this.fieldNodeTransformer(parentTypeName, newName, selection, fragments)
: selection;
if (this.dataTransformer != null || this.errorsTransformer != null) {
newSelections.push({
kind: Kind.FIELD,
name: {
kind: Kind.NAME,
value: '__typename',
},
});
}

let transformedSelection: SelectionNode | Array<SelectionNode>;
if (this.fieldNodeTransformer == null) {
transformedSelection = selection;
} else {
transformedSelection = this.fieldNodeTransformer(
parentTypeName,
newName,
selection,
fragments,
transformationContext
);
transformedSelection = transformedSelection === undefined ? selection : transformedSelection;
}

if (Array.isArray(transformedSelection)) {
newSelections = newSelections.concat(transformedSelection);
Expand Down
18 changes: 15 additions & 3 deletions packages/wrap/src/transforms/TransformInterfaceFields.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GraphQLSchema, isInterfaceType, GraphQLFieldConfig } from 'graphql';

import { Transform, Request } from '@graphql-tools/utils';
import { Transform, Request, ExecutionResult } from '@graphql-tools/utils';
import { FieldTransformer, FieldNodeTransformer } from '../types';

import TransformCompositeFields from './TransformCompositeFields';
Expand Down Expand Up @@ -33,7 +33,19 @@ export default class TransformInterfaceFields implements Transform {
return this.transformer.transformSchema(originalSchema);
}

public transformRequest(originalRequest: Request): Request {
return this.transformer.transformRequest(originalRequest);
public transformRequest(
originalRequest: Request,
delegationContext?: Record<string, any>,
transformationContext?: Record<string, any>
): Request {
return this.transformer.transformRequest(originalRequest, delegationContext, transformationContext);
}

public transformResult(
originalResult: ExecutionResult,
delegationContext?: Record<string, any>,
transformationContext?: Record<string, any>
): ExecutionResult {
return this.transformer.transformResult(originalResult, delegationContext, transformationContext);
}
}
18 changes: 15 additions & 3 deletions packages/wrap/src/transforms/TransformObjectFields.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GraphQLSchema, isObjectType, GraphQLFieldConfig } from 'graphql';

import { Transform, Request } from '@graphql-tools/utils';
import { Transform, Request, ExecutionResult } from '@graphql-tools/utils';
import { FieldTransformer, FieldNodeTransformer } from '../types';

import TransformCompositeFields from './TransformCompositeFields';
Expand Down Expand Up @@ -33,7 +33,19 @@ export default class TransformObjectFields implements Transform {
return this.transformer.transformSchema(originalSchema);
}

public transformRequest(originalRequest: Request): Request {
return this.transformer.transformRequest(originalRequest);
public transformRequest(
originalRequest: Request,
delegationContext?: Record<string, any>,
transformationContext?: Record<string, any>
): Request {
return this.transformer.transformRequest(originalRequest, delegationContext, transformationContext);
}

public transformResult(
originalResult: ExecutionResult,
delegationContext?: Record<string, any>,
transformationContext?: Record<string, any>
): ExecutionResult {
return this.transformer.transformResult(originalResult, delegationContext, transformationContext);
}
}
18 changes: 15 additions & 3 deletions packages/wrap/src/transforms/TransformRootFields.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GraphQLSchema, GraphQLFieldConfig } from 'graphql';

import { Transform, Request } from '@graphql-tools/utils';
import { Transform, Request, ExecutionResult } from '@graphql-tools/utils';

import TransformObjectFields from './TransformObjectFields';
import { RootFieldTransformer, FieldNodeTransformer } from '../types';
Expand Down Expand Up @@ -45,7 +45,19 @@ export default class TransformRootFields implements Transform {
return this.transformer.transformSchema(originalSchema);
}

public transformRequest(originalRequest: Request): Request {
return this.transformer.transformRequest(originalRequest);
public transformRequest(
originalRequest: Request,
delegationContext?: Record<string, any>,
transformationContext?: Record<string, any>
): Request {
return this.transformer.transformRequest(originalRequest, delegationContext, transformationContext);
}

public transformResult(
originalResult: ExecutionResult,
delegationContext?: Record<string, any>,
transformationContext?: Record<string, any>
): ExecutionResult {
return this.transformer.transformResult(originalResult, delegationContext, transformationContext);
}
}

0 comments on commit 2894c66

Please sign in to comment.