UNPKG

10.9 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2016, John Hewson
3 * All rights reserved.
4 */
5"use strict";
6var elm_ast_1 = require('./elm-ast');
7var type_1 = require('graphql/type');
8var utilities_1 = require('graphql/utilities');
9var query_to_elm_1 = require('./query-to-elm');
10function decoderForQuery(def, info, schema, fragmentDefinitionMap, seenFragments) {
11 return decoderFor(def, info, schema, fragmentDefinitionMap, seenFragments);
12}
13exports.decoderForQuery = decoderForQuery;
14function decoderForFragment(def, info, schema, fragmentDefinitionMap, seenFragments) {
15 return decoderFor(def, info, schema, fragmentDefinitionMap, seenFragments);
16}
17exports.decoderForFragment = decoderForFragment;
18function decoderFor(def, info, schema, fragmentDefinitionMap, seenFragments) {
19 function walkDefinition(def, info) {
20 if (def.kind == 'OperationDefinition') {
21 return walkOperationDefinition(def, info);
22 }
23 else if (def.kind == 'FragmentDefinition') {
24 return walkFragmentDefinition(def, info);
25 }
26 }
27 function walkOperationDefinition(def, info) {
28 info.enter(def);
29 if (def.operation == 'query' || def.operation == 'mutation') {
30 var decls = [];
31 // Name
32 var name_1;
33 if (def.name) {
34 name_1 = def.name.value;
35 }
36 else {
37 name_1 = 'AnonymousQuery';
38 }
39 var resultType = name_1[0].toUpperCase() + name_1.substr(1);
40 // todo: Directives
41 // SelectionSet
42 var expr = walkSelectionSet(def.selectionSet, info);
43 // VariableDefinition
44 var parameters = [];
45 if (def.variableDefinitions) {
46 for (var _i = 0, _a = def.variableDefinitions; _i < _a.length; _i++) {
47 var varDef = _a[_i];
48 var name_2 = varDef.variable.name.value;
49 var type = elm_ast_1.typeToString(query_to_elm_1.typeToElm(utilities_1.typeFromAST(schema, varDef.type)), 0);
50 // todo: default value
51 parameters.push({ name: name_2, type: type });
52 }
53 }
54 info.leave(def);
55 return { expr: 'map ' + resultType + ' ' + expr.expr };
56 }
57 }
58 function walkFragmentDefinition(def, info) {
59 info.enter(def);
60 var name = def.name.value;
61 var decls = [];
62 var resultType = name[0].toUpperCase() + name.substr(1);
63 // todo: Directives
64 // SelectionSet
65 var fields = walkSelectionSet(def.selectionSet, info);
66 var fieldNames = getSelectionSetFields(def.selectionSet, info);
67 var shape = "(\\" + fieldNames.join(' ') + " -> { " + fieldNames.map(function (f) { return f + ' = ' + f; }).join(', ') + " })";
68 info.leave(def);
69 return { expr: 'map ' + shape + ' ' + fields.expr };
70 }
71 function walkSelectionSet(selSet, info, seenFields) {
72 if (seenFields === void 0) { seenFields = []; }
73 info.enter(selSet);
74 var fields = [];
75 for (var _i = 0, _a = selSet.selections; _i < _a.length; _i++) {
76 var sel = _a[_i];
77 if (sel.kind == 'Field') {
78 var field = sel;
79 if (seenFields.indexOf(field.name.value) == -1) {
80 fields.push(walkField(field, info));
81 seenFields.push(field.name.value);
82 }
83 }
84 else if (sel.kind == 'FragmentSpread') {
85 // expand out all fragment spreads
86 var spreadName = sel.name.value;
87 var def_1 = fragmentDefinitionMap[spreadName];
88 fields.push(walkSelectionSet(def_1.selectionSet, info, seenFields));
89 }
90 else if (sel.kind == 'InlineFragment') {
91 throw new Error('Should not happen');
92 }
93 }
94 info.leave(selSet);
95 return { expr: fields.map(function (f) { return f.expr; }).filter(function (e) { return e.length > 0; }).join('\n |: ') };
96 }
97 function getSelectionSetFields(selSet, info) {
98 info.enter(selSet);
99 var fields = [];
100 for (var _i = 0, _a = selSet.selections; _i < _a.length; _i++) {
101 var sel = _a[_i];
102 if (sel.kind == 'Field') {
103 var field = sel;
104 var name_3 = query_to_elm_1.elmSafeName(field.name.value);
105 if (field.alias) {
106 name_3 = query_to_elm_1.elmSafeName(field.alias.value);
107 }
108 if (fields.indexOf(name_3) == -1) {
109 fields.push(name_3);
110 }
111 }
112 else if (sel.kind == 'FragmentSpread') {
113 // expand out all fragment spreads
114 var spreadName = sel.name.value;
115 var def_2 = fragmentDefinitionMap[spreadName];
116 for (var _b = 0, _c = getSelectionSetFields(def_2.selectionSet, info); _b < _c.length; _b++) {
117 var name_4 = _c[_b];
118 if (fields.indexOf(name_4) == -1) {
119 fields.push(name_4);
120 }
121 }
122 }
123 else if (sel.kind == 'InlineFragment') {
124 throw new Error('Should not happen');
125 }
126 }
127 info.leave(selSet);
128 return fields;
129 }
130 function walkField(field, info) {
131 info.enter(field);
132 // Name
133 var name = query_to_elm_1.elmSafeName(field.name.value);
134 var originalName = field.name.value;
135 var info_type = info.getType();
136 var isMaybe = false;
137 if (info_type instanceof type_1.GraphQLNonNull) {
138 info_type = info_type['ofType'];
139 }
140 else {
141 isMaybe = true;
142 }
143 // Alias
144 if (field.alias) {
145 name = query_to_elm_1.elmSafeName(field.alias.value);
146 originalName = field.alias.value;
147 }
148 // Arguments (opt)
149 var args = field.arguments; // e.g. id: "1000"
150 // todo: Directives
151 if (query_to_elm_1.getRootType(info_type) instanceof type_1.GraphQLUnionType) {
152 // Union
153 return walkUnion(originalName, field, info);
154 }
155 else {
156 // SelectionSet
157 if (field.selectionSet) {
158 var prefix = '';
159 if (info_type instanceof type_1.GraphQLList) {
160 prefix = 'list ';
161 }
162 var fields = walkSelectionSet(field.selectionSet, info);
163 info.leave(field);
164 var fieldNames = getSelectionSetFields(field.selectionSet, info);
165 var shape = "(\\" + fieldNames.join(' ') + " -> { " + fieldNames.map(function (f) { return f + ' = ' + f; }).join(', ') + " })";
166 var left = '(field "' + originalName + '" ';
167 var right = '(map ' + shape + ' ' + fields.expr + '))';
168 var indent = ' ';
169 if (prefix) {
170 right = '(' + prefix + right + ')';
171 }
172 if (isMaybe) {
173 right = '(' + 'maybe ' + right + ')';
174 }
175 return { expr: left + indent + right };
176 }
177 else {
178 var decoder = leafTypeToDecoder(info_type);
179 info.leave(field);
180 var expr = { expr: '(field "' + originalName + '" (' + decoder + '))' };
181 if (isMaybe) {
182 expr = { expr: '(maybe ' + expr.expr + ')' };
183 }
184 return expr;
185 }
186 }
187 }
188 function walkUnion(originalName, field, info) {
189 var decoder = '\n (\\typename -> case typename of';
190 var indent = ' ';
191 var info_type = info.getType();
192 var isMaybe = false;
193 if (info_type instanceof type_1.GraphQLNonNull) {
194 info_type = info_type['ofType'];
195 }
196 else {
197 isMaybe = true;
198 }
199 var prefix = '';
200 var isList = false;
201 if (info_type instanceof type_1.GraphQLList) {
202 prefix = 'list ';
203 isList = true;
204 }
205 for (var _i = 0, _a = field.selectionSet.selections; _i < _a.length; _i++) {
206 var sel = _a[_i];
207 if (sel.kind == 'InlineFragment') {
208 var inlineFragment = sel;
209 decoder += "\n" + indent + "\"" + inlineFragment.typeCondition.name.value + "\" -> ";
210 info.enter(inlineFragment);
211 var fields = walkSelectionSet(inlineFragment.selectionSet, info);
212 info.leave(inlineFragment);
213 var fieldNames = getSelectionSetFields(inlineFragment.selectionSet, info);
214 var ctor = query_to_elm_1.elmSafeName(inlineFragment.typeCondition.name.value);
215 var shape = "(\\" + fieldNames.join(' ') + " -> " + ctor + " { " + fieldNames.map(function (f) { return f + ' = ' + f; }).join(', ') + " })";
216 var right = '(map ' + shape + ' ' + fields.expr + ')';
217 decoder += right;
218 }
219 else if (sel.kind == 'Field') {
220 var field_1 = sel;
221 if (field_1.name.value != '__typename') {
222 throw new Error('Unexpected field: ' + field_1.name.value);
223 }
224 }
225 else {
226 throw new Error('Unexpected: ' + sel.kind);
227 }
228 }
229 decoder += "\n" + indent + "_ -> fail \"Unexpected union type\")";
230 decoder = '((field "__typename" string) |> andThen ' + decoder + ')';
231 if (prefix) {
232 decoder = '(' + prefix + decoder + ')';
233 }
234 if (isMaybe) {
235 decoder = '(' + 'maybe ' + decoder + ')';
236 }
237 return { expr: '(field "' + originalName + '" ' + decoder + ')' };
238 }
239 function leafTypeToDecoder(type) {
240 var prefix = '';
241 if (type instanceof type_1.GraphQLList) {
242 prefix = 'list ';
243 type = type['ofType'];
244 }
245 // leaf types only
246 if (type instanceof type_1.GraphQLScalarType) {
247 switch (type.name) {
248 case 'Int': return prefix + 'int';
249 case 'Float': return prefix + 'float';
250 case 'Boolean': return prefix + 'bool';
251 case 'ID':
252 case 'String': return prefix + 'string';
253 }
254 }
255 else if (type instanceof type_1.GraphQLEnumType) {
256 return prefix + type.name.toLowerCase() + 'Decoder';
257 }
258 else {
259 throw new Error('not a leaf type: ' + type.name);
260 }
261 }
262 return walkDefinition(def, info);
263}
264exports.decoderFor = decoderFor;
265//# sourceMappingURL=query-to-decoder.js.map
\No newline at end of file