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
34x
34x
32x
32x
3x
29x
34x
32x
34x
34x
32x
32x
2x
30x
1x
29x
1x
30x
19x
19x
18x
19x
30x
30x
30x
30x
9x
21x
21x
28x
28x
28x
9x
19x
19x
21x
62x
62x
62x
28x
34x
34x
30x
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);
}
|