UNPKG

4.93 kBPlain TextView Raw
1import { Operation } from "apollo-codegen-core/lib/compiler";
2import {
3 GraphQLType,
4 GraphQLInputType,
5 GraphQLInputObjectType,
6 GraphQLInputField,
7 isInputObjectType,
8 isNonNullType,
9 isListType,
10 isInputType
11} from "graphql";
12
13import {
14 identifier,
15 TSType,
16 TSTypeAnnotation,
17 LVal,
18 arrowFunctionExpression,
19 variableDeclaration,
20 variableDeclarator,
21 parenthesizedExpression,
22 objectExpression,
23 Identifier,
24 objectProperty,
25 ArrowFunctionExpression,
26 ObjectProperty,
27 Expression,
28 isIdentifier
29} from "@babel/types";
30
31import { typeForInputType, typeReference, stringIdentifier } from "./types";
32import { InputType } from "./intermediates";
33import { OperationType } from "./genericTypes";
34import compact from "./compact";
35import generate from "@babel/generator";
36import { callExpression } from "@babel/types";
37import { logicalExpression } from "@babel/types";
38import { isLogicalExpression } from "@babel/types";
39import { memberExpression } from "@babel/types";
40
41const objectPropertyForGraphQLInputField = (field: GraphQLInputField) =>
42 objectProperty(identifier(field.name), identifier(field.name), false, true);
43
44const exactValueForGraphQLInputType = (
45 type: GraphQLInputType,
46 fieldIdentifier: Identifier
47): Expression => {
48 if (isInputObjectType(type)) {
49 return logicalExpression(
50 "&&",
51 fieldIdentifier,
52 callExpression(identifier(type.name), [fieldIdentifier])
53 );
54 } else if (isNonNullType(type)) {
55 const expression = exactValueForGraphQLInputType(
56 type.ofType,
57 fieldIdentifier
58 );
59 return isLogicalExpression(expression) ? expression.right : expression;
60 } else if (isListType(type)) {
61 const expression = exactValueForGraphQLInputType(
62 type.ofType,
63 fieldIdentifier
64 );
65 return isIdentifier(expression) && expression.name == fieldIdentifier.name
66 ? expression
67 : logicalExpression(
68 "&&",
69 fieldIdentifier,
70 memberExpression(
71 fieldIdentifier,
72 callExpression(identifier("map"), [
73 arrowFunctionExpression(
74 [identifier("x")],
75 exactValueForGraphQLInputType(type.ofType, identifier("x"))
76 )
77 ])
78 )
79 );
80 } else {
81 return fieldIdentifier;
82 }
83};
84
85const exactPropertyForGraphQLInputField = (field: GraphQLInputField) =>
86 objectProperty(
87 identifier(field.name),
88 exactValueForGraphQLInputType(field.type, identifier(field.name)),
89 false,
90 true
91 );
92
93export const typedIdentifier = (name: string, type: TSType): Identifier => ({
94 ...identifier(name),
95 typeAnnotation: TSTypeAnnotation(type) as any
96});
97
98const identifierForVariable = (variable: {
99 name: string;
100 type: GraphQLType;
101}): Identifier =>
102 typedIdentifier(
103 variable.name,
104 typeForInputType(InputType(variable.type as GraphQLInputType))
105 );
106
107const objectPropertiesForOperation = (operation: Operation): ObjectProperty[] =>
108 compact(
109 objectProperty(
110 identifier("query"),
111 stringIdentifier(operation.operationName)
112 ),
113 operation.variables.length > 0 &&
114 objectProperty(
115 identifier("variables"),
116 objectExpression(
117 operation.variables.map(variable =>
118 objectProperty(
119 identifier(variable.name),
120 isInputType(variable.type)
121 ? exactValueForGraphQLInputType(
122 variable.type,
123 identifier(variable.name)
124 )
125 : identifier(variable.name),
126 false,
127 true
128 )
129 )
130 )
131 )
132 );
133
134export const constructorDeclaration = (
135 name: string,
136 parameters: LVal[],
137 returnType: TSType,
138 properties: ObjectProperty[]
139) =>
140 variableDeclaration("const", [
141 variableDeclarator(identifier(name), {
142 ...arrowFunctionExpression(
143 parameters,
144 parenthesizedExpression(objectExpression(properties))
145 ),
146 returnType: TSTypeAnnotation(returnType) as any
147 } as ArrowFunctionExpression)
148 ]);
149
150export const constructorDeclarationForGraphQLInputObjectType = (
151 type: GraphQLInputObjectType
152) =>
153 ((fields: GraphQLInputField[]) =>
154 constructorDeclaration(
155 type.name,
156 [
157 {
158 ...identifier(
159 generate(
160 objectExpression(fields.map(objectPropertyForGraphQLInputField))
161 ).code
162 ),
163 typeAnnotation: TSTypeAnnotation(typeReference(type.name)) as any
164 }
165 ],
166 typeReference(type.name),
167 fields.map(exactPropertyForGraphQLInputField)
168 ))(Object.values(type.getFields()));
169
170export const constructorDeclarationForOperation = (operation: Operation) =>
171 constructorDeclaration(
172 operation.operationName,
173 operation.variables.map(identifierForVariable),
174 OperationType(typeReference(operation.operationName)),
175 objectPropertiesForOperation(operation)
176 );