Skip to content

Commit 955e549

Browse files
Merge pull request #97 from NeedleInAJayStack/fix/interface-ordering
Fix: interface and union ordering
2 parents 1d90f4f + 653d28c commit 955e549

File tree

16 files changed

+152
-43
lines changed

16 files changed

+152
-43
lines changed

Sources/Graphiti/Component/Component.swift

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import GraphQL
33
open class Component<Resolver, Context> {
44
let name: String
55
var description: String?
6+
var componentType: ComponentType
67

7-
init(name: String) {
8+
init(name: String, type: ComponentType) {
89
self.name = name
10+
componentType = type
911
}
1012

1113
func update(typeProvider _: SchemaTypeProvider, coders _: Coders) throws {}
@@ -18,3 +20,41 @@ public extension Component {
1820
return self
1921
}
2022
}
23+
24+
/// The type of a component. This is used as opposed to runtime type-checking because the
25+
/// component types are typically generics (and therefore hard to type-check).
26+
enum ComponentType {
27+
case none
28+
case connection
29+
case `enum`
30+
case input
31+
case interface
32+
case mutation
33+
case query
34+
case scalar
35+
case subscription
36+
case type
37+
case types
38+
case union
39+
40+
/// An index used to sort components into the correct schema build order. This order goes
41+
/// from "least other type references" to "most". By building in this order we are able to satisfy
42+
/// hard ordering requirements (interfaces MUST be built before inheriting types), as well as
43+
/// reduce unnecessary TypeReferences.
44+
var buildOrder: Int {
45+
switch self {
46+
case .none: return 0
47+
case .scalar: return 1
48+
case .enum: return 2
49+
case .interface: return 3
50+
case .input: return 4
51+
case .type: return 5
52+
case .types: return 6
53+
case .union: return 7
54+
case .connection: return 8
55+
case .query: return 9
56+
case .mutation: return 10
57+
case .subscription: return 11
58+
}
59+
}
60+
}

Sources/Graphiti/Connection/ConnectionType.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public final class ConnectionType<
2222

2323
let edge = Type<Resolver, Context, Edge<ObjectType>>(
2424
Edge<ObjectType>.self,
25-
as: name+"Edge"
25+
as: name + "Edge"
2626
) {
2727
Field("node", at: \.node)
2828
Field("cursor", at: \.cursor)
@@ -32,7 +32,7 @@ public final class ConnectionType<
3232

3333
let connection = Type<Resolver, Context, Connection<ObjectType>>(
3434
Connection<ObjectType>.self,
35-
as: name+"Connection"
35+
as: name + "Connection"
3636
) {
3737
Field("edges", at: \.edges)
3838
Field("pageInfo", at: \.pageInfo)
@@ -45,7 +45,10 @@ public final class ConnectionType<
4545
type _: ObjectType.Type,
4646
name: String?
4747
) {
48-
super.init(name: name ?? Reflection.name(for: ObjectType.self))
48+
super.init(
49+
name: name ?? Reflection.name(for: ObjectType.self),
50+
type: .connection
51+
)
4952
}
5053
}
5154

Sources/Graphiti/Enum/Enum.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ public final class Enum<
2323
}
2424
)
2525

26-
try typeProvider.map(EnumType.self, to: enumType)
27-
typeProvider.types.append(enumType)
26+
try typeProvider.add(type: EnumType.self, as: enumType)
2827
}
2928

3029
override func setGraphQLName(typeProvider: SchemaTypeProvider) throws {
@@ -37,7 +36,10 @@ public final class Enum<
3736
values: [Value<EnumType>]
3837
) {
3938
self.values = values
40-
super.init(name: name ?? Reflection.name(for: EnumType.self))
39+
super.init(
40+
name: name ?? Reflection.name(for: EnumType.self),
41+
type: .enum
42+
)
4143
}
4244
}
4345

Sources/Graphiti/Input/Input.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ public final class Input<
1717
fields: fields(typeProvider: typeProvider)
1818
)
1919

20-
try typeProvider.map(InputObjectType.self, to: inputObjectType)
21-
typeProvider.types.append(inputObjectType)
20+
try typeProvider.add(type: InputObjectType.self, as: inputObjectType)
2221
}
2322

