UNPKG

9.93 kBJavaScriptView Raw
1"use strict";
2var __importStar = (this && this.__importStar) || function (mod) {
3 if (mod && mod.__esModule) return mod;
4 var result = {};
5 if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
6 result["default"] = mod;
7 return result;
8};
9Object.defineProperty(exports, "__esModule", { value: true });
10const t = __importStar(require("@babel/types"));
11const graphql_1 = require("graphql");
12const graphql_tool_utilities_1 = require("graphql-tool-utilities");
13const utilities_1 = require("../utilities");
14function tsInterfaceBodyForObjectField({ fields = [] }, graphQLType, stack, context, requiresTypename = false) {
15 const { schema } = context.ast;
16 const isRootType = !Array.isArray(graphQLType) &&
17 (graphQLType === schema.getQueryType() ||
18 graphQLType === schema.getMutationType() ||
19 graphQLType === schema.getSubscriptionType());
20 const uniqueFields = fields.filter((field) => {
21 if (stack.hasSeenField(field)) {
22 return false;
23 }
24 stack.sawField(field);
25 return true;
26 });
27 const typenameField = {
28 fieldName: '__typename',
29 responseName: '__typename',
30 type: new graphql_1.GraphQLNonNull(graphql_1.GraphQLString),
31 isConditional: false,
32 };
33 const typename = ((context.options.addTypename && !isRootType) || requiresTypename) &&
34 !stack.hasSeenField(typenameField)
35 ? tsPropertyForField(typenameField, graphQLType, stack, context, requiresTypename)
36 : null;
37 const body = uniqueFields.map((field) => tsPropertyForField(field, graphQLType, stack, context, requiresTypename));
38 return t.tsInterfaceBody(typename ? [typename, ...body] : body);
39}
40exports.tsInterfaceBodyForObjectField = tsInterfaceBodyForObjectField;
41function tsTypeForInlineFragment(inlineFragment, _graphQLType, stack, context, requiresTypename = false) {
42 const { typeCondition } = inlineFragment;
43 const interfaceDeclaration = t.tsInterfaceDeclaration(t.identifier(stack.name), null, null, tsInterfaceBodyForObjectField(inlineFragment, typeCondition, stack, context, requiresTypename));
44 return context.export(interfaceDeclaration);
45}
46function tsTypeForObjectField(field, graphQLType, stack, context) {
47 const { inlineFragments = [] } = field;
48 const possibleTypes = graphql_1.isInterfaceType(graphQLType) || graphql_1.isUnionType(graphQLType)
49 ? context.ast.schema.getPossibleTypes(graphQLType)
50 : [];
51 if (inlineFragments.length) {
52 const fragmentTypes = [...inlineFragments].map((inlineFragment) => tsTypeForInlineFragment(inlineFragment, graphQLType, stack.fragment(inlineFragment.typeCondition), context, context.options.partial));
53 const typesCoveredByInlineFragments = new Set([...inlineFragments].reduce((types, inlineFragment) => [...types, ...inlineFragment.possibleTypes], []));
54 const missingPossibleTypes = possibleTypes.filter((possibleType) => {
55 return !typesCoveredByInlineFragments.has(possibleType);
56 });
57 const otherStack = stack.fragment();
58 const otherTypeInterface = t.tsInterfaceDeclaration(t.identifier(otherStack.name), null, null, tsInterfaceBodyForObjectField(field, missingPossibleTypes, otherStack, context, context.options.partial));
59 const otherType = context.export(otherTypeInterface);
60 return t.tsUnionType([...fragmentTypes, otherType]);
61 }
62 else if (possibleTypes.length === 1) {
63 // When we have an interface or union type, but no inline fragments, it
64 // means that there is only one conforming type for the union/ interface.
65 // Here, we construct a "nothing" type that stands in for future additions
66 // to the membership of the union/ interface.
67 const otherStack = stack.fragment();
68 const otherTypeInterface = t.tsInterfaceDeclaration(t.identifier(otherStack.name), null, null, tsInterfaceBodyForObjectField({ fields: [] }, [], otherStack, context, context.options.partial));
69 const interfaceStack = stack.fragment(possibleTypes[0]);
70 const interfaceDeclaration = t.tsInterfaceDeclaration(t.identifier(interfaceStack.name), null, null, tsInterfaceBodyForObjectField(field, graphQLType, interfaceStack, context));
71 return t.tsUnionType([
72 context.export(interfaceDeclaration),
73 context.export(otherTypeInterface),
74 ]);
75 }
76 const interfaceDeclaration = t.tsInterfaceDeclaration(t.identifier(stack.name), null, null, tsInterfaceBodyForObjectField(field, graphQLType, stack, context));
77 return context.export(interfaceDeclaration);
78}
79function tsTypenameForGraphQLType(type) {
80 return t.tsLiteralType(t.stringLiteral(type.name));
81}
82function tsPropertyForField(field, parentType, stack, context, isRequiredTypename = false) {
83 if (field.fieldName === '__typename' && parentType) {
84 const optional = !isRequiredTypename &&
85 (context.options.partial ||
86 field.isConditional ||
87 !graphql_1.isNonNullType(field.type));
88 const parentTypes = Array.isArray(parentType) ? parentType : [parentType];
89 const allPossibleTypes = parentTypes.reduce((all, type) => [
90 ...all,
91 ...(graphql_1.isAbstractType(type)
92 ? context.ast.schema.getPossibleTypes(type)
93 : [type]),
94 ], []);
95 let typename;
96 if (allPossibleTypes.length === 0) {
97 typename = t.tsLiteralType(t.stringLiteral(''));
98 }
99 else if (allPossibleTypes.length > 1) {
100 typename = t.tsUnionType(allPossibleTypes.map(tsTypenameForGraphQLType));
101 }
102 else {
103 typename = tsTypenameForGraphQLType(allPossibleTypes[0]);
104 }
105 const typenameProperty = t.tsPropertySignature(t.identifier(field.responseName), optional
106 ? t.tsTypeAnnotation(t.tsUnionType([typename, t.tsNullKeyword()]))
107 : t.tsTypeAnnotation(typename));
108 typenameProperty.optional = optional;
109 return typenameProperty;
110 }
111 const property = t.tsPropertySignature(t.identifier(field.responseName), t.tsTypeAnnotation(tsTypeForGraphQLType(field.type, field, stack, context)));
112 property.optional =
113 context.options.partial ||
114 field.isConditional ||
115 !graphql_1.isNonNullType(field.type);
116 return property;
117}
118function tsTypeForGraphQLType(graphQLType, field, stack, context) {
119 let type;
120 const forceNullable = context.options.partial ||
121 (field.isConditional && graphQLType === field.type);
122 const isNonNull = !forceNullable && graphql_1.isNonNullType(graphQLType);
123 const unwrappedGraphQLType = graphql_1.isNonNullType(graphQLType)
124 ? graphQLType.ofType
125 : graphQLType;
126 if (graphql_1.isScalarType(unwrappedGraphQLType)) {
127 if (utilities_1.scalarTypeMap.hasOwnProperty(unwrappedGraphQLType.name)) {
128 type = utilities_1.scalarTypeMap[unwrappedGraphQLType.name];
129 }
130 else {
131 context.file.import(unwrappedGraphQLType.name);
132 type = t.tsTypeReference(t.identifier(unwrappedGraphQLType.name));
133 }
134 }
135 else if (graphql_1.isEnumType(unwrappedGraphQLType)) {
136 context.file.import(unwrappedGraphQLType.name);
137 type = t.tsTypeReference(t.identifier(unwrappedGraphQLType.name));
138 }
139 else if (graphql_1.isListType(unwrappedGraphQLType)) {
140 const { ofType } = unwrappedGraphQLType;
141 const arrayType = tsTypeForGraphQLType(ofType, field, stack, context);
142 type = t.tsArrayType(t.isTSUnionType(arrayType) ? t.tsParenthesizedType(arrayType) : arrayType);
143 }
144 else if (graphql_1.isObjectType(unwrappedGraphQLType) ||
145 graphql_1.isInterfaceType(unwrappedGraphQLType) ||
146 graphql_1.isUnionType(unwrappedGraphQLType)) {
147 type = tsTypeForObjectField(field, unwrappedGraphQLType, stack.nested(field, unwrappedGraphQLType), context);
148 }
149 else {
150 type = t.tsAnyKeyword();
151 }
152 return isNonNull ? type : t.tsUnionType([type, t.tsNullKeyword()]);
153}
154function variablesInterface(variables, context) {
155 return t.tsInterfaceDeclaration(t.identifier('Variables'), null, null, t.tsInterfaceBody(variables
156 .filter(graphql_tool_utilities_1.isTypedVariable)
157 .map((variable) => tsPropertyForVariable(variable, context))));
158}
159exports.variablesInterface = variablesInterface;
160function tsPropertyForVariable({ name, type }, context) {
161 const property = t.tsPropertySignature(t.identifier(name), t.tsTypeAnnotation(tsTypeForGraphQLInputType(type, context)));
162 property.optional = !graphql_1.isNonNullType(type);
163 return property;
164}
165function tsTypeForGraphQLInputType(graphQLType, context) {
166 let type;
167 const unwrappedGraphQLType = graphql_1.isNonNullType(graphQLType)
168 ? graphQLType.ofType
169 : graphQLType;
170 if (graphql_1.isScalarType(unwrappedGraphQLType)) {
171 if (utilities_1.scalarTypeMap.hasOwnProperty(unwrappedGraphQLType.name)) {
172 type = utilities_1.scalarTypeMap[unwrappedGraphQLType.name];
173 }
174 else {
175 context.file.import(unwrappedGraphQLType.name);
176 type = t.tsTypeReference(t.identifier(unwrappedGraphQLType.name));
177 }
178 }
179 else if (graphql_1.isEnumType(unwrappedGraphQLType) ||
180 graphql_1.isInputObjectType(unwrappedGraphQLType)) {
181 context.file.import(unwrappedGraphQLType.name);
182 type = t.tsTypeReference(t.identifier(unwrappedGraphQLType.name));
183 }
184 else {
185 const { ofType } = unwrappedGraphQLType;
186 const arrayType = tsTypeForGraphQLInputType(ofType, context);
187 type = t.tsArrayType(graphql_1.isNonNullType(ofType) ? arrayType : t.tsParenthesizedType(arrayType));
188 }
189 return graphql_1.isNonNullType(graphQLType)
190 ? type
191 : t.tsUnionType([type, t.tsNullKeyword()]);
192}