diff --git a/codegen/lib/graphql_swift_gen/templates/type.swift.erb b/codegen/lib/graphql_swift_gen/templates/type.swift.erb index 1a2965a..5bc3c43 100644 --- a/codegen/lib/graphql_swift_gen/templates/type.swift.erb +++ b/codegen/lib/graphql_swift_gen/templates/type.swift.erb @@ -210,33 +210,54 @@ extension <%= schema_name %> { } <% when 'INPUT_OBJECT' %> open class <%= type.name %> { - <% type.input_fields.each do |field| %> + <% type.required_input_fields.each do |field| %> open var <%= escape_reserved_word(field.camelize_name) %>: <%= swift_input_type(field.type) %> <% end %> + <% type.optional_input_fields.each do |field| %> + open var <%= escape_reserved_word(field.camelize_name) %>: <%= swift_input_type(field.type) %> { + didSet { + <%= escape_reserved_word(field.camelize_name) %>Seen = true + } + } + private var <%= escape_reserved_word(field.camelize_name) %>Seen: Bool = false + <% end %> public init( - <% input_fields = type.required_input_fields + type.optional_input_fields %> + <% input_fields = type.required_input_fields + type.optional_input_fields # manually ordered with required fields first %> <% input_fields.each do |field| %> - <% default = field.type.non_null? ? "" : " = nil" %> <% seperator = field == input_fields.last ? "" : "," %> - <%= escape_reserved_word(field.camelize_name) %>: <%= swift_input_type(field.type) %><%= default %><%= seperator %> + <% if field.type.non_null? %> + <%= escape_reserved_word(field.camelize_name) %>: <%= swift_input_type(field.type) %><%= seperator %> + <% else %> + <%= escape_reserved_word(field.camelize_name) %>: <%= swift_input_type(field.type) %>? = nil<%= seperator %> + <% end %> <% end %> ) { - <% type.input_fields.each do |field| %> + <% type.required_input_fields.each do |field| %> self.<%= escape_reserved_word(field.camelize_name) %> = <%= escape_reserved_word(field.camelize_name) %> <% end %> + <% type.optional_input_fields.each do |field| %> + <% field_name = escape_reserved_word(field.camelize_name) %> + if let <%= field_name %> = <%= field_name %> { + self.<%= field_name %>Seen = true + self.<%= field_name %> = <%= field_name %> + } + <% end %> } func serialize() -> String { var fields: [String] = [] - <% type.input_fields.each do |field| %> - <% unless field.type.non_null? %> + <% type.required_input_fields.each do |field| %> + fields.append("<%= field.name %>:<%= generate_build_input_code(field.camelize_name, field.type.unwrap_non_null) %>") + <% end %> + <% type.optional_input_fields.each do |field| %> + if <%= escape_reserved_word(field.camelize_name) %>Seen { if let <%= escape_reserved_word(field.camelize_name) %> = <%= escape_reserved_word(field.camelize_name) %> { - <% end %> fields.append("<%= field.name %>:<%= generate_build_input_code(field.camelize_name, field.type.unwrap_non_null) %>") - <% unless field.type.non_null? %> + } else { + fields.append("<%= field.name %>:null") } - <% end %> + } <% end %> return "{\(fields.joined(separator: ","))}" } diff --git a/support/Tests/GraphQLSupportTests/IntegrationTests.swift b/support/Tests/GraphQLSupportTests/IntegrationTests.swift index 0824aaf..852d8e4 100644 --- a/support/Tests/GraphQLSupportTests/IntegrationTests.swift +++ b/support/Tests/GraphQLSupportTests/IntegrationTests.swift @@ -56,6 +56,24 @@ class IntegrationTests: XCTestCase { XCTAssertEqual(queryString, "mutation{set_integer(input:{key:\"answer\",value:42,negate:true})}") } + func testInputObjectExplictNilConstructor() { + let query = Generated.buildMutation { $0 + .setInteger(input: Generated.SetIntegerInput(key: "answer", value: 42, negate: .some(nil))) + } + let queryString = String(describing: query) + XCTAssertEqual(queryString, "mutation{set_integer(input:{key:\"answer\",value:42,negate:null})}") + } + + func testInputObjectExplictNilSetLater() { + let input = Generated.SetIntegerInput(key: "answer", value: 42) + input.negate = nil + let query = Generated.buildMutation { $0 + .setInteger(input: input) + } + let queryString = String(describing: query) + XCTAssertEqual(queryString, "mutation{set_integer(input:{key:\"answer\",value:42,negate:null})}") + } + func testScalarInput() { let ttl = date(year: 2017, month: 1, day: 31, hour: 10, minute: 9, second: 48) let query = Generated.buildMutation { $0