diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 00000000..584860b0 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,39 @@ +# Migration + +## 1.0 to 2.0 + +### TypeReference removal + +The `TypeReference` type was removed in v2.0.0, since it was made unnecessary when using the [GraphQL](https://github.com/GraphQLSwift/GraphQL) closure-based `field` API. Simply replace any `TypeReference` usage with the actual type: + +```swift +// Before +let schema = try! Schema { + Type(Object1.self) { } + Type(Object2.self) { + Field("object1", at: \.object1, as: TypeReference.self) + } +} + +// After +let schema = try! Schema { + Type(Object1.self) { } + Type(Object2.self) { + Field("object1", at: \.object1) + } +} +``` + +### Field/InputField `as` argument removal + +Since TypeReference was removed, there is no longer a functional need for the `as` argument on `Field` and `InputField` +types. To remove it, simply omit it and let the compiler determine the type from the signature of the `at` argument. + +### `Types` removal + +The deprecated `Types` type has been removed. Instead define types individually using the `Type` initializers. + +### Reflection `isEncodable` + +The deprecated `Reflection.isEncodable(type: Any.Type) -> Bool` function has been removed. Please re-implement in your +package if this functionality is needed. \ No newline at end of file diff --git a/Package.resolved b/Package.resolved index 253fc022..d84a2e53 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,52 +1,50 @@ { - "object": { - "pins": [ - { - "package": "GraphQL", - "repositoryURL": "https://github.com/GraphQLSwift/GraphQL.git", - "state": { - "branch": null, - "revision": "ec809df8cce95d6aea820f70f04067abc08080f2", - "version": "2.10.3" - } - }, - { - "package": "swift-atomics", - "repositoryURL": "https://github.com/apple/swift-atomics.git", - "state": { - "branch": null, - "revision": "cd142fd2f64be2100422d658e7411e39489da985", - "version": "1.2.0" - } - }, - { - "package": "swift-collections", - "repositoryURL": "https://github.com/apple/swift-collections", - "state": { - "branch": null, - "revision": "671108c96644956dddcd89dd59c203dcdb36cec7", - "version": "1.1.4" - } - }, - { - "package": "swift-nio", - "repositoryURL": "https://github.com/apple/swift-nio.git", - "state": { - "branch": null, - "revision": "914081701062b11e3bb9e21accc379822621995e", - "version": "2.76.1" - } - }, - { - "package": "swift-system", - "repositoryURL": "https://github.com/apple/swift-system.git", - "state": { - "branch": null, - "revision": "c8a44d836fe7913603e246acab7c528c2e780168", - "version": "1.4.0" - } + "pins" : [ + { + "identity" : "graphql", + "kind" : "remoteSourceControl", + "location" : "https://github.com/GraphQLSwift/GraphQL.git", + "state" : { + "revision" : "5e098b3b1789169dded5116c171f716d584225ea", + "version" : "3.0.0" } - ] - }, - "version": 1 + }, + { + "identity" : "swift-atomics", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-atomics.git", + "state" : { + "revision" : "cd142fd2f64be2100422d658e7411e39489da985", + "version" : "1.2.0" + } + }, + { + "identity" : "swift-collections", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-collections", + "state" : { + "revision" : "671108c96644956dddcd89dd59c203dcdb36cec7", + "version" : "1.1.4" + } + }, + { + "identity" : "swift-nio", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-nio.git", + "state" : { + "revision" : "f7dc3f527576c398709b017584392fb58592e7f5", + "version" : "2.75.0" + } + }, + { + "identity" : "swift-system", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-system.git", + "state" : { + "revision" : "c8a44d836fe7913603e246acab7c528c2e780168", + "version" : "1.4.0" + } + } + ], + "version" : 2 } diff --git a/Package.swift b/Package.swift index 08fb00e8..26346f1e 100644 --- a/Package.swift +++ b/Package.swift @@ -7,7 +7,7 @@ let package = Package( .library(name: "Graphiti", targets: ["Graphiti"]), ], dependencies: [ - .package(url: "https://github.com/GraphQLSwift/GraphQL.git", from: "2.10.0"), + .package(url: "https://github.com/GraphQLSwift/GraphQL.git", from: "3.0.0"), ], targets: [ .target(name: "Graphiti", dependencies: ["GraphQL"]), diff --git a/Sources/Graphiti/Argument/Argument.swift b/Sources/Graphiti/Argument/Argument.swift index 31b8ac82..737e1f99 100644 --- a/Sources/Graphiti/Argument/Argument.swift +++ b/Sources/Graphiti/Argument/Argument.swift @@ -17,6 +17,10 @@ public class Argument: ArgumentComponent return (name, argument) } + override func getName() -> String { + return name + } + init(name: String) { self.name = name } diff --git a/Sources/Graphiti/Argument/ArgumentComponent.swift b/Sources/Graphiti/Argument/ArgumentComponent.swift index c0378b49..0d8163ad 100644 --- a/Sources/Graphiti/Argument/ArgumentComponent.swift +++ b/Sources/Graphiti/Argument/ArgumentComponent.swift @@ -9,6 +9,10 @@ public class ArgumentComponent { ) throws -> (String, GraphQLArgument) { fatalError() } + + func getName() -> String { + fatalError() + } } public extension ArgumentComponent { diff --git a/Sources/Graphiti/Component/Component.swift b/Sources/Graphiti/Component/Component.swift index 18694b61..2cb031ab 100644 --- a/Sources/Graphiti/Component/Component.swift +++ b/Sources/Graphiti/Component/Component.swift @@ -11,7 +11,6 @@ open class Component { } func update(typeProvider _: SchemaTypeProvider, coders _: Coders) throws {} - func setGraphQLName(typeProvider _: SchemaTypeProvider) throws {} } public extension Component { @@ -36,25 +35,4 @@ enum ComponentType { case type case types case union - - /// An index used to sort components into the correct schema build order. This order goes - /// from "least other type references" to "most". By building in this order we are able to satisfy - /// hard ordering requirements (interfaces MUST be built before inheriting types), as well as - /// reduce unnecessary TypeReferences. - var buildOrder: Int { - switch self { - case .none: return 0 - case .scalar: return 1 - case .enum: return 2 - case .interface: return 3 - case .input: return 4 - case .connection: return 5 - case .type: return 6 - case .types: return 7 - case .union: return 8 - case .query: return 9 - case .mutation: return 10 - case .subscription: return 11 - } - } } diff --git a/Sources/Graphiti/Definition/Reflection.swift b/Sources/Graphiti/Definition/Reflection.swift index 618577c6..46a016c3 100644 --- a/Sources/Graphiti/Definition/Reflection.swift +++ b/Sources/Graphiti/Definition/Reflection.swift @@ -4,19 +4,6 @@ public enum Reflection { return description.hasSuffix("Protocol") } - @available(*, deprecated, message: "No longer used") - public static func isEncodable(type: Any.Type) -> Bool { - if isProtocol(type: type) { - return true - } - - if let type = type as? Wrapper.Type { - return isEncodable(type: type.wrappedType) - } - - return type is Encodable.Type - } - public static func name(for instance: Subject) -> String { var typeName: [Character] = [] var genericArgument: [Character] = [] diff --git a/Sources/Graphiti/Definition/TypeProvider.swift b/Sources/Graphiti/Definition/TypeProvider.swift index 164b1881..6be0f8c7 100644 --- a/Sources/Graphiti/Definition/TypeProvider.swift +++ b/Sources/Graphiti/Definition/TypeProvider.swift @@ -66,22 +66,12 @@ extension TypeProvider { from: GraphQLList(graphQLType), isOptional: isOptional ) - case .reference: - let name = getGraphQLName(of: type.wrappedType) - let referenceType = GraphQLTypeReference(name) - - return try getGraphQLOptionalType(from: referenceType, isOptional: isOptional) } } else { - if let graphQLType = graphQLTypeMap[AnyType(type)] { - return try getGraphQLOptionalType(from: graphQLType, isOptional: isOptional) - } else { - // If we haven't seen this type yet, just store it as a type reference and resolve later. - let name = getGraphQLName(of: type) - let referenceType = GraphQLTypeReference(name) - - return try getGraphQLOptionalType(from: referenceType, isOptional: isOptional) + guard let graphQLType = graphQLTypeMap[AnyType(type)] else { + throw GraphQLError(message: "Type not found \(type).") } + return try getGraphQLOptionalType(from: graphQLType, isOptional: isOptional) } } diff --git a/Sources/Graphiti/Definition/TypeReference.swift b/Sources/Graphiti/Definition/TypeReference.swift deleted file mode 100644 index f2f4cba1..00000000 --- a/Sources/Graphiti/Definition/TypeReference.swift +++ /dev/null @@ -1,11 +0,0 @@ -public enum TypeReference {} - -extension TypeReference: Wrapper { - static var wrappedType: Any.Type { - return Referent.self - } - - static var modifier: WrapperModifier { - return .reference - } -} diff --git a/Sources/Graphiti/Definition/Wrappers.swift b/Sources/Graphiti/Definition/Wrappers.swift index c5c7a590..3eae5294 100644 --- a/Sources/Graphiti/Definition/Wrappers.swift +++ b/Sources/Graphiti/Definition/Wrappers.swift @@ -1,7 +1,6 @@ enum WrapperModifier { case optional case list - case reference } protocol Wrapper { diff --git a/Sources/Graphiti/Enum/Enum.swift b/Sources/Graphiti/Enum/Enum.swift index 22b2ff40..f32fc988 100644 --- a/Sources/Graphiti/Enum/Enum.swift +++ b/Sources/Graphiti/Enum/Enum.swift @@ -26,10 +26,6 @@ public final class Enum< try typeProvider.add(type: EnumType.self, as: enumType) } - override func setGraphQLName(typeProvider: SchemaTypeProvider) throws { - try typeProvider.mapName(EnumType.self, to: name) - } - private init( type _: EnumType.Type, name: String?, diff --git a/Sources/Graphiti/Federation/Key/Key.swift b/Sources/Graphiti/Federation/Key/Key.swift index 0fe87992..e05c8e68 100644 --- a/Sources/Graphiti/Federation/Key/Key.swift +++ b/Sources/Graphiti/Federation/Key/Key.swift @@ -26,12 +26,10 @@ public class Key: KeyComponen } override func validate( - againstFields fieldNames: [String], - typeProvider: TypeProvider, - coders: Coders + againstFields fieldNames: [String] ) throws { // Ensure that every argument is included in the provided field list - for (name, _) in try arguments(typeProvider: typeProvider, coders: coders) { + for name in arguments.map({ $0.getName() }) { if !fieldNames.contains(name) { throw GraphQLError(message: "Argument name not found in type fields: \(name)") } diff --git a/Sources/Graphiti/Federation/Key/KeyComponent.swift b/Sources/Graphiti/Federation/Key/KeyComponent.swift index c897d1d6..0bb51bc4 100644 --- a/Sources/Graphiti/Federation/Key/KeyComponent.swift +++ b/Sources/Graphiti/Federation/Key/KeyComponent.swift @@ -17,9 +17,7 @@ public class KeyComponent { } func validate( - againstFields _: [String], - typeProvider _: TypeProvider, - coders _: Coders + againstFields _: [String] ) throws { fatalError() } diff --git a/Sources/Graphiti/Field/Field/Field.swift b/Sources/Graphiti/Field/Field/Field.swift index 22152bba..5ba7ea14 100644 --- a/Sources/Graphiti/Field/Field/Field.swift +++ b/Sources/Graphiti/Field/Field/Field.swift @@ -131,27 +131,6 @@ public extension Field { } } -public extension Field { - convenience init( - _ name: String, - at function: @escaping AsyncResolve, - as: FieldType.Type, - @ArgumentComponentBuilder _ argument: () -> ArgumentComponent - ) { - self.init(name: name, arguments: [argument()], asyncResolve: function) - } - - convenience init( - _ name: String, - at function: @escaping AsyncResolve, - as: FieldType.Type, - @ArgumentComponentBuilder _ arguments: () - -> [ArgumentComponent] = { [] } - ) { - self.init(name: name, arguments: arguments(), asyncResolve: function) - } -} - // MARK: SimpleAsyncResolve Initializers public extension Field { @@ -173,27 +152,6 @@ public extension Field { } } -public extension Field { - convenience init( - _ name: String, - at function: @escaping SimpleAsyncResolve, - as: FieldType.Type, - @ArgumentComponentBuilder _ argument: () -> ArgumentComponent - ) { - self.init(name: name, arguments: [argument()], simpleAsyncResolve: function) - } - - convenience init( - _ name: String, - at function: @escaping SimpleAsyncResolve, - as: FieldType.Type, - @ArgumentComponentBuilder _ arguments: () - -> [ArgumentComponent] = { [] } - ) { - self.init(name: name, arguments: arguments(), simpleAsyncResolve: function) - } -} - // MARK: SyncResolve Initializers // '@_disfavoredOverload' is included below because otherwise `SimpleAsyncResolve` initializers also match this signature, causing the @@ -220,29 +178,6 @@ public extension Field { } } -public extension Field { - @_disfavoredOverload - convenience init( - _ name: String, - at function: @escaping SyncResolve, - as: FieldType.Type, - @ArgumentComponentBuilder _ argument: () -> ArgumentComponent - ) { - self.init(name: name, arguments: [argument()], syncResolve: function) - } - - @_disfavoredOverload - convenience init( - _ name: String, - at function: @escaping SyncResolve, - as: FieldType.Type, - @ArgumentComponentBuilder _ arguments: () - -> [ArgumentComponent] = { [] } - ) { - self.init(name: name, arguments: arguments(), syncResolve: function) - } -} - // MARK: Keypath Initializers public extension Field where Arguments == NoArguments { @@ -260,22 +195,6 @@ public extension Field where Arguments == NoArguments { } } -public extension Field where Arguments == NoArguments { - convenience init( - _ name: String, - at keyPath: KeyPath, - as _: FieldType.Type - ) { - let syncResolve: SyncResolve = { type in - { _, _ in - type[keyPath: keyPath] - } - } - - self.init(name: name, arguments: [], syncResolve: syncResolve) - } -} - public extension Field { @available(macOS 10.15, iOS 15, watchOS 8, tvOS 15, *) convenience init( @@ -323,26 +242,3 @@ public extension Field { self.init(name: name, arguments: arguments(), concurrentResolve: function) } } - -public extension Field { - @available(macOS 10.15, iOS 15, watchOS 8, tvOS 15, *) - convenience init( - _ name: String, - at function: @escaping ConcurrentResolve, - as: FieldType.Type, - @ArgumentComponentBuilder _ argument: () -> ArgumentComponent - ) { - self.init(name: name, arguments: [argument()], concurrentResolve: function) - } - - @available(macOS 10.15, iOS 15, watchOS 8, tvOS 15, *) - convenience init( - _ name: String, - at function: @escaping ConcurrentResolve, - as: FieldType.Type, - @ArgumentComponentBuilder _ arguments: () - -> [ArgumentComponent] = { [] } - ) { - self.init(name: name, arguments: arguments(), concurrentResolve: function) - } -} diff --git a/Sources/Graphiti/Input/Input.swift b/Sources/Graphiti/Input/Input.swift index 89302101..3b3e21c0 100644 --- a/Sources/Graphiti/Input/Input.swift +++ b/Sources/Graphiti/Input/Input.swift @@ -15,17 +15,15 @@ public final class Input< let inputObjectType = try GraphQLInputObjectType( name: name, description: description, - fields: fields(typeProvider: typeProvider), + fields: { + try self.fields(typeProvider: typeProvider) + }, isOneOf: isOneOf ) try typeProvider.add(type: InputObjectType.self, as: inputObjectType) } - override func setGraphQLName(typeProvider: SchemaTypeProvider) throws { - try typeProvider.mapName(InputObjectType.self, to: name) - } - func fields(typeProvider: TypeProvider) throws -> InputObjectFieldMap { var map: InputObjectFieldMap = [:] diff --git a/Sources/Graphiti/InputField/InputField.swift b/Sources/Graphiti/InputField/InputField.swift index 46d41339..fb95ea81 100644 --- a/Sources/Graphiti/InputField/InputField.swift +++ b/Sources/Graphiti/InputField/InputField.swift @@ -39,25 +39,6 @@ public extension InputField { } } -public extension InputField { - convenience init( - _ name: String, - at _: KeyPath, - as _: FieldType.Type - ) { - self.init(name: name) - } -} - -public extension InputField { - convenience init( - _ name: String, - as _: FieldType.Type - ) { - self.init(name: name) - } -} - public extension InputField where FieldType: Encodable { func defaultValue(_ defaultValue: FieldType) -> Self { self.defaultValue = AnyEncodable(defaultValue) diff --git a/Sources/Graphiti/Interface/Interface.swift b/Sources/Graphiti/Interface/Interface.swift index d6601d0c..a6446daa 100644 --- a/Sources/Graphiti/Interface/Interface.swift +++ b/Sources/Graphiti/Interface/Interface.swift @@ -10,17 +10,15 @@ public final class Interface: TypeComponent< let interfaceType = try GraphQLInterfaceType( name: name, description: description, - fields: fields(typeProvider: typeProvider, coders: coders), + fields: { + try self.fields(typeProvider: typeProvider, coders: coders) + }, resolveType: nil ) try typeProvider.add(type: InterfaceType.self, as: interfaceType) } - override func setGraphQLName(typeProvider: SchemaTypeProvider) throws { - try typeProvider.mapName(InterfaceType.self, to: name) - } - func fields(typeProvider: TypeProvider, coders: Coders) throws -> GraphQLFieldMap { var map: GraphQLFieldMap = [:] diff --git a/Sources/Graphiti/Mutation/Mutation.swift b/Sources/Graphiti/Mutation/Mutation.swift index 42890e8f..51f8773e 100644 --- a/Sources/Graphiti/Mutation/Mutation.swift +++ b/Sources/Graphiti/Mutation/Mutation.swift @@ -11,7 +11,9 @@ public final class Mutation: Component { typeProvider.mutation = try GraphQLObjectType( name: name, description: description, - fields: fields(typeProvider: typeProvider, coders: coders), + fields: { + try self.fields(typeProvider: typeProvider, coders: coders) + }, isTypeOf: isTypeOf ) } diff --git a/Sources/Graphiti/Query/Query.swift b/Sources/Graphiti/Query/Query.swift index 727fc940..7c257e1d 100644 --- a/Sources/Graphiti/Query/Query.swift +++ b/Sources/Graphiti/Query/Query.swift @@ -8,34 +8,37 @@ public final class Query: Component { } override func update(typeProvider: SchemaTypeProvider, coders: Coders) throws { - var queryFields = try fields(typeProvider: typeProvider, coders: coders) - - // Add federated types and queries if they exist - if !typeProvider.federatedTypes.isEmpty { - let federatedTypes = typeProvider.federatedTypes - guard let sdl = typeProvider.federatedSDL else { - throw GraphQLError(message: "If federated types are included, SDL must be provided") - } - - // Add subgraph types to provider (_Service, _Any, _Entity) - let entity = entityType(federatedTypes) - typeProvider.types.append(serviceType) - typeProvider.types.append(anyType) - typeProvider.types.append(entity) - - // Add subgraph queries (_entities, _service) - queryFields["_entities"] = entitiesQuery( - for: typeProvider.federatedResolvers, - entityType: entity, - coders: coders - ) - queryFields["_service"] = serviceQuery(for: sdl) - } - typeProvider.query = try GraphQLObjectType( name: name, description: description, - fields: queryFields, + fields: { + var queryFields = try self.fields(typeProvider: typeProvider, coders: coders) + + // Add federated types and queries if they exist + if !typeProvider.federatedTypes.isEmpty { + let federatedTypes = typeProvider.federatedTypes + guard let sdl = typeProvider.federatedSDL else { + throw GraphQLError( + message: "If federated types are included, SDL must be provided" + ) + } + + // Add subgraph types to provider (_Service, _Any, _Entity) + let entity = entityType(federatedTypes) + typeProvider.types.append(serviceType) + typeProvider.types.append(anyType) + typeProvider.types.append(entity) + + // Add subgraph queries (_entities, _service) + queryFields["_entities"] = entitiesQuery( + for: typeProvider.federatedResolvers, + entityType: entity, + coders: coders + ) + queryFields["_service"] = serviceQuery(for: sdl) + } + return queryFields + }, isTypeOf: isTypeOf ) } diff --git a/Sources/Graphiti/Scalar/Scalar.swift b/Sources/Graphiti/Scalar/Scalar.swift index d62720ba..3de7bed2 100644 --- a/Sources/Graphiti/Scalar/Scalar.swift +++ b/Sources/Graphiti/Scalar/Scalar.swift @@ -51,10 +51,6 @@ open class Scalar: TypeComponent Map { try encoder.encode(scalar) diff --git a/Sources/Graphiti/Schema/Schema.swift b/Sources/Graphiti/Schema/Schema.swift index 75fd7017..959b297f 100644 --- a/Sources/Graphiti/Schema/Schema.swift +++ b/Sources/Graphiti/Schema/Schema.swift @@ -12,16 +12,7 @@ public final class Schema { let typeProvider = SchemaTypeProvider() typeProvider.federatedSDL = federatedSDL - // Collect types mappings first for component in components { - try component.setGraphQLName(typeProvider: typeProvider) - } - - // Order component by componentType build order - let sortedComponents = components.sorted { - $0.componentType.buildOrder <= $1.componentType.buildOrder - } - for component in sortedComponents { try component.update(typeProvider: typeProvider, coders: coders) } diff --git a/Sources/Graphiti/Subscription/Subscription.swift b/Sources/Graphiti/Subscription/Subscription.swift index 2a9a0bf5..e7752054 100644 --- a/Sources/Graphiti/Subscription/Subscription.swift +++ b/Sources/Graphiti/Subscription/Subscription.swift @@ -11,7 +11,9 @@ public final class Subscription: Component typeProvider.subscription = try GraphQLObjectType( name: name, description: description, - fields: fields(typeProvider: typeProvider, coders: coders), + fields: { + try self.fields(typeProvider: typeProvider, coders: coders) + }, isTypeOf: isTypeOf ) } diff --git a/Sources/Graphiti/Type/Type.swift b/Sources/Graphiti/Type/Type.swift index 4f9157d6..96c74bdc 100644 --- a/Sources/Graphiti/Type/Type.swift +++ b/Sources/Graphiti/Type/Type.swift @@ -13,30 +13,29 @@ public final class Type: TypeComponent< } override func update(typeProvider: SchemaTypeProvider, coders: Coders) throws { - let fieldDefs = try fields(typeProvider: typeProvider, coders: coders) let objectType = try GraphQLObjectType( name: name, description: description, - fields: fieldDefs, - interfaces: interfaces.map { - try typeProvider.getInterfaceType(from: $0) + fields: { + let fields = try self.fields(typeProvider: typeProvider, coders: coders) + // Validate federation keys, if present + for key in self.keys { + try key.validate(againstFields: Array(fields.keys)) + } + return fields + }, + interfaces: { + try self.interfaces.map { + try typeProvider.getInterfaceType(from: $0) + } }, isTypeOf: isTypeOf ) try typeProvider.add(type: ObjectType.self, as: objectType) - // If federation keys are included, validate and create resolver closure + // If federation keys are included, create resolver closure if !keys.isEmpty { - let fieldNames = Array(fieldDefs.keys) - for key in keys { - try key.validate( - againstFields: fieldNames, - typeProvider: typeProvider, - coders: coders - ) - } - let resolve: GraphQLFieldResolve = { source, args, context, eventLoopGroup, _ in guard let s = source as? Resolver else { throw GraphQLError( @@ -73,10 +72,6 @@ public final class Type: TypeComponent< } } - override func setGraphQLName(typeProvider: SchemaTypeProvider) throws { - try typeProvider.mapName(ObjectType.self, to: name) - } - func fields(typeProvider: TypeProvider, coders: Coders) throws -> GraphQLFieldMap { var map: GraphQLFieldMap = [:] diff --git a/Sources/Graphiti/Types/Types.swift b/Sources/Graphiti/Types/Types.swift deleted file mode 100644 index d52dcd09..00000000 --- a/Sources/Graphiti/Types/Types.swift +++ /dev/null @@ -1,24 +0,0 @@ -import GraphQL - -@available(*, deprecated, message: "No longer use this. Instead define types using `Type`.") -public final class Types: Component { - let types: [Any.Type] - - override func update(typeProvider: SchemaTypeProvider, coders _: Coders) throws { - typeProvider.types = try types.map { - try typeProvider.getNamedType(from: $0) - } - } - - init(types: [Any.Type]) { - self.types = types - super.init( - name: "", - type: .types - ) - } - - public convenience init(_ types: Any.Type...) { - self.init(types: types) - } -} diff --git a/Sources/Graphiti/Union/Union.swift b/Sources/Graphiti/Union/Union.swift index 6d8d0c37..791d4957 100644 --- a/Sources/Graphiti/Union/Union.swift +++ b/Sources/Graphiti/Union/Union.swift @@ -8,18 +8,16 @@ public final class Union: TypeComponent { Type(ChatObject.self, as: "Chat") { - Field("messages", at: ChatObject.messages, as: Connection.self) { + Field("messages", at: ChatObject.messages) { Argument("first", at: \.first) Argument("after", at: \.after) Argument("last", at: \.last) diff --git a/Tests/GraphitiTests/DirectiveTests/DirectiveTests.swift b/Tests/GraphitiTests/DirectiveTests/DirectiveTests.swift index 2beb6360..34db5c8f 100644 --- a/Tests/GraphitiTests/DirectiveTests/DirectiveTests.swift +++ b/Tests/GraphitiTests/DirectiveTests/DirectiveTests.swift @@ -153,7 +153,7 @@ class DirectiveTests: XCTestCase { } Query { - Field("test", at: OneOfResolver.test, as: TestObject.self) { + Field("test", at: OneOfResolver.test) { Argument("input", at: \.input) } } diff --git a/Tests/GraphitiTests/HelloWorldTests/HelloWorldTests.swift b/Tests/GraphitiTests/HelloWorldTests/HelloWorldTests.swift index d80c0513..eb316bc0 100644 --- a/Tests/GraphitiTests/HelloWorldTests/HelloWorldTests.swift +++ b/Tests/GraphitiTests/HelloWorldTests/HelloWorldTests.swift @@ -126,7 +126,7 @@ struct HelloAPI: API { Input(UserInput.self) { InputField("id", at: \.id) - InputField("name", as: String?.self) + InputField("name", at: \.name) InputField("friends", at: \.friends) } diff --git a/Tests/GraphitiTests/PartialSchemaTests.swift b/Tests/GraphitiTests/PartialSchemaTests.swift index 80043142..0a38c66e 100644 --- a/Tests/GraphitiTests/PartialSchemaTests.swift +++ b/Tests/GraphitiTests/PartialSchemaTests.swift @@ -12,7 +12,7 @@ class PartialSchemaTests: XCTestCase { .description("The id of the character.") Field("name", at: \.name) .description("The name of the character.") - Field("friends", at: \.friends, as: [TypeReference].self) + Field("friends", at: \.friends) .description( "The friends of the character, or an empty list if they have none." ) @@ -34,7 +34,7 @@ class PartialSchemaTests: XCTestCase { @FieldDefinitions override var query: Fields { - Field("hero", at: StarWarsResolver.hero, as: Character.self) { + Field("hero", at: StarWarsResolver.hero) { Argument("episode", at: \.episode) .description( "If omitted, returns the hero of the whole saga. If provided, returns the hero of that particular episode." @@ -61,7 +61,7 @@ class PartialSchemaTests: XCTestCase { Field("name", at: \.name) Field("appearsIn", at: \.appearsIn) Field("homePlanet", at: \.homePlanet) - Field("friends", at: Human.getFriends, as: [Character].self) + Field("friends", at: Human.getFriends) .description("The friends of the human, or an empty list if they have none.") Field("secretBackstory", at: Human.getSecretBackstory) .description("Where are they from and how they came to be who they are.") @@ -71,7 +71,7 @@ class PartialSchemaTests: XCTestCase { Field("name", at: \.name) Field("appearsIn", at: \.appearsIn) Field("primaryFunction", at: \.primaryFunction) - Field("friends", at: Droid.getFriends, as: [Character].self) + Field("friends", at: Droid.getFriends) .description("The friends of the droid, or an empty list if they have none.") Field("secretBackstory", at: Droid.getSecretBackstory) .description("Where are they from and how they came to be who they are.") @@ -89,7 +89,7 @@ class PartialSchemaTests: XCTestCase { Argument("id", at: \.id) .description("Id of the droid.") } - Field("search", at: StarWarsResolver.search, as: [SearchResult].self) { + Field("search", at: StarWarsResolver.search) { Argument("query", at: \.query) .defaultValue("R2-D2") } @@ -218,7 +218,7 @@ class PartialSchemaTests: XCTestCase { .description("The id of the character.") Field("name", at: \.name) .description("The name of the character.") - Field("friends", at: \.friends, as: [TypeReference].self) + Field("friends", at: \.friends) .description( "The friends of the character, or an empty list if they have none." ) @@ -238,7 +238,7 @@ class PartialSchemaTests: XCTestCase { }.description("One of the films in the Star Wars Trilogy.") }, query: { - Field("hero", at: StarWarsResolver.hero, as: Character.self) { + Field("hero", at: StarWarsResolver.hero) { Argument("episode", at: \.episode) .description( "If omitted, returns the hero of the whole saga. If provided, returns the hero of that particular episode." @@ -264,7 +264,7 @@ class PartialSchemaTests: XCTestCase { Field("name", at: \.name) Field("appearsIn", at: \.appearsIn) Field("homePlanet", at: \.homePlanet) - Field("friends", at: Human.getFriends, as: [Character].self) + Field("friends", at: Human.getFriends) .description( "The friends of the human, or an empty list if they have none." ) @@ -276,7 +276,7 @@ class PartialSchemaTests: XCTestCase { Field("name", at: \.name) Field("appearsIn", at: \.appearsIn) Field("primaryFunction", at: \.primaryFunction) - Field("friends", at: Droid.getFriends, as: [Character].self) + Field("friends", at: Droid.getFriends) .description( "The friends of the droid, or an empty list if they have none." ) @@ -294,7 +294,7 @@ class PartialSchemaTests: XCTestCase { Argument("id", at: \.id) .description("Id of the droid.") } - Field("search", at: StarWarsResolver.search, as: [SearchResult].self) { + Field("search", at: StarWarsResolver.search) { Argument("query", at: \.query) .defaultValue("R2-D2") } diff --git a/Tests/GraphitiTests/SchemaBuilderTests.swift b/Tests/GraphitiTests/SchemaBuilderTests.swift index 35106828..e531e57d 100644 --- a/Tests/GraphitiTests/SchemaBuilderTests.swift +++ b/Tests/GraphitiTests/SchemaBuilderTests.swift @@ -11,7 +11,7 @@ class SchemaBuilderTests: XCTestCase { // Add assets slightly out of order builder.addQuery { - Field("hero", at: StarWarsResolver.hero, as: Character.self) { + Field("hero", at: StarWarsResolver.hero) { Argument("episode", at: \.episode) .description( "If omitted, returns the hero of the whole saga. If provided, returns the hero of that particular episode." @@ -49,7 +49,7 @@ class SchemaBuilderTests: XCTestCase { Field("name", at: \.name) Field("appearsIn", at: \.appearsIn) Field("homePlanet", at: \.homePlanet) - Field("friends", at: Human.getFriends, as: [Character].self) + Field("friends", at: Human.getFriends) .description("The friends of the human, or an empty list if they have none.") Field("secretBackstory", at: Human.getSecretBackstory) .description("Where are they from and how they came to be who they are.") @@ -59,7 +59,7 @@ class SchemaBuilderTests: XCTestCase { Field("name", at: \.name) Field("appearsIn", at: \.appearsIn) Field("primaryFunction", at: \.primaryFunction) - Field("friends", at: Droid.getFriends, as: [Character].self) + Field("friends", at: Droid.getFriends) .description("The friends of the droid, or an empty list if they have none.") Field("secretBackstory", at: Droid.getSecretBackstory) .description("Where are they from and how they came to be who they are.") @@ -70,7 +70,7 @@ class SchemaBuilderTests: XCTestCase { .description("The id of the character.") Field("name", at: \.name) .description("The name of the character.") - Field("friends", at: \.friends, as: [TypeReference].self) + Field("friends", at: \.friends) .description( "The friends of the character, or an empty list if they have none." ) @@ -89,7 +89,7 @@ class SchemaBuilderTests: XCTestCase { Argument("id", at: \.id) .description("Id of the droid.") } - Field("search", at: StarWarsResolver.search, as: [SearchResult].self) { + Field("search", at: StarWarsResolver.search) { Argument("query", at: \.query) .defaultValue("R2-D2") } diff --git a/Tests/GraphitiTests/StarWarsAPI/StarWarsAPI.swift b/Tests/GraphitiTests/StarWarsAPI/StarWarsAPI.swift index 4b110771..fa751ba0 100644 --- a/Tests/GraphitiTests/StarWarsAPI/StarWarsAPI.swift +++ b/Tests/GraphitiTests/StarWarsAPI/StarWarsAPI.swift @@ -23,7 +23,7 @@ public struct StarWarsAPI: API { Field("name", at: \.name) .description("The name of the character.") - Field("friends", at: \.friends, as: [TypeReference].self) + Field("friends", at: Character.getFriends) .description("The friends of the character, or an empty list if they have none.") Field("appearsIn", at: \.appearsIn) @@ -52,7 +52,7 @@ public struct StarWarsAPI: API { Field("appearsIn", at: \.appearsIn) Field("homePlanet", at: \.homePlanet) - Field("friends", at: Human.getFriends, as: [Character].self) + Field("friends", at: Human.getFriends) .description("The friends of the human, or an empty list if they have none.") Field("secretBackstory", at: Human.getSecretBackstory) @@ -66,7 +66,7 @@ public struct StarWarsAPI: API { Field("appearsIn", at: \.appearsIn) Field("primaryFunction", at: \.primaryFunction) - Field("friends", at: Droid.getFriends, as: [Character].self) + Field("friends", at: Droid.getFriends) .description("The friends of the droid, or an empty list if they have none.") Field("secretBackstory", at: Droid.getSecretBackstory) @@ -77,7 +77,7 @@ public struct StarWarsAPI: API { Union(SearchResult.self, members: Planet.self, Human.self, Droid.self) Query { - Field("hero", at: StarWarsResolver.hero, as: Character.self) { + Field("hero", at: StarWarsResolver.hero) { Argument("episode", at: \.episode) .description( "If omitted, returns the hero of the whole saga. If provided, returns the hero of that particular episode." @@ -95,7 +95,7 @@ public struct StarWarsAPI: API { .description("Id of the droid.") } - Field("search", at: StarWarsResolver.search, as: [SearchResult].self) { + Field("search", at: StarWarsResolver.search) { Argument("query", at: \.query) .defaultValue("R2-D2") } diff --git a/Tests/GraphitiTests/UnionTests.swift b/Tests/GraphitiTests/UnionTests.swift index 6e93d8c2..33209c20 100644 --- a/Tests/GraphitiTests/UnionTests.swift +++ b/Tests/GraphitiTests/UnionTests.swift @@ -22,7 +22,7 @@ class UnionTests: XCTestCase { Union(SearchResult.self, members: Planet.self, Human.self, Droid.self) Query { - Field("search", at: StarWarsResolver.search, as: [SearchResult].self) { + Field("search", at: StarWarsResolver.search) { Argument("query", at: \.query) } } @@ -48,7 +48,7 @@ class UnionTests: XCTestCase { ]) Query { - Field("search", at: StarWarsResolver.search, as: [SearchResult].self) { + Field("search", at: StarWarsResolver.search) { Argument("query", at: \.query) } }