diff --git a/README.md b/README.md index 2cb0bf2f..62a4f239 100644 --- a/README.md +++ b/README.md @@ -74,16 +74,8 @@ app.listen(4000); const express = require('express'); const { graphqlHTTP } = require('express-graphql'); -const typeDefs = require('./schema'); -const resolvers = require('./resolvers'); -const { makeExecutableSchema } = require('graphql-tools'); -const schema = makeExecutableSchema({ - typeDefs: typeDefs, - resolvers: resolvers, -}); - -const { execute, subscribe } = require('graphql'); const { createServer } = require('http'); +const { execute, subscribe } = require('graphql'); const { SubscriptionServer } = require('subscriptions-transport-ws'); const PORT = 4000; @@ -93,7 +85,7 @@ var app = express(); app.use( '/graphql', graphqlHTTP({ - schema: schema, + schema: MyGraphQLSchema, graphiql: { subscriptionEndpoint: `ws://localhost:${PORT}/subscriptions` }, }), ); @@ -102,7 +94,7 @@ const ws = createServer(app); ws.listen(PORT, () => { // Set up the WebSocket for handling GraphQL subscriptions. - new SubscriptionServer( + SubscriptionServer.create( { execute, subscribe, @@ -142,9 +134,9 @@ The `graphqlHTTP` function accepts the following options: - **`headers`**: An optional string of initial state for the header editor. Only makes sense if headerEditorEnabled is `true`. Defaults to empty. - - **`subscriptionEndpoint`**: An optional GraphQL string contains the WebSocket server url for subscription. + - **`subscriptionEndpoint`**: An optional string contains the WebSocket server url for subscription. - - **`websocketClient`**: An optional GraphQL string for websocket client used for subscription, `v0`: subscriptions-transport-ws, `v1`: graphql-ws. Defaults to `v0` if not provided + - **`websocketClient`**: An optional string for websocket client used for subscription, `v0`: subscriptions-transport-ws, `v1`: graphql-ws. Defaults to `v0` if not provided - **`rootValue`**: A value to pass as the `rootValue` to the `execute()` function from [`GraphQL.js/src/execute.ts`](https://github.com/graphql/graphql-js/blob/main/src/execution/execute.ts#L148). diff --git a/examples/index.ts b/examples/index.ts index cb742cf1..015822df 100644 --- a/examples/index.ts +++ b/examples/index.ts @@ -1,28 +1,72 @@ +import { createServer } from 'http'; + import express from 'express'; -import { buildSchema } from 'graphql'; +import { execute, subscribe, buildSchema } from 'graphql'; +import { SubscriptionServer } from 'subscriptions-transport-ws'; import { graphqlHTTP } from '../src'; // Construct a schema, using GraphQL schema language const schema = buildSchema(` type Query { - hello: String + hello: String! + } + + type Subscription { + currentTime: String! } `); // The root provides a resolver function for each API endpoint const rootValue = { hello: () => 'Hello world!', + currentTime: () => currentTimeGenerator(), }; +async function* currentTimeGenerator() { + while (true) { + const currentTime = (new Date()).toLocaleTimeString(); + console.log('Pushed current time over subscriptions: ' + currentTime); + yield { currentTime }; + + await later(1); + } +} + +function later(delayInSeconds: number) { + return new Promise((resolve) => setTimeout(resolve, delayInSeconds * 1000)); +} + +const PORT = 4001; const app = express(); app.use( '/graphql', graphqlHTTP({ schema, rootValue, - graphiql: { headerEditorEnabled: true }, + graphiql: { + headerEditorEnabled: true, + subscriptionEndpoint: `ws://localhost:${PORT}/subscriptions`, + }, }), ); -app.listen(4000); -console.log('Running a GraphQL API server at http://localhost:4000/graphql'); + +const ws = createServer(app); + +ws.listen(PORT, () => { + // Set up the WebSocket for handling GraphQL subscriptions. + SubscriptionServer.create( + { + execute, + subscribe, + schema, + rootValue, + }, + { + server: ws, + path: '/subscriptions', + }, + ); +}); + +console.log(`Running a GraphQL API server at http://localhost:${PORT}/graphql`); diff --git a/examples/index_subscription.ts b/examples/index_subscription.ts deleted file mode 100644 index 553a464e..00000000 --- a/examples/index_subscription.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { createServer } from 'http'; - -import express from 'express'; -import { execute, subscribe } from 'graphql'; -import ws from 'ws'; -import { useServer } from 'graphql-ws/lib/use/ws'; - -import { graphqlHTTP } from '../src'; - -import { schema, roots, rootValue } from './schema'; - -const PORT = 4000; -const subscriptionEndpoint = `ws://localhost:${PORT}/subscriptions`; - -const app = express(); -app.use( - '/graphql', - graphqlHTTP({ - schema, - rootValue, - graphiql: { - subscriptionEndpoint, - websocketClient: 'v1', - }, - }), -); - -const server = createServer(app); - -const wsServer = new ws.Server({ - server, - path: '/subscriptions', -}); - -server.listen(PORT, () => { - useServer( - { - schema, - roots, - execute, - subscribe, - }, - wsServer, - ); - console.info( - `Running a GraphQL API server with subscriptions at http://localhost:${PORT}/graphql`, - ); -}); diff --git a/examples/index_subscription_legacy.ts b/examples/index_subscription_legacy.ts deleted file mode 100644 index 2cd6d8ba..00000000 --- a/examples/index_subscription_legacy.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { createServer } from 'http'; - -import express from 'express'; -import { execute, subscribe } from 'graphql'; -import { SubscriptionServer } from 'subscriptions-transport-ws'; - -import { graphqlHTTP } from '../src'; - -import { schema, rootValue } from './schema'; - -const PORT = 4000; -const subscriptionEndpoint = `ws://localhost:${PORT}/subscriptions`; - -const app = express(); -app.use( - '/graphql', - graphqlHTTP({ - schema, - rootValue, - graphiql: { subscriptionEndpoint }, - }), -); - -const ws = createServer(app); - -ws.listen(PORT, () => { - console.log( - `Running a GraphQL API server with subscriptions at http://localhost:${PORT}/graphql`, - ); -}); - -const onConnect = (_: any, __: any) => { - console.log('connecting ....'); -}; - -const onDisconnect = (_: any) => { - console.log('disconnecting ...'); -}; - -SubscriptionServer.create( - { - schema, - rootValue, - execute, - subscribe, - onConnect, - onDisconnect, - }, - { - server: ws, - path: '/subscriptions', - }, -); diff --git a/examples/schema.ts b/examples/schema.ts deleted file mode 100644 index 98e55cad..00000000 --- a/examples/schema.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { buildSchema } from 'graphql'; - -function sleep(ms: number) { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); -} - -export const schema = buildSchema(` -type Query { - hello: String -} -type Subscription { - countDown: Int -} -`); - -export const roots = { - Query: { - hello: () => 'Hello World!', - }, - subscription: { - /* eslint no-await-in-loop: "off" */ - - countDown: async function* fiveToOne() { - for (const number of [5, 4, 3, 2, 1]) { - await sleep(1000); // slow down a bit so user can see the count down on GraphiQL - yield { countDown: number }; - } - }, - }, -}; - -export const rootValue = { - hello: roots.Query.hello, - countDown: roots.subscription.countDown, -}; diff --git a/package.json b/package.json index 0313b6af..8f71a049 100644 --- a/package.json +++ b/package.json @@ -48,9 +48,7 @@ "check:spelling": "cspell '**/*'", "check:integrations": "mocha --full-trace integrationTests/*-test.js", "build:npm": "node resources/build-npm.js", - "start": "node -r ./resources/register.js examples/index.ts", - "start:subscription": "node -r ./resources/register.js examples/index_subscription.ts", - "start:subscription_legacy": "node -r ./resources/register.js examples/index_subscription_legacy.ts" + "start": "node -r ./resources/register.js examples/index.ts" }, "dependencies": { "accepts": "^1.3.7", @@ -100,7 +98,6 @@ "react-dom": "16.14.0", "restify": "8.5.1", "sinon": "9.2.1", - "subscriptions-transport-ws": "0.9.18", "supertest": "6.0.1", "ts-node": "9.0.0", "typescript": "4.1.2",