Skip to content

Commit

Permalink
Merge pull request #58 from cloudflare/update
Browse files Browse the repository at this point in the history
v2
  • Loading branch information
kristianfreeman authored Nov 4, 2024
2 parents 7a5e8c5 + 583ebb7 commit 106fa88
Show file tree
Hide file tree
Showing 27 changed files with 12,099 additions and 2,557 deletions.
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[*]
indent_style = space
indent_size = 2
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,5 @@ $RECYCLE.BIN/

### Cloudflare ###
worker

src/generated
21 changes: 0 additions & 21 deletions LICENSE

This file was deleted.

113 changes: 75 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,56 +1,66 @@
# workers-graphql-server

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).
An [Apollo GraphQL](https://www.apollographql.com/) server, built with [Cloudflare Workers](https://workers.cloudflare.com).

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).
Whether you host your APIs on-prem, in the cloud, or you're deploying [databases](https://developers.cloudflare.com/d1) to Cloudflare directly, you can deploy a globally distributed GraphQL server with Cloudflare Workers.

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)!
## Setup

[![Deploy to Cloudflare Workers](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/workers-graphql-server)

## Usage

You can begin building your own Workers GraphQL server by [installing Wrangler](https://workers.cloudflare.com/docs/quickstart/), the Workers command-line tool, and generating a new project:
Begin by cloning this repo and installing the dependencies:

```sh
wrangler generate my-graphql-server https://github.com/cloudflare/workers-graphql-server
$ git clone https://github.com/cloudflare/workers-graphql-server
$ npm install
```

You'll need to configure your project's `wrangler.toml` file to prepare your project for deployment. See the ["Configuration"](https://developers.cloudflare.com/workers/cli-wrangler/configuration/) docs for a guide on how to do this. Note that you'll need to [find your Cloudflare API keys](https://developers.cloudflare.com/workers/cli-wrangler/authentication/) to set up your config file.
You can begin running the project locally by running `npm run dev`.

You'll need to configure your project's `wrangler.toml` file to prepare your project for deployment. See the ["Configuration"](https://developers.cloudflare.com/workers/cli-wrangler/configuration/) docs for a guide on how to do this.

## Usage

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. Once you have the worker available, try this query as a sanity check:
The source for this project shows how to make requests to external APIs, using the [PokeAPI](https://pokeapi.co/) as an example. You can run an example query to ensure it works after deployment:

```graphql
query samplePokeAPIquery {
pokemon: pokemon(id:1) {
id,
name,
height,
weight,
sprites{
front_shiny,
query {
pokemon: pokemon(id: 1) {
id
name
height
weight
sprites {
front_shiny
back_shiny
}
}
}
```

To start using the project, configure your `graphQLOptions` object in `src/index.js`:
Resolvers are defined in `src/resolvers.ts`. You can also use [Service Bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/) to connect to other Workers services, and use them inside your resolvers.

If you change your GraphQL schema at `src/schema.graphql`, you'll need to run `npm run codegen` to update the generated types in `src/generated/graphql.ts`. This ensures that you can correctly import and type your resolvers.

## Configuration

You can optionally configure your `graphQLOptions` object in `src/index.js`:

```js
const graphQLOptions = {
baseEndpoint: '/', // String
playgroundEndpoint: '/___graphql', // ?String
forwardUnmatchedRequestsToOrigin: false, // Boolean
debug: false, // Boolean
cors: true, // Boolean or Object to further configure
kvCache: false, // Boolean
baseEndpoint: '/',
enableSandbox: true,
forwardUnmatchedRequestsToOrigin: false,
cors: true,
kvCache: false,
}
```

### Endpoints
### Base endpoint

Make requests to your GraphQL server by sending `POST` requests to the `baseEndpoint` (e.g. `graphql-on-workers.signalnerve.com/`).

### Sandbox

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`).
By default, the Apollo Sandbox is enabled. This allows you to test your GraphQL in a web GUI without needing to write any client code.

### Origin forwarding

Expand All @@ -62,37 +72,64 @@ While configuring your server, you may want to set the `debug` flag to `true`, t

### CORS

By default, the `cors` option allows cross-origin requests to the server from any origin. You may wish to configure it to whitelist specific origins, methods, or headers. To do this, change the `cors` option to an object:
By default, the `cors` option allows cross-origin requests to the server from any origin. You may wish to configure it to whitelist specific origins, methods, or headers. This is done by passing an object to `cors`, which is based on the [hono/cors](https://hono.dev/docs/middleware/builtin/cors) middleware:

```js
const graphQLOptions = {
// ... other options ...

cors: {
allowCredentials: 'true',
allowHeaders: 'Content-type',
allowOrigin: '*',
allowMethods: 'GET, POST, PUT',
origin: 'http://example.com',
allowHeaders: ['X-Custom-Header', 'Upgrade-Insecure-Requests'],
allowMethods: ['POST', 'GET', 'OPTIONS'],
exposeHeaders: ['Content-Length', 'X-Kuma-Revision'],
maxAge: 600,
credentials: true,
},
}
```

Note that by default, any field that you _don't_ pass here (e.g. `allowMethods`) will fallback to the default value. See `utils/setCors.js` for the default values for these fields.
### Caching

### REST caching

Version 1.1.0 of this project includes support for caching external requests made via instances of [`RESTDataSource`](https://www.apollographql.com/docs/apollo-server/features/data-sources/), using KV. To use caching in your project, [create a new KV namespace](https://workers.cloudflare.com/docs/reference/storage/writing-data), and in `wrangler.toml`, configure your namespace, calling it `WORKERS_GRAPHQL_CACHE`:
This project includes support for using Workers KV as a cache in your resolvers. To use caching in your project, [create a new KV namespace](https://workers.cloudflare.com/docs/reference/storage/writing-data), and in `wrangler.toml`, configure your namespace, calling it `KV_CACHE` (note that this binding name is _required_, currently):

```toml
# wrangler.toml

[[kv-namespaces]]
binding = "WORKERS_GRAPHQL_CACHE"
binding = "KV_CACHE"
id = "$myId"
```

With a configured KV namespace set up, you can opt-in to KV caching by changing the `kvCache` config value in `graphQLOptions` (in `index.js`) to `true`.

In any resolver function, you can access the `cache` object, which is an instance of [`KVCache`](https://github.com/cloudflare/workers-graphql-server/blob/master/src/kv-cache.ts). You can use `.get` and `.set` to interact with the cache:

```ts
pokemon: async (_parent, { id }, { cache }) => {
if (cache) {
const pokemon = await cache.get(id)
if (pokemon) {
return pokemon
}
}

// You can hook into any util functions, API wrappers, or other
// code that you need to resolve your query.
const pokemonData = await PokemonAPI.getPokemon(id)

// You can also cache the data if you need to, with an optional TTL
if (cache) await cache.set(id, pokemonData, { ttl: 60 })
return pokemonData
},
```

## Credits

This project is heavily based on the [@as-integrations/cloudflare-workers](https://github.com/apollo-server-integrations/apollo-server-integration-cloudflare-workers) package, which is a great tool for building GraphQL servers with Cloudflare Workers.

It is built with [Hono](https://github.com/honojs/hono), a simple and powerful web framework for Cloudflare Workers.

## License

This project is licensed with the [MIT License](https://github.com/cloudflare/workers-graphql-server/blob/master/LICENSE).
2 changes: 0 additions & 2 deletions cargo-generate.toml

This file was deleted.

16 changes: 16 additions & 0 deletions codegen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { CodegenConfig } from '@graphql-codegen/cli'

const config: CodegenConfig = {
overwrite: true,
schema: 'src/schema.graphql',
generates: {
'src/generated/graphql.ts': {
plugins: ['typescript', 'typescript-resolvers'],
},
'./graphql.schema.json': {
plugins: ['introspection'],
},
},
}

export default config
Loading

0 comments on commit 106fa88

Please sign in to comment.