-
-
Notifications
You must be signed in to change notification settings - Fork 796
/
createMergedResolver.ts
108 lines (86 loc) · 3.26 KB
/
createMergedResolver.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 { GraphQLError } from 'graphql';
import {
IFieldResolver,
getErrors,
setErrors,
relocatedError,
ERROR_SYMBOL,
extendedError,
} from '@graphql-tools/utils';
import { OBJECT_SUBSCHEMA_SYMBOL } from './symbols';
import { getSubschema, setObjectSubschema } from './Subschema';
import { defaultMergedResolver } from './defaultMergedResolver';
import { handleNull } from './results/handleNull';
function unwrapResult(parent: any, path: Array<string>): any {
let newParent: any = parent;
const pathLength = path.length;
for (let i = 0; i < pathLength; i++) {
const responseKey = path[i];
const errors = getErrors(newParent, responseKey);
const subschema = getSubschema(newParent, responseKey);
const object = newParent[responseKey];
if (object == null) {
return handleNull(errors);
}
setErrors(
object,
errors.map(error => relocatedError(error, error.path != null ? error.path.slice(1) : undefined))
);
setObjectSubschema(object, subschema);
newParent = object;
}
return newParent;
}
function dehoistResult(parent: any, delimeter = '__gqltf__'): any {
const result = Object.create(null);
Object.keys(parent).forEach(alias => {
let obj = result;
const fieldNames = alias.split(delimeter);
const fieldName = fieldNames.pop();
fieldNames.forEach(key => {
obj = obj[key] = obj[key] || Object.create(null);
});
obj[fieldName] = parent[alias];
});
result[ERROR_SYMBOL] = parent[ERROR_SYMBOL].map((error: GraphQLError) => {
if (error.path != null) {
const path = error.path.slice();
const pathSegment = path.shift();
const expandedPathSegment: Array<string | number> = (pathSegment as string).split(delimeter);
const newPath = expandedPathSegment.concat(path);
const graphQLToolsMergedPath = error.extensions.graphQLToolsMergedPath;
let newGraphQLToolsMergedPath = graphQLToolsMergedPath.slice();
newGraphQLToolsMergedPath.pop();
newGraphQLToolsMergedPath = newGraphQLToolsMergedPath.concat(newPath);
return extendedError(relocatedError(error, newPath), {
...error.extensions,
graphQLToolsMergedPath: newGraphQLToolsMergedPath,
});
}
return error;
});
result[OBJECT_SUBSCHEMA_SYMBOL] = parent[OBJECT_SUBSCHEMA_SYMBOL];
return result;
}
export function createMergedResolver({
fromPath,
dehoist,
delimeter = '__gqltf__',
}: {
fromPath?: Array<string>;
dehoist?: boolean;
delimeter?: string;
}): IFieldResolver<any, any> {
const parentErrorResolver: IFieldResolver<any, any> = (parent, args, context, info) =>
parent instanceof Error ? parent : defaultMergedResolver(parent, args, context, info);
const unwrappingResolver: IFieldResolver<any, any> =
fromPath != null
? (parent, args, context, info) => parentErrorResolver(unwrapResult(parent, fromPath), args, context, info)
: parentErrorResolver;
const dehoistingResolver: IFieldResolver<any, any> = dehoist
? (parent, args, context, info) => unwrappingResolver(dehoistResult(parent, delimeter), args, context, info)
: unwrappingResolver;
const noParentResolver: IFieldResolver<any, any> = (parent, args, context, info) =>
parent ? dehoistingResolver(parent, args, context, info) : {};
return noParentResolver;
}