Skip to content
This repository has been archived by the owner on Feb 9, 2023. It is now read-only.

Commit

Permalink
feat!: return an request handler instead of Response
Browse files Browse the repository at this point in the history
BREAKING CHANGE:
- Before:
  const response = startServerAndCreateCloudflareHandler(server, {
    cors: { // cors configuration },
    context: async () => {
      const cache = options.kvCache ? new KVCache() : server.cache;

      const dataSources: ApolloDataSources = {
        pokemonAPI: new PokemonAPI({ cache }),
      };

      return { dataSources };
    }
  });

- After:
  const handleGraphQLRequest = startServerAndCreateCloudflareHandler(server, {
    cors: options.cors,
    context: async () => {
      const cache = options.kvCache ? new KVCache() : server.cache;

      const dataSources: ApolloDataSources = {
        pokemonAPI: new PokemonAPI({ cache }),
      };

      return { dataSources };
    }
  });

  const response = await handleGraphQLRequest(request);
  • Loading branch information
kimyvgy committed Dec 20, 2022
1 parent c3b97fe commit 076d7ae
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 41 deletions.
42 changes: 36 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,20 @@ This is Apollo Server v4 integration for Cloudflare Workers. It provides:
- Source: https://github.com/kimyvgy/worker-apollo-server-template
- Live demo: https://worker-apollo-server.webee-asia.workers.dev/

## Install

```bash
npm install apollo-server-integration-cloudflare-workers
```

## Getting Started

1. Initialize an Apollo Server instance:

```javascript
import { ApolloServer } from '@apollo/server';
import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default';

const server = new ApolloServer<ContextValue>({
typeDefs,
resolvers,
Expand All @@ -32,19 +41,40 @@ const server = new ApolloServer<ContextValue>({
2. Call `startServerAndCreateCloudflareHandler(server, options)`:

```javascript
const response: Response = startServerAndCreateCloudflareHandler(server, {
request,
cors: options.cors,
context: async () => {
import type { GraphQLRequestHandler, CorsOptions } from 'apollo-server-integration-cloudflare-workers';
import { startServerAndCreateCloudflareHandler, KVCache } from 'apollo-server-integration-cloudflare-workers';

const handleGraphQLRequest: GraphQLRequestHandler = startServerAndCreateCloudflareHandler(server, {
context: async ({ request }) => {
const cache = options.kvCache ? new KVCache() : server.cache;

const dataSources: ApolloDataSources = {
pokemonAPI: new PokemonAPI({ cache }),
};

return { dataSources };
}
},

// Enable CORS headers on GraphQL requests
// Set to `true` for defaults or pass an object to configure each header
// cors: {
// allowCredentials: 'true',
// allowHeaders: 'Content-type',
// allowOrigin: '*',
// allowMethods: 'GET, POST, PUT',
// },
cors: true,
});

addEventListener((e) => handleGraphQLRequest(e.request));
```

3. Send the `response` to the browser.
## Support / Donate

<h3 align="center">Support the developer</h3>

<p align="center">
<a href="https://kimyvgy.webee.asia" target="_blank" title="Donate with: Paypal, Momo, Buymeacoffee">
<img src="https://user-images.githubusercontent.com/13513658/208368616-f20301e6-61d5-449b-aa87-5dda17b273b7.png">
</a>
</p>
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "apollo-server-integration-cloudflare-workers",
"description": "An integration to use Cloudflare Workers as a hosting service with Apollo Server v4",
"version": "1.0.2",
"version": "2.0.0",
"author": "Kim Nguyen",
"license": "MIT",
"repository": {
Expand Down
69 changes: 37 additions & 32 deletions src/start-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,29 @@ import {
HTTPGraphQLRequest,
} from '@apollo/server';

export type GraphQLRequestHandler = (request: Request) => Promise<Response>;

export interface CloudflareContextFunctionArgument {
request: Request;
}

export interface CloudflareHandlerOptions<TContext extends BaseContext> {
context?: ContextFunction<[CloudflareContextFunctionArgument], TContext>;
request: Request;
cors?: CorsOptions;
}

export async function startServerAndCreateCloudflareHandler(
export function startServerAndCreateCloudflareHandler(
server: ApolloServer<BaseContext>,
options: CloudflareHandlerOptions<BaseContext>,
): Promise<Response>;
export async function startServerAndCreateCloudflareHandler<TContext extends BaseContext>(
): GraphQLRequestHandler;
export function startServerAndCreateCloudflareHandler<TContext extends BaseContext>(
server: ApolloServer<TContext>,
options: WithRequired<CloudflareHandlerOptions<TContext>, 'context'>,
): Promise<Response>;
export async function startServerAndCreateCloudflareHandler<TContext extends BaseContext>(
): GraphQLRequestHandler;
export function startServerAndCreateCloudflareHandler<TContext extends BaseContext>(
server: ApolloServer<TContext>,
{ request, context, cors }: CloudflareHandlerOptions<TContext>,
): Promise<Response> {
{ context, cors }: CloudflareHandlerOptions<TContext>,
): GraphQLRequestHandler {
server.startInBackgroundHandlingStartupErrorsByLoggingAndFailingAllRequests();

const defaultContext: ContextFunction<
Expand All @@ -44,33 +45,37 @@ export async function startServerAndCreateCloudflareHandler<TContext extends Bas
TContext
> = context ?? defaultContext;

try {
if (request.method === 'OPTIONS') {
return withCors(new Response('', { status: 204 }), cors);
return async (request: Request) => {
let response: Response;

try {
if (request.method === 'OPTIONS') {
response = new Response('', { status: 204 });
}

const httpGraphQLRequest = await normalizeIncomingRequest(request);

const { body, headers, status } = await server.executeHTTPGraphQLRequest({
httpGraphQLRequest: httpGraphQLRequest,
context: () => contextFunction({ request }),
});

if (body.kind === 'chunked') {
throw Error('Incremental delivery not implemented');
}

response = new Response(body.string, {
status: status || 200,
headers: {
...Object.fromEntries(headers),
'content-length': Buffer.byteLength(body.string).toString(),
},
});
} catch (e) {
response = new Response((e as Error).message, { status: 400 });
}

const httpGraphQLRequest = await normalizeIncomingRequest(request);

const { body, headers, status } = await server.executeHTTPGraphQLRequest({
httpGraphQLRequest: httpGraphQLRequest,
context: () => contextFunction({ request }),
});

if (body.kind === 'chunked') {
throw Error('Incremental delivery not implemented');
}

const response = new Response(body.string, {
status: status || 200,
headers: {
...Object.fromEntries(headers),
'content-length': Buffer.byteLength(body.string).toString(),
},
});

return withCors(response, cors);
} catch (e) {
return withCors(new Response((e as Error).message, { status: 400 }), cors);
}
}

Expand Down

0 comments on commit 076d7ae

Please sign in to comment.