Skip to content

Commit e459369

Browse files
feat: Adds UniqueOperationTypesRule
1 parent 062a848 commit e459369

File tree

3 files changed

+400
-1
lines changed

3 files changed

+400
-1
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
2+
/**
3+
* Unique operation types
4+
*
5+
* A GraphQL document is only valid if it has only one type per operation.
6+
*/
7+
func UniqueOperationTypesRule(
8+
context: SDLValidationContext
9+
) -> Visitor {
10+
let schema = context.getSchema()
11+
var definedOperationTypes: [OperationType: OperationTypeDefinition] = .init()
12+
let existingOperationTypes = {
13+
var result = [OperationType: GraphQLObjectType]()
14+
if let queryType = schema?.queryType {
15+
result[.query] = queryType
16+
}
17+
if let mutationType = schema?.mutationType {
18+
result[.mutation] = mutationType
19+
}
20+
if let subscriptionType = schema?.subscriptionType {
21+
result[.subscription] = subscriptionType
22+
}
23+
return result
24+
}()
25+
26+
return Visitor(
27+
enter: { node, _, _, _, _ in
28+
if let operation = node as? SchemaDefinition {
29+
checkOperationTypes(operation.operationTypes)
30+
} else if let operation = node as? SchemaExtensionDefinition {
31+
checkOperationTypes(operation.definition.operationTypes)
32+
}
33+
return .continue
34+
}
35+
)
36+
37+
func checkOperationTypes(
38+
_ operationTypesNodes: [OperationTypeDefinition]
39+
) {
40+
for operationType in operationTypesNodes {
41+
let operation = operationType.operation
42+
43+
if existingOperationTypes[operation] != nil {
44+
context.report(
45+
error: GraphQLError(
46+
message: "Type for \(operation) already defined in the schema. It cannot be redefined.",
47+
nodes: [operationType]
48+
)
49+
)
50+
} else if let alreadyDefinedOperationType = definedOperationTypes[operation] {
51+
context.report(
52+
error: GraphQLError(
53+
message: "There can be only one \(operation) type in schema.",
54+
nodes: [alreadyDefinedOperationType, operationType]
55+
)
56+
)
57+
} else {
58+
definedOperationTypes[operation] = operationType
59+
}
60+
}
61+
}
62+
}

Sources/GraphQL/Validation/SpecifiedRules.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public let specifiedRules: [(ValidationContext) -> Visitor] = [
3838
*/
3939
public let specifiedSDLRules: [SDLValidationRule] = [
4040
LoneSchemaDefinitionRule,
41-
// UniqueOperationTypesRule,
41+
UniqueOperationTypesRule,
4242
// UniqueTypeNamesRule,
4343
// UniqueEnumValueNamesRule,
4444
// UniqueFieldDefinitionNamesRule,

0 commit comments

Comments
 (0)