Skip to content

Commit

Permalink
feat: add rsocket-graphql-apollo-link & rsocket-graphql-apollo-server (
Browse files Browse the repository at this point in the history
…#225)


Signed-off-by: Kevin Viglucci <[email protected]>
Co-authored-by: Oleh Dokuka <[email protected]>
  • Loading branch information
viglucci and OlegDokuka authored Apr 29, 2023
1 parent e9d5267 commit e7f4f5f
Show file tree
Hide file tree
Showing 27 changed files with 8,124 additions and 6,009 deletions.
2 changes: 1 addition & 1 deletion RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ How to publish new releases for this project.

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.

ex: `@rsocket/[email protected]`
ex: `rsocket-[email protected]`

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

Expand Down
7 changes: 6 additions & 1 deletion packages/rsocket-examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,14 @@
"start-client-server-request-response-websocket": "ts-node -r tsconfig-paths/register src/ClientServerRequestResponseExampleWebSocket.ts",
"start-client-server-composite-metadata-route": "ts-node -r tsconfig-paths/register src/ClientServerCompositeMetadataRouteExample.ts",
"start-client-server-rxjs-messaging-composite-metadata-route": "ts-node -r tsconfig-paths/register src/rxjs/RxjsMessagingCompositeMetadataRouteExample.ts",
"start-client-server-rxjs-requester-responder": "ts-node -r tsconfig-paths/register src/rxjs/RxjsRequesterResponderExample.ts"
"start-client-server-rxjs-requester-responder": "ts-node -r tsconfig-paths/register src/rxjs/RxjsRequesterResponderExample.ts",
"start-client-apollo-graphql": "ts-node -r tsconfig-paths/register src/graphql/apollo/client/example.ts",
"start-client-server-apollo-graphql": "ts-node -r tsconfig-paths/register src/graphql/apollo/client-server/example.ts"
},
"dependencies": {
"@apollo/client": "^3.5.10",
"graphql-tag": "^2.12.6",
"graphql-subscriptions": "^2.0.0",
"rsocket-adapter-rxjs": "^1.0.0-alpha.4",
"rsocket-composite-metadata": "^1.0.0-alpha.3",
"rsocket-core": "^1.0.0-alpha.3",
Expand Down
175 changes: 175 additions & 0 deletions packages/rsocket-examples/src/graphql/apollo/client-server/example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/*
* Copyright 2021-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { RSocket, RSocketConnector, RSocketServer } from "rsocket-core";
import { TcpClientTransport } from "rsocket-tcp-client";
import { TcpServerTransport } from "rsocket-tcp-server";
import { exit } from "process";
import { makeRSocketLink } from "rsocket-graphql-apollo-link";
import { RSocketApolloServer } from "rsocket-graphql-apollo-server";
import {
ApolloClient,
InMemoryCache,
NormalizedCacheObject,
} from "@apollo/client/core";
import gql from "graphql-tag";
import { resolvers } from "./resolvers";
import { DocumentNode } from "@apollo/client";
import * as fs from "fs";
import path from "path";
import { RSocketApolloGraphlQLPlugin } from "rsocket-graphql-apollo-server/src/RSocketApolloGraphlQLPlugin";

let apolloServer: RSocketApolloServer;
let rsocketClient: RSocket;

function readSchema() {
return fs.readFileSync(path.join(__dirname, "schema.graphql"), {
encoding: "utf8",
});
}

function makeRSocketServer({ handler }) {
return new RSocketServer({
transport: new TcpServerTransport({
listenOptions: {
port: 9090,
host: "127.0.0.1",
},
}),
acceptor: {
accept: async () => handler,
},
});
}

function makeRSocketConnector() {
return new RSocketConnector({
transport: new TcpClientTransport({
connectionOptions: {
host: "127.0.0.1",
port: 9090,
},
}),
});
}

function makeApolloServer({ typeDefs, resolvers }) {
const plugin = new RSocketApolloGraphlQLPlugin({ makeRSocketServer });
const server = new RSocketApolloServer({
typeDefs,
resolvers,
plugins: [() => plugin],
});
plugin.setApolloServer(server);
return server;
}

function makeApolloClient({ rsocketClient }) {
return new ApolloClient({
cache: new InMemoryCache(),
link: makeRSocketLink({
rsocket: rsocketClient,
}),
});
}

async function sendMessage(
client: ApolloClient<NormalizedCacheObject>,
{ message }: { message: String }
) {
console.log("Sending message", { message });
await client.mutate({
variables: {
message,
},
mutation: gql`
mutation CreateMessage($message: String) {
createMessage(message: $message) {
message
}
}
`,
});
}

function subcribe(
client: ApolloClient<NormalizedCacheObject>,
variables: Record<any, any>,
query: DocumentNode
) {
return client.subscribe({
variables,
query,
});
}

async function main() {
// server setup
const typeDefs = readSchema();
apolloServer = makeApolloServer({ typeDefs, resolvers });
await apolloServer.start();

// client setup
const connector = makeRSocketConnector();
rsocketClient = await connector.connect();

const apolloClient = makeApolloClient({ rsocketClient });

console.log("\nSubscribing to messages.");
let subscription = subcribe(
apolloClient,
{},
gql`
subscription ChannelMessages {
messageCreated {
message
}
}
`
).subscribe({
next(data) {
console.log("subscription event:", data);
},
error(err) {
console.log(`subscription error: ${err}`);
},
complete() {},
});

await sendMessage(apolloClient, {
message: "my first message",
});

await sendMessage(apolloClient, {
message: "my second message",
});

await sendMessage(apolloClient, {
message: "my third message",
});

subscription.unsubscribe();
}

main()
.catch((error: Error) => {
console.error(error);
exit(1);
})
.finally(async () => {
await apolloServer.stop();
rsocketClient.close();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2021-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { PubSub } from "graphql-subscriptions";

const pubsub = new PubSub();

export const resolvers = {
Query: {
echo: (parent, args, context, info) => {
const { message } = args;
return {
message,
};
},
},
Mutation: {
createMessage: async (_, { message }, context, info) => {
await pubsub.publish("POST_CREATED", {
messageCreated: {
message,
},
});
},
},
Subscription: {
messageCreated: {
// subscribe must return an AsyncIterator
// https://www.apollographql.com/docs/apollo-server/data/subscriptions/#resolving-a-subscription
subscribe: () => pubsub.asyncIterator(["POST_CREATED"]),
},
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""
Copyright 2021-2022 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

type ChatMessage {
message: String
}

type Query {
echo(message: String): ChatMessage
}

type Mutation {
createMessage(message: String): ChatMessage
}

type Subscription {
messageCreated: ChatMessage
}
Loading

0 comments on commit e7f4f5f

Please sign in to comment.