apollo-server-integrations / apollo-server-integration-aws-lambda

An integration to use AWS Lambda as a hosting service with Apollo Server
MIT License
45 stars 9 forks source link

Async/await lambdas #168

Open olliebatch opened 3 months ago

olliebatch commented 3 months ago

At the minute the output of startServerAndCreateLambdaHandler with the below returns a handler that expects a callback.

const handler = startServerAndCreateLambdaHandler(
    server,
    handlers.createAPIGatewayProxyEventV2RequestHandler(),
  );

The graphql handler has a third callback property. Callback's are not recommended by aws any more although still supported but other packages have moved away from general handling of them. E.G Middy.

It would be ideal to not require a callback property on the graphql handler.

BlenderDude commented 3 months ago

After digging into this, it appears that this is just a mismatch in typescript types that needs cleaned up. You can see here that the handler is actually implemented as async and does not use the callback parameter. I see now that the official Lambda types from aws-lambda define Handler as

export type Handler<TEvent = any, TResult = any> = (
    event: TEvent,
    context: Context,
    callback: Callback<TResult>,
) => void | Promise<TResult>;

When really the type we expose is

export type Handler<TEvent = any, TResult = any> = (
    event: TEvent,
    context: Context,
) => Promise<TResult>;

Typescript was happy on my end because the latter type does technically implement the former, but in practice any system using the callback parameter would fail as it goes unused in the code in favor of the async pattern.

If the type is causing issues, I recommend casting it as follows while I get an update pushed:

const handler = startServerAndCreateLambdaHandler(
  server,
  handlers.createAPIGatewayProxyEventV2RequestHandler(),
) as (event: APIGatewayProxyEventV2, context: Context) => Promise<APIGatewayProxyStructuredResultV2>;

Reminder that this is just an issue with the type system, the runtime will remain unchanged and is still using and has been using async/await