Skip to content

Commit be3fb26

Browse files
gh-action-runnergh-action-runner
authored andcommitted
Squashed 'apollo-ios-codegen/' changes from 163d398c..d689a45f
d689a45f feature: Reduce Generated Schema Types (#601) git-subtree-dir: apollo-ios-codegen git-subtree-split: d689a45f6ddd527fc77d8f62a7f2f0ad66b8d2f7
1 parent c66fa9d commit be3fb26

14 files changed

+140
-24
lines changed

Sources/ApolloCodegenLib/ApolloCodegen.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ public class ApolloCodegen {
191191
document: operationsDocument,
192192
experimentalLegacySafelistingCompatibleOperations:
193193
config.experimentalFeatures.legacySafelistingCompatibleOperations,
194+
reduceGeneratedSchemaTypes: config.options.reduceGeneratedSchemaTypes,
194195
validationOptions: validationOptions
195196
)
196197
}

Sources/ApolloCodegenLib/CodegenConfiguration/ApolloCodegenConfiguration.swift

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,8 @@ public struct ApolloCodegenConfiguration: Codable, Equatable {
652652
public let operationDocumentFormat: OperationDocumentFormat
653653
/// Customization options to be applied to the schema during code generation.
654654
public let schemaCustomization: SchemaCustomization
655+
/// Whether to reduce the number of schema types that are generated to only those that are referenced in an operation.
656+
public let reduceGeneratedSchemaTypes: Bool
655657
/// Generate import statements that are compatible with including `Apollo` via Cocoapods.
656658
///
657659
/// Cocoapods bundles all files from subspecs into the main target for a pod. This means that
@@ -703,6 +705,7 @@ public struct ApolloCodegenConfiguration: Codable, Equatable {
703705
public static let fieldMerging: FieldMerging = [.all]
704706
public static let operationDocumentFormat: OperationDocumentFormat = .definition
705707
public static let schemaCustomization: SchemaCustomization = .init()
708+
public static let reduceGeneratedSchemaTypes: Bool = false
706709
public static let cocoapodsCompatibleImportStatements: Bool = false
707710
public static let warningsOnDeprecatedUsage: Composition = .include
708711
public static let conversionStrategies: ConversionStrategies = .init()
@@ -721,6 +724,8 @@ public struct ApolloCodegenConfiguration: Codable, Equatable {
721724
/// - selectionSetInitializers: Which generated selection sets should include
722725
/// generated initializers.
723726
/// - operationDocumentFormat: How to generate the operation documents for your generated operations.
727+
/// - schemaCustomization: Customization options to be applied to the schema during code generation.
728+
/// - reduceGeneratedSchemaTypes: Whether to reduce the number of schema types that are generated to only those that are referenced in an operation.
724729
/// - cocoapodsCompatibleImportStatements: Generate import statements that are compatible with
725730
/// including `Apollo` via Cocoapods.
726731
/// - warningsOnDeprecatedUsage: Annotate generated Swift code with the Swift `available`
@@ -741,6 +746,7 @@ public struct ApolloCodegenConfiguration: Codable, Equatable {
741746
selectionSetInitializers: SelectionSetInitializers = Default.selectionSetInitializers,
742747
operationDocumentFormat: OperationDocumentFormat = Default.operationDocumentFormat,
743748
schemaCustomization: SchemaCustomization = Default.schemaCustomization,
749+
reduceGeneratedSchemaTypes: Bool = Default.reduceGeneratedSchemaTypes,
744750
cocoapodsCompatibleImportStatements: Bool = Default.cocoapodsCompatibleImportStatements,
745751
warningsOnDeprecatedUsage: Composition = Default.warningsOnDeprecatedUsage,
746752
conversionStrategies: ConversionStrategies = Default.conversionStrategies,
@@ -754,6 +760,7 @@ public struct ApolloCodegenConfiguration: Codable, Equatable {
754760
self.selectionSetInitializers = selectionSetInitializers
755761
self.operationDocumentFormat = operationDocumentFormat
756762
self.schemaCustomization = schemaCustomization
763+
self.reduceGeneratedSchemaTypes = reduceGeneratedSchemaTypes
757764
self.cocoapodsCompatibleImportStatements = cocoapodsCompatibleImportStatements
758765
self.warningsOnDeprecatedUsage = warningsOnDeprecatedUsage
759766
self.conversionStrategies = conversionStrategies
@@ -773,6 +780,7 @@ public struct ApolloCodegenConfiguration: Codable, Equatable {
773780
case apqs
774781
case operationDocumentFormat
775782
case schemaCustomization
783+
case reduceGeneratedSchemaTypes
776784
case cocoapodsCompatibleImportStatements
777785
case warningsOnDeprecatedUsage
778786
case conversionStrategies
@@ -819,6 +827,11 @@ public struct ApolloCodegenConfiguration: Codable, Equatable {
819827
SchemaCustomization.self,
820828
forKey: .schemaCustomization
821829
) ?? Default.schemaCustomization
830+
831+
reduceGeneratedSchemaTypes = try values.decodeIfPresent(
832+
Bool.self,
833+
forKey: .reduceGeneratedSchemaTypes
834+
) ?? Default.reduceGeneratedSchemaTypes
822835

823836
cocoapodsCompatibleImportStatements = try values.decodeIfPresent(
824837
Bool.self,
@@ -860,6 +873,7 @@ public struct ApolloCodegenConfiguration: Codable, Equatable {
860873
try container.encode(self.selectionSetInitializers, forKey: .selectionSetInitializers)
861874
try container.encode(self.operationDocumentFormat, forKey: .operationDocumentFormat)
862875
try container.encode(self.schemaCustomization, forKey: .schemaCustomization)
876+
try container.encode(self.reduceGeneratedSchemaTypes, forKey: .reduceGeneratedSchemaTypes)
863877
try container.encode(self.cocoapodsCompatibleImportStatements, forKey: .cocoapodsCompatibleImportStatements)
864878
try container.encode(self.warningsOnDeprecatedUsage, forKey: .warningsOnDeprecatedUsage)
865879
try container.encode(self.conversionStrategies, forKey: .conversionStrategies)
@@ -1697,6 +1711,62 @@ extension ApolloCodegenConfiguration.FileOutput {
16971711
}
16981712

16991713
extension ApolloCodegenConfiguration.OutputOptions {
1714+
/// Deprecated initializer.
1715+
///
1716+
/// - Parameters:
1717+
/// - additionalInflectionRules: Any non-default rules for pluralization or singularization
1718+
/// you wish to include.
1719+
/// - deprecatedEnumCases: How deprecated enum cases from the schema should be handled.
1720+
/// - schemaDocumentation: Whether schema documentation is added to the generated files.
1721+
/// - selectionSetInitializers: Which generated selection sets should include
1722+
/// generated initializers.
1723+
/// - operationDocumentFormat: How to generate the operation documents for your generated operations.
1724+
/// - cocoapodsCompatibleImportStatements: Generate import statements that are compatible with
1725+
/// including `Apollo` via Cocoapods.
1726+
/// - warningsOnDeprecatedUsage: Annotate generated Swift code with the Swift `available`
1727+
/// attribute and `deprecated` argument for parts of the GraphQL schema annotated with the
1728+
/// built-in `@deprecated` directive.
1729+
/// - conversionStrategies: Rules for how to convert the names of values from the schema in
1730+
/// generated code.
1731+
/// - pruneGeneratedFiles: Whether unused generated files will be automatically deleted.
1732+
/// - markOperationDefinitionsAsFinal: Whether generated GraphQL operation and local cache mutation
1733+
/// class types will be marked as `final`.
1734+
/// - appendSchemaTypeFilenameSuffix: `true` will add a filename suffix matching the schema type, the
1735+
/// default is `false`. This can be used to avoid filename conflicts when operation type names match
1736+
/// schema type names.
1737+
///
1738+
@available(*, deprecated,
1739+
renamed: "init(additionalInflectionRules:queryStringLiteralFormat:deprecatedEnumCases:schemaDocumentation:selectionSetInitializers:operationDocumentFormat:schemaCustomization:reduceGeneratedSchemaTypes:cocoapodsCompatibleImportStatements:warningsOnDeprecatedUsage:conversionStrategies:pruneGeneratedFiles:markOperationDefinitionsAsFinal:appendSchemaTypeFilenameSuffix:)"
1740+
)
1741+
public init(
1742+
additionalInflectionRules: [InflectionRule] = Default.additionalInflectionRules,
1743+
deprecatedEnumCases: ApolloCodegenConfiguration.Composition = Default.deprecatedEnumCases,
1744+
schemaDocumentation: ApolloCodegenConfiguration.Composition = Default.schemaDocumentation,
1745+
selectionSetInitializers: ApolloCodegenConfiguration.SelectionSetInitializers = Default.selectionSetInitializers,
1746+
operationDocumentFormat: ApolloCodegenConfiguration.OperationDocumentFormat = Default.operationDocumentFormat,
1747+
schemaCustomization: ApolloCodegenConfiguration.SchemaCustomization = Default.schemaCustomization,
1748+
cocoapodsCompatibleImportStatements: Bool = Default.cocoapodsCompatibleImportStatements,
1749+
warningsOnDeprecatedUsage: ApolloCodegenConfiguration.Composition = Default.warningsOnDeprecatedUsage,
1750+
conversionStrategies: ApolloCodegenConfiguration.ConversionStrategies = Default.conversionStrategies,
1751+
pruneGeneratedFiles: Bool = Default.pruneGeneratedFiles,
1752+
markOperationDefinitionsAsFinal: Bool = Default.markOperationDefinitionsAsFinal,
1753+
appendSchemaTypeFilenameSuffix: Bool = Default.appendSchemaTypeFilenameSuffix
1754+
) {
1755+
self.additionalInflectionRules = additionalInflectionRules
1756+
self.deprecatedEnumCases = deprecatedEnumCases
1757+
self.schemaDocumentation = schemaDocumentation
1758+
self.selectionSetInitializers = selectionSetInitializers
1759+
self.operationDocumentFormat = operationDocumentFormat
1760+
self.schemaCustomization = schemaCustomization
1761+
self.reduceGeneratedSchemaTypes = Default.reduceGeneratedSchemaTypes
1762+
self.cocoapodsCompatibleImportStatements = cocoapodsCompatibleImportStatements
1763+
self.warningsOnDeprecatedUsage = warningsOnDeprecatedUsage
1764+
self.conversionStrategies = conversionStrategies
1765+
self.pruneGeneratedFiles = pruneGeneratedFiles
1766+
self.markOperationDefinitionsAsFinal = markOperationDefinitionsAsFinal
1767+
self.appendSchemaTypeFilenameSuffix = appendSchemaTypeFilenameSuffix
1768+
}
1769+
17001770
/// Deprecated initializer.
17011771
///
17021772
/// - Parameters:
@@ -1746,6 +1816,7 @@ extension ApolloCodegenConfiguration.OutputOptions {
17461816
self.markOperationDefinitionsAsFinal = markOperationDefinitionsAsFinal
17471817
self.schemaCustomization = Default.schemaCustomization
17481818
self.appendSchemaTypeFilenameSuffix = Default.appendSchemaTypeFilenameSuffix
1819+
self.reduceGeneratedSchemaTypes = Default.reduceGeneratedSchemaTypes
17491820
}
17501821

17511822
/// Deprecated initializer.
@@ -1797,6 +1868,7 @@ extension ApolloCodegenConfiguration.OutputOptions {
17971868
self.markOperationDefinitionsAsFinal = markOperationDefinitionsAsFinal
17981869
self.schemaCustomization = Default.schemaCustomization
17991870
self.appendSchemaTypeFilenameSuffix = Default.appendSchemaTypeFilenameSuffix
1871+
self.reduceGeneratedSchemaTypes = Default.reduceGeneratedSchemaTypes
18001872
}
18011873

18021874
/// Whether the generated operations should use Automatic Persisted Queries.

Sources/ApolloCodegenLib/Templates/InterfaceTemplate.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ struct InterfaceTemplate: TemplateRenderer {
1818
"""
1919
\(documentation: graphqlInterface.documentation, config: config)
2020
\(graphqlInterface.name.typeNameDocumentation)
21-
static let \(graphqlInterface.render(as: .typename)) = \(config.ApolloAPITargetName).Interface(name: "\(graphqlInterface.name.schemaName)", keyFields: \(KeyFieldsTemplate()))
21+
static let \(graphqlInterface.render(as: .typename)) = \(config.ApolloAPITargetName).Interface(
22+
name: "\(graphqlInterface.name.schemaName)",
23+
keyFields: \(KeyFieldsTemplate()),
24+
implementingObjects: \(ImplementingObjectsTemplate())
25+
)
2226
"""
2327
}
2428

@@ -29,4 +33,14 @@ struct InterfaceTemplate: TemplateRenderer {
2933
[\(list: fields.map { "\"\($0)\"" })]
3034
"""
3135
}
36+
37+
private func ImplementingObjectsTemplate() -> TemplateString {
38+
return """
39+
[\(list: graphqlInterface.implementingObjects.map({ object in
40+
TemplateString("""
41+
"\(object.render(as: .typename))"
42+
""")
43+
}))]
44+
"""
45+
}
3246
}

Sources/GraphQLCompiler/ApolloCodegenFrontendBundle.swift

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

Sources/GraphQLCompiler/GraphQLJSFrontend.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,15 @@ public final class GraphQLJSFrontend {
9191
schema: GraphQLSchema,
9292
document: GraphQLDocument,
9393
experimentalLegacySafelistingCompatibleOperations: Bool = false,
94+
reduceGeneratedSchemaTypes: Bool,
9495
validationOptions: ValidationOptions
9596
) async throws -> CompilationResult {
9697
return try await library.call(
9798
"compileDocument",
9899
with: schema,
99100
document,
100101
experimentalLegacySafelistingCompatibleOperations,
102+
reduceGeneratedSchemaTypes,
101103
ValidationOptions.Bridged(from: validationOptions, bridge: self.bridge)
102104
)
103105
}

Sources/GraphQLCompiler/GraphQLSchema.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,18 +281,22 @@ public final class GraphQLInterfaceType: GraphQLAbstractType, GraphQLInterfaceIm
281281
public private(set) var interfaces: [GraphQLInterfaceType]!
282282

283283
public private(set) var keyFields: [String]!
284+
285+
public private(set) var implementingObjects: [GraphQLObjectType]!
284286

285287
/// Initializer to be used for creating mock objects in tests only.
286288
init(
287289
name: GraphQLName,
288290
documentation: String?,
289291
fields: [String: GraphQLField],
290292
interfaces: [GraphQLInterfaceType],
291-
keyFields: [String]
293+
keyFields: [String],
294+
implementingObjects: [GraphQLObjectType]
292295
) {
293296
self.fields = fields
294297
self.interfaces = interfaces
295298
self.keyFields = keyFields
299+
self.implementingObjects = implementingObjects
296300
super.init(name: name, documentation: documentation)
297301
}
298302

@@ -304,6 +308,7 @@ public final class GraphQLInterfaceType: GraphQLAbstractType, GraphQLInterfaceIm
304308
self.fields = try! bridge.invokeMethod("getFields", on: jsValue)
305309
self.interfaces = try! bridge.invokeMethod("getInterfaces", on: jsValue)
306310
self.keyFields = jsValue["_apolloKeyFields"]
311+
self.implementingObjects = jsValue["_implementingObjects"].isUndefined ? [] : Array<GraphQLObjectType>.fromJSValue(jsValue["_implementingObjects"], bridge: bridge)
307312
}
308313

309314
public override var debugDescription: String {

Sources/GraphQLCompiler/JavaScript/src/__tests__/deferDirectiveTests.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ describe("given SDL with valid defer directive", () => {
210210
);
211211

212212
it("should compile inline fragment with directive", () => {
213-
const compilationResult: CompilationResult = compileDocument(schema, document, false, emptyValidationOptions);
213+
const compilationResult: CompilationResult = compileDocument(schema, document, false, false, emptyValidationOptions);
214214
const operation = compilationResult.operations[0];
215215
const allAnimals = operation.selectionSet.selections[0] as Field;
216216
const inlineFragment = allAnimals?.selectionSet?.selections?.[0] as InlineFragment;
@@ -237,7 +237,7 @@ describe("given SDL with valid defer directive", () => {
237237
);
238238

239239
it("should compile inline fragment with directive and arguments", () => {
240-
const compilationResult: CompilationResult = compileDocument(schema, document, false, emptyValidationOptions);
240+
const compilationResult: CompilationResult = compileDocument(schema, document, false, false, emptyValidationOptions);
241241
const operation = compilationResult.operations[0];
242242
const allAnimals = operation.selectionSet.selections[0] as Field;
243243
const inlineFragment = allAnimals?.selectionSet?.selections?.[0] as InlineFragment;
@@ -270,7 +270,7 @@ describe("given SDL with valid defer directive", () => {
270270
);
271271

272272
it("should compile fragment spread with directive", () => {
273-
const compilationResult: CompilationResult = compileDocument(schema, document, false, emptyValidationOptions);
273+
const compilationResult: CompilationResult = compileDocument(schema, document, false, false, emptyValidationOptions);
274274
const operation = compilationResult.operations[0];
275275
const allAnimals = operation.selectionSet.selections[0] as Field;
276276
const inlineFragment = allAnimals?.selectionSet?.selections?.[0] as FragmentSpread;
@@ -299,7 +299,7 @@ describe("given SDL with valid defer directive", () => {
299299
);
300300

301301
it("should compile fragment spread with directive and arguments", () => {
302-
const compilationResult: CompilationResult = compileDocument(schema, document, false, emptyValidationOptions);
302+
const compilationResult: CompilationResult = compileDocument(schema, document, false, false, emptyValidationOptions);
303303
const operation = compilationResult.operations[0];
304304
const allAnimals = operation.selectionSet.selections[0] as Field;
305305
const inlineFragment = allAnimals?.selectionSet?.selections?.[0] as FragmentSpread;

Sources/GraphQLCompiler/JavaScript/src/__tests__/deprecatedEnumCasesCompilationTests.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ describe("given schema", () => {
4949
);
5050

5151
it("should compile enum values with deprecation reason", () => {
52-
const compilationResult: CompilationResult = compileDocument(schema, document, false, emptyValidationOptions);
52+
const compilationResult: CompilationResult = compileDocument(schema, document, false, false, emptyValidationOptions);
5353
const speciesEnum: GraphQLEnumType = compilationResult.referencedTypes.find(function(element) {
5454
return element.name == 'Species'
5555
}) as GraphQLEnumType

Sources/GraphQLCompiler/JavaScript/src/__tests__/inclusionConditionCompilationTests.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ describe("given schema", () => {
4848
);
4949

5050
it("should compile inline fragment with inclusion condition", () => {
51-
const compilationResult: CompilationResult = compileDocument(schema, document, false, emptyValidationOptions);
51+
const compilationResult: CompilationResult = compileDocument(schema, document, false, false, emptyValidationOptions);
5252
const operation = compilationResult.operations[0];
5353
const allAnimals = operation.selectionSet.selections[0] as Field;
5454
const inlineFragment = allAnimals?.selectionSet?.selections?.[0] as InlineFragment;

Sources/GraphQLCompiler/JavaScript/src/__tests__/referencedFragmentsTests.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ describe("operation with referencedFragments", () => {
6868
fragmentBDocument,
6969
fragmentCDocument])
7070

71-
const compilationResult: CompilationResult = compileDocument(schema, document, false, emptyValidationOptions);
71+
const compilationResult: CompilationResult = compileDocument(schema, document, false, false, emptyValidationOptions);
7272

7373
const operationA: OperationDefinition = compilationResult.operations.find(function(element) {
7474
return element.name == 'OperationA'
@@ -157,7 +157,7 @@ describe("operation with referencedFragments on child entity selection sets", ()
157157
fragmentBDocument,
158158
fragmentCDocument])
159159

160-
const compilationResult: CompilationResult = compileDocument(schema, document, false, emptyValidationOptions);
160+
const compilationResult: CompilationResult = compileDocument(schema, document, false, false, emptyValidationOptions);
161161

162162
const operationA: OperationDefinition = compilationResult.operations.find(function(element) {
163163
return element.name == 'OperationA'

0 commit comments

Comments
 (0)