2423
override func setGraphQLName(typeProvider: SchemaTypeProvider) throws {
@@ -42,7 +41,10 @@ public final class Input<
4241
fields: [InputFieldComponent<InputObjectType, Context>]
4342
) {
4443
self.fields = fields
45-
super.init(name: name ?? Reflection.name(for: InputObjectType.self))
44+
super.init(
45+
name: name ?? Reflection.name(for: InputObjectType.self),
46+
type: .connection
47+
)
4648
}
4749
}
4850

Sources/Graphiti/Interface/Interface.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ public final class Interface<Resolver, Context, InterfaceType>: TypeComponent<
1414
resolveType: nil
1515
)
1616

17-
try typeProvider.map(InterfaceType.self, to: interfaceType)
18-
typeProvider.types.append(interfaceType)
17+
try typeProvider.add(type: InterfaceType.self, as: interfaceType)
1918
}
2019

2120
override func setGraphQLName(typeProvider: SchemaTypeProvider) throws {
@@ -39,7 +38,10 @@ public final class Interface<Resolver, Context, InterfaceType>: TypeComponent<
3938
fields: [FieldComponent<InterfaceType, Context>]
4039
) {
4140
self.fields = fields
42-
super.init(name: name ?? Reflection.name(for: InterfaceType.self))
41+
super.init(
42+
name: name ?? Reflection.name(for: InterfaceType.self),
43+
type: .interface
44+
)
4345
}
4446
}
4547

Sources/Graphiti/Mutation/Mutation.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ public final class Mutation<Resolver, Context>: Component<Resolver, Context> {
3232
fields: [FieldComponent<Resolver, Context>]
3333
) {
3434
self.fields = fields
35-
super.init(name: name)
35+
super.init(
36+
name: name,
37+
type: .mutation
38+
)
3639
}
3740
}
3841

Sources/Graphiti/Query/Query.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ public final class Query<Resolver, Context>: Component<Resolver, Context> {
3232
fields: [FieldComponent<Resolver, Context>]
3333
) {
3434
self.fields = fields
35-
super.init(name: name)
35+
super.init(
36+
name: name,
37+
type: .query
38+
)
3639
}
3740
}
3841

Sources/Graphiti/Scalar/Scalar.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ open class Scalar<Resolver, Context, ScalarType: Codable>: TypeComponent<Resolve
3333
}
3434
)
3535

36-
try typeProvider.map(ScalarType.self, to: scalarType)
37-
typeProvider.types.append(scalarType)
36+
try typeProvider.add(type: ScalarType.self, as: scalarType)
3837
}
3938

4039
override func setGraphQLName(typeProvider: SchemaTypeProvider) throws {
@@ -53,7 +52,10 @@ open class Scalar<Resolver, Context, ScalarType: Codable>: TypeComponent<Resolve
5352
type _: ScalarType.Type,
5453
name: String?
5554
) {
56-
super.init(name: name ?? Reflection.name(for: ScalarType.self))
55+
super.init(
56+
name: name ?? Reflection.name(for: ScalarType.self),
57+
type: .scalar
58+
)
5759
}
5860
}
5961

Sources/Graphiti/Schema/Schema.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ public final class Schema<Resolver, Context> {
1515
try component.setGraphQLName(typeProvider: typeProvider)
1616
}
1717

18-
// Then build up GraphQLTypes
19-
for component in components {
18+
// Order component by componentType build order
19+
let sortedComponents = components.sorted {
20+
$0.componentType.buildOrder <= $1.componentType.buildOrder
21+
}
22+
for component in sortedComponents {
2023
try component.update(typeProvider: typeProvider, coders: coders)
2124
}
2225

Sources/Graphiti/Schema/SchemaTypeProvider.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,9 @@ final class SchemaTypeProvider: TypeProvider {
2020
var subscription: GraphQLObjectType?
2121
var types: [GraphQLNamedType] = []
2222
var directives: [GraphQLDirective] = []
23+
24+
func add(type: Any.Type, as graphQLType: GraphQLNamedType) throws {
25+
try map(type, to: graphQLType)
26+
types.append(graphQLType)
27+
}
2328
}

0 commit comments

Comments
 (0)