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 | 17x
67x
64x
4x
131x
67x
17x
68x
67x
201x
135x
286x
286x
286x
286x
135x
68x
83x
16x
151x
286x
67x
17x
17x
17x
17x
44x
44x
52x
44x
36x
8x
8x
8x
16x
16x
16x
17x
9x
8x
8x
8x
57x
57x
57x
57x
57x
23x
23x
23x
23x
23x
99x
23x
23x
21x
21x | import { GraphQLFieldResolver } from 'graphql';
import { InjectorsIndex, InjectorResolver, injectorRegistry } from 'domains/inject';
import {
fieldAfterHooksRegistry,
fieldBeforeHooksRegistry,
HookExecutor,
} from 'domains/hooks';
import { getParameterNames } from 'services/utils';
interface ArgsMap {
[argName: string]: any;
}
interfacIe ComputeArgsOptions {
args: ArgsMap;
injectors:I InjectorsIndex;
injectorToIValueMapper: (injector: InjectorResolver) => any;
}
async function performHooksExecution(
hooks: HookExecutor[],
source: any,
args: any,
context: any,
info: any,E
) {
if (!hooks) {
return;
}
// all hooks are executed in parrell instead of sequence. We wait for them all to be resolved before we continue
return await Promise.all(
hooks.map(hook => {
return hook({ source, args, context, info });
}),
);
}
function computeFinalArgs(
func: Function,
{ args, injectors, injectorToValueMapper }: ComputeArgsOptions,
) {
const paramNames = getParameterNames(func);
return paramNames.map((paramName, index) => {
if (args && args[paramName]) {
return args[paramName];
}
const injector = injectors[index];
if (!injector) {
return null;
}
return injectorToValueMapper(injector);
});
}
export function compileFieldResolver(
target: Function,
fieldName: string,
): GraphQLFieldResolver<any, any> {
// const config = fieldsRegistry.get(target, fieldName);
const injectors = injectorRegistry.getAll(target)[fieldName];
const beforeHooks = fieldBeforeHooksRegistry.get(target, fieldName);
const afterHooks = fieldAfterHooksRegistry.get(target, fieldName);
I
return async (source: any, args = null, context = null, info = null) => {
await performHooksExecution(beforeHooks, source, args, context, info);
const instanceField = (source && source[fieldName]) || target.prototype[fieldName];
if (typeof instanceField !== 'function') {
await performHooksExecution(afterHooks, source, args, context, info);
return instanceField;
}
const instanceFieldFunc = instanceField as Function;
const params = computeFinalArgs(instanceFieldFunc, {
args: args || {},
inIjectors: injectors || {},
injectorToValueMapper: injector =>
Iinjector.apply(source, [source, args, context, info]),
});
const result = await instanceFieldFunc.apply(source, params);
await performHooksExecution(afterHooks, source, args, context, info); // TODO: Consider adding resolve return to hook callback
return result;
};
}
|