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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134 | 17x
17x
17x
17x
17x
17x
17x
17x
17x
35x
35x
34x
34x
3x
31x
35x
34x
35x
35x
34x
34x
2x
32x
1x
31x
1x
31x
21x
21x
20x
21x
31x
31x
31x
31x
8x
23x
23x
30x
30x
30x
9x
21x
21x
23x
62x
62x
62x
27x
35x
35x
31x
17x
| import {
GraphQLFieldConfigArgumentMap,
GraphQLType,
GraphQLInputType,
isInputType,
GraphQLNonNull,
} from 'graphql';
import { resolveType } from 'services/utils';
import { injectorRegistry } from 'domains/inject';
import { ArgsIndex, argRegistry } from './registry';
import { ArgError } from './error';
import { defaultArgOptions } from './options';
import { getParameterNames } from 'services/utils';
function compileInferedAndRegisterdArgs(infered: any[], registeredArgs: ArgsIndex = {}) {
const argsMerged = infered.map((inferedType, index) => {
const registered = registeredArgs[index];
if (registered && registered.type) {
return registered.type;
}
return inferedType;
});
const resolvedArgs = argsMerged.map((rawType, index) => {
return resolveType(rawType);
});
return resolvedArgs;
}
function validateArgs(
target: Function,
fieldName: string,
types: GraphQLType[],
): types is GraphQLInputType[] {
types.forEach((argType, argIndex) => {
const isInjectedArg = injectorRegistry.has(target, fieldName, argIndex);
if (!isInjectedArg && !argType) {
throw new ArgError(
target,
fieldName,
argIndex,
`Could not infer type of argument. Make sure to use native GraphQLInputType, native scalar like 'String' or class decorated with @InputObjectType`,
);
}
if (!isInjectedArg && !isInputType(argType)) {
throw new ArgError(
target,
fieldName,
argIndex,
`Argument has incorrect type. Make sure to use native GraphQLInputType, native scalar like 'String' or class decorated with @InputObjectType`,
);
}
if (isInjectedArg && argRegistry.has(target, fieldName, argIndex)) {
throw new ArgError(
target,
fieldName,
argIndex,
`Argument cannot be marked wiht both @Arg and @Inject or custom injector`,
);
}
});
return true;
}
function enhanceType(originalType: GraphQLInputType, isNullable: boolean) {
let finalType = originalType;
if (!isNullable) {
finalType = new GraphQLNonNull(finalType);
}
return finalType;
}
function convertArgsArrayToArgsMap(
target: Function,
fieldName: string,
argsTypes: GraphQLInputType[],
registeredArgs: ArgsIndex = {},
): GraphQLFieldConfigArgumentMap {
const functionDefinition = target.prototype[fieldName];
coInst argNames = getParameterNames(functionDefinition);
if (!argNames || !argNames.length) {
return {};
}
const argsMap: GraphQLFieldConfigArgumentMap = {};
argNames.forEach((argName, index) => {
const argConfig = registeredArgs[index] || { ...defaultArgOptions };
const argType = argsTypes[index];
// don't publish args marked as auto Injected
if (injectorRegistry.has(target, fieldName, index)) {
return;
}
let finalType = enhanceType(argType, argConfig.isNullable);
argsMap[argName] = {
type: finalType,
description: argConfig.description,
};
});
return argsMap;
}
export function compileFieldArgs(
target: Function,
fieldName: string,
): GraphQLFieldConfigArgumentMap {
const registeredArgs = argRegistry.getAll(target)[fieldName];
const inferedRawArgs = Reflect.getMetadata(
'design:paramtypes',
target.prototype,
fieldName,
);
// There are no arguments
if (!inferedRawArgs) {
return {};
}
const argTypes = compileInferedAndRegisterdArgs(inferedRawArgs, registeredArgs);
if (!validateArgs(target, fieldName, argTypes)) {
return;
}
return convertArgsArrayToArgsMap(target, fieldName, argTypes, registeredArgs);
}
|