-
-
Notifications
You must be signed in to change notification settings - Fork 797
/
RenameObjectFieldArguments.ts
108 lines (97 loc) · 3.73 KB
/
RenameObjectFieldArguments.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { FieldNode, GraphQLFieldConfig, GraphQLSchema } from 'graphql';
import { DelegationContext, SubschemaConfig, Transform } from '@graphql-tools/delegate';
import { ExecutionRequest, MapperKind, mapSchema } from '@graphql-tools/utils';
import TransformObjectFields from './TransformObjectFields.js';
type RenamerFunction = (typeName: string, fieldName: string, argName: string) => string;
interface RenameObjectFieldArgumentsTransformationContext extends Record<string, any> {}
export default class RenameObjectFieldArguments<TContext = Record<string, any>>
implements Transform<RenameObjectFieldArgumentsTransformationContext, TContext>
{
private readonly renamer: RenamerFunction;
private readonly transformer: TransformObjectFields<TContext>;
private reverseMap: Record<string, Record<string, Record<string, string>>>;
constructor(renamer: RenamerFunction) {
this.renamer = renamer;
this.transformer = new TransformObjectFields(
(typeName, fieldName, fieldConfig) => {
const argsConfig = Object.fromEntries(
Object.entries(fieldConfig.args || []).map(([argName, conf]) => {
const newName = renamer(typeName, fieldName, argName);
if (newName !== undefined && newName !== argName) {
if (newName != null) {
return [newName, conf];
}
}
return [argName, conf];
}),
);
return [fieldName, { ...fieldConfig, args: argsConfig }];
},
(typeName: string, fieldName: string, inputFieldNode: FieldNode) => {
if (!(typeName in this.reverseMap)) {
return inputFieldNode;
}
if (!(fieldName in this.reverseMap[typeName])) {
return inputFieldNode;
}
const fieldNameMap = this.reverseMap[typeName][fieldName];
return {
...inputFieldNode,
arguments: (inputFieldNode.arguments || []).map(argNode => {
return argNode.name.value in fieldNameMap
? {
...argNode,
name: {
...argNode.name,
value: fieldNameMap[argNode.name.value],
},
}
: argNode;
}),
};
},
);
this.reverseMap = Object.create(null);
}
public transformSchema(
originalWrappingSchema: GraphQLSchema,
subschemaConfig: SubschemaConfig<any, any, any, TContext>,
): GraphQLSchema {
mapSchema(originalWrappingSchema, {
[MapperKind.OBJECT_FIELD]: (
fieldConfig: GraphQLFieldConfig<any, any>,
fieldName: string,
typeName,
): undefined => {
Object.entries(fieldConfig.args || {}).forEach(([argName]) => {
const newName = this.renamer(typeName, fieldName, argName);
if (newName !== undefined && newName !== fieldName) {
if (this.reverseMap[typeName] == null) {
this.reverseMap[typeName] = Object.create(null);
}
if (this.reverseMap[typeName][fieldName] == null) {
this.reverseMap[typeName][fieldName] = Object.create(null);
}
this.reverseMap[typeName][fieldName][newName] = argName;
}
});
return undefined;
},
[MapperKind.ROOT_OBJECT]() {
return undefined;
},
});
return this.transformer.transformSchema(originalWrappingSchema, subschemaConfig);
}
public transformRequest(
originalRequest: ExecutionRequest,
delegationContext: DelegationContext<TContext>,
transformationContext: RenameObjectFieldArgumentsTransformationContext,
): ExecutionRequest {
return this.transformer.transformRequest(
originalRequest,
delegationContext,
transformationContext,
);
}
}