Skip to content

Commit ebd2ea4

Browse files
Merge pull request #99 from d-exclaimation/custom-validation-rules
Making validate with validation rules public
2 parents 8f0a07e + ba984e6 commit ebd2ea4

File tree

5 files changed

+38
-33
lines changed

5 files changed

+38
-33
lines changed

Package.resolved

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
"repositoryURL": "https://github.com/apple/swift-nio.git",
1616
"state": {
1717
"branch": null,
18-
"revision": "51c3fc2e4a0fcdf4a25089b288dd65b73df1b0ef",
19-
"version": "2.37.0"
18+
"revision": "124119f0bb12384cef35aa041d7c3a686108722d",
19+
"version": "2.40.0"
2020
}
2121
}
2222
]

Sources/GraphQL/GraphQL.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ public func graphql(
7878
mutationStrategy: MutationFieldExecutionStrategy = SerialFieldExecutionStrategy(),
7979
subscriptionStrategy: SubscriptionFieldExecutionStrategy = SerialFieldExecutionStrategy(),
8080
instrumentation: Instrumentation = NoOpInstrumentation,
81+
validationRules: [(ValidationContext) -> Visitor] = [],
8182
schema: GraphQLSchema,
8283
request: String,
8384
rootValue: Any = (),
@@ -89,7 +90,7 @@ public func graphql(
8990

9091
let source = Source(body: request, name: "GraphQL request")
9192
let documentAST = try parse(instrumentation: instrumentation, source: source)
92-
let validationErrors = validate(instrumentation: instrumentation, schema: schema, ast: documentAST)
93+
let validationErrors = validate(instrumentation: instrumentation, schema: schema, ast: documentAST, rules: validationRules)
9394

9495
guard validationErrors.isEmpty else {
9596
return eventLoopGroup.next().makeSucceededFuture(GraphQLResult(errors: validationErrors))
@@ -195,6 +196,7 @@ public func graphqlSubscribe(
195196
mutationStrategy: MutationFieldExecutionStrategy = SerialFieldExecutionStrategy(),
196197
subscriptionStrategy: SubscriptionFieldExecutionStrategy = SerialFieldExecutionStrategy(),
197198
instrumentation: Instrumentation = NoOpInstrumentation,
199+
validationRules: [(ValidationContext) -> Visitor] = [],
198200
schema: GraphQLSchema,
199201
request: String,
200202
rootValue: Any = (),
@@ -206,7 +208,7 @@ public func graphqlSubscribe(
206208

207209
let source = Source(body: request, name: "GraphQL Subscription request")
208210
let documentAST = try parse(instrumentation: instrumentation, source: source)
209-
let validationErrors = validate(instrumentation: instrumentation, schema: schema, ast: documentAST)
211+
let validationErrors = validate(instrumentation: instrumentation, schema: schema, ast: documentAST, rules: validationRules)
210212

211213
guard validationErrors.isEmpty else {
212214
return eventLoopGroup.next().makeSucceededFuture(SubscriptionResult(errors: validationErrors))

Sources/GraphQL/Language/Visitor.swift

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -313,40 +313,43 @@ func visitInParallel(visitors: [Visitor]) -> Visitor {
313313
)
314314
}
315315

316-
enum VisitResult {
316+
public enum VisitResult {
317317
case `continue`
318318
case skip
319319
case `break`
320320
case node(Node?)
321321

322-
var isContinue: Bool {
322+
public var isContinue: Bool {
323323
if case .continue = self {
324324
return true
325325
}
326326
return false
327327
}
328328
}
329329

330-
struct Visitor {
331-
typealias Visit = (Node, IndexPathElement?, NodeResult?, [IndexPathElement], [NodeResult]) -> VisitResult
330+
/// A visitor is provided to visit, it contains the collection of
331+
/// relevant functions to be called during the visitor's traversal.
332+
public struct Visitor {
333+
/// A visitor is comprised of visit functions, which are called on each node during the visitor's traversal.
334+
public typealias Visit = (Node, IndexPathElement?, NodeResult?, [IndexPathElement], [NodeResult]) -> VisitResult
332335
private let enter: Visit
333336
private let leave: Visit
334337

335-
init(enter: @escaping Visit = ignore, leave: @escaping Visit = ignore) {
338+
public init(enter: @escaping Visit = ignore, leave: @escaping Visit = ignore) {
336339
self.enter = enter
337340
self.leave = leave
338341
}
339342

340-
func enter(node: Node, key: IndexPathElement?, parent: NodeResult?, path: [IndexPathElement], ancestors: [NodeResult]) -> VisitResult {
343+
public func enter(node: Node, key: IndexPathElement?, parent: NodeResult?, path: [IndexPathElement], ancestors: [NodeResult]) -> VisitResult {
341344
return enter(node, key, parent, path, ancestors)
342345
}
343346

344-
func leave(node: Node, key: IndexPathElement?, parent: NodeResult?, path: [IndexPathElement], ancestors: [NodeResult]) -> VisitResult {
347+
public func leave(node: Node, key: IndexPathElement?, parent: NodeResult?, path: [IndexPathElement], ancestors: [NodeResult]) -> VisitResult {
345348
return leave(node, key, parent, path, ancestors)
346349
}
347350
}
348351

349-
func ignore(node: Node, key: IndexPathElement?, parent: NodeResult?, path: [IndexPathElement], ancestors: [NodeResult]) -> VisitResult {
352+
public func ignore(node: Node, key: IndexPathElement?, parent: NodeResult?, path: [IndexPathElement], ancestors: [NodeResult]) -> VisitResult {
350353
return .continue
351354
}
352355

Sources/GraphQL/Validation/SpecifiedRules.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* This set includes all validation rules defined by the GraphQL spec.
33
*/
4-
let specifiedRules: [(ValidationContext) -> Visitor] = [
4+
public let specifiedRules: [(ValidationContext) -> Visitor] = [
55
// UniqueOperationNames,
66
// LoneAnonymousOperation,
77
// KnownTypeNames,

Sources/GraphQL/Validation/Validate.swift

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public func validate(
2929
* (see the language/visitor API). Visitor methods are expected to return
3030
* GraphQLErrors, or Arrays of GraphQLErrors when invalid.
3131
*/
32-
func validate(
32+
public func validate(
3333
instrumentation: Instrumentation = NoOpInstrumentation,
3434
schema: GraphQLSchema,
3535
ast: Document,
@@ -62,11 +62,11 @@ func visit(
6262
return context.errors
6363
}
6464

65-
enum HasSelectionSet {
65+
public enum HasSelectionSet {
6666
case operation(OperationDefinition)
6767
case fragment(FragmentDefinition)
6868

69-
var node: Node {
69+
public var node: Node {
7070
switch self {
7171
case .operation(let operation):
7272
return operation
@@ -77,7 +77,7 @@ enum HasSelectionSet {
7777
}
7878

7979
extension HasSelectionSet : Hashable {
80-
func hash(into hasher: inout Hasher) {
80+
public func hash(into hasher: inout Hasher) {
8181
switch self {
8282
case .operation(let operation):
8383
return hasher.combine(operation.hashValue)
@@ -86,7 +86,7 @@ extension HasSelectionSet : Hashable {
8686
}
8787
}
8888

89-
static func == (lhs: HasSelectionSet, rhs: HasSelectionSet) -> Bool {
89+
public static func == (lhs: HasSelectionSet, rhs: HasSelectionSet) -> Bool {
9090
switch (lhs, rhs) {
9191
case (.operation(let l), .operation(let r)):
9292
return l == r
@@ -98,15 +98,15 @@ extension HasSelectionSet : Hashable {
9898
}
9999
}
100100

101-
typealias VariableUsage = (node: Variable, type: GraphQLInputType?)
101+
public typealias VariableUsage = (node: Variable, type: GraphQLInputType?)
102102

103103
/**
104104
* An instance of this class is passed as the "this" context to all validators,
105105
* allowing access to commonly useful contextual information from within a
106106
* validation rule.
107107
*/
108-
final class ValidationContext {
109-
let schema: GraphQLSchema
108+
public final class ValidationContext {
109+
public let schema: GraphQLSchema
110110
let ast: Document
111111
let typeInfo: TypeInfo
112112
var errors: [GraphQLError]
@@ -128,11 +128,11 @@ final class ValidationContext {
128128
self.recursiveVariableUsages = [:]
129129
}
130130

131-
func report(error: GraphQLError) {
131+
public func report(error: GraphQLError) {
132132
errors.append(error)
133133
}
134134

135-
func getFragment(name: String) -> FragmentDefinition? {
135+
public func getFragment(name: String) -> FragmentDefinition? {
136136
var fragments = self.fragments
137137

138138
if fragments.isEmpty {
@@ -152,7 +152,7 @@ final class ValidationContext {
152152
return fragments[name]
153153
}
154154

155-
func getFragmentSpreads(node: SelectionSet) -> [FragmentSpread] {
155+
public func getFragmentSpreads(node: SelectionSet) -> [FragmentSpread] {
156156
var spreads = fragmentSpreads[node]
157157

158158
if spreads == nil {
@@ -181,7 +181,7 @@ final class ValidationContext {
181181
return spreads!
182182
}
183183

184-
func getRecursivelyReferencedFragments(operation: OperationDefinition) -> [FragmentDefinition] {
184+
public func getRecursivelyReferencedFragments(operation: OperationDefinition) -> [FragmentDefinition] {
185185
var fragments = recursivelyReferencedFragments[operation]
186186

187187
if fragments == nil {
@@ -210,7 +210,7 @@ final class ValidationContext {
210210
return fragments!
211211
}
212212

213-
func getVariableUsages(node: HasSelectionSet) -> [VariableUsage] {
213+
public func getVariableUsages(node: HasSelectionSet) -> [VariableUsage] {
214214
var usages = variableUsages[node]
215215

216216
if usages == nil {
@@ -236,7 +236,7 @@ final class ValidationContext {
236236
return usages!
237237
}
238238

239-
func getRecursiveVariableUsages(operation: OperationDefinition) -> [VariableUsage] {
239+
public func getRecursiveVariableUsages(operation: OperationDefinition) -> [VariableUsage] {
240240
var usages = recursiveVariableUsages[operation]
241241

242242
if usages == nil {
@@ -254,27 +254,27 @@ final class ValidationContext {
254254
return usages!
255255
}
256256

257-
var type: GraphQLOutputType? {
257+
public var type: GraphQLOutputType? {
258258
return typeInfo.type
259259
}
260260

261-
var parentType: GraphQLCompositeType? {
261+
public var parentType: GraphQLCompositeType? {
262262
return typeInfo.parentType
263263
}
264264

265-
var inputType: GraphQLInputType? {
265+
public var inputType: GraphQLInputType? {
266266
return typeInfo.inputType
267267
}
268268

269-
var fieldDef: GraphQLFieldDefinition? {
269+
public var fieldDef: GraphQLFieldDefinition? {
270270
return typeInfo.fieldDef
271271
}
272272

273-
var directive: GraphQLDirective? {
273+
public var directive: GraphQLDirective? {
274274
return typeInfo.directive
275275
}
276276

277-
var argument: GraphQLArgumentDefinition? {
277+
public var argument: GraphQLArgumentDefinition? {
278278
return typeInfo.argument
279279
}
280280
}

0 commit comments

Comments
 (0)