diff --git a/.env.example b/.env.example deleted file mode 100644 index 151db3c..0000000 --- a/.env.example +++ /dev/null @@ -1,6 +0,0 @@ -BUCKET_NAME="mybucketname" -CLOUDFLARE_ACCOUNT_ID="" -CLOUDFLARE_AUTH_EMAIL="" -CLOUDFLARE_AUTH_KEY="" -CLOUDFLARE_ZONE_ID="" -WORKER_ROUTE="serverless-workers.signalnerve.com/*" diff --git a/README.md b/README.md index d66460e..f548cc2 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # workers-graphql-server -An [Apollo GraphQL](https://www.apollographql.com/) server, built with [Cloudflare Workers](https://workers.cloudflare.com). Includes a GraphiQL route for testing requests. +An [Apollo GraphQL](https://www.apollographql.com/) server, built with [Cloudflare Workers](https://workers.cloudflare.com). [Try a demo by looking at a deployed GraphQL playground](https://graphql-on-workers.signalnerve.com/___graphql). -[Try a demo by looking at the GraphiQL explorer](https://graphql-on-workers.signalnerve.com/graphiql). +Why this rules: Cloudflare Workers is a serverless application platform for deploying your projects across Cloudflare's massive distributed network. Deploying your GraphQL application to the edge is a huge opportunity to build consistent low-latency API servers, with the added benefits of "serverless" (I know, the project has `server` in it): usage-based pricing, no cold starts, and instant, easy-to-use deployment software, using [Wrangler](https://github.com/cloudflare/wrangler). + +By the way - as a full-stack developer who _loves_ GraphQL, and the developer advocate for Cloudflare Workers, I would love to see what you build with this! Let me know [on Twitter](https://twitter.com/signalnerve)! ## Usage @@ -12,9 +14,26 @@ You can begin building your own Workers GraphQL server by [installing Wrangler]( wrangler generate my-graphql-server https://github.com/signalnerve/workers-graphql-server ``` -The source for this project includes an external REST data source, and defined types for the [PokeAPI](https://pokeapi.co/), as an example of how to integrate external APIs. +You'll need to configure your project's `wrangler.toml` file to prepare your project for deployment. See the docs (["Configuring and Publishing"](https://workers.cloudflare.com/docs/quickstart/configuring-and-publishing/)) for a guide on how to do this. Note that you'll need to [find your Cloudflare API keys](https://workers.cloudflare.com/docs/quickstart/api-keys/) to set up your config file. + +The source for this project includes an example external REST data source, and defined types for the [PokeAPI](https://pokeapi.co/), as an example of how to integrate external APIs. + +To start using the project, configure your `graphQLOptions` object in `src/index.js`: + +```js +const graphQLOptions = { + baseEndpoint: '/', // String + playgroundEndpoint: '/___graphql', // ?String + forwardUnmatchedRequestsToOrigin: false, // Boolean + debug: false, // Boolean +} +``` + +Make requests to your GraphQL server at the `baseEndpoint` (e.g. `graphql-on-workers.signalnerve.com/`) and, if configured, try GraphQL queries at the `playgroundEndpoint` (e.g. `graphql-on-workers.signalnerve.com/___graphql`). + +If you run your GraphQL server on a domain already registered with Cloudflare, you may want to pass any unmatched requests from inside your Workers script to your origin: in that case, set `forwardUnmatchedRequestToOrigin` to true (if you're running a GraphQL server on a [Workers.dev](https://workers.dev) subdomain, the default of `false` is fine). -By the way - as a fullstack developer who _loves GraphQL_, and the developer advocate for Cloudflare Workers, I would love to see what you build with this! Let me know [on Twitter](https://twitter.com/signalnerve)! +Finally, while configuring your server, you may want to set the `debug` flag to `true`, to allow script errors to be returned in your browser. This can be useful for debugging any errors while setting up your GraphQL server. ## License diff --git a/package-lock.json b/package-lock.json index b007be9..701306d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "graphql-on-workers", - "version": "0.1.0", + "version": "1.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index e025564..a5e5dae 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { - "name": "graphql-on-workers", + "name": "{{ project-name }}", "private": true, - "description": "graphql-on-workers", - "version": "0.9.9", - "author": "Kristian Freeman ", + "description": "🔥Lightning-fast, globally distributed Apollo GraphQL server, deployed at the edge using Cloudflare Workers", + "version": "1.1.0", + "author": "{{ authors }}", "dependencies": { "apollo-datasource-rest": "^0.3.2", "apollo-server-cloudflare": "^2.4.8", diff --git a/src/handlers/apollo.js b/src/handlers/apollo.js index 0742ef8..7fc1290 100644 --- a/src/handlers/apollo.js +++ b/src/handlers/apollo.js @@ -44,7 +44,7 @@ const server = new ApolloServer({ }), }) -const handler = request => +const handler = (request, _graphQLOptions) => graphqlCloudflare(() => server.createGraphQLServerOptions(request))(request) module.exports = handler diff --git a/src/handlers/graphiql.js b/src/handlers/graphiql.js deleted file mode 100644 index 7f5d8b6..0000000 --- a/src/handlers/graphiql.js +++ /dev/null @@ -1,147 +0,0 @@ -const html = ` - - - - - - - - - - - - - - - - - -
Loading...
- - - -` - -const headers = { 'Content-Type': 'text/html' } - -const handler = request => new Response(html, { headers }) - -module.exports = handler diff --git a/src/handlers/playground.js b/src/handlers/playground.js new file mode 100644 index 0000000..743b558 --- /dev/null +++ b/src/handlers/playground.js @@ -0,0 +1,497 @@ +const html = baseEndpoint => ` + + + + + + GraphQL Playground + + + + + + + + + +
+ +
Loading + GraphQL Playground +
+
+ +
+ + + +` + +const headers = { 'Content-Type': 'text/html' } +const handler = (request, { baseEndpoint }) => new Response(html(baseEndpoint), { headers }) + +module.exports = handler diff --git a/src/index.js b/src/index.js index 228286a..d3edb63 100644 --- a/src/index.js +++ b/src/index.js @@ -1,19 +1,38 @@ const apollo = require('./handlers/apollo') -const graphiql = require('./handlers/graphiql') +const playground = require('./handlers/playground') -const handleRequest = async request => { +const graphQLOptions = { + // Set the path for the GraphQL server + baseEndpoint: '/', + // Set the path for the GraphQL playground + // This option can be removed to disable the playground route + playgroundEndpoint: '/___graphql', + // When a request's path isn't matched, forward it to the origin + forwardUnmatchedRequestsToOrigin: false, + // Enable debug mode to return script errors directly in browser + debug: false, +} + +const handleRequest = request => { const url = new URL(request.url) try { - if (url.pathname === '/graphql') { - return apollo(request) - } else if (url.pathname === '/graphiql') { - return graphiql(request) + if (url.pathname === graphQLOptions.baseEndpoint) { + return apollo(request, graphQLOptions) + } else if ( + graphQLOptions.playgroundEndpoint && + url.pathname === graphQLOptions.playgroundEndpoint + ) { + return playground(request, graphQLOptions) + } else if (graphQLOptions.forwardUnmatchedRequestsToOrigin) { + return fetch(request) } else { return new Response('Not found', { status: 404 }) } } catch (err) { - return new Response(err, { status: 500 }) + return new Response(graphQLOptions.debug ? err : 'Something went wrong', { status: 500 }) } } -addEventListener('fetch', event => event.respondWith(handleRequest(event.request))) +addEventListener('fetch', event => { + event.respondWith(handleRequest(event.request)) +}) diff --git a/wrangler.toml.example b/wrangler.toml.example deleted file mode 100644 index f482e3d..0000000 --- a/wrangler.toml.example +++ /dev/null @@ -1,6 +0,0 @@ -name = "workers-graphql" -type = "webpack" -private = false -route = "yoururl.com/*" -account_id = "abc123" -zone_id = "def456"