Skip to content

Commit e7f4f5f

Browse files
viglucciOlegDokuka
andauthored
feat: add rsocket-graphql-apollo-link & rsocket-graphql-apollo-server (#225)
Signed-off-by: Kevin Viglucci <kviglucci@gmail.com> Co-authored-by: Oleh Dokuka <5380167+OlegDokuka@users.noreply.github.com>
1 parent e9d5267 commit e7f4f5f

27 files changed

+8124
-6009
lines changed

RELEASE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ How to publish new releases for this project.
88

99
You can either set versions in the `package.json` files manually, or use the `lerna version` command to set them via the Lerna CLI. When setting versions manually, you will also need to set the git tags for each package and version. For this reason, it is recommended you use the `lerna version` command, which will create these tags automatically.
1010

11-
ex: `@rsocket/adapter-rxjs@1.0.0-alpha.1`
11+
ex: `rsocket-adapter-rxjs@1.0.0-alpha.1`
1212

1313
Lerna will not push the git tags after creation. You should push the git tags once you are confident in your changes.
1414

packages/rsocket-examples/package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,14 @@
1919
"start-client-server-request-response-websocket": "ts-node -r tsconfig-paths/register src/ClientServerRequestResponseExampleWebSocket.ts",
2020
"start-client-server-composite-metadata-route": "ts-node -r tsconfig-paths/register src/ClientServerCompositeMetadataRouteExample.ts",
2121
"start-client-server-rxjs-messaging-composite-metadata-route": "ts-node -r tsconfig-paths/register src/rxjs/RxjsMessagingCompositeMetadataRouteExample.ts",
22-
"start-client-server-rxjs-requester-responder": "ts-node -r tsconfig-paths/register src/rxjs/RxjsRequesterResponderExample.ts"
22+
"start-client-server-rxjs-requester-responder": "ts-node -r tsconfig-paths/register src/rxjs/RxjsRequesterResponderExample.ts",
23+
"start-client-apollo-graphql": "ts-node -r tsconfig-paths/register src/graphql/apollo/client/example.ts",
24+
"start-client-server-apollo-graphql": "ts-node -r tsconfig-paths/register src/graphql/apollo/client-server/example.ts"
2325
},
2426
"dependencies": {
27+
"@apollo/client": "^3.5.10",
28+
"graphql-tag": "^2.12.6",
29+
"graphql-subscriptions": "^2.0.0",
2530
"rsocket-adapter-rxjs": "^1.0.0-alpha.4",
2631
"rsocket-composite-metadata": "^1.0.0-alpha.3",
2732
"rsocket-core": "^1.0.0-alpha.3",
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*
2+
* Copyright 2021-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { RSocket, RSocketConnector, RSocketServer } from "rsocket-core";
18+
import { TcpClientTransport } from "rsocket-tcp-client";
19+
import { TcpServerTransport } from "rsocket-tcp-server";
20+
import { exit } from "process";
21+
import { makeRSocketLink } from "rsocket-graphql-apollo-link";
22+
import { RSocketApolloServer } from "rsocket-graphql-apollo-server";
23+
import {
24+
ApolloClient,
25+
InMemoryCache,
26+
NormalizedCacheObject,
27+
} from "@apollo/client/core";
28+
import gql from "graphql-tag";
29+
import { resolvers } from "./resolvers";
30+
import { DocumentNode } from "@apollo/client";
31+
import * as fs from "fs";
32+
import path from "path";
33+
import { RSocketApolloGraphlQLPlugin } from "rsocket-graphql-apollo-server/src/RSocketApolloGraphlQLPlugin";
34+
35+
let apolloServer: RSocketApolloServer;
36+
let rsocketClient: RSocket;
37+
38+
function readSchema() {
39+
return fs.readFileSync(path.join(__dirname, "schema.graphql"), {
40+
encoding: "utf8",
41+
});
42+
}
43+
44+
function makeRSocketServer({ handler }) {
45+
return new RSocketServer({
46+
transport: new TcpServerTransport({
47+
listenOptions: {
48+
port: 9090,
49+
host: "127.0.0.1",
50+
},
51+
}),
52+
acceptor: {
53+
accept: async () => handler,
54+
},
55+
});
56+
}
57+
58+
function makeRSocketConnector() {
59+
return new RSocketConnector({
60+
transport: new TcpClientTransport({
61+
connectionOptions: {
62+
host: "127.0.0.1",
63+
port: 9090,
64+
},
65+
}),
66+
});
67+
}
68+
69+
function makeApolloServer({ typeDefs, resolvers }) {
70+
const plugin = new RSocketApolloGraphlQLPlugin({ makeRSocketServer });
71+
const server = new RSocketApolloServer({
72+
typeDefs,
73+
resolvers,
74+
plugins: [() => plugin],
75+
});
76+
plugin.setApolloServer(server);
77+
return server;
78+
}
79+
80+
function makeApolloClient({ rsocketClient }) {
81+
return new ApolloClient({
82+
cache: new InMemoryCache(),
83+
link: makeRSocketLink({
84+
rsocket: rsocketClient,
85+
}),
86+
});
87+
}
88+
89+
async function sendMessage(
90+
client: ApolloClient<NormalizedCacheObject>,
91+
{ message }: { message: String }
92+
) {
93+
console.log("Sending message", { message });
94+
await client.mutate({
95+
variables: {
96+
message,
97+
},
98+
mutation: gql`
99+
mutation CreateMessage($message: String) {
100+
createMessage(message: $message) {
101+
message
102+
}
103+
}
104+
`,
105+
});
106+
}
107+
108+
function subcribe(
109+
client: ApolloClient<NormalizedCacheObject>,
110+
variables: Record<any, any>,
111+
query: DocumentNode
112+
) {
113+
return client.subscribe({
114+
variables,
115+
query,
116+
});
117+
}
118+
119+
async function main() {
120+
// server setup
121+
const typeDefs = readSchema();
122+
apolloServer = makeApolloServer({ typeDefs, resolvers });
123+
await apolloServer.start();
124+
125+
// client setup
126+
const connector = makeRSocketConnector();
127+
rsocketClient = await connector.connect();
128+
129+
const apolloClient = makeApolloClient({ rsocketClient });
130+
131+
console.log("\nSubscribing to messages.");
132+
let subscription = subcribe(
133+
apolloClient,
134+
{},
135+
gql`
136+
subscription ChannelMessages {
137+
messageCreated {
138+
message
139+
}
140+
}
141+
`
142+
).subscribe({
143+
next(data) {
144+
console.log("subscription event:", data);
145+
},
146+
error(err) {
147+
console.log(`subscription error: ${err}`);
148+
},
149+
complete() {},
150+
});
151+
152+
await sendMessage(apolloClient, {
153+
message: "my first message",
154+
});
155+
156+
await sendMessage(apolloClient, {
157+
message: "my second message",
158+
});
159+
160+
await sendMessage(apolloClient, {
161+
message: "my third message",
162+
});
163+
164+
subscription.unsubscribe();
165+
}
166+
167+
main()
168+
.catch((error: Error) => {
169+
console.error(error);
170+
exit(1);
171+
})
172+
.finally(async () => {
173+
await apolloServer.stop();
174+
rsocketClient.close();
175+
});
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2021-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
import { PubSub } from "graphql-subscriptions";
17+
18+
const pubsub = new PubSub();
19+
20+
export const resolvers = {
21+
Query: {
22+
echo: (parent, args, context, info) => {
23+
const { message } = args;
24+
return {
25+
message,
26+
};
27+
},
28+
},
29+
Mutation: {
30+
createMessage: async (_, { message }, context, info) => {
31+
await pubsub.publish("POST_CREATED", {
32+
messageCreated: {
33+
message,
34+
},
35+
});
36+
},
37+
},
38+
Subscription: {
39+
messageCreated: {
40+
// subscribe must return an AsyncIterator
41+
// https://www.apollographql.com/docs/apollo-server/data/subscriptions/#resolving-a-subscription
42+
subscribe: () => pubsub.asyncIterator(["POST_CREATED"]),
43+
},
44+
},
45+
};
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""
2+
Copyright 2021-2022 the original author or authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
"""
16+
17+
type ChatMessage {
18+
message: String
19+
}
20+
21+
type Query {
22+
echo(message: String): ChatMessage
23+
}
24+
25+
type Mutation {
26+
createMessage(message: String): ChatMessage
27+
}
28+
29+
type Subscription {
30+
messageCreated: ChatMessage
31+
}

0 commit comments

Comments
 (0)