Skip to content

Commit 31ae3b0

Browse files
Makes Client/Server callback dynamic
This allows self-referencing and simplifies creation.
1 parent 47ebc0b commit 31ae3b0

File tree

3 files changed

+133
-105
lines changed

3 files changed

+133
-105
lines changed

Sources/GraphQLWS/Client.swift

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ import GraphQL
88
class Client {
99
let messenger: Messenger
1010

11-
let onMessage: (String) -> Void
12-
let onConnectionError: (ConnectionErrorResponse) -> Void
13-
let onConnectionAck: (ConnectionAckResponse) -> Void
14-
let onConnectionKeepAlive: (ConnectionKeepAliveResponse) -> Void
15-
let onData: (DataResponse) -> Void
16-
let onError: (ErrorResponse) -> Void
17-
let onComplete: (CompleteResponse) -> Void
11+
var onConnectionError: (ConnectionErrorResponse) -> Void = { _ in }
12+
var onConnectionAck: (ConnectionAckResponse) -> Void = { _ in }
13+
var onConnectionKeepAlive: (ConnectionKeepAliveResponse) -> Void = { _ in }
14+
var onData: (DataResponse) -> Void = { _ in }
15+
var onError: (ErrorResponse) -> Void = { _ in }
16+
var onComplete: (CompleteResponse) -> Void = { _ in }
17+
var onMessage: (String) -> Void = { _ in }
1818

1919
let encoder = GraphQLJSONEncoder()
2020
let decoder = JSONDecoder()
@@ -23,30 +23,10 @@ class Client {
2323
///
2424
/// - Parameters:
2525
/// - messenger: The messenger to bind the client to.
26-
/// - onConnectionError: Callback run on receipt of a `connection_error` message
27-
/// - onConnectionAck: Callback run on receipt of a `connection_ack` message
28-
/// - onData: Callback run on receipt of a `data` message
29-
/// - onError: Callback run on receipt of an `error` message
30-
/// - onComplete: Callback run on receipt of a `complete` message
31-
/// - onMessage: Callback run on receipt of any message
3226
init(
33-
messenger: Messenger,
34-
onConnectionError: @escaping (ConnectionErrorResponse) -> Void = { _ in () },
35-
onConnectionAck: @escaping (ConnectionAckResponse) -> Void = { _ in () },
36-
onConnectionKeepAlive: @escaping (ConnectionKeepAliveResponse) -> Void = { _ in () },
37-
onData: @escaping (DataResponse) -> Void = { _ in () },
38-
onError: @escaping (ErrorResponse) -> Void = { _ in () },
39-
onComplete: @escaping (CompleteResponse) -> Void = { _ in () },
40-
onMessage: @escaping (String) -> Void = { _ in () }
27+
messenger: Messenger
4128
) {
4229
self.messenger = messenger
43-
self.onMessage = onMessage
44-
self.onConnectionError = onConnectionError
45-
self.onConnectionAck = onConnectionAck
46-
self.onConnectionKeepAlive = onConnectionKeepAlive
47-
self.onData = onData
48-
self.onError = onError
49-
self.onComplete = onComplete
5030

5131
self.messenger.onRecieve { [weak self] message in
5232
guard let self = self else { return }
@@ -125,6 +105,48 @@ class Client {
125105
}
126106
}
127107

108+
/// Define the callback run on receipt of a `connection_error` message
109+
/// - Parameter callback: The callback to assign
110+
func onConnectionError(_ callback: @escaping (ConnectionErrorResponse) -> Void) {
111+
self.onConnectionError = callback
112+
}
113+
114+
/// Define the callback run on receipt of a `connection_ack` message
115+
/// - Parameter callback: The callback to assign
116+
func onConnectionAck(_ callback: @escaping (ConnectionAckResponse) -> Void) {
117+
self.onConnectionAck = callback
118+
}
119+
120+
/// Define the callback run on receipt of a `connection_ka` message
121+
/// - Parameter callback: The callback to assign
122+
func onConnectionKeepAlive(_ callback: @escaping (ConnectionKeepAliveResponse) -> Void) {
123+
self.onConnectionKeepAlive = callback
124+
}
125+
126+
/// Define the callback run on receipt of a `data` message
127+
/// - Parameter callback: The callback to assign
128+
func onData(_ callback: @escaping (DataResponse) -> Void) {
129+
self.onData = callback
130+
}
131+
132+
/// Define the callback run on receipt of an `error` message
133+
/// - Parameter callback: The callback to assign
134+
func onError(_ callback: @escaping (ErrorResponse) -> Void) {
135+
self.onError = callback
136+
}
137+
138+
/// Define the callback run on receipt of any message
139+
/// - Parameter callback: The callback to assign
140+
func onComplete(_ callback: @escaping (CompleteResponse) -> Void) {
141+
self.onComplete = callback
142+
}
143+
144+
/// Define the callback run on receipt of a `complete` message
145+
/// - Parameter callback: The callback to assign
146+
func onMessage(_ callback: @escaping (String) -> Void) {
147+
self.onMessage = callback
148+
}
149+
128150
/// Send a `connection_init` request through the messenger
129151
func sendConnectionInit(payload: ConnectionInitAuth?) {
130152
messenger.send(

Sources/GraphQLWS/Server.swift

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ import RxSwift
1111
class Server {
1212
let messenger: Messenger
1313

14-
let auth: (ConnectionInitRequest) throws -> Void
1514
let onExecute: (GraphQLRequest) -> EventLoopFuture<GraphQLResult>
1615
let onSubscribe: (GraphQLRequest) -> EventLoopFuture<SubscriptionResult>
17-
let onExit: () -> Void
18-
let onMessage: (String) -> Void
16+
17+
var auth: (ConnectionInitRequest) throws -> Void = { _ in }
18+
var onExit: () -> Void = { }
19+
var onMessage: (String) -> Void = { _ in }
1920

2021
var initialized = false
2122

@@ -27,25 +28,16 @@ class Server {
2728
///
2829
/// - Parameters:
2930
/// - messenger: The messenger to bind the server to.
30-
/// - auth: Callback run during `connection_init` resolution that allows authorization using the `payload`. Throw to indicate that authorization has failed.
3131
/// - onExecute: Callback run during `start` resolution for non-streaming queries. Typically this is `API.execute`.
3232
/// - onSubscribe: Callback run during `start` resolution for streaming queries. Typically this is `API.subscribe`.
33-
/// - onExit: Callback run when the communication is shut down, either by the client or server
34-
/// - onMessage: callback run on receipt of any message
3533
init(
3634
messenger: Messenger,
37-
auth: @escaping (ConnectionInitRequest) throws -> Void,
3835
onExecute: @escaping (GraphQLRequest) -> EventLoopFuture<GraphQLResult>,
39-
onSubscribe: @escaping (GraphQLRequest) -> EventLoopFuture<SubscriptionResult>,
40-
onExit: @escaping () -> Void,
41-
onMessage: @escaping (String) -> Void = { _ in () }
36+
onSubscribe: @escaping (GraphQLRequest) -> EventLoopFuture<SubscriptionResult>
4237
) {
4338
self.messenger = messenger
44-
self.auth = auth
4539
self.onExecute = onExecute
4640
self.onSubscribe = onSubscribe
47-
self.onExit = onExit
48-
self.onMessage = onMessage
4941

5042
self.messenger.onRecieve { [weak self] message in
5143
guard let self = self else { return }
@@ -116,6 +108,25 @@ class Server {
116108
// }
117109
}
118110

111+
/// Define the callback run during `connection_init` resolution that allows authorization using the `payload`.
112+
/// Throw to indicate that authorization has failed.
113+
/// - Parameter callback: The callback to assign
114+
func auth(_ callback: @escaping (ConnectionInitRequest) throws -> Void) {
115+
self.auth = callback
116+
}
117+
118+
/// Define the callback run when the communication is shut down, either by the client or server
119+
/// - Parameter callback: The callback to assign
120+
func onExit(_ callback: @escaping () -> Void) {
121+
self.onExit = callback
122+
}
123+
124+
/// Define the callback run on receipt of any message
125+
/// - Parameter callback: The callback to assign
126+
func onMessage(_ callback: @escaping (String) -> Void) {
127+
self.onMessage = callback
128+
}
129+
119130
private func onConnectionInit(_ connectionInitRequest: ConnectionInitRequest) {
120131
guard !initialized else {
121132
let error = GraphQLWSError.tooManyInitializations()

Tests/GraphQLWSTests/GraphQLWSTests.swift

Lines changed: 59 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ class GraphqlWsTests: XCTestCase {
2525

2626
server = Server(
2727
messenger: serverMessenger,
28-
auth: { _ in },
2928
onExecute: { graphQLRequest in
3029
api.execute(
3130
request: graphQLRequest.query,
@@ -39,43 +38,41 @@ class GraphqlWsTests: XCTestCase {
3938
context: context,
4039
on: eventLoop
4140
)
42-
},
43-
onExit: {}
41+
}
4442
)
4543
}
4644

4745
func testSingleOp() throws {
48-
let encoder = GraphQLJSONEncoder()
4946
let id = UUID().description
5047

5148
// Test single-op conversation
5249
var messages = [String]()
5350
let completeExpectation = XCTestExpectation()
5451

55-
let client = Client(
56-
messenger: clientMessenger,
57-
onConnectionAck: { _ in
58-
self.clientMessenger.send(StartRequest(
59-
payload: GraphQLRequest(
60-
query: """
61-
query {
62-
hello
63-
}
64-
"""
65-
),
66-
id: id
67-
).toJSON(encoder))
68-
},
69-
onError: { _ in
70-
completeExpectation.fulfill()
71-
},
72-
onComplete: { _ in
73-
completeExpectation.fulfill()
74-
},
75-
onMessage: { message in
76-
messages.append(message)
77-
}
78-
)
52+
let client = Client(messenger: clientMessenger)
53+
54+
client.onConnectionAck { [weak client] _ in
55+
guard let client = client else { return }
56+
client.sendStart(
57+
payload: GraphQLRequest(
58+
query: """
59+
query {
60+
hello
61+
}
62+
"""
63+
),
64+
id: id
65+
)
66+
}
67+
client.onError { _ in
68+
completeExpectation.fulfill()
69+
}
70+
client.onComplete { _ in
71+
completeExpectation.fulfill()
72+
}
73+
client.onMessage { message in
74+
messages.append(message)
75+
}
7976

8077
client.sendConnectionInit(payload: ConnectionInitAuth(authToken: ""))
8178

@@ -88,7 +85,6 @@ class GraphqlWsTests: XCTestCase {
8885
}
8986

9087
func testStreaming() throws {
91-
let encoder = GraphQLJSONEncoder()
9288
let id = UUID().description
9389

9490
// Test streaming conversation
@@ -98,43 +94,42 @@ class GraphqlWsTests: XCTestCase {
9894
var dataIndex = 1
9995
let dataIndexMax = 3
10096

101-
let client = Client(
102-
messenger: clientMessenger,
103-
onConnectionAck: { _ in
104-
self.clientMessenger.send(StartRequest(
105-
payload: GraphQLRequest(
106-
query: """
107-
subscription {
108-
hello
109-
}
110-
"""
111-
),
112-
id: id
113-
).toJSON(encoder))
114-
115-
// Short sleep to allow for server to register subscription
116-
usleep(3000)
117-
97+
let client = Client(messenger: clientMessenger)
98+
client.onConnectionAck { [weak client] _ in
99+
guard let client = client else { return }
100+
client.sendStart(
101+
payload: GraphQLRequest(
102+
query: """
103+
subscription {
104+
hello
105+
}
106+
"""
107+
),
108+
id: id
109+
)
110+
111+
// Short sleep to allow for server to register subscription
112+
usleep(3000)
113+
114+
pubsub.onNext("hello \(dataIndex)")
115+
}
116+
client.onData { _ in
117+
dataIndex = dataIndex + 1
118+
if dataIndex <= dataIndexMax {
118119
pubsub.onNext("hello \(dataIndex)")
119-
},
120-
onData: { _ in
121-
dataIndex = dataIndex + 1
122-
if dataIndex <= dataIndexMax {
123-
pubsub.onNext("hello \(dataIndex)")
124-
} else {
125-
pubsub.onCompleted()
126-
}
127-
},
128-
onError: { _ in
129-
completeExpectation.fulfill()
130-
},
131-
onComplete: { _ in
132-
completeExpectation.fulfill()
133-
},
134-
onMessage: { message in
135-
messages.append(message)
120+
} else {
121+
pubsub.onCompleted()
136122
}
137-
)
123+
}
124+
client.onError { _ in
125+
completeExpectation.fulfill()
126+
}
127+
client.onComplete { _ in
128+
completeExpectation.fulfill()
129+
}
130+
client.onMessage { message in
131+
messages.append(message)
132+
}
138133

139134
client.sendConnectionInit(payload: ConnectionInitAuth(authToken: ""))
140135

0 commit comments

Comments
 (0)