1 | import { GraphQLInt, GraphQLFloat, GraphQLBoolean, GraphQLID, GraphQLString, GraphQLSchema, GraphQLObjectType, GraphQLInputObjectType, GraphQLList, GraphQLNonNull, GraphQLInterfaceType, GraphQLUnionType, GraphQLEnumType, GraphQLScalarType } from 'graphql';
|
2 |
|
3 | function builtInScalar(builtInType) {
|
4 | return {
|
5 | kind: 'Scalar',
|
6 | builtInType,
|
7 | };
|
8 | }
|
9 | function createTypesFactory() {
|
10 | return {
|
11 | String: builtInScalar(GraphQLString),
|
12 | Int: builtInScalar(GraphQLInt),
|
13 | Float: builtInScalar(GraphQLFloat),
|
14 | Boolean: builtInScalar(GraphQLBoolean),
|
15 | ID: builtInScalar(GraphQLID),
|
16 | scalarType({ name, description, serialize, parseValue, parseLiteral, }) {
|
17 | return {
|
18 | kind: 'Scalar',
|
19 | graphqlTypeConfig: {
|
20 | name,
|
21 | description,
|
22 | serialize,
|
23 | parseLiteral,
|
24 | parseValue,
|
25 | },
|
26 | };
|
27 | },
|
28 | enumType({ name, description, values, }) {
|
29 | return {
|
30 | kind: 'Enum',
|
31 | name,
|
32 | description,
|
33 | values,
|
34 | };
|
35 | },
|
36 | arg(type, description) {
|
37 | return {
|
38 | kind: 'Argument',
|
39 | type,
|
40 | description,
|
41 | };
|
42 | },
|
43 | defaultArg(type, defaultArg, description) {
|
44 | return {
|
45 | kind: 'DefaultArgument',
|
46 | type: type,
|
47 | description,
|
48 | default: defaultArg,
|
49 | };
|
50 | },
|
51 | field(name, { type, args = {}, resolve, description, deprecationReason, extensions }) {
|
52 | return {
|
53 | kind: 'Field',
|
54 | name,
|
55 | type,
|
56 | description,
|
57 | deprecationReason,
|
58 | args,
|
59 | resolve,
|
60 | extensions
|
61 | };
|
62 | },
|
63 | defaultField(name, type, opts) {
|
64 | return {
|
65 | kind: 'Field',
|
66 | name: String(name),
|
67 | type,
|
68 | description: opts && opts.description,
|
69 | deprecationReason: opts && opts.deprecationReason,
|
70 | args: {},
|
71 | resolve: (src) => src[name],
|
72 | };
|
73 | },
|
74 | abstractField(name, type, opts) {
|
75 | return {
|
76 | kind: 'AbstractField',
|
77 | name,
|
78 | description: opts && opts.description,
|
79 | deprecationReason: opts && opts.deprecationReason,
|
80 | type,
|
81 | };
|
82 | },
|
83 | objectType({ name, description, interfaces = [], fields, isTypeOf, extensions, }) {
|
84 | const obj = {
|
85 | kind: 'ObjectType',
|
86 | name,
|
87 | description,
|
88 | interfaces,
|
89 | fieldsFn: undefined,
|
90 | isTypeOf,
|
91 | extensions,
|
92 | };
|
93 | obj.fieldsFn = () => fields(obj);
|
94 | return obj;
|
95 | },
|
96 | inputObjectType({ name, description, fields, }) {
|
97 | let inputObj = {
|
98 | kind: 'InputObject',
|
99 | name,
|
100 | description,
|
101 | fieldsFn: null,
|
102 | };
|
103 | inputObj.fieldsFn = () => fields(inputObj);
|
104 | return inputObj;
|
105 | },
|
106 | unionType({ name, types, resolveType, }) {
|
107 | return {
|
108 | kind: 'Union',
|
109 | name,
|
110 | types,
|
111 | resolveType,
|
112 | };
|
113 | },
|
114 | interfaceType({ name, description, interfaces = [], fields, }) {
|
115 | const obj = {
|
116 | kind: 'Interface',
|
117 | name,
|
118 | description,
|
119 | interfaces,
|
120 | fieldsFn: undefined,
|
121 | };
|
122 | obj.fieldsFn = () => fields(obj);
|
123 | return obj;
|
124 | },
|
125 | List(ofType) {
|
126 | return {
|
127 | kind: 'List',
|
128 | ofType: ofType,
|
129 | };
|
130 | },
|
131 | ListInput(ofType) {
|
132 | return {
|
133 | kind: 'ListInput',
|
134 | ofType: ofType,
|
135 | };
|
136 | },
|
137 | NonNull(ofType) {
|
138 | return {
|
139 | kind: 'NonNull',
|
140 | ofType: ofType,
|
141 | };
|
142 | },
|
143 | NonNullInput(ofType) {
|
144 | return {
|
145 | kind: 'NonNullInput',
|
146 | ofType: ofType,
|
147 | };
|
148 | },
|
149 | queryType({ name = 'Query', fields, }) {
|
150 | return {
|
151 | kind: 'ObjectType',
|
152 | name,
|
153 | interfaces: [],
|
154 | fieldsFn: () => fields,
|
155 | };
|
156 | },
|
157 | mutationType({ name = 'Mutation', fields, }) {
|
158 | return {
|
159 | kind: 'ObjectType',
|
160 | name,
|
161 | interfaces: [],
|
162 | fieldsFn: fields,
|
163 | };
|
164 | },
|
165 | subscriptionField(name, { type, args = {}, subscribe, resolve, description, deprecationReason, }) {
|
166 | return {
|
167 | kind: 'SubscriptionField',
|
168 | name,
|
169 | type,
|
170 | args,
|
171 | subscribe,
|
172 | resolve,
|
173 | description,
|
174 | deprecationReason,
|
175 | };
|
176 | },
|
177 | subscriptionType({ name = 'Subscription', fields, }) {
|
178 | return {
|
179 | kind: 'SubscriptionObject',
|
180 | name,
|
181 | fields,
|
182 | };
|
183 | },
|
184 | };
|
185 | }
|
186 |
|
187 | function buildGraphQLSchema(schema) {
|
188 | const typeMap = new Map();
|
189 | return new GraphQLSchema({
|
190 | query: toGraphQLOutputType(schema.query, typeMap),
|
191 | mutation: schema.mutation &&
|
192 | toGraphQLOutputType(schema.mutation, typeMap),
|
193 | subscription: schema.subscription && toGraphQLSubscriptionObject(schema.subscription, typeMap),
|
194 | types: schema.types && schema.types.map((type) => toGraphQLOutputType(type, typeMap)),
|
195 | directives: schema.directives
|
196 | });
|
197 | }
|
198 | function toGraphQLArgs(args, typeMap) {
|
199 | const graphqlArgs = {};
|
200 | Object.keys(args).forEach((k) => {
|
201 | const arg = args[k];
|
202 | graphqlArgs[k] = {
|
203 | type: toGraphQLInputType(arg.type, typeMap),
|
204 | description: arg.description,
|
205 | defaultValue: arg.kind === 'DefaultArgument' ? arg.default : undefined,
|
206 | };
|
207 | });
|
208 | return graphqlArgs;
|
209 | }
|
210 | function toGraphQLSubscriptionObject(subscriptionObj, typeMap) {
|
211 | return new GraphQLObjectType({
|
212 | name: subscriptionObj.name,
|
213 | fields: () => {
|
214 | const gqlFieldConfig = {};
|
215 | subscriptionObj.fields.forEach((field) => {
|
216 | gqlFieldConfig[field.name] = {
|
217 | type: toGraphQLOutputType(field.type, typeMap),
|
218 | description: field.description,
|
219 | subscribe: field.subscribe,
|
220 | resolve: field.resolve,
|
221 | args: toGraphQLArgs(field.args, typeMap),
|
222 | deprecationReason: field.deprecationReason,
|
223 | };
|
224 | });
|
225 | return gqlFieldConfig;
|
226 | },
|
227 | });
|
228 | }
|
229 | function toGraphQLInputType(t, typeMap) {
|
230 | const found = typeMap.get(t);
|
231 | if (found) {
|
232 | return typeMap.get(t);
|
233 | }
|
234 | switch (t.kind) {
|
235 | case 'Scalar':
|
236 | case 'Enum':
|
237 | return toGraphQLOutputType(t, typeMap);
|
238 | case 'NonNullInput':
|
239 | return new GraphQLNonNull(toGraphQLInputType(t.ofType, typeMap));
|
240 | case 'ListInput':
|
241 | return new GraphQLList(toGraphQLInputType(t.ofType, typeMap));
|
242 | case 'InputObject':
|
243 | const fields = t.fieldsFn();
|
244 | function graphqlFields() {
|
245 | const gqlFieldConfig = {};
|
246 | Object.keys(fields).forEach((k) => {
|
247 | const field = fields[k];
|
248 | gqlFieldConfig[k] = {
|
249 | type: toGraphQLInputType(field.type, typeMap),
|
250 | description: field.description,
|
251 | deprecationReason: field.deprecationReason,
|
252 | };
|
253 | });
|
254 | return gqlFieldConfig;
|
255 | }
|
256 | const obj = new GraphQLInputObjectType({
|
257 | name: t.name,
|
258 | fields: graphqlFields,
|
259 | });
|
260 | typeMap.set(t, obj);
|
261 | return obj;
|
262 | }
|
263 | }
|
264 | function toGraphQLOutputType(t, typeMap) {
|
265 | const found = typeMap.get(t);
|
266 | if (found) {
|
267 | return found;
|
268 | }
|
269 | switch (t.kind) {
|
270 | case 'Scalar':
|
271 | let scalar;
|
272 | if ('builtInType' in t) {
|
273 | scalar = t.builtInType;
|
274 | }
|
275 | else {
|
276 | scalar = new GraphQLScalarType({
|
277 | ...t.graphqlTypeConfig,
|
278 | });
|
279 | }
|
280 | typeMap.set(t, scalar);
|
281 | return scalar;
|
282 | case 'Enum':
|
283 | const enumT = new GraphQLEnumType({
|
284 | name: t.name,
|
285 | description: t.description,
|
286 | values: t.values.reduce((acc, val) => {
|
287 | acc[val.name] = {
|
288 | value: val.value,
|
289 | deprecationReason: val.deprecationReason,
|
290 | description: val.description,
|
291 | };
|
292 | return acc;
|
293 | }, {}),
|
294 | });
|
295 | typeMap.set(t, enumT);
|
296 | return enumT;
|
297 | case 'NonNull':
|
298 | return new GraphQLNonNull(toGraphQLOutputType(t.ofType, typeMap));
|
299 | case 'List':
|
300 | return new GraphQLList(toGraphQLOutputType(t.ofType, typeMap));
|
301 | case 'ObjectType':
|
302 | const obj = new GraphQLObjectType({
|
303 | name: t.name,
|
304 | interfaces: t.interfaces.map((intf) => toGraphQLOutputType(intf, typeMap)),
|
305 | isTypeOf: t.isTypeOf,
|
306 | fields: () => {
|
307 | const fields = t.fieldsFn();
|
308 | const gqlFieldConfig = {};
|
309 | fields.forEach((field) => {
|
310 | gqlFieldConfig[field.name] = {
|
311 | type: toGraphQLOutputType(field.type, typeMap),
|
312 | description: field.description,
|
313 | resolve: field.resolve,
|
314 | args: toGraphQLArgs(field.args, typeMap),
|
315 | deprecationReason: field.deprecationReason,
|
316 | extensions: field.extensions
|
317 | };
|
318 | });
|
319 | return gqlFieldConfig;
|
320 | },
|
321 | extensions: t.extensions,
|
322 | });
|
323 | typeMap.set(t, obj);
|
324 | return obj;
|
325 | case 'Union':
|
326 | const union = new GraphQLUnionType({
|
327 | name: t.name,
|
328 | types: t.types.map((t) => toGraphQLOutputType(t, typeMap)),
|
329 | resolveType: async (src, ctx, info) => {
|
330 | const resolved = await t.resolveType(src, ctx, info);
|
331 | if (typeof resolved === 'string' || resolved == null)
|
332 | return resolved;
|
333 | return typeMap.get(resolved);
|
334 | },
|
335 | });
|
336 | typeMap.set(t, union);
|
337 | return union;
|
338 | case 'Interface':
|
339 | const intf = new GraphQLInterfaceType({
|
340 | name: t.name,
|
341 | fields: () => {
|
342 | const fields = t.fieldsFn();
|
343 | const result = {};
|
344 | fields.forEach((field) => {
|
345 | result[field.name] = {
|
346 | type: toGraphQLOutputType(field.type, typeMap),
|
347 | description: field.description,
|
348 | deprecationReason: field.deprecationReason,
|
349 | };
|
350 | });
|
351 | return result;
|
352 | },
|
353 | interfaces: t.interfaces.map((intf) => toGraphQLOutputType(intf, typeMap)),
|
354 | });
|
355 | typeMap.set(t, intf);
|
356 | return intf;
|
357 | }
|
358 | }
|
359 |
|
360 | export { buildGraphQLSchema, createTypesFactory, toGraphQLInputType, toGraphQLOutputType };
|