appsync_lambda_main!() { /* proc-macro */ }
Expand description
Generates the code required to handle AWS AppSync Direct Lambda resolver events based on a GraphQL schema.
This macro takes a path to a GraphQL schema file and generates the complete foundation for implementing an AWS AppSync Direct Lambda resolver:
- Rust types for all GraphQL types (enums, inputs, objects)
- Query/Mutation/Subscription operation enums
- AWS Lambda runtime setup with logging to handle the AWS AppSync event
- Optional AWS SDK client initialization
§Schema Path Argument
The first argument to this macro must be a string literal containing the path to your GraphQL schema file. The schema path can be:
- An absolute filesystem path (e.g. “/home/user/project/schema.graphql”)
- A relative path, that will be relative to your crate’s root directory (e.g. “schema.graphql”, “graphql/schema.gql”)
- When in a workspace context, the relative path will be relative to the workspace root directory
§Options
batch = bool
: Enable/disable batch request handling (default: true)hook = fn_name
: Add a custom hook function for request validation/authexclude_lambda_handler = bool
: Skip generation of Lambda handler codeonly_lambda_handler = bool
: Only generate Lambda handler codeexclude_appsync_types = bool
: Skip generation of GraphQL type definitionsonly_appsync_types = bool
: Only generate GraphQL type definitionsexclude_appsync_operations = bool
: Skip generation of operation enumsonly_appsync_operations = bool
: Only generate operation enumstype_override
- see section below for detailsname_override
- see section below for detailsfield_type_override
(Deprecated): Same astype_override
§Type Overrides
The type_override
option allows overriding Rust types affected to various schema elements:
- GraphQL
type
andinput
Field types:type_override = Type.field: CustomType
- Operation return types (Query/Mutation):
type_override = OpType.operation: CustomType
- Operation arguments (Query/Mutation/Subscription):
type_override = OpType.operation.arg: CustomType
These overrides are only for the Rust code and must be compatible for serialization/deserialization purposes,
i.e. you can use String
for a GraphQL ID
but you cannot use a u32
for a GraphQL Float
.
§Name Overrides
The name_override
option supports renaming various schema elements:
- Type/input/enum names:
name_override = TypeName: NewTypeName
- Field names:
name_override = Type.field: new_field_name
- Enum variants:
name_override = Enum.VARIANT: NewVariant
These overrides are only for the Rust code and will not change serialization/deserialization,
i.e. serde
will rename to the original GraphQL schema name.
§AWS SDK Clients
AWS SDK clients can be initialized by providing function definitions that return a cached SDK client type. Each client is initialized only once and stored in a static OnceLock, making subsequent function calls essentially free:
- Function name: Any valid Rust identifier that will be used to access the client
- Return type: Must be a valid AWS SDK client like
aws_sdk_dynamodb::Client
use lambda_appsync::appsync_lambda_main;
// Single client
appsync_lambda_main!(
"schema.graphql",
dynamodb() -> aws_sdk_dynamodb::Client,
);
// Multiple clients
appsync_lambda_main!(
"schema.graphql",
dynamodb() -> aws_sdk_dynamodb::Client,
s3() -> aws_sdk_s3::Client,
);
These client functions can then be called from anywhere in the Lambda crate:
use crate::{dynamodb, s3};
async fn do_something() {
let dynamodb_client = dynamodb();
let s3_client = s3();
// Use clients...
}
§Examples
§Basic usage with authentication hook:
use lambda_appsync::{appsync_lambda_main, AppsyncEvent, AppsyncResponse, AppsyncIdentity};
fn is_authorized(identity: &AppsyncIdentity) -> bool {
todo!()
}
// If the function returns Some(AppsyncResponse), the Lambda function will immediately return it.
// Otherwise, the normal flow of the AppSync operation processing will continue.
// This is primarily intended for advanced authentication checks that AppSync cannot perform, such as verifying that a user is requesting their own ID.
async fn auth_hook(
event: &lambda_appsync::AppsyncEvent<Operation>
) -> Option<lambda_appsync::AppsyncResponse> {
// Verify JWT token, check permissions etc
if !is_authorized(&event.identity) {
return Some(AppsyncResponse::unauthorized());
}
None
}
appsync_lambda_main!(
"schema.graphql",
hook = auth_hook,
dynamodb() -> aws_sdk_dynamodb::Client
);
§Generate only types for lib code generation:
use lambda_appsync::appsync_lambda_main;
appsync_lambda_main!(
"schema.graphql",
only_appsync_types = true
);
§Override field types, operation return type or argument types:
use lambda_appsync::appsync_lambda_main;
appsync_lambda_main!(
"schema.graphql",
// Use String instead of the default lambda_appsync::ID
// Override Player.id to use String instead of ID
type_override = Player.id: String,
// Multiple overrides, here changing another `Player` field type
type_override = Player.team: String,
// Return value override
type_override = Query.gameStatus: String,
type_override = Mutation.setGameStatus: String,
// Argument override
type_override = Query.player.id: String,
type_override = Mutation.deletePlayer.id: String,
type_override = Subscription.onDeletePlayer.id: String,
);
§Override type, input, enum, fields or variants names:
use lambda_appsync::appsync_lambda_main;
appsync_lambda_main!(
"schema.graphql",
// Override Player struct name
name_override = Player: NewPlayer,
// Override Player struct field name
name_override = Player.name: email,
// Override team `PYTHON` to be `Snake` (instead of `Python`)
name_override = Team.PYTHON: Snake,
name_override = WeirdFieldNames.await: no_await,
name_override = WeirdFieldNames.crate: no_crate,
name_override = WeirdFieldNames.u8: no_u8,
// MUST also override ALL the operations return type !!!
type_override = Query.players: NewPlayer,
type_override = Query.player: NewPlayer,
type_override = Mutation.createPlayer: NewPlayer,
type_override = Mutation.deletePlayer: NewPlayer,
);
Note that when using name_override
, the macro does not automatically change the case:
you are responsible to provide the appropriate casing or Clippy will complain.
§Disable batch processing:
lambda_appsync::appsync_lambda_main!(
"schema.graphql",
batch = false
);