diff --git a/Tests/ApolloCodegenInternalTestHelpers/MockGraphQLType.swift b/Tests/ApolloCodegenInternalTestHelpers/MockGraphQLType.swift index be17a759d..a00059be5 100644 --- a/Tests/ApolloCodegenInternalTestHelpers/MockGraphQLType.swift +++ b/Tests/ApolloCodegenInternalTestHelpers/MockGraphQLType.swift @@ -9,7 +9,7 @@ public extension GraphQLCompositeType { _ name: String = "" ) -> GraphQLCompositeType { GraphQLCompositeType( - name: name, + name: GraphQLName(schemaName: name), documentation: nil ) } @@ -23,7 +23,7 @@ public extension GraphQLObjectType { documentation: String? = nil ) -> GraphQLObjectType { GraphQLObjectType( - name: name, + name: GraphQLName(schemaName: name), documentation: documentation, fields: fields, interfaces: interfaces @@ -39,7 +39,7 @@ public extension GraphQLInterfaceType { documentation: String? = nil ) -> GraphQLInterfaceType { GraphQLInterfaceType( - name: name, + name: GraphQLName(schemaName: name), documentation: documentation, fields: fields, interfaces: interfaces @@ -54,7 +54,7 @@ public extension GraphQLUnionType { documentation: String? = nil ) -> GraphQLUnionType { GraphQLUnionType( - name: name, + name: GraphQLName(schemaName: name), documentation: documentation, types: types ) @@ -73,7 +73,7 @@ public extension GraphQLScalarType { documentation: String? = nil ) -> GraphQLScalarType { GraphQLScalarType( - name: name, + name: GraphQLName(schemaName: name), documentation: documentation, specifiedByURL: specifiedByURL ) @@ -112,7 +112,7 @@ public extension GraphQLEnumType { documentation: String? = nil ) -> GraphQLEnumType { GraphQLEnumType( - name: name, + name: GraphQLName(schemaName: name), documentation: documentation, values: values ) @@ -126,7 +126,7 @@ public extension GraphQLEnumValue { documentation: String? = nil ) -> GraphQLEnumValue { GraphQLEnumValue( - name: Name(value: name), + name: GraphQLName(schemaName: name), documentation: documentation, deprecationReason: deprecationReason ) @@ -137,12 +137,13 @@ public extension GraphQLInputObjectType { class func mock( _ name: String, fields: [GraphQLInputField] = [], - documentation: String? = nil + documentation: String? = nil, + config: ApolloCodegenConfiguration = .mock() ) -> GraphQLInputObjectType { GraphQLInputObjectType( - name: name, + name: GraphQLName(schemaName: name), documentation: documentation, - fields: OrderedDictionary.init(uniqueKeysWithValues: fields.map({ ($0.name, $0) })) + fields: OrderedDictionary.init(uniqueKeysWithValues: fields.map({ ($0.render(config: config), $0) })) ) } } @@ -156,7 +157,7 @@ public extension GraphQLInputField { deprecationReason: String? = nil ) -> GraphQLInputField { GraphQLInputField( - name: name, + name: GraphQLName(schemaName: name), type: type, documentation: documentation, deprecationReason: deprecationReason, diff --git a/Tests/ApolloCodegenInternalTestHelpers/MockIRSubscripts.swift b/Tests/ApolloCodegenInternalTestHelpers/MockIRSubscripts.swift index 1189adae6..036e8c5df 100644 --- a/Tests/ApolloCodegenInternalTestHelpers/MockIRSubscripts.swift +++ b/Tests/ApolloCodegenInternalTestHelpers/MockIRSubscripts.swift @@ -4,34 +4,34 @@ import GraphQLCompiler extension IR.Schema { public subscript(object name: String) -> GraphQLObjectType? { - return referencedTypes.objects.first { $0.name == name } + return referencedTypes.objects.first { $0.name.schemaName == name } } public subscript(interface name: String) -> GraphQLInterfaceType? { - return referencedTypes.interfaces.first { $0.name == name } + return referencedTypes.interfaces.first { $0.name.schemaName == name } } public subscript(union name: String) -> GraphQLUnionType? { - return referencedTypes.unions.first { $0.name == name } + return referencedTypes.unions.first { $0.name.schemaName == name } } public subscript(scalar name: String) -> GraphQLScalarType? { - return referencedTypes.scalars.first { $0.name == name } + return referencedTypes.scalars.first { $0.name.schemaName == name } } public subscript(enum name: String) -> GraphQLEnumType? { - return referencedTypes.enums.first { $0.name == name } + return referencedTypes.enums.first { $0.name.schemaName == name } } public subscript(inputObject name: String) -> GraphQLInputObjectType? { - return referencedTypes.inputObjects.first { $0.name == name } + return referencedTypes.inputObjects.first { $0.name.schemaName == name } } } extension CompilationResult { public subscript(type name: String) -> GraphQLNamedType? { - return referencedTypes.first { $0.name == name } + return referencedTypes.first { $0.name.schemaName == name } } public subscript(operation name: String) -> CompilationResult.OperationDefinition? { diff --git a/Tests/ApolloCodegenTests/ApolloCodegenConfigurationCodableTests.swift b/Tests/ApolloCodegenTests/ApolloCodegenConfigurationCodableTests.swift index 1ef927d1b..706185a85 100644 --- a/Tests/ApolloCodegenTests/ApolloCodegenConfigurationCodableTests.swift +++ b/Tests/ApolloCodegenTests/ApolloCodegenConfigurationCodableTests.swift @@ -43,6 +43,18 @@ class ApolloCodegenConfigurationCodableTests: XCTestCase { ], deprecatedEnumCases: .exclude, schemaDocumentation: .exclude, + schemaCustomization: .init( + customTypeNames: [ + "MyEnum": .enum( + name: "CustomEnum", + cases: [ + "CaseOne": "CustomCaseOne" + ] + ), + "MyInterface": .type(name: "CustomInterface"), + "MyObject": .type(name: "CustomObject") + ] + ), cocoapodsCompatibleImportStatements: true, warningsOnDeprecatedUsage: .exclude, conversionStrategies:.init( @@ -104,6 +116,20 @@ class ApolloCodegenConfigurationCodableTests: XCTestCase { "definition" ], "pruneGeneratedFiles" : false, + "schemaCustomization" : { + "customTypeNames" : { + "MyEnum" : { + "enum" : { + "cases" : { + "CaseOne" : "CustomCaseOne" + }, + "name" : "CustomEnum" + } + }, + "MyInterface" : "CustomInterface", + "MyObject" : "CustomObject" + } + }, "schemaDocumentation" : "exclude", "selectionSetInitializers" : { "localCacheMutations" : true diff --git a/Tests/ApolloCodegenTests/ApolloCodegenTests.swift b/Tests/ApolloCodegenTests/ApolloCodegenTests.swift index 8d83d41bb..c37404404 100644 --- a/Tests/ApolloCodegenTests/ApolloCodegenTests.swift +++ b/Tests/ApolloCodegenTests/ApolloCodegenTests.swift @@ -2484,5 +2484,117 @@ class ApolloCodegenTests: XCTestCase { expect(matches.contains(where: { $0.contains(".swiftpm") })).to(beFalse()) expect(matches.contains(where: { $0.contains(".Pods") })).to(beFalse()) } + + // MARK: - Schema Customization Tests + + func test_typeNames_givenSchemaCustomization_shouldGenerateCustomTypeNames() async throws { + // given + let schemaPath = ApolloCodegenInternalTestHelpers.Resources.AnimalKingdom.Schema.path + let operationsPath = ApolloCodegenInternalTestHelpers.Resources.url + .appendingPathComponent("animalkingdom-graphql") + .appendingPathComponent("**/*.graphql").path + + let config = ApolloCodegen.ConfigurationContext(config: ApolloCodegenConfiguration( + schemaNamespace: "AnimalKingdomAPI", + input: .init(schemaPath: schemaPath, operationSearchPaths: [operationsPath]), + output: .init( + schemaTypes: .init(path: directoryURL.path, + moduleType: .swiftPackageManager), + operations: .inSchemaModule + ), + options: .init( + schemaCustomization: .init( + customTypeNames: [ + "Crocodile": .type(name: "CustomCrocodile"), // Object + "Animal": .type(name: "CustomAnimal"), // Interface + "ClassroomPet": .type(name: "CustomClassroomPet"), // Union + "Date": .type(name: "CustomDate"), // Custom Scalar + "SkinCovering": .enum( // Enum + name: "CustomSkinCovering", + cases: [ + "HAIR": "CUSTOMHAIR" + ] + ), + "PetSearchFilters": .inputObject( // Input Object + name: "CustomPetSearchFilters", + fields: [ + "size": "customSize" + ] + ) + ] + ) + ) + ), rootURL: nil) + + let subject = ApolloCodegen( + config: config, + operationIdentifierFactory: OperationIdentifierFactory(), + itemsToGenerate: .code + ) + + // when + let compilationResult = try await subject.compileGraphQLResult() + + let ir = IRBuilder(compilationResult: compilationResult) + + subject.processSchemaCustomizations(ir: ir) + + for objType in ir.schema.referencedTypes.objects { + if objType.name.schemaName == "Crocodile" { + expect(objType.name.customName).to(equal("CustomCrocodile")) + break + } + } + + for interfaceType in ir.schema.referencedTypes.interfaces { + if interfaceType.name.schemaName == "Animal" { + expect(interfaceType.name.customName).to(equal("CustomAnimal")) + break + } + } + + for unionType in ir.schema.referencedTypes.unions { + if unionType.name.schemaName == "ClassroomPet" { + expect(unionType.name.customName).to(equal("CustomClassroomPet")) + break + } + } + + for customScalarType in ir.schema.referencedTypes.customScalars { + if customScalarType.name.schemaName == "Date" { + expect(customScalarType.name.customName).to(equal("CustomDate")) + break + } + } + + for enumType in ir.schema.referencedTypes.enums { + if enumType.name.schemaName == "SkinCovering" { + expect(enumType.name.customName).to(equal("CustomSkinCovering")) + + for enumCase in enumType.values { + if enumCase.name.schemaName == "HAIR" { + expect(enumCase.name.customName).to(equal("CUSTOMHAIR")) + } + } + + break + } + } + + for inputObjectType in ir.schema.referencedTypes.inputObjects { + if inputObjectType.name.schemaName == "PetSearchFilters" { + expect(inputObjectType.name.customName).to(equal("CustomPetSearchFilters")) + + for inputField in inputObjectType.fields.values { + if inputField.name.schemaName == "size" { + expect(inputField.name.customName).to(equal("customSize")) + } + } + + break + } + } + + } } diff --git a/Tests/ApolloCodegenTests/ApolloSchemaDownloaderInternalTests.swift b/Tests/ApolloCodegenTests/ApolloSchemaDownloaderInternalTests.swift index f087c78f9..e9508c580 100644 --- a/Tests/ApolloCodegenTests/ApolloSchemaDownloaderInternalTests.swift +++ b/Tests/ApolloCodegenTests/ApolloSchemaDownloaderInternalTests.swift @@ -48,10 +48,10 @@ class ApolloSchemaDownloaderInternalTests: XCTestCase { let schema = try await frontend.loadSchema(from: [source]) let authorType = try await schema.getType(named: "Author") - XCTAssertEqual(authorType?.name, "Author") + XCTAssertEqual(authorType?.name.schemaName, "Author") let postType = try await schema.getType(named: "Post") - XCTAssertEqual(postType?.name, "Post") + XCTAssertEqual(postType?.name.schemaName, "Post") } // MARK: Request Tests diff --git a/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/CustomScalarFileGeneratorTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/CustomScalarFileGeneratorTests.swift index 200c3bb14..8b1f2517a 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/CustomScalarFileGeneratorTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/CustomScalarFileGeneratorTests.swift @@ -35,7 +35,7 @@ class CustomScalarFileGeneratorTests: XCTestCase { // given buildSubject() - let expected = graphqlScalar.name + let expected = graphqlScalar.name.schemaName // then expect(self.subject.fileName).to(equal(expected)) @@ -48,4 +48,17 @@ class CustomScalarFileGeneratorTests: XCTestCase { // then expect(self.subject.overwrite).to(beFalse()) } + + // MARK: Schema Customization Tests + + func test__filename_matchesCustomName() throws { + // given + let customName = "MyCustomScalar" + graphqlScalar.name.customName = customName + buildSubject() + + // then + expect(self.subject.fileName).to(equal(customName)) + } + } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/EnumFileGeneratorTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/EnumFileGeneratorTests.swift index 29c28e827..885334b70 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/EnumFileGeneratorTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/EnumFileGeneratorTests.swift @@ -35,7 +35,7 @@ class EnumFileGeneratorTests: XCTestCase { // given buildSubject() - let expected = graphqlEnum.formattedName + let expected = graphqlEnum.name.schemaName // then expect(self.subject.fileName).to(equal(expected)) @@ -48,4 +48,16 @@ class EnumFileGeneratorTests: XCTestCase { // then expect(self.subject.overwrite).to(beTrue()) } + + // MARK: Schema Customization Tests + + func test__filename_matchesCustomName() throws { + // given + let customName = "MyCustomEnum" + graphqlEnum.name.customName = customName + buildSubject() + + // then + expect(self.subject.fileName).to(equal(customName)) + } } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/InputObjectFileGeneratorTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/InputObjectFileGeneratorTests.swift index 305e798ee..c3775d471 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/InputObjectFileGeneratorTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/InputObjectFileGeneratorTests.swift @@ -35,7 +35,7 @@ class InputObjectFileGeneratorTests: XCTestCase { // given buildSubject() - let expected = graphqlInputObject.name + let expected = graphqlInputObject.name.schemaName // then expect(self.subject.fileName).to(equal(expected)) @@ -48,4 +48,16 @@ class InputObjectFileGeneratorTests: XCTestCase { // then expect(self.subject.overwrite).to(beTrue()) } + + // MARK: Schema Customization Tests + + func test__filename_matchesCustomName() throws { + // given + let customName = "MyCustomInputObject" + graphqlInputObject.name.customName = customName + buildSubject() + + // then + expect(self.subject.fileName).to(equal(customName)) + } } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/InterfaceFileGeneratorTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/InterfaceFileGeneratorTests.swift index 1400eafd1..e1f3b812c 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/InterfaceFileGeneratorTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/InterfaceFileGeneratorTests.swift @@ -35,7 +35,7 @@ class InterfaceFileGeneratorTests: XCTestCase { // given buildSubject() - let expected = graphqlInterface.name + let expected = graphqlInterface.name.schemaName // then expect(self.subject.fileName).to(equal(expected)) @@ -48,4 +48,16 @@ class InterfaceFileGeneratorTests: XCTestCase { // then expect(self.subject.overwrite).to(beTrue()) } + + // MARK: Schema Customization Tests + + func test__filename_matchesCustomName() throws { + // given + let customName = "MyCustomInterface" + graphqlInterface.name.customName = customName + buildSubject() + + // then + expect(self.subject.fileName).to(equal(customName)) + } } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/MockObjectFileGeneratorTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/MockObjectFileGeneratorTests.swift index 817bfe9ef..6d06b3089 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/MockObjectFileGeneratorTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/MockObjectFileGeneratorTests.swift @@ -37,7 +37,7 @@ class MockObjectFileGeneratorTests: XCTestCase { // given buildSubject() - let expected = "\(graphqlObject.name)+Mock" + let expected = "\(graphqlObject.name.schemaName)+Mock" // then expect(self.subject.fileName).to(equal(expected)) @@ -50,4 +50,16 @@ class MockObjectFileGeneratorTests: XCTestCase { // then expect(self.subject.overwrite).to(beTrue()) } + + // MARK: Schema Customization Tests + + func test__filename_matchesCustomName() throws { + // given + let customName = "MyCustomObject" + graphqlObject.name.customName = customName + buildSubject() + + // then + expect(self.subject.fileName).to(equal("\(customName)+Mock")) + } } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/ObjectFileGeneratorTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/ObjectFileGeneratorTests.swift index fa03529e1..bf734823d 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/ObjectFileGeneratorTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/ObjectFileGeneratorTests.swift @@ -35,7 +35,7 @@ class ObjectFileGeneratorTests: XCTestCase { // given buildSubject() - let expected = graphqlObject.name + let expected = graphqlObject.name.schemaName // then expect(self.subject.fileName).to(equal(expected)) @@ -48,4 +48,16 @@ class ObjectFileGeneratorTests: XCTestCase { // then expect(self.subject.overwrite).to(beTrue()) } + + // MARK: Schema Customization Tests + + func test__filename_matchesCustomName() throws { + // given + let customName = "MyCustomObject" + graphqlObject.name.customName = customName + buildSubject() + + // then + expect(self.subject.fileName).to(equal(customName)) + } } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/UnionFileGeneratorTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/UnionFileGeneratorTests.swift index c3196f0fa..0677982b4 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/UnionFileGeneratorTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/FileGenerators/UnionFileGeneratorTests.swift @@ -35,7 +35,7 @@ class UnionFileGeneratorTests: XCTestCase { // given buildSubject() - let expected = graphqlUnion.name + let expected = graphqlUnion.name.schemaName // then expect(self.subject.fileName).to(equal(expected)) @@ -48,4 +48,16 @@ class UnionFileGeneratorTests: XCTestCase { // then expect(self.subject.overwrite).to(beTrue()) } + + // MARK: Schema Customization Tests + + func test__filename_matchesCustomName() throws { + // given + let customName = "MyCustomUnion" + graphqlUnion.name.customName = customName + buildSubject() + + // then + expect(self.subject.fileName).to(equal(customName)) + } } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/CustomScalarTemplateTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/CustomScalarTemplateTests.swift index 4cbe9a6e3..4d0a61041 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/CustomScalarTemplateTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/CustomScalarTemplateTests.swift @@ -19,10 +19,14 @@ class CustomScalarTemplateTests: XCTestCase { private func buildSubject( name: String = "MyCustomScalar", + customName: String? = nil, config: ApolloCodegenConfiguration = .mock() ) { + let scalarType = GraphQLScalarType.mock(name: name) + scalarType.name.customName = customName + subject = CustomScalarTemplate( - graphqlScalar: GraphQLScalarType.mock(name: name), + graphqlScalar: scalarType, config: ApolloCodegen.ConfigurationContext(config: config) ) } @@ -253,4 +257,26 @@ class CustomScalarTemplateTests: XCTestCase { } } + // MARK: - Schema Customization Tests + + func test__render__givenCustomScalar_withCustomName_shouldRenderWithCustomName() throws { + // given + buildSubject( + name: "MyScalar", + customName: "MyCustomScalar" + ) + + let expected = """ + // Renamed from GraphQL schema value: 'MyScalar' + typealias MyCustomScalar = String + + """ + + // when + let rendered = renderSubject() + + // then + expect(rendered).to(equalLineByLine(expected)) + } + } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/EnumTemplateTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/EnumTemplateTests.swift index 5dfd79c48..ff1ebbff7 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/EnumTemplateTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/EnumTemplateTests.swift @@ -23,22 +23,27 @@ class EnumTemplateTests: XCTestCase { /// - config: Code generation configuration. private func buildSubject( name: String = "TestEnum", + customName: String? = nil, documentation: String? = nil, - values: [(String, String?, documentation: String?)] = [("ONE", nil, nil), ("TWO", nil, nil)], + values: [(String, String?, documentation: String?, customName: String?)] = [("ONE", nil, nil, nil), ("TWO", nil, nil, nil)], config: ApolloCodegenConfiguration = ApolloCodegenConfiguration.mock() ) { + let enumType = GraphQLEnumType.mock( + name: name, + values: values.map({ + let enumValue = GraphQLEnumValue.mock( + name: $0.0, + deprecationReason: $0.1, + documentation: $0.documentation + ) + enumValue.name.customName = $0.customName + return enumValue + }), + documentation: documentation + ) + enumType.name.customName = customName subject = EnumTemplate( - graphqlEnum: GraphQLEnumType.mock( - name: name, - values: values.map({ - GraphQLEnumValue.mock( - name: $0.0, - deprecationReason: $0.1, - documentation: $0.documentation - ) - }), - documentation: documentation - ), + graphqlEnum: enumType, config: ApolloCodegen.ConfigurationContext(config: config) ) } @@ -132,20 +137,20 @@ class EnumTemplateTests: XCTestCase { name: "casedEnum", values: [ // Mixed case - ("lowercase", nil, nil), - ("UPPERCASE", nil, nil), - ("Capitalized", nil, nil), - ("snake_case", nil, nil), - ("UPPER_SNAKE_CASE", nil, nil), - ("_1", nil, nil), - ("_one_two_three_", nil, nil), - ("camelCased", nil, nil), - ("UpperCamelCase", nil, nil), - ("BEFORE2023", nil, nil), + ("lowercase", nil, nil, nil), + ("UPPERCASE", nil, nil, nil), + ("Capitalized", nil, nil, nil), + ("snake_case", nil, nil, nil), + ("UPPER_SNAKE_CASE", nil, nil, nil), + ("_1", nil, nil, nil), + ("_one_two_three_", nil, nil, nil), + ("camelCased", nil, nil, nil), + ("UpperCamelCase", nil, nil, nil), + ("BEFORE2023", nil, nil, nil), // Escaped keywords - ("associatedtype", nil, nil), - ("Protocol", nil, nil), + ("associatedtype", nil, nil, nil), + ("Protocol", nil, nil, nil), ], config: .mock( options: .init(conversionStrategies: .init(enumCases: .camelCase)) @@ -183,20 +188,20 @@ class EnumTemplateTests: XCTestCase { name: "casedEnum", values: [ // Mixed case - ("lowercase", nil, nil), - ("UPPERCASE", nil, nil), - ("Capitalized", nil, nil), - ("snake_case", nil, nil), - ("UPPER_SNAKE_CASE", nil, nil), - ("_1", nil, nil), - ("_one_two_three_", nil, nil), - ("camelCased", nil, nil), - ("UpperCamelCase", nil, nil), - ("BEFORE2023", nil, nil), + ("lowercase", nil, nil, nil), + ("UPPERCASE", nil, nil, nil), + ("Capitalized", nil, nil, nil), + ("snake_case", nil, nil, nil), + ("UPPER_SNAKE_CASE", nil, nil, nil), + ("_1", nil, nil, nil), + ("_one_two_three_", nil, nil, nil), + ("camelCased", nil, nil, nil), + ("UpperCamelCase", nil, nil, nil), + ("BEFORE2023", nil, nil, nil), // Escaped keywords - ("associatedtype", nil, nil), - ("Protocol", nil, nil), + ("associatedtype", nil, nil, nil), + ("Protocol", nil, nil, nil), ], config: .mock( options: .init(conversionStrategies: .init(enumCases: .none)) @@ -234,9 +239,9 @@ class EnumTemplateTests: XCTestCase { // given / when buildSubject( values: [ - ("ONE", nil, nil), - ("TWO", "Deprecated for tests", nil), - ("THREE", nil, nil) + ("ONE", nil, nil, nil), + ("TWO", "Deprecated for tests", nil, nil), + ("THREE", nil, nil, nil) ], config: ApolloCodegenConfiguration.mock(options: .init( deprecatedEnumCases: .include, @@ -265,9 +270,9 @@ class EnumTemplateTests: XCTestCase { // given / when buildSubject( values: [ - ("ONE", nil, nil), - ("TWO", "Deprecated for tests", nil), - ("THREE", nil, nil) + ("ONE", nil, nil, nil), + ("TWO", "Deprecated for tests", nil, nil), + ("THREE", nil, nil, nil) ], config: ApolloCodegenConfiguration.mock(options: .init( deprecatedEnumCases: .include, @@ -296,9 +301,9 @@ class EnumTemplateTests: XCTestCase { // given / when buildSubject( values: [ - ("ONE", "Deprecated for tests", nil), - ("TWO", nil, nil), - ("THREE", "Deprecated for tests", nil) + ("ONE", "Deprecated for tests", nil, nil), + ("TWO", nil, nil, nil), + ("THREE", "Deprecated for tests", nil, nil) ], config: ApolloCodegenConfiguration.mock(options: .init( deprecatedEnumCases: .exclude, @@ -324,9 +329,9 @@ class EnumTemplateTests: XCTestCase { // given / when buildSubject( values: [ - ("ONE", "Deprecated for tests", nil), - ("TWO", nil, nil), - ("THREE", "Deprecated for tests", nil) + ("ONE", "Deprecated for tests", nil, nil), + ("TWO", nil, nil, nil), + ("THREE", "Deprecated for tests", nil, nil) ], config: ApolloCodegenConfiguration.mock(options: .init( deprecatedEnumCases: .exclude, @@ -356,9 +361,9 @@ class EnumTemplateTests: XCTestCase { buildSubject( documentation: documentation, values: [ - ("ONE", "Deprecated for tests", "Doc: One"), - ("TWO", nil, "Doc: Two"), - ("THREE", "Deprecated for tests", nil) + ("ONE", "Deprecated for tests", "Doc: One", nil), + ("TWO", nil, "Doc: Two", nil), + ("THREE", "Deprecated for tests", nil, nil) ], config: ApolloCodegenConfiguration.mock(options: .init( deprecatedEnumCases: .include, @@ -395,9 +400,9 @@ class EnumTemplateTests: XCTestCase { buildSubject( documentation: documentation, values: [ - ("ONE", "Deprecated for tests", "Doc: One"), - ("TWO", nil, "Doc: Two"), - ("THREE", "Deprecated for tests", nil) + ("ONE", "Deprecated for tests", "Doc: One", nil), + ("TWO", nil, "Doc: Two", nil), + ("THREE", "Deprecated for tests", nil, nil) ], config: ApolloCodegenConfiguration.mock(options: .init( deprecatedEnumCases: .include, @@ -434,9 +439,9 @@ class EnumTemplateTests: XCTestCase { buildSubject( documentation: documentation, values: [ - ("ONE", "Deprecated for tests", "Doc: One"), - ("TWO", nil, "Doc: Two"), - ("THREE", "Deprecated for tests", nil) + ("ONE", "Deprecated for tests", "Doc: One", nil), + ("TWO", nil, "Doc: Two", nil), + ("THREE", "Deprecated for tests", nil, nil) ], config: ApolloCodegenConfiguration.mock(options: .init( deprecatedEnumCases: .include, @@ -484,4 +489,35 @@ class EnumTemplateTests: XCTestCase { } } + // MARK: - Schema Customization Tests + + func test__render__givenEnumAndValues_withCustomNames_shouldRenderWithCustomNames() throws { + // given + buildSubject( + name: "MyEnum", + customName: "MyCustomEnum", + values: [ + // Mixed case + ("caseOne", nil, nil, nil), + ("myCase", nil, nil, "myCustomCase") + ] + ) + + let expected = """ + // Renamed from GraphQL schema value: 'MyEnum' + enum MyCustomEnum: String, EnumType { + case caseOne = "caseOne" + // Renamed from GraphQL schema value: 'myCase' + case myCustomCase = "myCase" + } + + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected)) + } + } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/InputObjectTemplateTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/InputObjectTemplateTests.swift index 5268b7f88..7bc49141c 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/InputObjectTemplateTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/InputObjectTemplateTests.swift @@ -14,16 +14,21 @@ class InputObjectTemplateTests: XCTestCase { private func buildSubject( name: String = "MockInput", + customName: String? = nil, fields: [GraphQLInputField] = [], documentation: String? = nil, config: ApolloCodegenConfiguration = .mock(.swiftPackageManager) ) { + let inputObject = GraphQLInputObjectType.mock( + name, + fields: fields, + documentation: documentation, + config: config + ) + inputObject.name.customName = customName + subject = InputObjectTemplate( - graphqlInputObject: GraphQLInputObjectType.mock( - name, - fields: fields, - documentation: documentation - ), + graphqlInputObject: inputObject, config: ApolloCodegen.ConfigurationContext(config: config) ) } @@ -2540,4 +2545,66 @@ class InputObjectTemplateTests: XCTestCase { } } + // MARK: - Schema Customization Tests + + func test__render__givenInputObjectAndField_withCustomNames_shouldRenderWithCustomNames() throws { + // given + let customInputField = GraphQLInputField.mock( + "myField", + type: .nonNull(.string()), + defaultValue: nil + ) + customInputField.name.customName = "myCustomField" + buildSubject( + name: "MyInputObject", + customName: "MyCustomInputObject", + fields: [ + GraphQLInputField.mock( + "fieldOne", + type: .nonNull(.string()), + defaultValue: nil + ), + customInputField + ] + ) + + let expected = """ + // Renamed from GraphQL schema value: 'MyInputObject' + public struct MyCustomInputObject: InputObject { + public private(set) var __data: InputDict + + public init(_ data: InputDict) { + __data = data + } + + public init( + fieldOne: String, + myCustomField: String + ) { + __data = InputDict([ + "fieldOne": fieldOne, + "myField": myCustomField + ]) + } + + public var fieldOne: String { + get { __data["fieldOne"] } + set { __data["fieldOne"] = newValue } + } + + // Renamed from GraphQL schema value: 'myField' + public var myCustomField: String { + get { __data["myField"] } + set { __data["myField"] = newValue } + } + } + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/InterfaceTemplateTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/InterfaceTemplateTests.swift index e1d5492d2..6d66c3316 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/InterfaceTemplateTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/InterfaceTemplateTests.swift @@ -17,16 +17,20 @@ class InterfaceTemplateTests: XCTestCase { private func buildSubject( name: String = "Dog", + customName: String? = nil, documentation: String? = nil, config: ApolloCodegenConfiguration = .mock() ) { + let interfaceType = GraphQLInterfaceType.mock( + name, + fields: [:], + interfaces: [], + documentation: documentation + ) + interfaceType.name.customName = customName + subject = InterfaceTemplate( - graphqlInterface: GraphQLInterfaceType.mock( - name, - fields: [:], - interfaces: [], - documentation: documentation - ), + graphqlInterface: interfaceType, config: ApolloCodegen.ConfigurationContext(config: config) ) } @@ -135,4 +139,25 @@ class InterfaceTemplateTests: XCTestCase { } } + // MARK: Schema Customization Tests + + func test__render__givenInterface_withCustomName_shouldRenderWithCustomName() throws { + // given + buildSubject( + name: "MyInterface", + customName: "MyCustomInterface" + ) + + let expected = """ + // Renamed from GraphQL schema value: 'MyInterface' + static let MyCustomInterface = ApolloAPI.Interface(name: "MyInterface") + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected)) + } + } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/MockInterfacesTemplateTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/MockInterfacesTemplateTests.swift index 1d2713af6..91611d42e 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/MockInterfacesTemplateTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/MockInterfacesTemplateTests.swift @@ -25,7 +25,7 @@ class MockInterfacesTemplateTests: XCTestCase { let config = ApolloCodegenConfiguration.mock(output: .mock(testMocks: testMocks)) subject = MockInterfacesTemplate( - graphQLInterfaces: interfaces, + graphqlInterfaces: interfaces, config: ApolloCodegen.ConfigurationContext(config: config) ) } @@ -163,4 +163,26 @@ class MockInterfacesTemplateTests: XCTestCase { } } + // Schema Customization Tests + + func test__render__givenInterface_withCustomName_shouldRenderWithCustomName() throws { + // given + let myInterface = GraphQLInterfaceType.mock("MyInterface") + myInterface.name.customName = "MyCustomInterface" + buildSubject(interfaces: [myInterface]) + + let expected = """ + public extension MockObject { + typealias MyCustomInterface = Interface + } + + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected)) + } + } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/MockObjectTemplateTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/MockObjectTemplateTests.swift index 206061ae7..eecf31d2f 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/MockObjectTemplateTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/MockObjectTemplateTests.swift @@ -21,6 +21,7 @@ class MockObjectTemplateTests: XCTestCase { private func buildSubject( name: String = "Dog", + customName: String? = nil, interfaces: [GraphQLInterfaceType] = [], fields: [String : GraphQLField] = [:], schemaNamespace: String = "TestSchema", @@ -35,12 +36,14 @@ class MockObjectTemplateTests: XCTestCase { ) ir = IRBuilder.mock(compilationResult: .mock()) + let objectType = GraphQLObjectType.mock( + name, + interfaces: interfaces + ) + objectType.name.customName = customName subject = MockObjectTemplate( - graphqlObject: GraphQLObjectType.mock( - name, - interfaces: interfaces - ), - fields: fields + graphqlObject: objectType, + fields: fields .map { ($0.key, $0.value.type, $0.value.deprecationReason) }, config: ApolloCodegen.ConfigurationContext(config: config), ir: ir @@ -941,5 +944,28 @@ class MockObjectTemplateTests: XCTestCase { expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) } } + + // MARK: - Schema Customization Tests + + func test__render__givenMockObject_withCustomName_shouldRenderWithCustomName() throws { + // given + buildSubject( + name: "MyObject", + customName: "MyCustomObject" + ) + + let expected = """ + public class MyCustomObject: MockObject { + public static let objectType: ApolloAPI.Object = TestSchema.Objects.MyCustomObject + public static let _mockFields = MockFields() + public typealias MockValueCollectionType = Array> + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/MockUnionsTemplateTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/MockUnionsTemplateTests.swift index 20c389f04..d2e27ae5a 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/MockUnionsTemplateTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/MockUnionsTemplateTests.swift @@ -25,7 +25,7 @@ class MockUnionsTemplateTests: XCTestCase { let config = ApolloCodegenConfiguration.mock(output: .mock(testMocks: testMocks)) subject = MockUnionsTemplate( - graphQLUnions: unions, + graphqlUnions: unions, config: ApolloCodegen.ConfigurationContext(config: config) ) } @@ -160,4 +160,26 @@ class MockUnionsTemplateTests: XCTestCase { } } + // Schema Customization Tests + + func test__render__givenUnion_withCustomName_shouldRenderWithCustomName() throws { + // given + let myUnion = GraphQLUnionType.mock("MyUnion") + myUnion.name.customName = "MyCustomUnion" + buildSubject(unions: [myUnion]) + + let expected = """ + public extension MockObject { + typealias MyCustomUnion = Union + } + + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected)) + } + } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/ObjectTemplateTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/ObjectTemplateTests.swift index 5436a8e0c..4bfb028cc 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/ObjectTemplateTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/ObjectTemplateTests.swift @@ -18,16 +18,19 @@ class ObjectTemplateTests: XCTestCase { private func buildSubject( name: String = "Dog", + customName: String? = nil, interfaces: [GraphQLInterfaceType] = [], documentation: String? = nil, config: ApolloCodegenConfiguration = .mock() ) { + let objectType = GraphQLObjectType.mock( + name, + interfaces: interfaces, + documentation: documentation + ) + objectType.name.customName = customName subject = ObjectTemplate( - graphqlObject: GraphQLObjectType.mock( - name, - interfaces: interfaces, - documentation: documentation - ), + graphqlObject: objectType, config: ApolloCodegen.ConfigurationContext(config: config) ) } @@ -192,4 +195,33 @@ class ObjectTemplateTests: XCTestCase { } } + // MARK: - Schema Customization + + func test__render__giveObjectTypeAndInterface_withCustomNames_shouldRenderWithCustomNames() throws { + // given + let implementedInterface = GraphQLInterfaceType.mock("MyInterface", fields: ["myField": GraphQLField.mock("myField", type: .scalar(.string()))]) + implementedInterface.name.customName = "MyCustomInterface" + buildSubject( + name: "MyObject", + customName: "MyCustomObject", + interfaces: [ + implementedInterface + ] + ) + + let expected = """ + // Renamed from GraphQL schema value: 'MyObject' + static let MyCustomObject = ApolloAPI.Object( + typename: "MyObject", + implementedInterfaces: [TestSchema.Interfaces.MyCustomInterface.self] + ) + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + } diff --git a/Tests/ApolloCodegenTests/CodeGeneration/Templates/UnionTemplateTests.swift b/Tests/ApolloCodegenTests/CodeGeneration/Templates/UnionTemplateTests.swift index 7c684ced7..f805ccf5b 100644 --- a/Tests/ApolloCodegenTests/CodeGeneration/Templates/UnionTemplateTests.swift +++ b/Tests/ApolloCodegenTests/CodeGeneration/Templates/UnionTemplateTests.swift @@ -17,20 +17,24 @@ class UnionTemplateTests: XCTestCase { private func buildSubject( name: String = "ClassroomPet", + customName: String? = nil, + types: [GraphQLObjectType] = [ + GraphQLObjectType.mock("cat"), + GraphQLObjectType.mock("bird"), + GraphQLObjectType.mock("rat"), + GraphQLObjectType.mock("petRock") + ], documentation: String? = nil, config: ApolloCodegenConfiguration = .mock() ) { + let unionType = GraphQLUnionType.mock( + name, + types: types, + documentation: documentation + ) + unionType.name.customName = customName subject = UnionTemplate( - graphqlUnion: GraphQLUnionType.mock( - name, - types: [ - GraphQLObjectType.mock("cat"), - GraphQLObjectType.mock("bird"), - GraphQLObjectType.mock("rat"), - GraphQLObjectType.mock("petRock") - ], - documentation: documentation - ), + graphqlUnion: unionType, config: ApolloCodegen.ConfigurationContext(config: config) ) } @@ -281,4 +285,38 @@ class UnionTemplateTests: XCTestCase { } } + // MARK: - Schema Customization Tests + + func test__render__givenUnion_withCustomName_shouldRenderWithCustomName() throws { + // given + let customObjectType = GraphQLObjectType.mock("MyObject") + customObjectType.name.customName = "MyCustomObject" + + buildSubject( + name: "MyUnion", + customName: "MyCustomUnion", + types: [ + GraphQLObjectType.mock("cat"), + customObjectType + ] + ) + + + let expected = """ + // Renamed from GraphQL schema value: 'MyUnion' + static let MyCustomUnion = Union( + name: "MyUnion", + possibleTypes: [ + TestSchema.Objects.Cat.self, + TestSchema.Objects.MyCustomObject.self + ] + """ + + // when + let actual = renderSubject() + + // then + expect(actual).to(equalLineByLine(expected, ignoringExtraLines: true)) + } + } diff --git a/Tests/ApolloCodegenTests/Configuration/ApolloCodegenConfiguration+SchemaCustomizationTests.swift b/Tests/ApolloCodegenTests/Configuration/ApolloCodegenConfiguration+SchemaCustomizationTests.swift new file mode 100644 index 000000000..dc55f713f --- /dev/null +++ b/Tests/ApolloCodegenTests/Configuration/ApolloCodegenConfiguration+SchemaCustomizationTests.swift @@ -0,0 +1,605 @@ +import XCTest +import ApolloCodegenLib +import Nimble + +final class ApolloCodegenConfiguration_SchemaCustomizationTests: XCTestCase { + + var testJSONEncoder: JSONEncoder! + + override func setUpWithError() throws { + try super.setUpWithError() + testJSONEncoder = JSONEncoder() + testJSONEncoder.outputFormatting = [.prettyPrinted, .sortedKeys, .withoutEscapingSlashes] + } + + override func tearDownWithError() throws { + testJSONEncoder = nil + try super.tearDownWithError() + } + + // MARK: - Custom Type Names + + func test__encodeType_withCustomName() throws { + // given + let subject = ApolloCodegenConfiguration.SchemaCustomization( + customTypeNames: [ + "MyObject": .type(name: "CustomObject") + ] + ) + + let expected = """ + { + "customTypeNames" : { + "MyObject" : "CustomObject" + } + } + """ + + // when + let encodedJSON = try testJSONEncoder.encode(subject) + let actual = encodedJSON.asString + + //then + expect(actual).to(equalLineByLine(expected)) + } + + func test__decodeType_withCustomName() throws { + // given + let subject = """ + { + "customTypeNames" : { + "MyObject" : "CustomObject" + } + } + """ + + let expected = ApolloCodegenConfiguration.SchemaCustomization( + customTypeNames: [ + "MyObject": .type(name: "CustomObject") + ] + ) + + // when + let actual = try JSONDecoder().decode(ApolloCodegenConfiguration.SchemaCustomization.self, from: subject.asData) + + //then + expect(actual).to(equal(expected)) + } + + func test__encodeEmptyType_shouldThrowError() throws { + // given + let subject = ApolloCodegenConfiguration.SchemaCustomization( + customTypeNames: [ + "MyObject": .type(name: "") + ] + ) + + //then + expect { + _ = try self.testJSONEncoder.encode(subject) + }.to(throwError { error in + guard case let ApolloCodegenConfiguration.SchemaCustomization.Error.emptyCustomization(type) = error else { + fail("Expected .emptyCustomization, got .\(error)") + return + } + expect(type).to(equal("MyObject")) + }) + } + + func test__decodeEmptyType_shouldThrowError() throws { + // given + let subject = """ + { + "customTypeNames" : { + "MyObject" : "" + } + } + """ + + ///then + expect { + try JSONDecoder().decode(ApolloCodegenConfiguration.SchemaCustomization.self, from: subject.asData) + }.to(throwError { error in + guard case let ApolloCodegenConfiguration.SchemaCustomization.Error.emptyCustomization(type) = error else { + fail("Expected .emptyCustomization, got .\(error)") + return + } + expect(type).to(equal("MyObject")) + }) + } + + // MARK: - Custom Enum Names + + func test__encodeEnum_withCustomNameAndCases() throws { + // given + let subject = ApolloCodegenConfiguration.SchemaCustomization( + customTypeNames: [ + "MyEnum": .enum( + name: "CustomEnum", + cases: [ + "CaseOne": "CustomCaseOne" + ] + ) + ] + ) + + let expected = """ + { + "customTypeNames" : { + "MyEnum" : { + "enum" : { + "cases" : { + "CaseOne" : "CustomCaseOne" + }, + "name" : "CustomEnum" + } + } + } + } + """ + + // when + let encodedJSON = try testJSONEncoder.encode(subject) + let actual = encodedJSON.asString + + //then + expect(actual).to(equalLineByLine(expected)) + } + + func test__decodeEnum_withCustomNameAndCases() throws { + // given + let subject = """ + { + "customTypeNames" : { + "MyEnum" : { + "enum" : { + "cases" : { + "CaseOne" : "CustomCaseOne" + }, + "name" : "CustomEnum" + } + } + } + } + """ + + let expected = ApolloCodegenConfiguration.SchemaCustomization( + customTypeNames: [ + "MyEnum": .enum( + name: "CustomEnum", + cases: [ + "CaseOne": "CustomCaseOne" + ] + ) + ] + ) + + // when + let actual = try JSONDecoder().decode(ApolloCodegenConfiguration.SchemaCustomization.self, from: subject.asData) + + //then + expect(actual).to(equal(expected)) + } + + func test__encodeEnum_withCustomName_asType() throws { + // given + let subject = ApolloCodegenConfiguration.SchemaCustomization( + customTypeNames: [ + "MyEnum": .enum( + name: "CustomEnum", + cases: nil + ) + ] + ) + + let expected = """ + { + "customTypeNames" : { + "MyEnum" : "CustomEnum" + } + } + """ + + // when + let encodedJSON = try testJSONEncoder.encode(subject) + let actual = encodedJSON.asString + + //then + expect(actual).to(equalLineByLine(expected)) + } + + func test__decodeEnum_withCustomName_asType() throws { + // given + let subject = """ + { + "customTypeNames" : { + "MyEnum" : { + "enum" : { + "name" : "CustomEnum" + } + } + } + } + """ + + let expected = ApolloCodegenConfiguration.SchemaCustomization( + customTypeNames: [ + "MyEnum": .type(name: "CustomEnum") + ] + ) + + // when + let actual = try JSONDecoder().decode(ApolloCodegenConfiguration.SchemaCustomization.self, from: subject.asData) + + //then + expect(actual).to(equal(expected)) + } + + func test__encodeEnum_withCustomCases() throws { + // given + let subject = ApolloCodegenConfiguration.SchemaCustomization( + customTypeNames: [ + "MyEnum": .enum( + name: nil, + cases: [ + "CaseOne": "CustomCaseOne" + ] + ) + ] + ) + + let expected = """ + { + "customTypeNames" : { + "MyEnum" : { + "enum" : { + "cases" : { + "CaseOne" : "CustomCaseOne" + } + } + } + } + } + """ + + // when + let encodedJSON = try testJSONEncoder.encode(subject) + let actual = encodedJSON.asString + + //then + expect(actual).to(equalLineByLine(expected)) + } + + func test__decodeEnum_withCustomCases() throws { + // given + let subject = """ + { + "customTypeNames" : { + "MyEnum" : { + "enum" : { + "cases" : { + "CaseOne" : "CustomCaseOne" + } + } + } + } + } + """ + + let expected = ApolloCodegenConfiguration.SchemaCustomization( + customTypeNames: [ + "MyEnum": .enum( + name: nil, + cases: [ + "CaseOne": "CustomCaseOne" + ] + ) + ] + ) + + // when + let actual = try JSONDecoder().decode(ApolloCodegenConfiguration.SchemaCustomization.self, from: subject.asData) + + //then + expect(actual).to(equal(expected)) + } + + func test__encodeEmptyEnum_shouldThrowError() throws { + // given + let subject = ApolloCodegenConfiguration.SchemaCustomization( + customTypeNames: [ + "MyEnum": .enum( + name: nil, + cases: [:] + ) + ] + ) + + //then + expect { + _ = try self.testJSONEncoder.encode(subject) + }.to(throwError { error in + guard case let ApolloCodegenConfiguration.SchemaCustomization.Error.emptyCustomization(type) = error else { + fail("Expected .emptyCustomization, got .\(error)") + return + } + expect(type).to(equal("MyEnum")) + }) + } + + func test__decodeEmptyEnum_shouldThrowError() throws { + // given + let subject = """ + { + "customTypeNames" : { + "MyEnum" : { + "enum" : { + "cases" : { + }, + "name" : "" + } + } + } + } + """ + + //then + expect { + try JSONDecoder().decode(ApolloCodegenConfiguration.SchemaCustomization.self, from: subject.asData) + }.to(throwError { error in + guard case let ApolloCodegenConfiguration.SchemaCustomization.Error.emptyCustomization(type) = error else { + fail("Expected .emptyCustomization, got .\(error)") + return + } + expect(type).to(equal("MyEnum")) + }) + } + + // MARK: - Custom InputObjects Names + + func test__encodeInputObject_withCustomNameAndFields() throws { + // given + let subject = ApolloCodegenConfiguration.SchemaCustomization( + customTypeNames: [ + "MyInputObject": .inputObject( + name: "CustomInputObject", + fields: [ + "FieldOne": "CustomFieldOne" + ] + ) + ] + ) + + let expected = """ + { + "customTypeNames" : { + "MyInputObject" : { + "inputObject" : { + "fields" : { + "FieldOne" : "CustomFieldOne" + }, + "name" : "CustomInputObject" + } + } + } + } + """ + + // when + let encodedJSON = try testJSONEncoder.encode(subject) + let actual = encodedJSON.asString + + //then + expect(actual).to(equalLineByLine(expected)) + } + + func test__decodeInputObject_withCustomNameAndFields() throws { + // given + let subject = """ + { + "customTypeNames" : { + "MyInputObject" : { + "inputObject" : { + "fields" : { + "FieldOne" : "CustomFieldOne" + }, + "name" : "CustomInputObject" + } + } + } + } + """ + + let expected = ApolloCodegenConfiguration.SchemaCustomization( + customTypeNames: [ + "MyInputObject": .inputObject( + name: "CustomInputObject", + fields: [ + "FieldOne": "CustomFieldOne" + ] + ) + ] + ) + + // when + let actual = try JSONDecoder().decode(ApolloCodegenConfiguration.SchemaCustomization.self, from: subject.asData) + + //then + expect(actual).to(equal(expected)) + } + + func test__encodeInputObject_withCustomName_asType() throws { + // given + let subject = ApolloCodegenConfiguration.SchemaCustomization( + customTypeNames: [ + "MyInputObject": .inputObject( + name: "CustomInputObject", + fields: nil + ) + ] + ) + + let expected = """ + { + "customTypeNames" : { + "MyInputObject" : "CustomInputObject" + } + } + """ + + // when + let encodedJSON = try testJSONEncoder.encode(subject) + let actual = encodedJSON.asString + + //then + expect(actual).to(equalLineByLine(expected)) + } + + func test__decodeInputObject_withCustomName_asType() throws { + // given + let subject = """ + { + "customTypeNames" : { + "MyInputObject" : { + "inputObject" : { + "name" : "CustomInputObject" + } + } + } + } + """ + + let expected = ApolloCodegenConfiguration.SchemaCustomization( + customTypeNames: [ + "MyInputObject": .type(name: "CustomInputObject") + ] + ) + + // when + let actual = try JSONDecoder().decode(ApolloCodegenConfiguration.SchemaCustomization.self, from: subject.asData) + + //then + expect(actual).to(equal(expected)) + } + + func test__encodeInputObject_withCustomFields() throws { + // given + let subject = ApolloCodegenConfiguration.SchemaCustomization( + customTypeNames: [ + "MyInputObject": .inputObject( + name: nil, + fields: [ + "FieldOne": "CustomFieldOne" + ] + ) + ] + ) + + let expected = """ + { + "customTypeNames" : { + "MyInputObject" : { + "inputObject" : { + "fields" : { + "FieldOne" : "CustomFieldOne" + } + } + } + } + } + """ + + // when + let encodedJSON = try testJSONEncoder.encode(subject) + let actual = encodedJSON.asString + + //then + expect(actual).to(equalLineByLine(expected)) + } + + func test__decodeInputObject_withCustomFields() throws { + // given + let subject = """ + { + "customTypeNames" : { + "MyInputObject" : { + "inputObject" : { + "fields" : { + "FieldOne" : "CustomFieldOne" + } + } + } + } + } + """ + + let expected = ApolloCodegenConfiguration.SchemaCustomization( + customTypeNames: [ + "MyInputObject": .inputObject( + name: nil, + fields: [ + "FieldOne": "CustomFieldOne" + ] + ) + ] + ) + + // when + let actual = try JSONDecoder().decode(ApolloCodegenConfiguration.SchemaCustomization.self, from: subject.asData) + + //then + expect(actual).to(equal(expected)) + } + + func test__encodeEmptyInputObject_shouldThrowError() throws { + // given + let subject = ApolloCodegenConfiguration.SchemaCustomization( + customTypeNames: [ + "MyInputObject": .inputObject( + name: nil, + fields: [:] + ) + ] + ) + + //then + expect { + _ = try self.testJSONEncoder.encode(subject) + }.to(throwError { error in + guard case let ApolloCodegenConfiguration.SchemaCustomization.Error.emptyCustomization(type) = error else { + fail("Expected .emptyCustomization, got .\(error)") + return + } + expect(type).to(equal("MyInputObject")) + }) + } + + func test__decodeEmptyInputObject_shouldThrowError() throws { + // given + let subject = """ + { + "customTypeNames" : { + "MyInputObject" : { + "inputObject" : { + "fields" : { + }, + "name" : "" + } + } + } + } + """ + + ///then + expect { + try JSONDecoder().decode(ApolloCodegenConfiguration.SchemaCustomization.self, from: subject.asData) + }.to(throwError { error in + guard case let ApolloCodegenConfiguration.SchemaCustomization.Error.emptyCustomization(type) = error else { + fail("Expected .emptyCustomization, got .\(error)") + return + } + expect(type).to(equal("MyInputObject")) + }) + } + +} diff --git a/Tests/ApolloCodegenTests/Extensions/GraphQLNamedType+SwiftTests.swift b/Tests/ApolloCodegenTests/Extensions/GraphQLNamedType+SwiftTests.swift index ac7ab0193..aedee5fdc 100644 --- a/Tests/ApolloCodegenTests/Extensions/GraphQLNamedType+SwiftTests.swift +++ b/Tests/ApolloCodegenTests/Extensions/GraphQLNamedType+SwiftTests.swift @@ -8,24 +8,24 @@ class GraphQLNamedType_SwiftTests: XCTestCase { func test_swiftName_givenGraphQLScalar_boolean_providesCompatibleSwiftName() { let graphqlNamedType = GraphQLType.scalar(.boolean()) - expect(graphqlNamedType.namedType.swiftName).to(equal("Bool")) + expect(graphqlNamedType.namedType.name.swiftName).to(equal("Bool")) } func test_swiftName_givenGraphQLScalar_int_providesCompatibleSwiftName() { let graphqlNamedType = GraphQLType.scalar(.integer()) - expect(graphqlNamedType.namedType.swiftName).to(equal("Int")) + expect(graphqlNamedType.namedType.name.swiftName).to(equal("Int")) } func test_swiftName_givenGraphQLScalar_float_providesCompatibleSwiftName() { let graphqlNamedType = GraphQLType.scalar(.float()) - expect(graphqlNamedType.namedType.swiftName).to(equal("Double")) + expect(graphqlNamedType.namedType.name.swiftName).to(equal("Double")) } func test_swiftName_givenGraphQLScalar_string_providesCompatibleSwiftName() { let graphqlNamedType = GraphQLType.scalar(.string()) - expect(graphqlNamedType.namedType.swiftName).to(equal("String")) + expect(graphqlNamedType.namedType.name.swiftName).to(equal("String")) } } diff --git a/Tests/ApolloCodegenTests/Frontend/CompilationTests.swift b/Tests/ApolloCodegenTests/Frontend/CompilationTests.swift index 3cb58a51f..f9ec60bc1 100644 --- a/Tests/ApolloCodegenTests/Frontend/CompilationTests.swift +++ b/Tests/ApolloCodegenTests/Frontend/CompilationTests.swift @@ -77,7 +77,7 @@ class CompilationTests: XCTestCase { let operation = try XCTUnwrap(compilationResult.operations.first) XCTAssertEqual(operation.name, "HeroAndFriendsNames") XCTAssertEqual(operation.operationType, .query) - XCTAssertEqual(operation.rootType.name, "Query") + XCTAssertEqual(operation.rootType.name.schemaName, "Query") XCTAssertEqual(operation.variables[0].name, "episode") XCTAssertEqual(operation.variables[0].type.typeReference, "Episode") @@ -94,7 +94,7 @@ class CompilationTests: XCTestCase { XCTAssertEqual(friendsField.name, "friends") XCTAssertEqual(friendsField.type.typeReference, "[Character]") - XCTAssertEqualUnordered(compilationResult.referencedTypes.map(\.name), + XCTAssertEqualUnordered(compilationResult.referencedTypes.map(\.name.schemaName), ["Human", "Droid", "Query", "Episode", "Character", "String"]) } @@ -158,7 +158,7 @@ class CompilationTests: XCTestCase { let compilationResult = try await compileFrontend() let inputObject = try XCTUnwrap( - compilationResult.referencedTypes.first { $0.name == "TestInput"} as? GraphQLInputObjectType + compilationResult.referencedTypes.first { $0.name.schemaName == "TestInput"} as? GraphQLInputObjectType ) let listField = try XCTUnwrap(inputObject.fields["listField"]) let defaultValue = try XCTUnwrap(listField.defaultValue) diff --git a/Tests/ApolloCodegenTests/Frontend/SchemaLoadingTests.swift b/Tests/ApolloCodegenTests/Frontend/SchemaLoadingTests.swift index 1a0c05875..7e24104da 100644 --- a/Tests/ApolloCodegenTests/Frontend/SchemaLoadingTests.swift +++ b/Tests/ApolloCodegenTests/Frontend/SchemaLoadingTests.swift @@ -30,7 +30,7 @@ class SchemaLoadingTests: XCTestCase { from: [try codegenFrontend.makeSource(introspectionResult, filePath: "schema.json")] ) - await expect { try await schema.getType(named: "Character")?.name } + await expect { try await schema.getType(named: "Character")?.name.schemaName } .to(equal("Character")) } @@ -46,7 +46,7 @@ class SchemaLoadingTests: XCTestCase { let schema = try await codegenFrontend.loadSchema(from: [source]) - await expect { try await schema.getType(named: "Character")?.name } + await expect { try await schema.getType(named: "Character")?.name.schemaName } .to(equal("Character")) } diff --git a/Tests/TestCodeGenConfigurations/EmbeddedInTarget-InSchemaModule/apollo-codegen-config.json b/Tests/TestCodeGenConfigurations/EmbeddedInTarget-InSchemaModule/apollo-codegen-config.json index a6a4c69ae..fb475dc32 100644 --- a/Tests/TestCodeGenConfigurations/EmbeddedInTarget-InSchemaModule/apollo-codegen-config.json +++ b/Tests/TestCodeGenConfigurations/EmbeddedInTarget-InSchemaModule/apollo-codegen-config.json @@ -14,7 +14,31 @@ "pruneGeneratedFiles" : true, "queryStringLiteralFormat" : "multiline", "warningsOnDeprecatedUsage" : "include", - "operationDocumentFormat" : ["operationId"] + "operationDocumentFormat" : ["operationId"], + "schemaCustomization" : { + "customTypeNames" : { + "SkinCovering" : { + "enum" : { + "cases" : { + "HAIR" : "CUSTOMHAIR" + }, + "name" : "CustomSkinCovering" + } + }, + "Animal" : "CustomAnimal", + "Crocodile" : "CustomCrocodile", + "ClassroomPet" : "CustomClassroomPet", + "Date" : "CustomDate", + "PetSearchFilters" : { + "inputObject" : { + "fields" : { + "size" : "customSize" + }, + "name" : "CustomPetSearchFilters" + } + } + } + } }, "input" : { "operationSearchPaths" : [ diff --git a/Tests/TestCodeGenConfigurations/EmbeddedInTarget-RelativeAbsolute/apollo-codegen-config.json b/Tests/TestCodeGenConfigurations/EmbeddedInTarget-RelativeAbsolute/apollo-codegen-config.json index 6125aa6b5..d0546f255 100644 --- a/Tests/TestCodeGenConfigurations/EmbeddedInTarget-RelativeAbsolute/apollo-codegen-config.json +++ b/Tests/TestCodeGenConfigurations/EmbeddedInTarget-RelativeAbsolute/apollo-codegen-config.json @@ -13,7 +13,31 @@ }, "pruneGeneratedFiles" : true, "queryStringLiteralFormat" : "multiline", - "warningsOnDeprecatedUsage" : "include" + "warningsOnDeprecatedUsage" : "include", + "schemaCustomization" : { + "customTypeNames" : { + "SkinCovering" : { + "enum" : { + "cases" : { + "HAIR" : "CUSTOMHAIR" + }, + "name" : "CustomSkinCovering" + } + }, + "Animal" : "CustomAnimal", + "Crocodile" : "CustomCrocodile", + "ClassroomPet" : "CustomClassroomPet", + "Date" : "CustomDate", + "PetSearchFilters" : { + "inputObject" : { + "fields" : { + "size" : "customSize" + }, + "name" : "CustomPetSearchFilters" + } + } + } + } }, "input" : { "operationSearchPaths" : [ diff --git a/Tests/TestCodeGenConfigurations/Other-CocoaPods/CocoaPodsProject.xcodeproj/project.pbxproj b/Tests/TestCodeGenConfigurations/Other-CocoaPods/CocoaPodsProject.xcodeproj/project.pbxproj index e3430e5bc..15d1f1519 100644 --- a/Tests/TestCodeGenConfigurations/Other-CocoaPods/CocoaPodsProject.xcodeproj/project.pbxproj +++ b/Tests/TestCodeGenConfigurations/Other-CocoaPods/CocoaPodsProject.xcodeproj/project.pbxproj @@ -9,6 +9,12 @@ /* Begin PBXBuildFile section */ 1B7ED6E41035FB2A0D763AD8 /* Pods_CocoaPodsProjectTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D3E998DF0E4DCCF80C445451 /* Pods_CocoaPodsProjectTests.framework */; }; 665BDA862AE30BE2004DD21F /* Object.swift in Sources */ = {isa = PBXBuildFile; fileRef = 665BDA852AE30BE2004DD21F /* Object.swift */; }; + 66F434EB2C12B5EC00679212 /* CustomClassroomPet.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F434EA2C12B5EC00679212 /* CustomClassroomPet.graphql.swift */; }; + 66F434ED2C12B60800679212 /* CustomSkinCovering.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F434EC2C12B60800679212 /* CustomSkinCovering.graphql.swift */; }; + 66F434EF2C12B60E00679212 /* CustomCrocodile.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F434EE2C12B60E00679212 /* CustomCrocodile.graphql.swift */; }; + 66F434F12C12B61400679212 /* CustomPetSearchFilters.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F434F02C12B61400679212 /* CustomPetSearchFilters.graphql.swift */; }; + 66F434F32C12B61900679212 /* CustomAnimal.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F434F22C12B61900679212 /* CustomAnimal.graphql.swift */; }; + 66F434F52C12B67E00679212 /* CustomCrocodile+Mock.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F434F42C12B67E00679212 /* CustomCrocodile+Mock.graphql.swift */; }; B51EE231D8798C8408AB9CD5 /* Pods_CocoaPodsProject.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C684794938D6314DF12AB411 /* Pods_CocoaPodsProject.framework */; }; DE4790B02BFBD66E00939CCC /* ID.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE4790AF2BFBD66E00939CCC /* ID.swift */; }; E607A69C29FB43F80059899E /* CocoaPodsProjectApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A69B29FB43F80059899E /* CocoaPodsProjectApp.swift */; }; @@ -30,9 +36,7 @@ E607A75629FB692F0059899E /* AllAnimalsQuery.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A72629FB692F0059899E /* AllAnimalsQuery.graphql.swift */; }; E607A75729FB692F0059899E /* AllAnimalsIncludeSkipQuery.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A72729FB692F0059899E /* AllAnimalsIncludeSkipQuery.graphql.swift */; }; E607A75829FB692F0059899E /* PetSearchQuery.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A72829FB692F0059899E /* PetSearchQuery.graphql.swift */; }; - E607A75929FB692F0059899E /* ClassroomPet.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A72B29FB692F0059899E /* ClassroomPet.graphql.swift */; }; E607A75A29FB692F0059899E /* CustomDate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A72D29FB692F0059899E /* CustomDate.swift */; }; - E607A75B29FB692F0059899E /* SkinCovering.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A72F29FB692F0059899E /* SkinCovering.graphql.swift */; }; E607A75C29FB692F0059899E /* RelativeSize.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A73029FB692F0059899E /* RelativeSize.graphql.swift */; }; E607A75D29FB692F0059899E /* Rat.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A73229FB692F0059899E /* Rat.graphql.swift */; }; E607A75E29FB692F0059899E /* Bird.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A73329FB692F0059899E /* Bird.graphql.swift */; }; @@ -44,15 +48,12 @@ E607A76429FB69300059899E /* Cat.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A73929FB692F0059899E /* Cat.graphql.swift */; }; E607A76529FB69300059899E /* Fish.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A73A29FB692F0059899E /* Fish.graphql.swift */; }; E607A76629FB69300059899E /* Human.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A73B29FB692F0059899E /* Human.graphql.swift */; }; - E607A76729FB69300059899E /* Crocodile.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A73C29FB692F0059899E /* Crocodile.graphql.swift */; }; E607A76829FB69300059899E /* SchemaConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A73D29FB692F0059899E /* SchemaConfiguration.swift */; }; E607A76929FB69300059899E /* PetAdoptionInput.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A73F29FB692F0059899E /* PetAdoptionInput.graphql.swift */; }; - E607A76A29FB69300059899E /* PetSearchFilters.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A74029FB692F0059899E /* PetSearchFilters.graphql.swift */; }; E607A76B29FB69300059899E /* MeasurementsInput.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A74129FB692F0059899E /* MeasurementsInput.graphql.swift */; }; E607A76C29FB69300059899E /* SchemaMetadata.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A74229FB692F0059899E /* SchemaMetadata.graphql.swift */; }; E607A76D29FB69300059899E /* HousePet.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A74429FB692F0059899E /* HousePet.graphql.swift */; }; E607A76E29FB69300059899E /* Pet.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A74529FB692F0059899E /* Pet.graphql.swift */; }; - E607A76F29FB69300059899E /* Animal.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A74629FB692F0059899E /* Animal.graphql.swift */; }; E607A77029FB69300059899E /* WarmBlooded.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A74729FB692F0059899E /* WarmBlooded.graphql.swift */; }; E607A77F29FB69920059899E /* Human+Mock.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A77229FB69920059899E /* Human+Mock.graphql.swift */; }; E607A78029FB69920059899E /* Height+Mock.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A77329FB69920059899E /* Height+Mock.graphql.swift */; }; @@ -66,7 +67,6 @@ E607A78829FB69920059899E /* Dog+Mock.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A77B29FB69920059899E /* Dog+Mock.graphql.swift */; }; E607A78929FB69920059899E /* Fish+Mock.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A77C29FB69920059899E /* Fish+Mock.graphql.swift */; }; E607A78A29FB69920059899E /* Mutation+Mock.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A77D29FB69920059899E /* Mutation+Mock.graphql.swift */; }; - E607A78B29FB69920059899E /* Crocodile+Mock.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E607A77E29FB69920059899E /* Crocodile+Mock.graphql.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -82,6 +82,12 @@ /* Begin PBXFileReference section */ 4C671E51FD3FF74D8B077F45 /* Pods-CocoaPodsProjectTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CocoaPodsProjectTests.release.xcconfig"; path = "Target Support Files/Pods-CocoaPodsProjectTests/Pods-CocoaPodsProjectTests.release.xcconfig"; sourceTree = ""; }; 665BDA852AE30BE2004DD21F /* Object.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Object.swift; sourceTree = ""; }; + 66F434EA2C12B5EC00679212 /* CustomClassroomPet.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomClassroomPet.graphql.swift; sourceTree = ""; }; + 66F434EC2C12B60800679212 /* CustomSkinCovering.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomSkinCovering.graphql.swift; sourceTree = ""; }; + 66F434EE2C12B60E00679212 /* CustomCrocodile.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomCrocodile.graphql.swift; sourceTree = ""; }; + 66F434F02C12B61400679212 /* CustomPetSearchFilters.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomPetSearchFilters.graphql.swift; sourceTree = ""; }; + 66F434F22C12B61900679212 /* CustomAnimal.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomAnimal.graphql.swift; sourceTree = ""; }; + 66F434F42C12B67E00679212 /* CustomCrocodile+Mock.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CustomCrocodile+Mock.graphql.swift"; sourceTree = ""; }; 7D6507DAD078EC7A270097F0 /* Pods-CocoaPodsProject.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CocoaPodsProject.release.xcconfig"; path = "Target Support Files/Pods-CocoaPodsProject/Pods-CocoaPodsProject.release.xcconfig"; sourceTree = ""; }; 951B5BB1CBB3B06FF1E6F602 /* Pods-CocoaPodsProject.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CocoaPodsProject.debug.xcconfig"; path = "Target Support Files/Pods-CocoaPodsProject/Pods-CocoaPodsProject.debug.xcconfig"; sourceTree = ""; }; C684794938D6314DF12AB411 /* Pods_CocoaPodsProject.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CocoaPodsProject.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -111,9 +117,7 @@ E607A72629FB692F0059899E /* AllAnimalsQuery.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllAnimalsQuery.graphql.swift; sourceTree = ""; }; E607A72729FB692F0059899E /* AllAnimalsIncludeSkipQuery.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllAnimalsIncludeSkipQuery.graphql.swift; sourceTree = ""; }; E607A72829FB692F0059899E /* PetSearchQuery.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PetSearchQuery.graphql.swift; sourceTree = ""; }; - E607A72B29FB692F0059899E /* ClassroomPet.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClassroomPet.graphql.swift; sourceTree = ""; }; E607A72D29FB692F0059899E /* CustomDate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomDate.swift; sourceTree = ""; }; - E607A72F29FB692F0059899E /* SkinCovering.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SkinCovering.graphql.swift; sourceTree = ""; }; E607A73029FB692F0059899E /* RelativeSize.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RelativeSize.graphql.swift; sourceTree = ""; }; E607A73229FB692F0059899E /* Rat.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Rat.graphql.swift; sourceTree = ""; }; E607A73329FB692F0059899E /* Bird.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Bird.graphql.swift; sourceTree = ""; }; @@ -125,15 +129,12 @@ E607A73929FB692F0059899E /* Cat.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cat.graphql.swift; sourceTree = ""; }; E607A73A29FB692F0059899E /* Fish.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fish.graphql.swift; sourceTree = ""; }; E607A73B29FB692F0059899E /* Human.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Human.graphql.swift; sourceTree = ""; }; - E607A73C29FB692F0059899E /* Crocodile.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Crocodile.graphql.swift; sourceTree = ""; }; E607A73D29FB692F0059899E /* SchemaConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaConfiguration.swift; sourceTree = ""; }; E607A73F29FB692F0059899E /* PetAdoptionInput.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PetAdoptionInput.graphql.swift; sourceTree = ""; }; - E607A74029FB692F0059899E /* PetSearchFilters.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PetSearchFilters.graphql.swift; sourceTree = ""; }; E607A74129FB692F0059899E /* MeasurementsInput.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MeasurementsInput.graphql.swift; sourceTree = ""; }; E607A74229FB692F0059899E /* SchemaMetadata.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaMetadata.graphql.swift; sourceTree = ""; }; E607A74429FB692F0059899E /* HousePet.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HousePet.graphql.swift; sourceTree = ""; }; E607A74529FB692F0059899E /* Pet.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Pet.graphql.swift; sourceTree = ""; }; - E607A74629FB692F0059899E /* Animal.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animal.graphql.swift; sourceTree = ""; }; E607A74729FB692F0059899E /* WarmBlooded.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WarmBlooded.graphql.swift; sourceTree = ""; }; E607A77229FB69920059899E /* Human+Mock.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Human+Mock.graphql.swift"; sourceTree = ""; }; E607A77329FB69920059899E /* Height+Mock.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Height+Mock.graphql.swift"; sourceTree = ""; }; @@ -147,7 +148,6 @@ E607A77B29FB69920059899E /* Dog+Mock.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Dog+Mock.graphql.swift"; sourceTree = ""; }; E607A77C29FB69920059899E /* Fish+Mock.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Fish+Mock.graphql.swift"; sourceTree = ""; }; E607A77D29FB69920059899E /* Mutation+Mock.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Mutation+Mock.graphql.swift"; sourceTree = ""; }; - E607A77E29FB69920059899E /* Crocodile+Mock.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Crocodile+Mock.graphql.swift"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -321,7 +321,7 @@ E607A72A29FB692F0059899E /* Unions */ = { isa = PBXGroup; children = ( - E607A72B29FB692F0059899E /* ClassroomPet.graphql.swift */, + 66F434EA2C12B5EC00679212 /* CustomClassroomPet.graphql.swift */, ); path = Unions; sourceTree = ""; @@ -339,7 +339,7 @@ E607A72E29FB692F0059899E /* Enums */ = { isa = PBXGroup; children = ( - E607A72F29FB692F0059899E /* SkinCovering.graphql.swift */, + 66F434EC2C12B60800679212 /* CustomSkinCovering.graphql.swift */, E607A73029FB692F0059899E /* RelativeSize.graphql.swift */, ); path = Enums; @@ -348,6 +348,7 @@ E607A73129FB692F0059899E /* Objects */ = { isa = PBXGroup; children = ( + 66F434EE2C12B60E00679212 /* CustomCrocodile.graphql.swift */, E607A73229FB692F0059899E /* Rat.graphql.swift */, E607A73329FB692F0059899E /* Bird.graphql.swift */, E607A73429FB692F0059899E /* PetRock.graphql.swift */, @@ -358,7 +359,6 @@ E607A73929FB692F0059899E /* Cat.graphql.swift */, E607A73A29FB692F0059899E /* Fish.graphql.swift */, E607A73B29FB692F0059899E /* Human.graphql.swift */, - E607A73C29FB692F0059899E /* Crocodile.graphql.swift */, ); path = Objects; sourceTree = ""; @@ -366,8 +366,8 @@ E607A73E29FB692F0059899E /* InputObjects */ = { isa = PBXGroup; children = ( + 66F434F02C12B61400679212 /* CustomPetSearchFilters.graphql.swift */, E607A73F29FB692F0059899E /* PetAdoptionInput.graphql.swift */, - E607A74029FB692F0059899E /* PetSearchFilters.graphql.swift */, E607A74129FB692F0059899E /* MeasurementsInput.graphql.swift */, ); path = InputObjects; @@ -376,9 +376,9 @@ E607A74329FB692F0059899E /* Interfaces */ = { isa = PBXGroup; children = ( + 66F434F22C12B61900679212 /* CustomAnimal.graphql.swift */, E607A74429FB692F0059899E /* HousePet.graphql.swift */, E607A74529FB692F0059899E /* Pet.graphql.swift */, - E607A74629FB692F0059899E /* Animal.graphql.swift */, E607A74729FB692F0059899E /* WarmBlooded.graphql.swift */, ); path = Interfaces; @@ -387,6 +387,7 @@ E607A77129FB69920059899E /* AnimalKingdomAPITestMocks */ = { isa = PBXGroup; children = ( + 66F434F42C12B67E00679212 /* CustomCrocodile+Mock.graphql.swift */, E607A77229FB69920059899E /* Human+Mock.graphql.swift */, E607A77329FB69920059899E /* Height+Mock.graphql.swift */, E607A77429FB69920059899E /* Query+Mock.graphql.swift */, @@ -399,7 +400,6 @@ E607A77B29FB69920059899E /* Dog+Mock.graphql.swift */, E607A77C29FB69920059899E /* Fish+Mock.graphql.swift */, E607A77D29FB69920059899E /* Mutation+Mock.graphql.swift */, - E607A77E29FB69920059899E /* Crocodile+Mock.graphql.swift */, ); path = AnimalKingdomAPITestMocks; sourceTree = ""; @@ -573,42 +573,42 @@ files = ( E607A76029FB692F0059899E /* Dog.graphql.swift in Sources */, E607A74A29FB692F0059899E /* ClassroomPetDetails.graphql.swift in Sources */, - E607A75929FB692F0059899E /* ClassroomPet.graphql.swift in Sources */, + 66F434EB2C12B5EC00679212 /* CustomClassroomPet.graphql.swift in Sources */, E607A75F29FB692F0059899E /* PetRock.graphql.swift in Sources */, E607A76129FB69300059899E /* Height.graphql.swift in Sources */, 665BDA862AE30BE2004DD21F /* Object.swift in Sources */, E607A76C29FB69300059899E /* SchemaMetadata.graphql.swift in Sources */, E607A76329FB69300059899E /* Query.graphql.swift in Sources */, E607A75229FB692F0059899E /* DogQuery.graphql.swift in Sources */, + 66F434ED2C12B60800679212 /* CustomSkinCovering.graphql.swift in Sources */, E607A75829FB692F0059899E /* PetSearchQuery.graphql.swift in Sources */, - E607A76A29FB69300059899E /* PetSearchFilters.graphql.swift in Sources */, E607A76629FB69300059899E /* Human.graphql.swift in Sources */, + 66F434EF2C12B60E00679212 /* CustomCrocodile.graphql.swift in Sources */, E607A76229FB69300059899E /* Mutation.graphql.swift in Sources */, E607A76E29FB69300059899E /* Pet.graphql.swift in Sources */, E607A76929FB69300059899E /* PetAdoptionInput.graphql.swift in Sources */, E607A75029FB692F0059899E /* PetSearchLocalCacheMutation.graphql.swift in Sources */, E607A76429FB69300059899E /* Cat.graphql.swift in Sources */, E607A75D29FB692F0059899E /* Rat.graphql.swift in Sources */, - E607A75B29FB692F0059899E /* SkinCovering.graphql.swift in Sources */, E607A74B29FB692F0059899E /* DogFragment.graphql.swift in Sources */, + 66F434F12C12B61400679212 /* CustomPetSearchFilters.graphql.swift in Sources */, E607A74E29FB692F0059899E /* PetDetailsMutation.graphql.swift in Sources */, E607A74F29FB692F0059899E /* AllAnimalsLocalCacheMutation.graphql.swift in Sources */, E607A75729FB692F0059899E /* AllAnimalsIncludeSkipQuery.graphql.swift in Sources */, E607A76529FB69300059899E /* Fish.graphql.swift in Sources */, E607A75E29FB692F0059899E /* Bird.graphql.swift in Sources */, - E607A76729FB69300059899E /* Crocodile.graphql.swift in Sources */, E607A74929FB692F0059899E /* HeightInMeters.graphql.swift in Sources */, E607A76829FB69300059899E /* SchemaConfiguration.swift in Sources */, E607A75629FB692F0059899E /* AllAnimalsQuery.graphql.swift in Sources */, E607A75429FB692F0059899E /* ClassroomPetsQuery.graphql.swift in Sources */, E607A74D29FB692F0059899E /* WarmBloodedDetails.graphql.swift in Sources */, + 66F434F32C12B61900679212 /* CustomAnimal.graphql.swift in Sources */, E607A69E29FB43F80059899E /* ContentView.swift in Sources */, DE4790B02BFBD66E00939CCC /* ID.swift in Sources */, E607A76B29FB69300059899E /* MeasurementsInput.graphql.swift in Sources */, E607A74829FB692F0059899E /* PetDetails.graphql.swift in Sources */, E607A76D29FB69300059899E /* HousePet.graphql.swift in Sources */, E607A75A29FB692F0059899E /* CustomDate.swift in Sources */, - E607A76F29FB69300059899E /* Animal.graphql.swift in Sources */, E607A75C29FB692F0059899E /* RelativeSize.graphql.swift in Sources */, E607A69C29FB43F80059899E /* CocoaPodsProjectApp.swift in Sources */, E607A75129FB692F0059899E /* PetAdoptionMutation.graphql.swift in Sources */, @@ -620,6 +620,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 66F434F52C12B67E00679212 /* CustomCrocodile+Mock.graphql.swift in Sources */, E607A78629FB69920059899E /* MockObject+Unions.graphql.swift in Sources */, E607A78729FB69920059899E /* Cat+Mock.graphql.swift in Sources */, E607A78029FB69920059899E /* Height+Mock.graphql.swift in Sources */, @@ -631,7 +632,6 @@ E607A6AE29FB43F90059899E /* CocoaPodsProjectTests.swift in Sources */, E607A78229FB69920059899E /* PetRock+Mock.graphql.swift in Sources */, E607A78A29FB69920059899E /* Mutation+Mock.graphql.swift in Sources */, - E607A78B29FB69920059899E /* Crocodile+Mock.graphql.swift in Sources */, E607A78129FB69920059899E /* Query+Mock.graphql.swift in Sources */, E607A78329FB69920059899E /* Bird+Mock.graphql.swift in Sources */, ); diff --git a/Tests/TestCodeGenConfigurations/Other-CocoaPods/apollo-codegen-config.json b/Tests/TestCodeGenConfigurations/Other-CocoaPods/apollo-codegen-config.json index 3235d6e7f..0978d2b81 100644 --- a/Tests/TestCodeGenConfigurations/Other-CocoaPods/apollo-codegen-config.json +++ b/Tests/TestCodeGenConfigurations/Other-CocoaPods/apollo-codegen-config.json @@ -13,7 +13,31 @@ }, "pruneGeneratedFiles" : true, "queryStringLiteralFormat" : "multiline", - "warningsOnDeprecatedUsage" : "include" + "warningsOnDeprecatedUsage" : "include", + "schemaCustomization" : { + "customTypeNames" : { + "SkinCovering" : { + "enum" : { + "cases" : { + "HAIR" : "CUSTOMHAIR" + }, + "name" : "CustomSkinCovering" + } + }, + "Animal" : "CustomAnimal", + "Crocodile" : "CustomCrocodile", + "ClassroomPet" : "CustomClassroomPet", + "Date" : "CustomDate", + "PetSearchFilters" : { + "inputObject" : { + "fields" : { + "size" : "customSize" + }, + "name" : "CustomPetSearchFilters" + } + } + } + } }, "input" : { "operationSearchPaths" : [ diff --git a/Tests/TestCodeGenConfigurations/Other-CustomTarget/CustomTargetProject.xcodeproj/project.pbxproj b/Tests/TestCodeGenConfigurations/Other-CustomTarget/CustomTargetProject.xcodeproj/project.pbxproj index 27dfd1a97..8642fb428 100644 --- a/Tests/TestCodeGenConfigurations/Other-CustomTarget/CustomTargetProject.xcodeproj/project.pbxproj +++ b/Tests/TestCodeGenConfigurations/Other-CustomTarget/CustomTargetProject.xcodeproj/project.pbxproj @@ -8,6 +8,12 @@ /* Begin PBXBuildFile section */ 665BDA882AE30E9D004DD21F /* Object.swift in Sources */ = {isa = PBXBuildFile; fileRef = 665BDA872AE30E9D004DD21F /* Object.swift */; }; + 66F434F72C12B6D200679212 /* CustomClassroomPet.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F434F62C12B6D200679212 /* CustomClassroomPet.graphql.swift */; }; + 66F434F92C12B6DA00679212 /* CustomSkinCovering.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F434F82C12B6DA00679212 /* CustomSkinCovering.graphql.swift */; }; + 66F434FB2C12B6E200679212 /* CustomCrocodile.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F434FA2C12B6E200679212 /* CustomCrocodile.graphql.swift */; }; + 66F434FD2C12B6E900679212 /* CustomPetSearchFilters.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F434FC2C12B6E900679212 /* CustomPetSearchFilters.graphql.swift */; }; + 66F434FF2C12B6F100679212 /* CustomAnimal.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F434FE2C12B6F100679212 /* CustomAnimal.graphql.swift */; }; + 66F435012C12B6FC00679212 /* CustomCrocodile+Mock.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F435002C12B6FC00679212 /* CustomCrocodile+Mock.graphql.swift */; }; DE454BCC28B43262009DC80E /* CustomTargetProject.h in Headers */ = {isa = PBXBuildFile; fileRef = DE454BCB28B43262009DC80E /* CustomTargetProject.h */; settings = {ATTRIBUTES = (Public, ); }; }; DE4790B22BFBDA8500939CCC /* ID.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE4790B12BFBDA8400939CCC /* ID.swift */; }; E6BACC1C29FC909F008B46F2 /* AnimalKingdomAPI.h in Headers */ = {isa = PBXBuildFile; fileRef = E6BACC1B29FC909F008B46F2 /* AnimalKingdomAPI.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -15,9 +21,7 @@ E6BACC5729FC9468008B46F2 /* PetDetailsMutation.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC2329FC9468008B46F2 /* PetDetailsMutation.graphql.swift */; }; E6BACC5829FC9468008B46F2 /* AllAnimalsLocalCacheMutation.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC2429FC9468008B46F2 /* AllAnimalsLocalCacheMutation.graphql.swift */; }; E6BACC5929FC9468008B46F2 /* PetSearchLocalCacheMutation.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC2529FC9468008B46F2 /* PetSearchLocalCacheMutation.graphql.swift */; }; - E6BACC5A29FC9468008B46F2 /* ClassroomPet.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC2829FC9468008B46F2 /* ClassroomPet.graphql.swift */; }; E6BACC5B29FC9468008B46F2 /* CustomDate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC2A29FC9468008B46F2 /* CustomDate.swift */; }; - E6BACC5C29FC9468008B46F2 /* SkinCovering.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC2C29FC9468008B46F2 /* SkinCovering.graphql.swift */; }; E6BACC5D29FC9468008B46F2 /* RelativeSize.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC2D29FC9468008B46F2 /* RelativeSize.graphql.swift */; }; E6BACC5E29FC9468008B46F2 /* Rat.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC2F29FC9468008B46F2 /* Rat.graphql.swift */; }; E6BACC5F29FC9468008B46F2 /* Bird.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC3029FC9468008B46F2 /* Bird.graphql.swift */; }; @@ -29,15 +33,12 @@ E6BACC6529FC9468008B46F2 /* Cat.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC3629FC9468008B46F2 /* Cat.graphql.swift */; }; E6BACC6629FC9468008B46F2 /* Fish.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC3729FC9468008B46F2 /* Fish.graphql.swift */; }; E6BACC6729FC9468008B46F2 /* Human.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC3829FC9468008B46F2 /* Human.graphql.swift */; }; - E6BACC6829FC9468008B46F2 /* Crocodile.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC3929FC9468008B46F2 /* Crocodile.graphql.swift */; }; E6BACC6929FC9468008B46F2 /* SchemaConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC3A29FC9468008B46F2 /* SchemaConfiguration.swift */; }; E6BACC6A29FC9468008B46F2 /* PetAdoptionInput.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC3C29FC9468008B46F2 /* PetAdoptionInput.graphql.swift */; }; - E6BACC6B29FC9468008B46F2 /* PetSearchFilters.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC3D29FC9468008B46F2 /* PetSearchFilters.graphql.swift */; }; E6BACC6C29FC9468008B46F2 /* MeasurementsInput.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC3E29FC9468008B46F2 /* MeasurementsInput.graphql.swift */; }; E6BACC6D29FC9468008B46F2 /* SchemaMetadata.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC3F29FC9468008B46F2 /* SchemaMetadata.graphql.swift */; }; E6BACC6E29FC9468008B46F2 /* HousePet.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC4129FC9468008B46F2 /* HousePet.graphql.swift */; }; E6BACC6F29FC9468008B46F2 /* Pet.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC4229FC9468008B46F2 /* Pet.graphql.swift */; }; - E6BACC7029FC9468008B46F2 /* Animal.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC4329FC9468008B46F2 /* Animal.graphql.swift */; }; E6BACC7129FC9468008B46F2 /* WarmBlooded.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC4429FC9468008B46F2 /* WarmBlooded.graphql.swift */; }; E6BACC7229FC9468008B46F2 /* PetDetails.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC4629FC9468008B46F2 /* PetDetails.graphql.swift */; }; E6BACC7329FC9468008B46F2 /* HeightInMeters.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6BACC4729FC9468008B46F2 /* HeightInMeters.graphql.swift */; }; @@ -66,7 +67,6 @@ E6CE964E2A00716300E66222 /* Dog+Mock.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6CE96412A00716300E66222 /* Dog+Mock.graphql.swift */; }; E6CE964F2A00716300E66222 /* Fish+Mock.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6CE96422A00716300E66222 /* Fish+Mock.graphql.swift */; }; E6CE96502A00716300E66222 /* Mutation+Mock.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6CE96432A00716300E66222 /* Mutation+Mock.graphql.swift */; }; - E6CE96512A00716300E66222 /* Crocodile+Mock.graphql.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6CE96442A00716300E66222 /* Crocodile+Mock.graphql.swift */; }; E6CE96532A0071DF00E66222 /* ApolloTestSupport in Frameworks */ = {isa = PBXBuildFile; productRef = E6CE96522A0071DF00E66222 /* ApolloTestSupport */; }; /* End PBXBuildFile section */ @@ -104,6 +104,12 @@ /* Begin PBXFileReference section */ 663EB6712A58B3C300A63215 /* apollo-ios */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = "apollo-ios"; path = "../../../apollo-ios"; sourceTree = ""; }; 665BDA872AE30E9D004DD21F /* Object.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Object.swift; sourceTree = ""; }; + 66F434F62C12B6D200679212 /* CustomClassroomPet.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomClassroomPet.graphql.swift; sourceTree = ""; }; + 66F434F82C12B6DA00679212 /* CustomSkinCovering.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomSkinCovering.graphql.swift; sourceTree = ""; }; + 66F434FA2C12B6E200679212 /* CustomCrocodile.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomCrocodile.graphql.swift; sourceTree = ""; }; + 66F434FC2C12B6E900679212 /* CustomPetSearchFilters.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomPetSearchFilters.graphql.swift; sourceTree = ""; }; + 66F434FE2C12B6F100679212 /* CustomAnimal.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomAnimal.graphql.swift; sourceTree = ""; }; + 66F435002C12B6FC00679212 /* CustomCrocodile+Mock.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CustomCrocodile+Mock.graphql.swift"; sourceTree = ""; }; DE454BC928B43262009DC80E /* CustomTargetProject.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CustomTargetProject.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DE454BCB28B43262009DC80E /* CustomTargetProject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CustomTargetProject.h; sourceTree = ""; }; DE4790B12BFBDA8400939CCC /* ID.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ID.swift; sourceTree = ""; }; @@ -113,9 +119,7 @@ E6BACC2329FC9468008B46F2 /* PetDetailsMutation.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PetDetailsMutation.graphql.swift; sourceTree = ""; }; E6BACC2429FC9468008B46F2 /* AllAnimalsLocalCacheMutation.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllAnimalsLocalCacheMutation.graphql.swift; sourceTree = ""; }; E6BACC2529FC9468008B46F2 /* PetSearchLocalCacheMutation.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PetSearchLocalCacheMutation.graphql.swift; sourceTree = ""; }; - E6BACC2829FC9468008B46F2 /* ClassroomPet.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClassroomPet.graphql.swift; sourceTree = ""; }; E6BACC2A29FC9468008B46F2 /* CustomDate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomDate.swift; sourceTree = ""; }; - E6BACC2C29FC9468008B46F2 /* SkinCovering.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SkinCovering.graphql.swift; sourceTree = ""; }; E6BACC2D29FC9468008B46F2 /* RelativeSize.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RelativeSize.graphql.swift; sourceTree = ""; }; E6BACC2F29FC9468008B46F2 /* Rat.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Rat.graphql.swift; sourceTree = ""; }; E6BACC3029FC9468008B46F2 /* Bird.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Bird.graphql.swift; sourceTree = ""; }; @@ -127,15 +131,12 @@ E6BACC3629FC9468008B46F2 /* Cat.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Cat.graphql.swift; sourceTree = ""; }; E6BACC3729FC9468008B46F2 /* Fish.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Fish.graphql.swift; sourceTree = ""; }; E6BACC3829FC9468008B46F2 /* Human.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Human.graphql.swift; sourceTree = ""; }; - E6BACC3929FC9468008B46F2 /* Crocodile.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Crocodile.graphql.swift; sourceTree = ""; }; E6BACC3A29FC9468008B46F2 /* SchemaConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaConfiguration.swift; sourceTree = ""; }; E6BACC3C29FC9468008B46F2 /* PetAdoptionInput.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PetAdoptionInput.graphql.swift; sourceTree = ""; }; - E6BACC3D29FC9468008B46F2 /* PetSearchFilters.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PetSearchFilters.graphql.swift; sourceTree = ""; }; E6BACC3E29FC9468008B46F2 /* MeasurementsInput.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MeasurementsInput.graphql.swift; sourceTree = ""; }; E6BACC3F29FC9468008B46F2 /* SchemaMetadata.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemaMetadata.graphql.swift; sourceTree = ""; }; E6BACC4129FC9468008B46F2 /* HousePet.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HousePet.graphql.swift; sourceTree = ""; }; E6BACC4229FC9468008B46F2 /* Pet.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Pet.graphql.swift; sourceTree = ""; }; - E6BACC4329FC9468008B46F2 /* Animal.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animal.graphql.swift; sourceTree = ""; }; E6BACC4429FC9468008B46F2 /* WarmBlooded.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WarmBlooded.graphql.swift; sourceTree = ""; }; E6BACC4629FC9468008B46F2 /* PetDetails.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PetDetails.graphql.swift; sourceTree = ""; }; E6BACC4729FC9468008B46F2 /* HeightInMeters.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeightInMeters.graphql.swift; sourceTree = ""; }; @@ -162,7 +163,6 @@ E6CE96412A00716300E66222 /* Dog+Mock.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Dog+Mock.graphql.swift"; sourceTree = ""; }; E6CE96422A00716300E66222 /* Fish+Mock.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Fish+Mock.graphql.swift"; sourceTree = ""; }; E6CE96432A00716300E66222 /* Mutation+Mock.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Mutation+Mock.graphql.swift"; sourceTree = ""; }; - E6CE96442A00716300E66222 /* Crocodile+Mock.graphql.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Crocodile+Mock.graphql.swift"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -280,7 +280,7 @@ E6BACC2729FC9468008B46F2 /* Unions */ = { isa = PBXGroup; children = ( - E6BACC2829FC9468008B46F2 /* ClassroomPet.graphql.swift */, + 66F434F62C12B6D200679212 /* CustomClassroomPet.graphql.swift */, ); path = Unions; sourceTree = ""; @@ -298,7 +298,7 @@ E6BACC2B29FC9468008B46F2 /* Enums */ = { isa = PBXGroup; children = ( - E6BACC2C29FC9468008B46F2 /* SkinCovering.graphql.swift */, + 66F434F82C12B6DA00679212 /* CustomSkinCovering.graphql.swift */, E6BACC2D29FC9468008B46F2 /* RelativeSize.graphql.swift */, ); path = Enums; @@ -307,6 +307,7 @@ E6BACC2E29FC9468008B46F2 /* Objects */ = { isa = PBXGroup; children = ( + 66F434FA2C12B6E200679212 /* CustomCrocodile.graphql.swift */, E6BACC2F29FC9468008B46F2 /* Rat.graphql.swift */, E6BACC3029FC9468008B46F2 /* Bird.graphql.swift */, E6BACC3129FC9468008B46F2 /* PetRock.graphql.swift */, @@ -317,7 +318,6 @@ E6BACC3629FC9468008B46F2 /* Cat.graphql.swift */, E6BACC3729FC9468008B46F2 /* Fish.graphql.swift */, E6BACC3829FC9468008B46F2 /* Human.graphql.swift */, - E6BACC3929FC9468008B46F2 /* Crocodile.graphql.swift */, ); path = Objects; sourceTree = ""; @@ -325,8 +325,8 @@ E6BACC3B29FC9468008B46F2 /* InputObjects */ = { isa = PBXGroup; children = ( + 66F434FC2C12B6E900679212 /* CustomPetSearchFilters.graphql.swift */, E6BACC3C29FC9468008B46F2 /* PetAdoptionInput.graphql.swift */, - E6BACC3D29FC9468008B46F2 /* PetSearchFilters.graphql.swift */, E6BACC3E29FC9468008B46F2 /* MeasurementsInput.graphql.swift */, ); path = InputObjects; @@ -335,9 +335,9 @@ E6BACC4029FC9468008B46F2 /* Interfaces */ = { isa = PBXGroup; children = ( + 66F434FE2C12B6F100679212 /* CustomAnimal.graphql.swift */, E6BACC4129FC9468008B46F2 /* HousePet.graphql.swift */, E6BACC4229FC9468008B46F2 /* Pet.graphql.swift */, - E6BACC4329FC9468008B46F2 /* Animal.graphql.swift */, E6BACC4429FC9468008B46F2 /* WarmBlooded.graphql.swift */, ); path = Interfaces; @@ -396,6 +396,7 @@ E6CE96372A00716300E66222 /* AnimalKingdomAPITestMocks */ = { isa = PBXGroup; children = ( + 66F435002C12B6FC00679212 /* CustomCrocodile+Mock.graphql.swift */, E6CE96382A00716300E66222 /* Human+Mock.graphql.swift */, E6CE96392A00716300E66222 /* Height+Mock.graphql.swift */, E6CE963A2A00716300E66222 /* Query+Mock.graphql.swift */, @@ -408,7 +409,6 @@ E6CE96412A00716300E66222 /* Dog+Mock.graphql.swift */, E6CE96422A00716300E66222 /* Fish+Mock.graphql.swift */, E6CE96432A00716300E66222 /* Mutation+Mock.graphql.swift */, - E6CE96442A00716300E66222 /* Crocodile+Mock.graphql.swift */, ); path = AnimalKingdomAPITestMocks; sourceTree = ""; @@ -576,36 +576,36 @@ files = ( E6BACC6C29FC9468008B46F2 /* MeasurementsInput.graphql.swift in Sources */, E6BACC6F29FC9468008B46F2 /* Pet.graphql.swift in Sources */, - E6BACC6B29FC9468008B46F2 /* PetSearchFilters.graphql.swift in Sources */, E6BACC5F29FC9468008B46F2 /* Bird.graphql.swift in Sources */, - E6BACC6829FC9468008B46F2 /* Crocodile.graphql.swift in Sources */, E6BACC5E29FC9468008B46F2 /* Rat.graphql.swift in Sources */, + 66F434F72C12B6D200679212 /* CustomClassroomPet.graphql.swift in Sources */, E6BACC6129FC9468008B46F2 /* Dog.graphql.swift in Sources */, - E6BACC5C29FC9468008B46F2 /* SkinCovering.graphql.swift in Sources */, DE4790B22BFBDA8500939CCC /* ID.swift in Sources */, E6BACC6D29FC9468008B46F2 /* SchemaMetadata.graphql.swift in Sources */, E6BACC6A29FC9468008B46F2 /* PetAdoptionInput.graphql.swift in Sources */, 665BDA882AE30E9D004DD21F /* Object.swift in Sources */, E6BACC6629FC9468008B46F2 /* Fish.graphql.swift in Sources */, + 66F434FB2C12B6E200679212 /* CustomCrocodile.graphql.swift in Sources */, E6BACC7829FC9468008B46F2 /* PetAdoptionMutation.graphql.swift in Sources */, E6BACC7329FC9468008B46F2 /* HeightInMeters.graphql.swift in Sources */, E6BACC6029FC9468008B46F2 /* PetRock.graphql.swift in Sources */, + 66F434FF2C12B6F100679212 /* CustomAnimal.graphql.swift in Sources */, E6BACC6229FC9468008B46F2 /* Height.graphql.swift in Sources */, E6BACC6729FC9468008B46F2 /* Human.graphql.swift in Sources */, + 66F434F92C12B6DA00679212 /* CustomSkinCovering.graphql.swift in Sources */, E6BACC6529FC9468008B46F2 /* Cat.graphql.swift in Sources */, E6BACC7229FC9468008B46F2 /* PetDetails.graphql.swift in Sources */, E6BACC7D29FC9468008B46F2 /* AllAnimalsQuery.graphql.swift in Sources */, E6BACC5829FC9468008B46F2 /* AllAnimalsLocalCacheMutation.graphql.swift in Sources */, - E6BACC7029FC9468008B46F2 /* Animal.graphql.swift in Sources */, E6BACC7B29FC9468008B46F2 /* ClassroomPetsQuery.graphql.swift in Sources */, E6BACC5929FC9468008B46F2 /* PetSearchLocalCacheMutation.graphql.swift in Sources */, E6BACC7F29FC9468008B46F2 /* PetSearchQuery.graphql.swift in Sources */, - E6BACC5A29FC9468008B46F2 /* ClassroomPet.graphql.swift in Sources */, E6BACC7929FC9468008B46F2 /* DogQuery.graphql.swift in Sources */, E6BACC5B29FC9468008B46F2 /* CustomDate.swift in Sources */, E6BACC7729FC9468008B46F2 /* WarmBloodedDetails.graphql.swift in Sources */, E6BACC5D29FC9468008B46F2 /* RelativeSize.graphql.swift in Sources */, E6BACC7529FC9468008B46F2 /* DogFragment.graphql.swift in Sources */, + 66F434FD2C12B6E900679212 /* CustomPetSearchFilters.graphql.swift in Sources */, E6BACC6E29FC9468008B46F2 /* HousePet.graphql.swift in Sources */, E6BACC6329FC9468008B46F2 /* Mutation.graphql.swift in Sources */, E6BACC7429FC9468008B46F2 /* ClassroomPetDetails.graphql.swift in Sources */, @@ -621,6 +621,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 66F435012C12B6FC00679212 /* CustomCrocodile+Mock.graphql.swift in Sources */, E6CE964C2A00716300E66222 /* MockObject+Unions.graphql.swift in Sources */, E6CE964D2A00716300E66222 /* Cat+Mock.graphql.swift in Sources */, E6CE96462A00716300E66222 /* Height+Mock.graphql.swift in Sources */, @@ -632,7 +633,6 @@ E6BACC8C29FC9A9C008B46F2 /* CustomTargetProjectTests.swift in Sources */, E6CE96482A00716300E66222 /* PetRock+Mock.graphql.swift in Sources */, E6CE96502A00716300E66222 /* Mutation+Mock.graphql.swift in Sources */, - E6CE96512A00716300E66222 /* Crocodile+Mock.graphql.swift in Sources */, E6CE96472A00716300E66222 /* Query+Mock.graphql.swift in Sources */, E6CE96492A00716300E66222 /* Bird+Mock.graphql.swift in Sources */, ); diff --git a/Tests/TestCodeGenConfigurations/Other-CustomTarget/apollo-codegen-config.json b/Tests/TestCodeGenConfigurations/Other-CustomTarget/apollo-codegen-config.json index 81dc40291..e39e55b52 100644 --- a/Tests/TestCodeGenConfigurations/Other-CustomTarget/apollo-codegen-config.json +++ b/Tests/TestCodeGenConfigurations/Other-CustomTarget/apollo-codegen-config.json @@ -13,7 +13,31 @@ }, "pruneGeneratedFiles" : true, "queryStringLiteralFormat" : "multiline", - "warningsOnDeprecatedUsage" : "include" + "warningsOnDeprecatedUsage" : "include", + "schemaCustomization" : { + "customTypeNames" : { + "SkinCovering" : { + "enum" : { + "cases" : { + "HAIR" : "CUSTOMHAIR" + }, + "name" : "CustomSkinCovering" + } + }, + "Animal" : "CustomAnimal", + "Crocodile" : "CustomCrocodile", + "ClassroomPet" : "CustomClassroomPet", + "Date" : "CustomDate", + "PetSearchFilters" : { + "inputObject" : { + "fields" : { + "size" : "customSize" + }, + "name" : "CustomPetSearchFilters" + } + } + } + } }, "input" : { "operationSearchPaths" : [ diff --git a/Tests/TestCodeGenConfigurations/SPMInXcodeProject/apollo-codegen-config.json b/Tests/TestCodeGenConfigurations/SPMInXcodeProject/apollo-codegen-config.json index 228c0ba3c..256daa6f0 100644 --- a/Tests/TestCodeGenConfigurations/SPMInXcodeProject/apollo-codegen-config.json +++ b/Tests/TestCodeGenConfigurations/SPMInXcodeProject/apollo-codegen-config.json @@ -13,7 +13,31 @@ }, "pruneGeneratedFiles" : true, "queryStringLiteralFormat" : "multiline", - "warningsOnDeprecatedUsage" : "include" + "warningsOnDeprecatedUsage" : "include", + "schemaCustomization" : { + "customTypeNames" : { + "SkinCovering" : { + "enum" : { + "cases" : { + "HAIR" : "CUSTOMHAIR" + }, + "name" : "CustomSkinCovering" + } + }, + "Animal" : "CustomAnimal", + "Crocodile" : "CustomCrocodile", + "ClassroomPet" : "CustomClassroomPet", + "Date" : "CustomDate", + "PetSearchFilters" : { + "inputObject" : { + "fields" : { + "size" : "customSize" + }, + "name" : "CustomPetSearchFilters" + } + } + } + } }, "input" : { "operationSearchPaths" : [ diff --git a/Tests/TestCodeGenConfigurations/SwiftPackageManager/Tests/SwiftPackageTests/TestMockUsageTests.swift b/Tests/TestCodeGenConfigurations/SwiftPackageManager/Tests/SwiftPackageTests/TestMockUsageTests.swift index afb1c8b44..6cfc25ce9 100644 --- a/Tests/TestCodeGenConfigurations/SwiftPackageManager/Tests/SwiftPackageTests/TestMockUsageTests.swift +++ b/Tests/TestCodeGenConfigurations/SwiftPackageManager/Tests/SwiftPackageTests/TestMockUsageTests.swift @@ -18,7 +18,7 @@ class TestMockUsageTests: XCTestCase { let mockHeight = Mock(feet: 2, inches: 7) let mockHuman = Mock(firstName: "Human") - let mockCrocodile = Mock(id: "Crocodile", skinCovering: .case(.scales)) + let mockCrocodile = Mock(id: "Crocodile", skinCovering: .case(.scales)) let mockBird = Mock(id: "Bird", skinCovering: .case(.feathers)) // when diff --git a/Tests/TestCodeGenConfigurations/SwiftPackageManager/apollo-codegen-config.json b/Tests/TestCodeGenConfigurations/SwiftPackageManager/apollo-codegen-config.json index 228c0ba3c..256daa6f0 100644 --- a/Tests/TestCodeGenConfigurations/SwiftPackageManager/apollo-codegen-config.json +++ b/Tests/TestCodeGenConfigurations/SwiftPackageManager/apollo-codegen-config.json @@ -13,7 +13,31 @@ }, "pruneGeneratedFiles" : true, "queryStringLiteralFormat" : "multiline", - "warningsOnDeprecatedUsage" : "include" + "warningsOnDeprecatedUsage" : "include", + "schemaCustomization" : { + "customTypeNames" : { + "SkinCovering" : { + "enum" : { + "cases" : { + "HAIR" : "CUSTOMHAIR" + }, + "name" : "CustomSkinCovering" + } + }, + "Animal" : "CustomAnimal", + "Crocodile" : "CustomCrocodile", + "ClassroomPet" : "CustomClassroomPet", + "Date" : "CustomDate", + "PetSearchFilters" : { + "inputObject" : { + "fields" : { + "size" : "customSize" + }, + "name" : "CustomPetSearchFilters" + } + } + } + } }, "input" : { "operationSearchPaths" : [ diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/ApolloCodegen.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/ApolloCodegen.swift index 58ef7a526..d34b527fd 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/ApolloCodegen.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/ApolloCodegen.swift @@ -118,10 +118,11 @@ public class ApolloCodegen { try config.validateConfigValues() let compilationResult = try await compileGraphQLResult() - try config.validate(compilationResult) let ir = IRBuilder(compilationResult: compilationResult) + + processSchemaCustomizations(ir: ir) try await withThrowingTaskGroup(of: Void.self) { group in if itemsToGenerate.contains(.operationManifest) { @@ -321,6 +322,72 @@ public class ApolloCodegen { } } } + + func processSchemaCustomizations(ir: IRBuilder) { + for (name, customization) in config.options.schemaCustomization.customTypeNames { + if let type = ir.schema.referencedTypes.allTypes.first(where: { $0.name.schemaName == name }) { + if type is GraphQLObjectType || + type is GraphQLInterfaceType || + type is GraphQLUnionType { + switch customization { + case .type(let name): + type.name.customName = name + default: + break + } + } else if let scalarType = type as? GraphQLScalarType { + guard scalarType.isCustomScalar else { + return + } + + switch customization { + case .type(let name): + type.name.customName = name + default: + break + } + } else if let enumType = type as? GraphQLEnumType { + switch customization { + case .type(let name): + enumType.name.customName = name + break + case .enum(let name, let cases): + enumType.name.customName = name + + if let cases = cases { + for value in enumType.values { + if let caseName = cases[value.name.schemaName] { + value.name.customName = caseName + } + } + } + break + default: + break + } + } else if let inputObjectType = type as? GraphQLInputObjectType { + switch customization { + case .type(let name): + inputObjectType.name.customName = name + break + case .inputObject(let name, let fields): + inputObjectType.name.customName = name + + if let fields = fields { + for (_, field) in inputObjectType.fields { + if let fieldName = fields[field.name.schemaName] { + field.name.customName = fieldName + } + } + } + break + default: + break + } + } + } + } + } /// Generates the schema types and schema metadata files for the `ir`'s compiled schema. private func generateSchemaFiles( @@ -333,10 +400,10 @@ public class ApolloCodegen { nonFatalErrors.merge( try await nonFatalErrorCollectingTaskGroup() { group in - for graphQLObject in ir.schema.referencedTypes.objects { + for graphqlObject in ir.schema.referencedTypes.objects { addFileGenerationTask( for: ObjectFileGenerator( - graphqlObject: graphQLObject, + graphqlObject: graphqlObject, config: config ), to: &group, @@ -344,10 +411,10 @@ public class ApolloCodegen { ) if config.output.testMocks != .none { - let fields = await ir.fieldCollector.collectedFields(for: graphQLObject) + let fields = await ir.fieldCollector.collectedFields(for: graphqlObject) addFileGenerationTask( for: MockObjectFileGenerator( - graphqlObject: graphQLObject, + graphqlObject: graphqlObject, fields: fields, ir: ir, config: config @@ -362,10 +429,10 @@ public class ApolloCodegen { nonFatalErrors.merge( try await nonFatalErrorCollectingTaskGroup() { group in - for graphQLEnum in ir.schema.referencedTypes.enums { + for graphqlEnum in ir.schema.referencedTypes.enums { addFileGenerationTask( for: EnumFileGenerator( - graphqlEnum: graphQLEnum, + graphqlEnum: graphqlEnum, config: config ), to: &group, @@ -378,10 +445,10 @@ public class ApolloCodegen { nonFatalErrors.merge( try await nonFatalErrorCollectingTaskGroup() { group in - for graphQLInterface in ir.schema.referencedTypes.interfaces { + for graphqlInterface in ir.schema.referencedTypes.interfaces { addFileGenerationTask( for: InterfaceFileGenerator( - graphqlInterface: graphQLInterface, + graphqlInterface: graphqlInterface, config: config ), to: &group, @@ -393,10 +460,10 @@ public class ApolloCodegen { nonFatalErrors.merge( try await nonFatalErrorCollectingTaskGroup() { group in - for graphQLUnion in ir.schema.referencedTypes.unions { + for graphqlUnion in ir.schema.referencedTypes.unions { addFileGenerationTask( for: UnionFileGenerator( - graphqlUnion: graphQLUnion, + graphqlUnion: graphqlUnion, config: config ), to: &group, @@ -408,10 +475,10 @@ public class ApolloCodegen { nonFatalErrors.merge( try await nonFatalErrorCollectingTaskGroup() { group in - for graphQLInputObject in ir.schema.referencedTypes.inputObjects { + for graphqlInputObject in ir.schema.referencedTypes.inputObjects { addFileGenerationTask( for: InputObjectFileGenerator( - graphqlInputObject: graphQLInputObject, + graphqlInputObject: graphqlInputObject, config: config ), to: &group, @@ -423,10 +490,10 @@ public class ApolloCodegen { nonFatalErrors.merge( try await nonFatalErrorCollectingTaskGroup() { group in - for graphQLScalar in ir.schema.referencedTypes.customScalars { + for graphqlScalar in ir.schema.referencedTypes.customScalars { addFileGenerationTask( for: CustomScalarFileGenerator( - graphqlScalar: graphQLScalar, + graphqlScalar: graphqlScalar, config: config ), to: &group, fileManager: fileManager diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/ApolloCodegenConfiguration.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/ApolloCodegenConfiguration.swift index 7b88933c5..1d667a3ad 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/ApolloCodegenConfiguration.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/ApolloCodegenConfiguration.swift @@ -468,6 +468,8 @@ public struct ApolloCodegenConfiguration: Codable, Equatable { public let selectionSetInitializers: SelectionSetInitializers /// How to generate the operation documents for your generated operations. public let operationDocumentFormat: OperationDocumentFormat + /// Customization options to be applie to the schema during code generation. + public let schemaCustomization: SchemaCustomization /// Generate import statements that are compatible with including `Apollo` via Cocoapods. /// /// Cocoapods bundles all files from subspecs into the main target for a pod. This means that @@ -514,6 +516,7 @@ public struct ApolloCodegenConfiguration: Codable, Equatable { public static let schemaDocumentation: Composition = .include public static let selectionSetInitializers: SelectionSetInitializers = [.localCacheMutations] public static let operationDocumentFormat: OperationDocumentFormat = .definition + public static let schemaCustomization: SchemaCustomization = .init() public static let cocoapodsCompatibleImportStatements: Bool = false public static let warningsOnDeprecatedUsage: Composition = .include public static let conversionStrategies: ConversionStrategies = .init() @@ -546,6 +549,7 @@ public struct ApolloCodegenConfiguration: Codable, Equatable { schemaDocumentation: Composition = Default.schemaDocumentation, selectionSetInitializers: SelectionSetInitializers = Default.selectionSetInitializers, operationDocumentFormat: OperationDocumentFormat = Default.operationDocumentFormat, + schemaCustomization: SchemaCustomization = Default.schemaCustomization, cocoapodsCompatibleImportStatements: Bool = Default.cocoapodsCompatibleImportStatements, warningsOnDeprecatedUsage: Composition = Default.warningsOnDeprecatedUsage, conversionStrategies: ConversionStrategies = Default.conversionStrategies, @@ -557,6 +561,7 @@ public struct ApolloCodegenConfiguration: Codable, Equatable { self.schemaDocumentation = schemaDocumentation self.selectionSetInitializers = selectionSetInitializers self.operationDocumentFormat = operationDocumentFormat + self.schemaCustomization = schemaCustomization self.cocoapodsCompatibleImportStatements = cocoapodsCompatibleImportStatements self.warningsOnDeprecatedUsage = warningsOnDeprecatedUsage self.conversionStrategies = conversionStrategies @@ -574,6 +579,7 @@ public struct ApolloCodegenConfiguration: Codable, Equatable { case selectionSetInitializers case apqs case operationDocumentFormat + case schemaCustomization case cocoapodsCompatibleImportStatements case warningsOnDeprecatedUsage case conversionStrategies @@ -614,6 +620,11 @@ public struct ApolloCodegenConfiguration: Codable, Equatable { forKey: .apqs )?.operationDocumentFormat ?? Default.operationDocumentFormat + + schemaCustomization = try values.decodeIfPresent( + SchemaCustomization.self, + forKey: .schemaCustomization + ) ?? Default.schemaCustomization cocoapodsCompatibleImportStatements = try values.decodeIfPresent( Bool.self, @@ -649,6 +660,7 @@ public struct ApolloCodegenConfiguration: Codable, Equatable { try container.encode(self.schemaDocumentation, forKey: .schemaDocumentation) try container.encode(self.selectionSetInitializers, forKey: .selectionSetInitializers) try container.encode(self.operationDocumentFormat, forKey: .operationDocumentFormat) + try container.encode(self.schemaCustomization, forKey: .schemaCustomization) try container.encode(self.cocoapodsCompatibleImportStatements, forKey: .cocoapodsCompatibleImportStatements) try container.encode(self.warningsOnDeprecatedUsage, forKey: .warningsOnDeprecatedUsage) try container.encode(self.conversionStrategies, forKey: .conversionStrategies) @@ -1368,6 +1380,7 @@ extension ApolloCodegenConfiguration.OutputOptions { self.conversionStrategies = conversionStrategies self.pruneGeneratedFiles = pruneGeneratedFiles self.markOperationDefinitionsAsFinal = markOperationDefinitionsAsFinal + self.schemaCustomization = Default.schemaCustomization } /// Deprecated initializer. @@ -1417,6 +1430,7 @@ extension ApolloCodegenConfiguration.OutputOptions { self.conversionStrategies = conversionStrategies self.pruneGeneratedFiles = pruneGeneratedFiles self.markOperationDefinitionsAsFinal = markOperationDefinitionsAsFinal + self.schemaCustomization = Default.schemaCustomization } /// Whether the generated operations should use Automatic Persisted Queries. diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/CodegenConfiguration/ApolloCodegenConfiguration+SchemaCustomization.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/CodegenConfiguration/ApolloCodegenConfiguration+SchemaCustomization.swift new file mode 100644 index 000000000..a6c4883c3 --- /dev/null +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/CodegenConfiguration/ApolloCodegenConfiguration+SchemaCustomization.swift @@ -0,0 +1,233 @@ +import Foundation + +extension ApolloCodegenConfiguration { + + public struct SchemaCustomization: Codable, Equatable { + + // MARK: - Properties + + /// Dictionary with Keys representing the types being renamed/customized, and + public let customTypeNames: [String: CustomSchemaTypeName] + + /// Default property values + public struct Default { + public static let customTypeNames: [String: CustomSchemaTypeName] = [:] + } + + // MARK: - Initialization + + /// Designated initializer + /// + /// - Parameters: + /// - customTypeNames: Dictionary repsenting the types to be renamed and how to rename them. + public init( + customTypeNames: [String: CustomSchemaTypeName] = Default.customTypeNames + ) { + self.customTypeNames = customTypeNames + } + + // MARK: - Codable + + enum CodingKeys: CodingKey, CaseIterable { + case customTypeNames + } + + public init(from decoder: any Decoder) throws { + let values = try decoder.container(keyedBy: CodingKeys.self) + try throwIfContainsUnexpectedKey( + container: values, + type: Self.self, + decoder: decoder + ) + + customTypeNames = try values.decode( + [String: CustomSchemaTypeName].self, + forKey: .customTypeNames + ) + } + + public func encode(to encoder: any Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + try container.encode(self.customTypeNames, forKey: .customTypeNames) + } + + // MARK: - Enums + + public enum CustomSchemaTypeName: Codable, ExpressibleByStringLiteral, Equatable { + case type(name: String) + case `enum`(name: String?, cases: [String: String]?) + case inputObject(name: String?, fields: [String: String]?) + + public init(stringLiteral value: String) { + self = .type(name: value) + } + + enum CodingKeys: CodingKey, CaseIterable { + case type + case `enum` + case inputObject + } + + enum TypeCodingKeys: CodingKey, CaseIterable { + case name + } + + enum EnumCodingKeys: CodingKey, CaseIterable { + case name + case cases + } + + enum InputObjectCodingKeys: CodingKey, CaseIterable { + case name + case fields + } + + public init(from decoder: any Decoder) throws { + guard let originalTypeName = decoder.codingPath.last?.stringValue else { + preconditionFailure("Unable to get original type name value from JSON during decoding.") + } + var customTypeName: CustomSchemaTypeName? + + if let container = try? decoder.container(keyedBy: CodingKeys.self) { + switch container.allKeys.first { + case .type: + let subContainer = try container.nestedContainer(keyedBy: TypeCodingKeys.self, forKey: .type) + let name = try subContainer.decodeIfPresentOrEmpty(type: String.self, key: .name) + guard let name = name else { + throw Error.emptyCustomization(type: originalTypeName) + } + customTypeName = .type(name: name) + break + case .enum: + let subContainer = try container.nestedContainer(keyedBy: EnumCodingKeys.self, forKey: .enum) + let name = try subContainer.decodeIfPresentOrEmpty(type: String.self, key: .name) + let cases = try subContainer.decodeIfPresentOrEmpty(type: [String: String].self, key: .cases) + + guard name != nil || cases != nil else { + throw Error.emptyCustomization(type: originalTypeName) + } + + if let name = name, cases == nil { + customTypeName = .type(name: name) + } else { + customTypeName = .enum(name: name, cases: cases) + } + break + case .inputObject: + let subContainer = try container.nestedContainer(keyedBy: InputObjectCodingKeys.self, forKey: .inputObject) + let name = try subContainer.decodeIfPresentOrEmpty(type: String.self, key: .name) + let fields = try subContainer.decodeIfPresentOrEmpty(type: [String: String].self, key: .fields) + + guard name != nil || fields != nil else { + throw Error.emptyCustomization(type: originalTypeName) + } + + if let name = name, fields == nil { + customTypeName = .type(name: name) + } else { + customTypeName = .inputObject(name: name, fields: fields) + } + break + case .none: + break + } + } else if let container = try? decoder.singleValueContainer() { + let name = try container.decode(String.self) + guard !name.isEmpty else { + throw Error.emptyCustomization(type: originalTypeName) + } + customTypeName = .type(name: name) + } + + if let customTypeName = customTypeName { + self = customTypeName + } else { + throw Error.decodingFailure(type: originalTypeName) + } + } + + public func encode(to encoder: any Encoder) throws { + guard let originalTypeName = encoder.codingPath.last?.stringValue else { + preconditionFailure("Unable to get original type name value from type during decoding.") + } + switch self { + case .type(let name): + guard !name.isEmpty else { + throw Error.emptyCustomization(type: originalTypeName) + } + var container = encoder.singleValueContainer() + try container.encode(name) + case .enum(let name, let cases): + guard (name != nil && !(name ?? "").isEmpty) || (cases != nil && !(cases ?? [:]).isEmpty) else { + throw Error.emptyCustomization(type: originalTypeName) + } + + if cases == nil { + var container = encoder.singleValueContainer() + try container.encode(name) + } else { + var container = encoder.container(keyedBy: CodingKeys.self) + var subContainer = container.nestedContainer(keyedBy: EnumCodingKeys.self, forKey: .enum) + try subContainer.encodeIfPresent(name, forKey: .name) + try subContainer.encodeIfPresent(cases, forKey: .cases) + } + case .inputObject(let name, let fields): + guard (name != nil && !(name ?? "").isEmpty) || (fields != nil && !(fields ?? [:]).isEmpty) else { + throw Error.emptyCustomization(type: originalTypeName) + } + + if name != nil, fields == nil { + var container = encoder.singleValueContainer() + try container.encode(name) + } else { + var container = encoder.container(keyedBy: CodingKeys.self) + var subContainer = container.nestedContainer(keyedBy: InputObjectCodingKeys.self, forKey: .inputObject) + try subContainer.encodeIfPresent(name, forKey: .name) + try subContainer.encodeIfPresent(fields, forKey: .fields) + } + } + } + + } + + public enum Error: Swift.Error, LocalizedError { + case decodingFailure(type: String) + case emptyCustomization(type: String) + + public var errorDescription: String? { + switch self { + case let .decodingFailure(type): + return """ + Unable to decode type '\(type)' when processing custom schema + type names. + """ + case let .emptyCustomization(type): + return """ + No customization data was provided for type '\(type)', customization + will be ignored. + """ + } + } + } + + } + +} + +extension KeyedDecodingContainer { + fileprivate func decodeIfPresentOrEmpty(type: String.Type, key: KeyedDecodingContainer.Key) throws -> String? { + if let value = try decodeIfPresent(type, forKey: key) { + return value.isEmpty ? nil : value + } + return nil + } + + fileprivate func decodeIfPresentOrEmpty(type: [String: String].Type, key: KeyedDecodingContainer.Key) throws -> [String: String]? { + if let value = try decodeIfPresent(type, forKey: key) { + return value.isEmpty ? nil : value + } + return nil + } +} + diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/ConfigurationValidation.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/ConfigurationValidation.swift index 00281f825..c2abebe7f 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/ConfigurationValidation.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/ConfigurationValidation.swift @@ -67,7 +67,7 @@ extension ApolloCodegen.ConfigurationContext { func validate(_ compilationResult: CompilationResult) throws { guard !compilationResult.referencedTypes.contains(where: { namedType in - namedType.swiftName == self.schemaNamespace.firstUppercased + namedType.name.swiftName == self.schemaNamespace.firstUppercased }), !compilationResult.fragments.contains(where: { fragmentDefinition in fragmentDefinition.name == self.schemaNamespace.firstUppercased diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/CustomScalarFileGenerator.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/CustomScalarFileGenerator.swift index 6c096aa00..a7adb5ff9 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/CustomScalarFileGenerator.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/CustomScalarFileGenerator.swift @@ -13,6 +13,6 @@ struct CustomScalarFileGenerator: FileGenerator { } var target: FileTarget { .customScalar } - var fileName: String { graphqlScalar.name } + var fileName: String { graphqlScalar.render(as: .filename) } var overwrite: Bool { false } } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/EnumFileGenerator.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/EnumFileGenerator.swift index e8e156c23..4456f3578 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/EnumFileGenerator.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/EnumFileGenerator.swift @@ -13,5 +13,5 @@ struct EnumFileGenerator: FileGenerator { } var target: FileTarget { .enum } - var fileName: String { graphqlEnum.name } + var fileName: String { graphqlEnum.render(as: .filename) } } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/InputObjectFileGenerator.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/InputObjectFileGenerator.swift index 1dddd3c34..e72433f58 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/InputObjectFileGenerator.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/InputObjectFileGenerator.swift @@ -13,5 +13,5 @@ struct InputObjectFileGenerator: FileGenerator { InputObjectTemplate(graphqlInputObject: graphqlInputObject, config: config) } var target: FileTarget { .inputObject } - var fileName: String { graphqlInputObject.name } + var fileName: String { graphqlInputObject.render(as: .filename) } } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/InterfaceFileGenerator.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/InterfaceFileGenerator.swift index 871b569c7..f4c0af572 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/InterfaceFileGenerator.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/InterfaceFileGenerator.swift @@ -13,5 +13,5 @@ struct InterfaceFileGenerator: FileGenerator { } var target: FileTarget { .interface } - var fileName: String { graphqlInterface.name } + var fileName: String { graphqlInterface.render(as: .filename) } } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/MockInterfacesFileGenerator.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/MockInterfacesFileGenerator.swift index 0d7445630..f994e31ed 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/MockInterfacesFileGenerator.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/MockInterfacesFileGenerator.swift @@ -7,20 +7,20 @@ import GraphQLCompiler /// for testing purposes. struct MockInterfacesFileGenerator: FileGenerator { - let graphQLInterfaces: OrderedSet + let graphqlInterfaces: OrderedSet let config: ApolloCodegen.ConfigurationContext init?(ir: IRBuilder, config: ApolloCodegen.ConfigurationContext) { let interfaces = ir.schema.referencedTypes.interfaces guard !interfaces.isEmpty else { return nil } - self.graphQLInterfaces = interfaces + self.graphqlInterfaces = interfaces self.config = config } var template: any TemplateRenderer { MockInterfacesTemplate( - graphQLInterfaces: graphQLInterfaces, + graphqlInterfaces: graphqlInterfaces, config: config ) } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/MockObjectFileGenerator.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/MockObjectFileGenerator.swift index 9403d9f70..936a9e582 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/MockObjectFileGenerator.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/MockObjectFileGenerator.swift @@ -23,5 +23,5 @@ struct MockObjectFileGenerator: FileGenerator { } var target: FileTarget { .testMock } - var fileName: String { "\(graphqlObject.name)+Mock" } + var fileName: String { "\(graphqlObject.render(as: .filename))+Mock" } } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/MockUnionsFileGenerator.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/MockUnionsFileGenerator.swift index 577f68e63..990632be1 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/MockUnionsFileGenerator.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/MockUnionsFileGenerator.swift @@ -1,26 +1,26 @@ import Foundation import IR -import GraphQLCompiler import OrderedCollections +import GraphQLCompiler /// Generates a file providing the ability to mock the GraphQLUnionTypes in a schema /// for testing purposes. struct MockUnionsFileGenerator: FileGenerator { - let graphQLUnions: OrderedSet + let graphqlUnions: OrderedSet let config: ApolloCodegen.ConfigurationContext init?(ir: IRBuilder, config: ApolloCodegen.ConfigurationContext) { let unions = ir.schema.referencedTypes.unions guard !unions.isEmpty else { return nil } - self.graphQLUnions = unions + self.graphqlUnions = unions self.config = config } var template: any TemplateRenderer { MockUnionsTemplate( - graphQLUnions: graphQLUnions, + graphqlUnions: graphqlUnions, config: config ) } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/ObjectFileGenerator.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/ObjectFileGenerator.swift index 40eccabc8..b7d2c244d 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/ObjectFileGenerator.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/ObjectFileGenerator.swift @@ -14,5 +14,5 @@ struct ObjectFileGenerator: FileGenerator { } var target: FileTarget { .object } - var fileName: String { graphqlObject.name } + var fileName: String { graphqlObject.render(as: .filename) } } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/UnionFileGenerator.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/UnionFileGenerator.swift index e42d3507b..fff0bab58 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/UnionFileGenerator.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/FileGenerators/UnionFileGenerator.swift @@ -13,5 +13,5 @@ struct UnionFileGenerator: FileGenerator { config: config ) } var target: FileTarget { .union } - var fileName: String { graphqlUnion.name } + var fileName: String { graphqlUnion.render(as: .filename) } } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/CustomScalarTemplate.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/CustomScalarTemplate.swift index c665a47c8..c3b5d9853 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/CustomScalarTemplate.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/CustomScalarTemplate.swift @@ -26,8 +26,9 @@ struct CustomScalarTemplate: TemplateRenderer { TemplateString( """ \(documentation: documentationTemplate, config: config) + \(graphqlScalar.name.typeNameDocumentation) \(accessControlModifier(for: .parent))\ - typealias \(graphqlScalar.formattedName) = String + typealias \(graphqlScalar.render(as: .typename)) = String """ ) diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/EnumTemplate.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/EnumTemplate.swift index a3ae8c3a0..cd4614a4b 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/EnumTemplate.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/EnumTemplate.swift @@ -18,8 +18,9 @@ struct EnumTemplate: TemplateRenderer { TemplateString( """ \(documentation: graphqlEnum.documentation, config: config) + \(graphqlEnum.name.typeNameDocumentation) \(accessControlModifier(for: .parent))\ - enum \(graphqlEnum.formattedName): String, EnumType { + enum \(graphqlEnum.render(as: .typename)): String, EnumType { \(graphqlEnum.values.compactMap({ enumCase(for: $0) }), separator: "\n") @@ -43,15 +44,16 @@ struct EnumTemplate: TemplateRenderer { \(if: shouldRenderDocumentation, "///") \(documentation: "**Deprecated**: \($0.escapedSwiftStringSpecialCharacters())") """ }) + \(graphqlEnumValue.name.typeNameDocumentation) \(caseDefinition(for: graphqlEnumValue)) """ } private func caseDefinition(for graphqlEnumValue: GraphQLEnumValue) -> TemplateString { """ - case \(graphqlEnumValue.name.rendered(as: .swiftEnumCase, config: config.config))\ + case \(graphqlEnumValue.render(as: .enumCase, config: config))\ \(if: config.options.conversionStrategies.enumCases != .none, """ - = "\(graphqlEnumValue.name.rendered(as: .rawValue, config: config.config))" + = "\(graphqlEnumValue.render(as: .enumRawValue, config: config))" """) """ } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/InputObjectTemplate.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/InputObjectTemplate.swift index 02c2e0b22..d5e5c3622 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/InputObjectTemplate.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/InputObjectTemplate.swift @@ -21,8 +21,9 @@ struct InputObjectTemplate: TemplateRenderer { return TemplateString( """ \(documentation: graphqlInputObject.documentation, config: config) + \(graphqlInputObject.name.typeNameDocumentation) \(accessControlModifier(for: .parent))\ - struct \(graphqlInputObject.formattedName): InputObject { + struct \(graphqlInputObject.render(as: .typename)): InputObject { \(memberAccessControl)private(set) var __data: InputDict \(memberAccessControl)init(_ data: InputDict) { @@ -82,7 +83,7 @@ struct InputObjectTemplate: TemplateRenderer { private func deprecatedMessage(for fields: GraphQLInputFieldDictionary) -> String { guard !fields.isEmpty else { return "" } - let names: String = fields.values.map({ $0.name }).joined(separator: ", ") + let names: String = fields.values.map({ $0.render(config: config) }).joined(separator: ", ") if fields.count > 1 { return "Arguments '\(names)' are deprecated." @@ -96,7 +97,7 @@ struct InputObjectTemplate: TemplateRenderer { ) -> TemplateString { TemplateString(""" \(fields.map({ - "\($1.name.renderAsInputObjectName(config: config.config)): \($1.renderInputValueType(includeDefault: true, config: config.config))" + "\($1.render(config: config)): \($1.renderInputValueType(includeDefault: true, config: config.config))" }), separator: ",\n") """) } @@ -105,7 +106,7 @@ struct InputObjectTemplate: TemplateRenderer { _ fields: GraphQLInputFieldDictionary ) -> TemplateString { TemplateString(""" - \(fields.map({ "\"\($1.name)\": \($1.name.renderAsInputObjectName(config: config.config))" }), separator: ",\n") + \(fields.map({ "\"\($1.name.schemaName)\": \($1.render(config: config))" }), separator: ",\n") """) } @@ -113,10 +114,11 @@ struct InputObjectTemplate: TemplateRenderer { """ \(documentation: field.documentation, config: config) \(deprecationReason: field.deprecationReason, config: config) + \(field.name.typeNameDocumentation) \(accessControlModifier(for: .member))\ - var \(field.name.renderAsInputObjectName(config: config.config)): \(field.renderInputValueType(config: config.config)) { - get { __data["\(field.name)"] } - set { __data["\(field.name)"] = newValue } + var \(field.render(config: config)): \(field.renderInputValueType(config: config.config)) { + get { __data["\(field.name.schemaName)"] } + set { __data["\(field.name.schemaName)"] = newValue } } """ } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/InterfaceTemplate.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/InterfaceTemplate.swift index e8598b416..52644799f 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/InterfaceTemplate.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/InterfaceTemplate.swift @@ -17,7 +17,8 @@ struct InterfaceTemplate: TemplateRenderer { ) -> TemplateString { """ \(documentation: graphqlInterface.documentation, config: config) - static let \(graphqlInterface.formattedName) = \(config.ApolloAPITargetName).Interface(name: "\(graphqlInterface.name)") + \(graphqlInterface.name.typeNameDocumentation) + static let \(graphqlInterface.render(as: .typename)) = \(config.ApolloAPITargetName).Interface(name: "\(graphqlInterface.name.schemaName)") """ } } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/MockInterfacesTemplate.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/MockInterfacesTemplate.swift index 2b9327910..a6e9bbad0 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/MockInterfacesTemplate.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/MockInterfacesTemplate.swift @@ -5,7 +5,7 @@ import TemplateString struct MockInterfacesTemplate: TemplateRenderer { - let graphQLInterfaces: OrderedSet + let graphqlInterfaces: OrderedSet let config: ApolloCodegen.ConfigurationContext @@ -16,8 +16,8 @@ struct MockInterfacesTemplate: TemplateRenderer { ) -> TemplateString { TemplateString(""" \(accessControlModifier(for: .parent))extension MockObject { - \(graphQLInterfaces.map { - "typealias \($0.formattedName) = Interface" + \(graphqlInterfaces.map { + "typealias \($0.render(as: .typename)) = Interface" }, separator: "\n") } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/MockObjectTemplate.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/MockObjectTemplate.swift index 35807e9a1..eda7d8914 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/MockObjectTemplate.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/MockObjectTemplate.swift @@ -27,7 +27,7 @@ struct MockObjectTemplate: TemplateRenderer { func renderBodyTemplate( nonFatalErrorRecorder: ApolloCodegen.NonFatalError.Recorder ) -> TemplateString { - let objectName = graphqlObject.formattedName + let objectName = graphqlObject.render(as: .typename) let fields: [TemplateField] = fields .sorted { $0.0 < $1.0 } .map { @@ -128,7 +128,7 @@ struct MockObjectTemplate: TemplateRenderer { case is GraphQLInterfaceType, is GraphQLUnionType: mockType = "(any AnyMock)" default: - mockType = "Mock<\(graphQLCompositeType.formattedName)>" + mockType = "Mock<\(graphQLCompositeType.render(as: .typename))>" } return TemplateString("\(mockType)\(if: !forceNonNull, "?")").description case .scalar, diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/MockUnionsTemplate.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/MockUnionsTemplate.swift index bc97c30dd..cb876086e 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/MockUnionsTemplate.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/MockUnionsTemplate.swift @@ -5,7 +5,7 @@ import TemplateString struct MockUnionsTemplate: TemplateRenderer { - let graphQLUnions: OrderedSet + let graphqlUnions: OrderedSet let config: ApolloCodegen.ConfigurationContext @@ -16,8 +16,8 @@ struct MockUnionsTemplate: TemplateRenderer { ) -> TemplateString { TemplateString(""" \(accessControlModifier(for: .parent))extension MockObject { - \(graphQLUnions.map { - "typealias \($0.formattedName) = Union" + \(graphqlUnions.map { + "typealias \($0.render(as: .typename)) = Union" }, separator: "\n") } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/ObjectTemplate.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/ObjectTemplate.swift index 63eb1dd5d..38c0c0d5e 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/ObjectTemplate.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/ObjectTemplate.swift @@ -17,8 +17,9 @@ struct ObjectTemplate: TemplateRenderer { ) -> TemplateString { """ \(documentation: graphqlObject.documentation, config: config) - static let \(graphqlObject.formattedName) = \(config.ApolloAPITargetName).Object( - typename: "\(graphqlObject.name)\", + \(graphqlObject.name.typeNameDocumentation) + static let \(graphqlObject.render(as: .typename)) = \(config.ApolloAPITargetName).Object( + typename: "\(graphqlObject.name.schemaName)\", implementedInterfaces: \(ImplementedInterfacesTemplate()) ) """ @@ -29,7 +30,7 @@ struct ObjectTemplate: TemplateRenderer { [\(list: graphqlObject.interfaces.map({ interface in TemplateString(""" \(if: !config.output.schemaTypes.isInModule, "\(config.schemaNamespace.firstUppercased).")\ - Interfaces.\(interface.formattedName).self + Interfaces.\(interface.render(as: .typename)).self """) }))] """ diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/GraphQLEnumValue+Rendered.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/GraphQLEnumValue+Rendered.swift deleted file mode 100644 index 50bb20a29..000000000 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/GraphQLEnumValue+Rendered.swift +++ /dev/null @@ -1,28 +0,0 @@ -import GraphQLCompiler - -extension GraphQLEnumValue.Name { - - enum RenderContext { - /// Renders the value as a case in a generated Swift enum. - case swiftEnumCase - /// Renders the value as the rawValue for the enum case. - case rawValue - } - - func rendered( - as context: RenderContext, - config: ApolloCodegenConfiguration - ) -> String { - switch (context, config.options.conversionStrategies.enumCases) { - case (.rawValue, _): - return value - - case (.swiftEnumCase, .none): - return value.asEnumCaseName - - case (.swiftEnumCase, .camelCase): - return value.convertToCamelCase().asEnumCaseName - } - } - -} diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/GraphQLName+RenderingHelper.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/GraphQLName+RenderingHelper.swift new file mode 100644 index 000000000..3a4e8d25e --- /dev/null +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/GraphQLName+RenderingHelper.swift @@ -0,0 +1,161 @@ +import Foundation +import GraphQLCompiler + +extension GraphQLNamedType { + + enum RenderContext { + case filename + case typename + } + + func render( + as context: RenderContext + ) -> String { + //If the name has been customized return it unchanged + if let customName = name.customName { + return customName + } + + switch context { + case .filename: + return self.name.schemaName + case .typename: + return renderTypeName() + } + } + + private func renderTypeName() -> String { + switch self { + case let type as GraphQLScalarType: + if !type.isCustomScalar || self.name.schemaName == "ID" { + return self.name.swiftName + } + fallthrough + case is GraphQLAbstractType: fallthrough + case is GraphQLCompositeType: fallthrough + case is GraphQLEnumType: fallthrough + case is GraphQLInputObjectType: fallthrough + case is GraphQLInterfaceType: fallthrough + case is GraphQLUnionType: fallthrough + case is GraphQLObjectType: + let uppercasedName = self.name.swiftName.firstUppercased + return SwiftKeywords.TypeNamesToSuffix.contains(uppercasedName) ? + "\(uppercasedName)\(typenameSuffix)" : uppercasedName + default: + break + } + + return self.name.swiftName + } + + private var typenameSuffix: String { + switch self { + case is GraphQLEnumType: + return "_Enum" + case is GraphQLInputObjectType: + return "_InputObject" + case is GraphQLInterfaceType: + return "_Interface" + case is GraphQLObjectType: + return "_Object" + case is GraphQLScalarType: + return "_Scalar" + case is GraphQLUnionType: + return "_Union" + default: + return "_GraphQL" + } + } + +} + +extension GraphQLEnumValue { + + enum RenderContext { + case enumCase + case enumRawValue + } + + func render( + as context: RenderContext, + config: ApolloCodegen.ConfigurationContext + ) -> String { + render(as: context, config: config.config) + } + + func render( + as context: RenderContext, + config: ApolloCodegenConfiguration + ) -> String { + //If the name has been customized and its not for .enumRawValue, return it unchanged + if let customName = name.customName, context != .enumRawValue { + return customName + } + + switch context { + case .enumCase: + return renderEnumCase(config) + case .enumRawValue: + return name.schemaName + } + } + + private func renderEnumCase( + _ config: ApolloCodegenConfiguration + ) -> String { + switch config.options.conversionStrategies.enumCases { + case .none: + return self.name.schemaName.asEnumCaseName + case .camelCase: + return self.name.schemaName.convertToCamelCase().asEnumCaseName + } + } +} + +extension GraphQLInputField { + + func render( + config: ApolloCodegen.ConfigurationContext + ) -> String { + render(config: config.config) + } + + func render( + config: ApolloCodegenConfiguration + ) -> String { + //If the name has been customized return it unchanged + if let customName = name.customName { + return customName + } + + return renderInputField(config) + } + + private func renderInputField( + _ config: ApolloCodegenConfiguration + ) -> String { + var typename = name.schemaName + switch config.options.conversionStrategies.inputObjects { + case .none: + break + case .camelCase: + typename = typename.convertToCamelCase() + break + } + + return typename.escapeIf(in: SwiftKeywords.FieldAccessorNamesToEscape) + } + +} + +extension GraphQLScalarType { + + var isSwiftType: Bool { + switch name.schemaName { + case "String", "Int", "Float", "Boolean": + return true + default: + return false + } + } +} diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/GraphQLNamedType+NameFormatting.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/GraphQLNamedType+NameFormatting.swift deleted file mode 100644 index 521809a65..000000000 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/GraphQLNamedType+NameFormatting.swift +++ /dev/null @@ -1,89 +0,0 @@ -import GraphQLCompiler -import Foundation - -extension GraphQLNamedType { - /// Provides a Swift type name for GraphQL-specific type names that are not compatible with Swift. - var swiftName: String { - switch name { - case "Boolean": return "Bool" - case "Float": return "Double" - default: return name - } - } - - @objc var formattedName: String { swiftName } -} - -extension GraphQLScalarType { - - var isSwiftType: Bool { - switch name { - case "String", "Int", "Float", "Boolean": - return true - default: - return false - } - } - - override var formattedName: String { - // ID should be suffixed if it's used as the name for any type other than built-in scalar ID. - if !isCustomScalar || name == "ID" { - return swiftName - } - - let uppercasedName = swiftName.firstUppercased - return SwiftKeywords.TypeNamesToSuffix.contains(uppercasedName) ? - "\(uppercasedName)_Scalar" : uppercasedName - } - -} - -extension GraphQLEnumType { - - override var formattedName: String { - let uppercasedName = swiftName.firstUppercased - return SwiftKeywords.TypeNamesToSuffix.contains(uppercasedName) ? - "\(uppercasedName)_Enum" : uppercasedName - } - -} - -extension GraphQLInputObjectType { - - override var formattedName: String { - let uppercasedName = swiftName.firstUppercased - return SwiftKeywords.TypeNamesToSuffix.contains(uppercasedName) ? - "\(uppercasedName)_InputObject" : uppercasedName - } - -} - -extension GraphQLObjectType { - - override var formattedName: String { - let uppercasedName = swiftName.firstUppercased - return SwiftKeywords.TypeNamesToSuffix.contains(uppercasedName) ? - "\(uppercasedName)_Object" : uppercasedName - } - -} - -extension GraphQLInterfaceType { - - override var formattedName: String { - let uppercasedName = swiftName.firstUppercased - return SwiftKeywords.TypeNamesToSuffix.contains(uppercasedName) ? - "\(uppercasedName)_Interface" : uppercasedName - } - -} - -extension GraphQLUnionType { - - override var formattedName: String { - let uppercasedName = swiftName.firstUppercased - return SwiftKeywords.TypeNamesToSuffix.contains(uppercasedName) ? - "\(uppercasedName)_Union" : uppercasedName - } - -} diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/GraphQLType+Rendered.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/GraphQLType+Rendered.swift index f9c30533d..1e302dc94 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/GraphQLType+Rendered.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/GraphQLType+Rendered.swift @@ -137,13 +137,16 @@ extension GraphQLType { extension GraphQLNamedType { - var testMockFieldTypeName: String { - if SwiftKeywords.TestMockFieldAbstractTypeNamesToNamespace.contains(name) && + func testMockFieldTypeName( + _ config: ApolloCodegenConfiguration + ) -> String { + let typename = render(as: .typename) + if SwiftKeywords.TestMockFieldAbstractTypeNamesToNamespace.contains(typename) && self is GraphQLAbstractType { - return "MockObject.\(formattedName)" + return "MockObject.\(typename)" } - return formattedName + return typename } fileprivate func qualifiedRootTypeName( @@ -154,9 +157,9 @@ extension GraphQLNamedType { let typeName: String = { if case .testMockField = context { - return newTypeName ?? testMockFieldTypeName.firstUppercased + return newTypeName ?? testMockFieldTypeName(config) } else { - return newTypeName ?? self.formattedName + return newTypeName ?? self.render(as: .typename) } }() diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/InputVariableRenderable.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/InputVariableRenderable.swift index 664865914..c22471a4a 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/InputVariableRenderable.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/InputVariableRenderable.swift @@ -31,8 +31,11 @@ extension InputVariableRenderable { case let .int(int): return TemplateString(int.description) case let .float(float): return TemplateString(float.description) case let .enum(enumValue): - let name = GraphQLEnumValue.Name(value: enumValue) - return ".init(.\(name.rendered(as: .swiftEnumCase, config: config)))" + let enumCase = GraphQLEnumValue( + name: GraphQLName(schemaName: enumValue), + documentation: nil, + deprecationReason: nil) + return ".init(.\(enumCase.render(as: .enumCase, config: config)))" case let .list(list): switch type { case let .nonNull(.list(listInnerType)), @@ -81,11 +84,11 @@ fileprivate extension GraphQLInputObjectType { let variable = InputVariable(type: field.type, defaultValue: entry.value) - return "\(entry.0): " + variable.renderVariableDefaultValue(config: config) + return "\(field.render(config: config)): " + variable.renderVariableDefaultValue(config: config) } return """ - \(if: !config.output.operations.isInModule, "\(config.schemaNamespace.firstUppercased).")\(name)(\(list: entries)) + \(if: !config.output.operations.isInModule, "\(config.schemaNamespace.firstUppercased).")\(render(as: .typename))(\(list: entries)) """ } } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/String+SwiftNameEscaping.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/String+SwiftNameEscaping.swift index 2c6b557e2..e0120cecb 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/String+SwiftNameEscaping.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/RenderingHelpers/String+SwiftNameEscaping.swift @@ -31,7 +31,7 @@ extension String { SwiftKeywords.TestMockConflictingFieldNames.contains(self) } - private func escapeIf(in set: Set) -> String { + func escapeIf(in set: Set) -> String { set.contains(self) ? "`\(self)`" : self } @@ -86,22 +86,6 @@ extension String { return propertyName } - - func renderAsInputObjectName( - config: ApolloCodegenConfiguration - ) -> String { - var propertyName = self - - switch config.options.conversionStrategies.inputObjects { - case .none: - break - case .camelCase: - propertyName = propertyName.convertToCamelCase() - break - } - - return propertyName.escapeIf(in: SwiftKeywords.FieldAccessorNamesToEscape) - } /// Convert to `camelCase` from a number of different `snake_case` variants. /// @@ -181,7 +165,7 @@ enum SwiftKeywords { "hash" ] - fileprivate static let FieldAccessorNamesToEscape: Set = [ + static let FieldAccessorNamesToEscape: Set = [ "associatedtype", "class", "deinit", diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/SchemaMetadataTemplate.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/SchemaMetadataTemplate.swift index f91b66f14..765ce27fc 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/SchemaMetadataTemplate.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/SchemaMetadataTemplate.swift @@ -56,7 +56,7 @@ struct SchemaMetadataTemplate: TemplateRenderer { static func objectType(forTypename typename: String) -> \(config.ApolloAPITargetName).Object? { switch typename { \(schema.referencedTypes.objects.map { - "case \"\($0.name)\": return \(schemaNamespace).Objects.\($0.formattedName)" + "case \"\($0.name.schemaName)\": return \(schemaNamespace).Objects.\($0.render(as: .typename))" }, separator: "\n") default: return nil } diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/SelectionSetTemplate.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/SelectionSetTemplate.swift index b43909540..686c22a0f 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/SelectionSetTemplate.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/SelectionSetTemplate.swift @@ -156,7 +156,7 @@ struct SelectionSetTemplate { pluralizer: config.pluralizer)) \(if: config.options.schemaDocumentation == .include, """ /// - /// Parent Type: `\(selectionSet.typeInfo.parentType.formattedName)` + /// Parent Type: `\(selectionSet.typeInfo.parentType.render(as: .typename))` """) """ } @@ -259,7 +259,7 @@ struct SelectionSetTemplate { } private func GeneratedSchemaTypeReference(_ type: GraphQLCompositeType) -> TemplateString { - "\(config.schemaNamespace.firstUppercased).\(type.schemaTypesNamespace).\(type.formattedName)" + "\(config.schemaNamespace.firstUppercased).\(type.schemaTypesNamespace).\(type.render(as: .typename))" } // MARK: - Selections @@ -1076,7 +1076,7 @@ extension IR.ScopeCondition { } else { return TemplateString( """ - \(ifLet: type, { "As\($0.formattedName)" })\ + \(ifLet: type, { "As\($0.render(as: .typename))" })\ \(ifLet: conditions, { "If\($0.typeNameComponents)"}) """ ).description diff --git a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/UnionTemplate.swift b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/UnionTemplate.swift index d49b6f001..5817c8770 100644 --- a/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/UnionTemplate.swift +++ b/apollo-ios-codegen/Sources/ApolloCodegenLib/Templates/UnionTemplate.swift @@ -18,8 +18,9 @@ struct UnionTemplate: TemplateRenderer { TemplateString( """ \(documentation: graphqlUnion.documentation, config: config) - static let \(graphqlUnion.formattedName) = Union( - name: "\(graphqlUnion.name)", + \(graphqlUnion.name.typeNameDocumentation) + static let \(graphqlUnion.render(as: .typename)) = Union( + name: "\(graphqlUnion.name.schemaName)", possibleTypes: \(PossibleTypesTemplate()) ) """ @@ -35,7 +36,7 @@ struct UnionTemplate: TemplateRenderer { ) -> TemplateString { """ \(if: !config.output.schemaTypes.isInModule, "\(config.schemaNamespace.firstUppercased).")\ - Objects.\(type.formattedName).self + Objects.\(type.render(as: .typename)).self """ } diff --git a/apollo-ios-codegen/Sources/GraphQLCompiler/GraphQLName.swift b/apollo-ios-codegen/Sources/GraphQLCompiler/GraphQLName.swift new file mode 100644 index 000000000..732879ced --- /dev/null +++ b/apollo-ios-codegen/Sources/GraphQLCompiler/GraphQLName.swift @@ -0,0 +1,51 @@ +import Foundation +import TemplateString + +public protocol GraphQLNamedItem { + var name: GraphQLName { get } +} + +public class GraphQLName: Hashable { + public let schemaName: String + + public var customName: String? + + public var swiftName: String { + switch schemaName { + case "Boolean": return "Bool" + case "Float": return "Double" + default: return schemaName + } + } + + private var shouldRenderDocumentation: Bool { + if let customName, !customName.isEmpty { + return true + } + return false + } + + public var typeNameDocumentation: TemplateString? { + guard shouldRenderDocumentation else { return nil } + return """ + // Renamed from GraphQL schema value: '\(schemaName)' + """ + } + + public init( + schemaName: String + ) { + self.schemaName = schemaName + } + + // MARK: - Hashable + + public func hash(into hasher: inout Hasher) { + hasher.combine(schemaName) + } + + public static func == (lhs: GraphQLName, rhs: GraphQLName) -> Bool { + return lhs.schemaName == rhs.schemaName + } + +} diff --git a/apollo-ios-codegen/Sources/GraphQLCompiler/GraphQLSchema.swift b/apollo-ios-codegen/Sources/GraphQLCompiler/GraphQLSchema.swift index fc2e53664..e3e9f804b 100644 --- a/apollo-ios-codegen/Sources/GraphQLCompiler/GraphQLSchema.swift +++ b/apollo-ios-codegen/Sources/GraphQLCompiler/GraphQLSchema.swift @@ -20,8 +20,8 @@ protocol GraphQLSchemaType: JavaScriptReferencedObject { } public class GraphQLNamedType: - JavaScriptReferencedObject, @unchecked Sendable, Hashable, CustomDebugStringConvertible { - public let name: String + JavaScriptReferencedObject, @unchecked Sendable, Hashable, CustomDebugStringConvertible, GraphQLNamedItem { + public let name: GraphQLName public let documentation: String? @@ -29,7 +29,7 @@ public class GraphQLNamedType: _ jsValue: JSValue, bridge: isolated JavaScriptBridge ) { - self.name = jsValue["name"] + self.name = .init(schemaName: jsValue["name"]) self.documentation = jsValue["description"] } @@ -37,7 +37,7 @@ public class GraphQLNamedType: /// Initializer to be used for creating mock objects in tests only. init( - name: String, + name: GraphQLName, documentation: String? ) { self.name = name @@ -60,7 +60,7 @@ public class GraphQLNamedType: } public var debugDescription: String { - name + name.schemaName } } @@ -71,7 +71,7 @@ public final class GraphQLScalarType: GraphQLNamedType { public var isCustomScalar: Bool { guard self.specifiedByURL == nil else { return true } - switch name { + switch name.schemaName { case "String", "Int", "Float", "Boolean": return false default: @@ -86,7 +86,7 @@ public final class GraphQLScalarType: GraphQLNamedType { /// Initializer to be used for creating mock objects in tests only. init( - name: String, + name: GraphQLName, documentation: String?, specifiedByURL: String? ) { @@ -109,7 +109,7 @@ public final class GraphQLEnumType: GraphQLNamedType { /// Initializer to be used for creating mock objects in tests only. init( - name: String, + name: GraphQLName, documentation: String?, values: [GraphQLEnumValue] ) { @@ -118,17 +118,9 @@ public final class GraphQLEnumType: GraphQLNamedType { } } -public struct GraphQLEnumValue: JavaScriptObjectDecodable { - - public struct Name { - public let value: String +public struct GraphQLEnumValue: JavaScriptObjectDecodable, GraphQLNamedItem { - public init(value: String) { - self.value = value - } - } - - public let name: Name + public let name: GraphQLName public let documentation: String? @@ -136,8 +128,8 @@ public struct GraphQLEnumValue: JavaScriptObjectDecodable { public var isDeprecated: Bool { deprecationReason != nil } - init( - name: Name, + public init( + name: GraphQLName, documentation: String?, deprecationReason: String? ) { @@ -151,7 +143,7 @@ public struct GraphQLEnumValue: JavaScriptObjectDecodable { bridge: isolated JavaScriptBridge ) -> GraphQLEnumValue { self.init( - name: .init(value: jsValue["name"]), + name: .init(schemaName: jsValue["name"]), documentation: jsValue["description"], deprecationReason: jsValue["deprecationReason"] ) @@ -173,7 +165,7 @@ public final class GraphQLInputObjectType: GraphQLNamedType { /// Initializer to be used for creating mock objects in tests only. init( - name: String, + name: GraphQLName, documentation: String?, fields: GraphQLInputFieldDictionary ) { @@ -182,8 +174,8 @@ public final class GraphQLInputObjectType: GraphQLNamedType { } } -public struct GraphQLInputField: JavaScriptObjectDecodable { - public let name: String +public class GraphQLInputField: JavaScriptObjectDecodable, GraphQLNamedItem { + public let name: GraphQLName public let type: GraphQLType @@ -196,9 +188,9 @@ public struct GraphQLInputField: JavaScriptObjectDecodable { static func fromJSValue( _ jsValue: JSValue, bridge: isolated JavaScriptBridge - ) -> GraphQLInputField { + ) -> Self { self.init( - name: jsValue["name"], + name: .init(schemaName: jsValue["name"]), type: GraphQLType.fromJSValue(jsValue["type"], bridge: bridge), documentation: jsValue["description"], deprecationReason: jsValue["deprecationReason"], @@ -206,8 +198,8 @@ public struct GraphQLInputField: JavaScriptObjectDecodable { ) } - init( - name: String, + required init( + name: GraphQLName, type: GraphQLType, documentation: String?, deprecationReason: String?, @@ -245,7 +237,7 @@ public final class GraphQLObjectType: GraphQLCompositeType, GraphQLInterfaceImpl /// Initializer to be used for creating mock objects in tests only. init( - name: String, + name: GraphQLName, documentation: String?, fields: [String: GraphQLField], interfaces: [GraphQLInterfaceType] @@ -280,7 +272,7 @@ public final class GraphQLInterfaceType: GraphQLAbstractType, GraphQLInterfaceIm /// Initializer to be used for creating mock objects in tests only. init( - name: String, + name: GraphQLName, documentation: String?, fields: [String: GraphQLField], interfaces: [GraphQLInterfaceType] @@ -314,7 +306,7 @@ public final class GraphQLUnionType: GraphQLAbstractType { /// Initializer to be used for creating mock objects in tests only. init( - name: String, + name: GraphQLName, documentation: String?, types: [GraphQLObjectType] ) { diff --git a/apollo-ios-codegen/Sources/GraphQLCompiler/GraphQLType.swift b/apollo-ios-codegen/Sources/GraphQLCompiler/GraphQLType.swift index 770accf39..f890abc94 100644 --- a/apollo-ios-codegen/Sources/GraphQLCompiler/GraphQLType.swift +++ b/apollo-ios-codegen/Sources/GraphQLCompiler/GraphQLType.swift @@ -15,7 +15,7 @@ public indirect enum GraphQLType: Sendable, Hashable { let .scalar(type as GraphQLNamedType), let .enum(type as GraphQLNamedType), let .inputObject(type as GraphQLNamedType): - return type.name + return type.name.schemaName case let .nonNull(ofType): return "\(ofType.typeReference)!" diff --git a/docs/source/code-generation/codegen-configuration.mdx b/docs/source/code-generation/codegen-configuration.mdx index 82000b800..16e74a3ca 100644 --- a/docs/source/code-generation/codegen-configuration.mdx +++ b/docs/source/code-generation/codegen-configuration.mdx @@ -445,7 +445,28 @@ The top-level properties are: "inputObjects": "camelCase" }, "pruneGeneratedFiles": true, - "markOperationDefinitionsAsFinal": true + "markOperationDefinitionsAsFinal": true, + "schemaCustomization" : { + "customTypeNames" : { + "MyEnum" : { + "enum" : { + "cases" : { + "MyCase" : "CustomCase" + }, + "name" : "CustomEnum" + } + }, + "MyObject" : "CustomAnimal", + "MyInputObject" : { + "inputObject" : { + "fields" : { + "myField" : "customField" + }, + "name" : "CustomInputObject" + } + } + } + } } ``` @@ -464,7 +485,7 @@ let configuration = ApolloCodegenConfiguration( selectionSetInitializers: [ .localCacheMutations, .operation(named: "MyOperation"), - .fragment(named: "MyFragment) + .fragment(named: "MyFragment") ], operationDocumentFormat: [.document, .operationId], cocoapodsCompatibleImportStatements: false, @@ -475,7 +496,105 @@ let configuration = ApolloCodegenConfiguration( inputObjects: .camelCase ), pruneGeneratedFiles: true, - markOperationDefinitionsAsFinal: true + markOperationDefinitionsAsFinal: true, + schemaCustomization: .init( + customTypeNames: [ + "MyEnum" : .enum( + name: "CustomEnum", + cases: [ + "MyCase" : "CustomCase" + ] + ), + "MyObject" : .type( + name: "CustomObject" + ), + "MyInputObject" : .inputObject( + name: "CustomInputObject", + fields: [ + "myField" : "customField" + ] + ) + ] + ) + ) +) +``` + + + +### Schema Customization + +#### Custom Type Names + +Schema types can have their names used in Swift code customized by using the [`customTypeNames`](https://www.apollographql.com/docs/ios/docc/documentation/apollocodegenlib/apollocodegenconfiguration/schemacustomization/customtypenames) option under [`schemaCustomization`](https://www.apollographql.com/docs/ios/docc/documentation/apollocodegenlib/apollocodegenconfiguration/schemacustomization) to provide new names for the types which you wish to rename in Swift. This does not affect your schema directly, or network requests sent to your server, only the type names used by you in your Swift code. The `customTypeNames` option accepts a `Dictionary` which maps schema type names given as a `String` to a [`CustomSchemaTypeName`](https://www.apollographql.com/docs/ios/docc/documentation/apollocodegenlib/apollocodegenconfiguration/schemacustomization/customschematypename) enum case with associated values for how to customize the given schema type. + +You can customize the name of the following schema types: +- Custom Scalar +- Enum (including individual case names) +- Input Object (including individual field names) +- Interface +- Object +- Union + +The `CustomSchemaTypeName` enum contains the following possible cases: + +| Case | Descriptions | +| ---- | ------------ | +| `.type(name:)` | This case can be used to customize the name of any type in your schema by supplying a `String` to the `name` parameter representing the desired new name. | +| `.enum(name:cases:)` | This case must be used when you want to customize the cases of an enum type. You can optionally supply a `String` to the `name` parameter to customize the name of the enum itself, and supply a `[String: String]` dictionary to the `cases` parameter to customize any cases you desire. | +| `.inputObject(name:fields:)` | This case must be used when you want to customize the fields of an Input Object type. You can optionally supply a `String` to the `name` parameter to customize the name of the Input Object itself, and supply a `[String: String]` dictionary to the `fields` parameter to customize any fields you desire. | + + + +```json title="CLI Configuration JSON" +"options": { + "schemaCustomization" : { + "customTypeNames" : { + "MyEnum" : { + "enum" : { + "cases" : { + "MyCase" : "CustomCase" + }, + "name" : "CustomEnum" + } + }, + "MyObject" : "CustomAnimal", + "MyInputObject" : { + "inputObject" : { + "fields" : { + "myField" : "customField" + }, + "name" : "CustomInputObject" + } + } + } + } +} +``` + +```swift title="Swift Codegen Setup" +let configuration = ApolloCodegenConfiguration( + // Other properties not shown + options: ApolloCodegenConfiguration.OutputOptions( + schemaCustomization: .init( + customTypeNames: [ + "MyEnum" : .enum( + name: "CustomEnum", + cases: [ + "MyCase" : "CustomCase" + ] + ), + "MyObject" : .type( + name: "CustomObject" + ), + "MyInputObject" : .inputObject( + name: "CustomInputObject", + fields: [ + "myField" : "customField" + ] + ) + ] + ) ) ) ```