1 | "use strict";
|
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
4 | };
|
5 | Object.defineProperty(exports, "__esModule", { value: true });
|
6 | exports.SwiftAPIGenerator = exports.generateSource = void 0;
|
7 | const path_1 = __importDefault(require("path"));
|
8 | const graphql_1 = require("graphql");
|
9 | const language_1 = require("./language");
|
10 | const helpers_1 = require("./helpers");
|
11 | const graphql_2 = require("apollo-codegen-core/lib/utilities/graphql");
|
12 | const typeCase_1 = require("apollo-codegen-core/lib/compiler/visitors/typeCase");
|
13 | const collectFragmentsReferenced_1 = require("apollo-codegen-core/lib/compiler/visitors/collectFragmentsReferenced");
|
14 | const generateOperationId_1 = require("apollo-codegen-core/lib/compiler/visitors/generateOperationId");
|
15 | const collectAndMergeFields_1 = require("apollo-codegen-core/lib/compiler/visitors/collectAndMergeFields");
|
16 | require("apollo-codegen-core/lib/utilities/array");
|
17 | const { join, wrap } = language_1.SwiftSource;
|
18 | function generateSource(context, outputIndividualFiles, suppressMultilineStringLiterals, only) {
|
19 | const generator = new SwiftAPIGenerator(context);
|
20 | if (outputIndividualFiles) {
|
21 | generator.withinFile(`Types.graphql.swift`, () => {
|
22 | generator.fileHeader();
|
23 | generator.namespaceDeclaration(context.options.namespace, () => {
|
24 | context.typesUsed.forEach(type => {
|
25 | generator.typeDeclarationForGraphQLType(type, true);
|
26 | });
|
27 | });
|
28 | });
|
29 | const inputFilePaths = new Set();
|
30 | Object.values(context.operations).forEach(operation => {
|
31 | inputFilePaths.add(operation.filePath);
|
32 | });
|
33 | Object.values(context.fragments).forEach(fragment => {
|
34 | inputFilePaths.add(fragment.filePath);
|
35 | });
|
36 | for (const inputFilePath of inputFilePaths) {
|
37 | if (only && inputFilePath !== only)
|
38 | continue;
|
39 | generator.withinFile(`${path_1.default.basename(inputFilePath)}.swift`, () => {
|
40 | generator.fileHeader();
|
41 | generator.namespaceExtensionDeclaration(context.options.namespace, () => {
|
42 | Object.values(context.operations).forEach(operation => {
|
43 | if (operation.filePath === inputFilePath) {
|
44 | generator.classDeclarationForOperation(operation, true, suppressMultilineStringLiterals);
|
45 | }
|
46 | });
|
47 | Object.values(context.fragments).forEach(fragment => {
|
48 | if (fragment.filePath === inputFilePath) {
|
49 | generator.structDeclarationForFragment(fragment, true, suppressMultilineStringLiterals);
|
50 | }
|
51 | });
|
52 | });
|
53 | });
|
54 | }
|
55 | }
|
56 | else {
|
57 | generator.fileHeader();
|
58 | generator.namespaceDeclaration(context.options.namespace, () => {
|
59 | context.typesUsed.forEach(type => {
|
60 | generator.typeDeclarationForGraphQLType(type, false);
|
61 | });
|
62 | Object.values(context.operations).forEach(operation => {
|
63 | generator.classDeclarationForOperation(operation, false, suppressMultilineStringLiterals);
|
64 | });
|
65 | Object.values(context.fragments).forEach(fragment => {
|
66 | generator.structDeclarationForFragment(fragment, false, suppressMultilineStringLiterals);
|
67 | });
|
68 | });
|
69 | }
|
70 | return generator;
|
71 | }
|
72 | exports.generateSource = generateSource;
|
73 | class SwiftAPIGenerator extends language_1.SwiftGenerator {
|
74 | constructor(context) {
|
75 | super(context);
|
76 | this.helpers = new helpers_1.Helpers(context.options);
|
77 | }
|
78 | fileHeader() {
|
79 | this.printOnNewline(language_1.SwiftSource.raw `// @generated`);
|
80 | this.printOnNewline(language_1.SwiftSource.raw `// This file was automatically generated and should not be edited.`);
|
81 | this.printNewline();
|
82 | this.printOnNewline(language_1.swift `import Apollo`);
|
83 | this.printOnNewline(language_1.swift `import Foundation`);
|
84 | }
|
85 | classDeclarationForOperation(operation, outputIndividualFiles, suppressMultilineStringLiterals) {
|
86 | const { operationName, operationType, variables, source, selectionSet } = operation;
|
87 | let className;
|
88 | let protocol;
|
89 | switch (operationType) {
|
90 | case "query":
|
91 | className = `${this.helpers.operationClassName(operationName)}Query`;
|
92 | protocol = "GraphQLQuery";
|
93 | break;
|
94 | case "mutation":
|
95 | className = `${this.helpers.operationClassName(operationName)}Mutation`;
|
96 | protocol = "GraphQLMutation";
|
97 | break;
|
98 | case "subscription":
|
99 | className = `${this.helpers.operationClassName(operationName)}Subscription`;
|
100 | protocol = "GraphQLSubscription";
|
101 | break;
|
102 | default:
|
103 | throw new graphql_1.GraphQLError(`Unsupported operation type "${operationType}"`);
|
104 | }
|
105 | const { options: { namespace }, fragments } = this.context;
|
106 | const isRedundant = !!namespace && outputIndividualFiles;
|
107 | const modifiers = isRedundant ? ["final"] : ["public", "final"];
|
108 | this.classDeclaration({
|
109 | className,
|
110 | modifiers,
|
111 | adoptedProtocols: [protocol]
|
112 | }, () => {
|
113 | if (source) {
|
114 | this.comment("The raw GraphQL definition of this operation.");
|
115 | this.printOnNewline(language_1.swift `public let operationDefinition: String =`);
|
116 | this.withIndent(() => {
|
117 | this.multilineString(source, suppressMultilineStringLiterals);
|
118 | });
|
119 | }
|
120 | this.printNewlineIfNeeded();
|
121 | this.printOnNewline(language_1.swift `public let operationName: String = ${language_1.SwiftSource.string(operationName)}`);
|
122 | const fragmentsReferenced = collectFragmentsReferenced_1.collectFragmentsReferenced(operation.selectionSet, fragments);
|
123 | if (this.context.options.generateOperationIds) {
|
124 | const { operationId, sourceWithFragments } = generateOperationId_1.generateOperationId(operation, fragments, fragmentsReferenced);
|
125 | operation.operationId = operationId;
|
126 | operation.sourceWithFragments = sourceWithFragments;
|
127 | this.printNewlineIfNeeded();
|
128 | this.printOnNewline(language_1.swift `public let operationIdentifier: String? = ${language_1.SwiftSource.string(operationId)}`);
|
129 | }
|
130 | if (fragmentsReferenced.size > 0) {
|
131 | this.printNewlineIfNeeded();
|
132 | this.printOnNewline(language_1.swift `public var queryDocument: String`);
|
133 | this.withinBlock(() => {
|
134 | this.printOnNewline(language_1.swift `var document: String = operationDefinition`);
|
135 | fragmentsReferenced.forEach(fragmentName => {
|
136 | this.printOnNewline(language_1.swift `document.append("\\n" + ${this.helpers.structNameForFragmentName(fragmentName)}.fragmentDefinition)`);
|
137 | });
|
138 | this.printOnNewline(language_1.swift `return document`);
|
139 | });
|
140 | }
|
141 | this.printNewlineIfNeeded();
|
142 | if (variables && variables.length > 0) {
|
143 | const properties = variables.map(({ name, type }) => {
|
144 | const typeName = this.helpers.typeNameFromGraphQLType(type);
|
145 | const isOptional = !(graphql_1.isNonNullType(type) ||
|
146 | (graphql_1.isListType(type) && graphql_1.isNonNullType(type.ofType)));
|
147 | return { name, propertyName: name, type, typeName, isOptional };
|
148 | });
|
149 | this.propertyDeclarations(properties);
|
150 | this.printNewlineIfNeeded();
|
151 | this.initializerDeclarationForProperties(properties);
|
152 | this.printNewlineIfNeeded();
|
153 | this.printOnNewline(language_1.swift `public var variables: GraphQLMap?`);
|
154 | this.withinBlock(() => {
|
155 | this.printOnNewline(wrap(language_1.swift `return [`, join(properties.map(({ name, propertyName }) => language_1.swift `${language_1.SwiftSource.string(name)}: ${propertyName}`), ", ") || language_1.swift `:`, language_1.swift `]`));
|
156 | });
|
157 | }
|
158 | else {
|
159 | this.initializerDeclarationForProperties([]);
|
160 | }
|
161 | this.structDeclarationForSelectionSet({
|
162 | structName: "Data",
|
163 | selectionSet
|
164 | }, outputIndividualFiles);
|
165 | });
|
166 | }
|
167 | structDeclarationForFragment({ fragmentName, selectionSet, source }, outputIndividualFiles, suppressMultilineStringLiterals) {
|
168 | const structName = this.helpers.structNameForFragmentName(fragmentName);
|
169 | this.structDeclarationForSelectionSet({
|
170 | structName,
|
171 | adoptedProtocols: ["GraphQLFragment"],
|
172 | selectionSet
|
173 | }, outputIndividualFiles, () => {
|
174 | if (source) {
|
175 | this.comment("The raw GraphQL definition of this fragment.");
|
176 | this.printOnNewline(language_1.swift `public static let fragmentDefinition: String =`);
|
177 | this.withIndent(() => {
|
178 | this.multilineString(source, suppressMultilineStringLiterals);
|
179 | });
|
180 | }
|
181 | });
|
182 | }
|
183 | structDeclarationForSelectionSet({ structName, adoptedProtocols = ["GraphQLSelectionSet"], selectionSet }, outputIndividualFiles, before) {
|
184 | const typeCase = typeCase_1.typeCaseForSelectionSet(selectionSet, !!this.context.options.mergeInFieldsFromFragmentSpreads);
|
185 | this.structDeclarationForVariant({
|
186 | structName,
|
187 | adoptedProtocols,
|
188 | variant: typeCase.default,
|
189 | typeCase
|
190 | }, outputIndividualFiles, before, () => {
|
191 | const variants = typeCase.variants.map(this.helpers.propertyFromVariant, this.helpers);
|
192 | for (const variant of variants) {
|
193 | this.propertyDeclarationForVariant(variant);
|
194 | this.structDeclarationForVariant({
|
195 | structName: variant.structName,
|
196 | variant
|
197 | }, outputIndividualFiles);
|
198 | }
|
199 | });
|
200 | }
|
201 | structDeclarationForVariant({ structName, adoptedProtocols = ["GraphQLSelectionSet"], variant, typeCase }, outputIndividualFiles, before, after) {
|
202 | const { options: { namespace, mergeInFieldsFromFragmentSpreads, omitDeprecatedEnumCases } } = this.context;
|
203 | this.structDeclaration({ structName, adoptedProtocols, namespace }, outputIndividualFiles, () => {
|
204 | if (before) {
|
205 | before();
|
206 | }
|
207 | this.printNewlineIfNeeded();
|
208 | this.printOnNewline(language_1.swift `public static let possibleTypes: [String] = [`);
|
209 | this.print(join(variant.possibleTypes.map(type => language_1.swift `${language_1.SwiftSource.string(type.name)}`), ", "));
|
210 | this.print(language_1.swift `]`);
|
211 | this.printNewlineIfNeeded();
|
212 | this.printOnNewline(language_1.swift `public static var selections: [GraphQLSelection] {`);
|
213 | this.withIndent(() => {
|
214 | this.printOnNewline(language_1.swift `return `);
|
215 | if (typeCase) {
|
216 | this.typeCaseInitialization(typeCase);
|
217 | }
|
218 | else {
|
219 | this.selectionSetInitialization(variant);
|
220 | }
|
221 | });
|
222 | this.printOnNewline(language_1.swift `}`);
|
223 | this.printNewlineIfNeeded();
|
224 | this.printOnNewline(language_1.swift `public private(set) var resultMap: ResultMap`);
|
225 | this.printNewlineIfNeeded();
|
226 | this.printOnNewline(language_1.swift `public init(unsafeResultMap: ResultMap)`);
|
227 | this.withinBlock(() => {
|
228 | this.printOnNewline(language_1.swift `self.resultMap = unsafeResultMap`);
|
229 | });
|
230 | if (typeCase) {
|
231 | this.initializersForTypeCase(typeCase);
|
232 | }
|
233 | else {
|
234 | this.initializersForVariant(variant);
|
235 | }
|
236 | const fields = collectAndMergeFields_1.collectAndMergeFields(variant, !!mergeInFieldsFromFragmentSpreads).map(field => this.helpers.propertyFromField(field));
|
237 | const fragmentSpreads = variant.fragmentSpreads.map(fragmentSpread => {
|
238 | const isConditional = variant.possibleTypes.some(type => !fragmentSpread.selectionSet.possibleTypes.includes(type));
|
239 | return this.helpers.propertyFromFragmentSpread(fragmentSpread, isConditional);
|
240 | });
|
241 | fields.forEach(this.propertyDeclarationForField, this);
|
242 | if (fragmentSpreads.length > 0) {
|
243 | this.printNewlineIfNeeded();
|
244 | this.printOnNewline(language_1.swift `public var fragments: Fragments`);
|
245 | this.withinBlock(() => {
|
246 | this.printOnNewline(language_1.swift `get`);
|
247 | this.withinBlock(() => {
|
248 | this.printOnNewline(language_1.swift `return Fragments(unsafeResultMap: resultMap)`);
|
249 | });
|
250 | this.printOnNewline(language_1.swift `set`);
|
251 | this.withinBlock(() => {
|
252 | this.printOnNewline(language_1.swift `resultMap += newValue.resultMap`);
|
253 | });
|
254 | });
|
255 | this.structDeclaration({
|
256 | structName: "Fragments"
|
257 | }, outputIndividualFiles, () => {
|
258 | this.printOnNewline(language_1.swift `public private(set) var resultMap: ResultMap`);
|
259 | this.printNewlineIfNeeded();
|
260 | this.printOnNewline(language_1.swift `public init(unsafeResultMap: ResultMap)`);
|
261 | this.withinBlock(() => {
|
262 | this.printOnNewline(language_1.swift `self.resultMap = unsafeResultMap`);
|
263 | });
|
264 | for (const fragmentSpread of fragmentSpreads) {
|
265 | const { propertyName, typeName, structName, isConditional } = fragmentSpread;
|
266 | this.printNewlineIfNeeded();
|
267 | this.printOnNewline(language_1.swift `public var ${propertyName}: ${typeName}`);
|
268 | this.withinBlock(() => {
|
269 | this.printOnNewline(language_1.swift `get`);
|
270 | this.withinBlock(() => {
|
271 | if (isConditional) {
|
272 | this.printOnNewline(language_1.swift `if !${structName}.possibleTypes.contains(resultMap["__typename"]! as! String) { return nil }`);
|
273 | }
|
274 | this.printOnNewline(language_1.swift `return ${structName}(unsafeResultMap: resultMap)`);
|
275 | });
|
276 | this.printOnNewline(language_1.swift `set`);
|
277 | this.withinBlock(() => {
|
278 | if (isConditional) {
|
279 | this.printOnNewline(language_1.swift `guard let newValue = newValue else { return }`);
|
280 | this.printOnNewline(language_1.swift `resultMap += newValue.resultMap`);
|
281 | }
|
282 | else {
|
283 | this.printOnNewline(language_1.swift `resultMap += newValue.resultMap`);
|
284 | }
|
285 | });
|
286 | });
|
287 | }
|
288 | });
|
289 | }
|
290 | for (const field of fields) {
|
291 | if (graphql_1.isCompositeType(graphql_1.getNamedType(field.type)) && field.selectionSet) {
|
292 | this.structDeclarationForSelectionSet({
|
293 | structName: field.structName,
|
294 | selectionSet: field.selectionSet
|
295 | }, outputIndividualFiles);
|
296 | }
|
297 | }
|
298 | if (after) {
|
299 | after();
|
300 | }
|
301 | });
|
302 | }
|
303 | initializersForTypeCase(typeCase) {
|
304 | const variants = typeCase.variants;
|
305 | if (variants.length == 0) {
|
306 | this.initializersForVariant(typeCase.default);
|
307 | }
|
308 | else {
|
309 | const remainder = typeCase.remainder;
|
310 | for (const variant of remainder ? [remainder, ...variants] : variants) {
|
311 | this.initializersForVariant(variant, variant === remainder
|
312 | ? undefined
|
313 | : this.helpers.structNameForVariant(variant), false);
|
314 | }
|
315 | }
|
316 | }
|
317 | initializersForVariant(variant, namespace, useInitializerIfPossible = true) {
|
318 | if (useInitializerIfPossible && variant.possibleTypes.length == 1) {
|
319 | const properties = this.helpers.propertiesForSelectionSet(variant);
|
320 | if (!properties)
|
321 | return;
|
322 | this.printNewlineIfNeeded();
|
323 | this.printOnNewline(language_1.swift `public init`);
|
324 | this.parametersForProperties(properties);
|
325 | this.withinBlock(() => {
|
326 | this.printOnNewline(wrap(language_1.swift `self.init(unsafeResultMap: [`, join([
|
327 | language_1.swift `"__typename": ${language_1.SwiftSource.string(variant.possibleTypes[0].toString())}`,
|
328 | ...properties.map(p => this.propertyAssignmentForField(p, properties))
|
329 | ], ", ") || language_1.swift `:`, language_1.swift `])`));
|
330 | });
|
331 | }
|
332 | else {
|
333 | const structName = this.scope.typeName;
|
334 | for (const possibleType of variant.possibleTypes) {
|
335 | const properties = this.helpers.propertiesForSelectionSet({
|
336 | possibleTypes: [possibleType],
|
337 | selections: variant.selections
|
338 | }, namespace);
|
339 | if (!properties)
|
340 | continue;
|
341 | this.printNewlineIfNeeded();
|
342 | this.printOnNewline(language_1.SwiftSource.raw `public static func make${possibleType}`);
|
343 | this.parametersForProperties(properties);
|
344 | this.print(language_1.swift ` -> ${structName}`);
|
345 | this.withinBlock(() => {
|
346 | this.printOnNewline(wrap(language_1.swift `return ${structName}(unsafeResultMap: [`, join([
|
347 | language_1.swift `"__typename": ${language_1.SwiftSource.string(possibleType.toString())}`,
|
348 | ...properties.map(p => this.propertyAssignmentForField(p, properties))
|
349 | ], ", ") || language_1.swift `:`, language_1.swift `])`));
|
350 | });
|
351 | }
|
352 | }
|
353 | }
|
354 | propertyAssignmentForField(field, properties) {
|
355 | const { responseKey, propertyName, type, isConditional, structName } = field;
|
356 | const parameterName = this.helpers.internalParameterName(propertyName, properties);
|
357 | const valueExpression = graphql_1.isCompositeType(graphql_1.getNamedType(type))
|
358 | ? this.helpers.mapExpressionForType(type, isConditional, expression => language_1.swift `${expression}.resultMap`, language_1.SwiftSource.identifier(parameterName), structName, "ResultMap")
|
359 | : language_1.SwiftSource.identifier(parameterName);
|
360 | return language_1.swift `${language_1.SwiftSource.string(responseKey)}: ${valueExpression}`;
|
361 | }
|
362 | propertyDeclarationForField(field) {
|
363 | const { responseKey, propertyName, typeName, type, isOptional, isConditional } = field;
|
364 | const unmodifiedFieldType = graphql_1.getNamedType(type);
|
365 | this.printNewlineIfNeeded();
|
366 | this.comment(field.description);
|
367 | this.deprecationAttributes(field.isDeprecated, field.deprecationReason);
|
368 | this.printOnNewline(language_1.swift `public var ${propertyName}: ${typeName}`);
|
369 | this.withinBlock(() => {
|
370 | if (graphql_1.isCompositeType(unmodifiedFieldType)) {
|
371 | const structName = this.helpers.structNameForPropertyName(responseKey);
|
372 | if (graphql_2.isList(type)) {
|
373 | this.printOnNewline(language_1.swift `get`);
|
374 | this.withinBlock(() => {
|
375 | const resultMapTypeName = this.helpers.typeNameFromGraphQLType(type, "ResultMap", false);
|
376 | let expression;
|
377 | if (isOptional) {
|
378 | expression = language_1.swift `(resultMap[${language_1.SwiftSource.string(responseKey)}] as? ${resultMapTypeName})`;
|
379 | }
|
380 | else {
|
381 | expression = language_1.swift `(resultMap[${language_1.SwiftSource.string(responseKey)}] as! ${resultMapTypeName})`;
|
382 | }
|
383 | this.printOnNewline(language_1.swift `return ${this.helpers.mapExpressionForType(type, isConditional, expression => language_1.swift `${structName}(unsafeResultMap: ${expression})`, expression, "ResultMap", structName)}`);
|
384 | });
|
385 | this.printOnNewline(language_1.swift `set`);
|
386 | this.withinBlock(() => {
|
387 | let newValueExpression = this.helpers.mapExpressionForType(type, isConditional, expression => language_1.swift `${expression}.resultMap`, language_1.swift `newValue`, structName, "ResultMap");
|
388 | this.printOnNewline(language_1.swift `resultMap.updateValue(${newValueExpression}, forKey: ${language_1.SwiftSource.string(responseKey)})`);
|
389 | });
|
390 | }
|
391 | else {
|
392 | this.printOnNewline(language_1.swift `get`);
|
393 | this.withinBlock(() => {
|
394 | if (isOptional) {
|
395 | this.printOnNewline(language_1.swift `return (resultMap[${language_1.SwiftSource.string(responseKey)}] as? ResultMap).flatMap { ${structName}(unsafeResultMap: $0) }`);
|
396 | }
|
397 | else {
|
398 | this.printOnNewline(language_1.swift `return ${structName}(unsafeResultMap: resultMap[${language_1.SwiftSource.string(responseKey)}]! as! ResultMap)`);
|
399 | }
|
400 | });
|
401 | this.printOnNewline(language_1.swift `set`);
|
402 | this.withinBlock(() => {
|
403 | let newValueExpression;
|
404 | if (isOptional) {
|
405 | newValueExpression = "newValue?.resultMap";
|
406 | }
|
407 | else {
|
408 | newValueExpression = "newValue.resultMap";
|
409 | }
|
410 | this.printOnNewline(language_1.swift `resultMap.updateValue(${newValueExpression}, forKey: ${language_1.SwiftSource.string(responseKey)})`);
|
411 | });
|
412 | }
|
413 | }
|
414 | else {
|
415 | this.printOnNewline(language_1.swift `get`);
|
416 | this.withinBlock(() => {
|
417 | if (isOptional) {
|
418 | this.printOnNewline(language_1.swift `return resultMap[${language_1.SwiftSource.string(responseKey)}] as? ${typeName.slice(0, -1)}`);
|
419 | }
|
420 | else {
|
421 | this.printOnNewline(language_1.swift `return resultMap[${language_1.SwiftSource.string(responseKey)}]! as! ${typeName}`);
|
422 | }
|
423 | });
|
424 | this.printOnNewline(language_1.swift `set`);
|
425 | this.withinBlock(() => {
|
426 | this.printOnNewline(language_1.swift `resultMap.updateValue(newValue, forKey: ${language_1.SwiftSource.string(responseKey)})`);
|
427 | });
|
428 | }
|
429 | });
|
430 | }
|
431 | propertyDeclarationForVariant(variant) {
|
432 | const { propertyName, typeName, structName } = variant;
|
433 | this.printNewlineIfNeeded();
|
434 | this.printOnNewline(language_1.swift `public var ${propertyName}: ${typeName}`);
|
435 | this.withinBlock(() => {
|
436 | this.printOnNewline(language_1.swift `get`);
|
437 | this.withinBlock(() => {
|
438 | this.printOnNewline(language_1.swift `if !${structName}.possibleTypes.contains(__typename) { return nil }`);
|
439 | this.printOnNewline(language_1.swift `return ${structName}(unsafeResultMap: resultMap)`);
|
440 | });
|
441 | this.printOnNewline(language_1.swift `set`);
|
442 | this.withinBlock(() => {
|
443 | this.printOnNewline(language_1.swift `guard let newValue = newValue else { return }`);
|
444 | this.printOnNewline(language_1.swift `resultMap = newValue.resultMap`);
|
445 | });
|
446 | });
|
447 | }
|
448 | initializerDeclarationForProperties(properties) {
|
449 | this.printOnNewline(language_1.swift `public init`);
|
450 | this.parametersForProperties(properties);
|
451 | this.withinBlock(() => {
|
452 | properties.forEach(({ propertyName }) => {
|
453 | this.printOnNewline(language_1.swift `self.${propertyName} = ${this.helpers.internalParameterName(propertyName, properties)}`);
|
454 | });
|
455 | });
|
456 | }
|
457 | parametersForProperties(properties) {
|
458 | this.print(language_1.swift `(`);
|
459 | this.print(join(properties.map(({ propertyName, typeName, isOptional }) => {
|
460 | const internalName = this.helpers.internalParameterName(propertyName, properties);
|
461 | const decl = internalName === propertyName
|
462 | ? propertyName
|
463 | : language_1.swift `${propertyName} ${internalName}`;
|
464 | return join([
|
465 | language_1.swift `${decl}: ${typeName}`,
|
466 | isOptional ? language_1.swift ` = nil` : undefined
|
467 | ]);
|
468 | }), ", "));
|
469 | this.print(language_1.swift `)`);
|
470 | }
|
471 | typeCaseInitialization(typeCase) {
|
472 | if (typeCase.variants.length < 1) {
|
473 | this.selectionSetInitialization(typeCase.default);
|
474 | return;
|
475 | }
|
476 | this.print(language_1.swift `[`);
|
477 | this.withIndent(() => {
|
478 | this.printOnNewline(language_1.swift `GraphQLTypeCase(`);
|
479 | this.withIndent(() => {
|
480 | this.printOnNewline(language_1.swift `variants: [`);
|
481 | this.print(join(typeCase.variants.flatMap(variant => {
|
482 | const structName = this.helpers.structNameForVariant(variant);
|
483 | return variant.possibleTypes.map(type => language_1.swift `${language_1.SwiftSource.string(type.toString())}: ${structName}.selections`);
|
484 | }), ", "));
|
485 | this.print(language_1.swift `],`);
|
486 | this.printOnNewline(language_1.swift `default: `);
|
487 | this.selectionSetInitialization(typeCase.default);
|
488 | });
|
489 | this.printOnNewline(language_1.swift `)`);
|
490 | });
|
491 | this.printOnNewline(language_1.swift `]`);
|
492 | }
|
493 | selectionSetInitialization(selectionSet) {
|
494 | this.print(language_1.swift `[`);
|
495 | this.withIndent(() => {
|
496 | for (const selection of selectionSet.selections) {
|
497 | switch (selection.kind) {
|
498 | case "Field": {
|
499 | const { name, alias, args, type } = selection;
|
500 | const responseKey = selection.alias || selection.name;
|
501 | const structName = this.helpers.structNameForPropertyName(responseKey);
|
502 | this.printOnNewline(language_1.swift `GraphQLField(`);
|
503 | this.print(join([
|
504 | language_1.swift `${language_1.SwiftSource.string(name)}`,
|
505 | alias
|
506 | ? language_1.swift `alias: ${language_1.SwiftSource.string(alias)}`
|
507 | : undefined,
|
508 | args && args.length
|
509 | ? language_1.swift `arguments: ${this.helpers.dictionaryLiteralForFieldArguments(args)}`
|
510 | : undefined,
|
511 | language_1.swift `type: ${this.helpers.fieldTypeEnum(type, structName)}`
|
512 | ], ", "));
|
513 | this.print(language_1.swift `),`);
|
514 | break;
|
515 | }
|
516 | case "BooleanCondition":
|
517 | this.printOnNewline(language_1.swift `GraphQLBooleanCondition(`);
|
518 | this.print(join([
|
519 | language_1.swift `variableName: ${language_1.SwiftSource.string(selection.variableName)}`,
|
520 | language_1.swift `inverted: ${selection.inverted}`,
|
521 | language_1.swift `selections: `
|
522 | ], ", "));
|
523 | this.selectionSetInitialization(selection.selectionSet);
|
524 | this.print(language_1.swift `),`);
|
525 | break;
|
526 | case "TypeCondition": {
|
527 | this.printOnNewline(language_1.swift `GraphQLTypeCondition(`);
|
528 | this.print(join([
|
529 | language_1.swift `possibleTypes: [${join(selection.selectionSet.possibleTypes.map(type => language_1.swift `${language_1.SwiftSource.string(type.name)}`), ", ")}]`,
|
530 | language_1.swift `selections: `
|
531 | ], ", "));
|
532 | this.selectionSetInitialization(selection.selectionSet);
|
533 | this.print(language_1.swift `),`);
|
534 | break;
|
535 | }
|
536 | case "FragmentSpread": {
|
537 | const structName = this.helpers.structNameForFragmentName(selection.fragmentName);
|
538 | this.printOnNewline(language_1.swift `GraphQLFragmentSpread(${structName}.self),`);
|
539 | break;
|
540 | }
|
541 | }
|
542 | }
|
543 | });
|
544 | this.printOnNewline(language_1.swift `]`);
|
545 | }
|
546 | typeDeclarationForGraphQLType(type, outputIndividualFiles) {
|
547 | if (graphql_1.isEnumType(type)) {
|
548 | this.enumerationDeclaration(type);
|
549 | }
|
550 | else if (graphql_1.isInputObjectType(type)) {
|
551 | this.structDeclarationForInputObjectType(type, outputIndividualFiles);
|
552 | }
|
553 | }
|
554 | enumerationDeclaration(type) {
|
555 | const { name, description } = type;
|
556 | const values = type.getValues().filter(value => {
|
557 | return (!value.isDeprecated || !this.context.options.omitDeprecatedEnumCases);
|
558 | });
|
559 | this.printNewlineIfNeeded();
|
560 | this.comment(description || undefined);
|
561 | this.printOnNewline(language_1.swift `public enum ${name}: RawRepresentable, Equatable, Hashable, CaseIterable, Apollo.JSONDecodable, Apollo.JSONEncodable`);
|
562 | this.withinBlock(() => {
|
563 | this.printOnNewline(language_1.swift `public typealias RawValue = String`);
|
564 | values.forEach(value => {
|
565 | this.comment(value.description || undefined);
|
566 | this.deprecationAttributes(value.isDeprecated, value.deprecationReason || undefined);
|
567 | this.printOnNewline(language_1.swift `case ${this.helpers.enumCaseName(value.name)}`);
|
568 | });
|
569 | this.comment("Auto generated constant for unknown enum values");
|
570 | this.printOnNewline(language_1.swift `case __unknown(RawValue)`);
|
571 | this.printNewlineIfNeeded();
|
572 | this.printOnNewline(language_1.swift `public init?(rawValue: RawValue)`);
|
573 | this.withinBlock(() => {
|
574 | this.printOnNewline(language_1.swift `switch rawValue`);
|
575 | this.withinBlock(() => {
|
576 | values.forEach(value => {
|
577 | this.printOnNewline(language_1.swift `case ${language_1.SwiftSource.string(value.value)}: self = ${this.helpers.enumDotCaseName(value.name)}`);
|
578 | });
|
579 | this.printOnNewline(language_1.swift `default: self = .__unknown(rawValue)`);
|
580 | });
|
581 | });
|
582 | this.printNewlineIfNeeded();
|
583 | this.printOnNewline(language_1.swift `public var rawValue: RawValue`);
|
584 | this.withinBlock(() => {
|
585 | this.printOnNewline(language_1.swift `switch self`);
|
586 | this.withinBlock(() => {
|
587 | values.forEach(value => {
|
588 | this.printOnNewline(language_1.swift `case ${this.helpers.enumDotCaseName(value.name)}: return ${language_1.SwiftSource.string(value.value)}`);
|
589 | });
|
590 | this.printOnNewline(language_1.swift `case .__unknown(let value): return value`);
|
591 | });
|
592 | });
|
593 | this.printNewlineIfNeeded();
|
594 | this.printOnNewline(language_1.swift `public static func == (lhs: ${name}, rhs: ${name}) -> Bool`);
|
595 | this.withinBlock(() => {
|
596 | this.printOnNewline(language_1.swift `switch (lhs, rhs)`);
|
597 | this.withinBlock(() => {
|
598 | values.forEach(value => {
|
599 | const enumDotCaseName = this.helpers.enumDotCaseName(value.name);
|
600 | const tuple = language_1.swift `(${enumDotCaseName}, ${enumDotCaseName})`;
|
601 | this.printOnNewline(language_1.swift `case ${tuple}: return true`);
|
602 | });
|
603 | this.printOnNewline(language_1.swift `case (.__unknown(let lhsValue), .__unknown(let rhsValue)): return lhsValue == rhsValue`);
|
604 | this.printOnNewline(language_1.swift `default: return false`);
|
605 | });
|
606 | });
|
607 | this.printNewlineIfNeeded();
|
608 | this.printOnNewline(language_1.swift `public static var allCases: [${name}]`);
|
609 | this.withinBlock(() => {
|
610 | this.printOnNewline(language_1.swift `return [`);
|
611 | values.forEach(value => {
|
612 | const enumDotCaseName = this.helpers.enumDotCaseName(value.name);
|
613 | this.withIndent(() => {
|
614 | this.printOnNewline(language_1.swift `${enumDotCaseName},`);
|
615 | });
|
616 | });
|
617 | this.printOnNewline(language_1.swift `]`);
|
618 | });
|
619 | });
|
620 | }
|
621 | structDeclarationForInputObjectType(type, outputIndividualFiles) {
|
622 | const { name: structName, description } = type;
|
623 | const adoptedProtocols = ["GraphQLMapConvertible"];
|
624 | const fields = Object.values(type.getFields());
|
625 | const properties = fields.map(this.helpers.propertyFromInputField, this.helpers);
|
626 | properties.forEach(property => {
|
627 | if (property.isOptional) {
|
628 | property.typeName = `Swift.Optional<${property.typeName}>`;
|
629 | }
|
630 | });
|
631 | this.structDeclaration({ structName, description: description || undefined, adoptedProtocols }, outputIndividualFiles, () => {
|
632 | this.printOnNewline(language_1.swift `public var graphQLMap: GraphQLMap`);
|
633 | this.printNewlineIfNeeded();
|
634 | if (properties.length > 0) {
|
635 | this.comment("- Parameters:");
|
636 | properties.forEach(property => {
|
637 | var propertyDescription = "";
|
638 | if (property.description) {
|
639 | propertyDescription = `: ${property.description}`;
|
640 | }
|
641 | this.comment(` - ${property.propertyName}${propertyDescription}`, false);
|
642 | });
|
643 | }
|
644 | this.printOnNewline(language_1.swift `public init`);
|
645 | this.print(language_1.swift `(`);
|
646 | this.print(join(properties.map(({ propertyName, typeName, isOptional }) => {
|
647 | const internalName = this.helpers.internalParameterName(propertyName, properties);
|
648 | const decl = internalName === propertyName
|
649 | ? propertyName
|
650 | : language_1.swift `${propertyName} ${internalName}`;
|
651 | return join([
|
652 | language_1.swift `${decl}: ${typeName}`,
|
653 | isOptional ? language_1.swift ` = nil` : undefined
|
654 | ]);
|
655 | }), ", "));
|
656 | this.print(language_1.swift `)`);
|
657 | this.withinBlock(() => {
|
658 | this.printOnNewline(wrap(language_1.swift `graphQLMap = [`, join(properties.map(({ name, propertyName }) => language_1.swift `${language_1.SwiftSource.string(name)}: ${this.helpers.internalParameterName(propertyName, properties)}`), ", ") || language_1.swift `:`, language_1.swift `]`));
|
659 | });
|
660 | for (const { name, propertyName, typeName, description, isOptional } of properties) {
|
661 | this.printNewlineIfNeeded();
|
662 | this.comment(description || undefined);
|
663 | this.printOnNewline(language_1.swift `public var ${propertyName}: ${typeName}`);
|
664 | this.withinBlock(() => {
|
665 | this.printOnNewline(language_1.swift `get`);
|
666 | this.withinBlock(() => {
|
667 | if (isOptional) {
|
668 | this.printOnNewline(language_1.swift `return graphQLMap[${language_1.SwiftSource.string(name)}] as? ${typeName} ?? ${typeName}.none`);
|
669 | }
|
670 | else {
|
671 | this.printOnNewline(language_1.swift `return graphQLMap[${language_1.SwiftSource.string(name)}] as! ${typeName}`);
|
672 | }
|
673 | });
|
674 | this.printOnNewline(language_1.swift `set`);
|
675 | this.withinBlock(() => {
|
676 | this.printOnNewline(language_1.swift `graphQLMap.updateValue(newValue, forKey: ${language_1.SwiftSource.string(name)})`);
|
677 | });
|
678 | });
|
679 | }
|
680 | });
|
681 | }
|
682 | }
|
683 | exports.SwiftAPIGenerator = SwiftAPIGenerator;
|
684 |
|
\ | No newline at end of file |