Expand description
A type-safe framework for AWS AppSync Direct Lambda resolvers.
This crate provides procedural macros and types for implementing AWS AppSync Direct Lambda resolvers. It converts GraphQL schemas into type-safe Rust code with full AWS Lambda runtime support.
The recommended entry point is make_appsync!, a convenience macro that generates all
necessary types, the Operation dispatch enum, and a Handlers trait from a .graphql
schema file. For finer control (e.g. shared-types libraries or multi-Lambda setups), the
three composable macros make_types!, make_operation!, and make_handlers! can be
used individually. Resolver functions are annotated with appsync_operation.
§Key Concepts
§Macros
§All-in-one
-
make_appsync!— reads a GraphQL schema file at compile time and generates:- Rust types for all GraphQL objects/enums/inputs,
- an
Operationenum covering every query/mutation/subscription field, and - a
Handlerstrait with aDefaultHandlersstruct for wiring up the Lambda runtime.
This is the recommended macro for single-crate projects.
§Composable
make_types!— generates Rust structs and enums from the schema’stype,input, andenumdefinitions.make_operation!— generates theOperationenum, sub-enums (QueryField,MutationField,SubscriptionField), argument extraction, and theexecutedispatch method. Requires the types frommake_types!to be in scope.make_handlers!— generates theHandlerstrait andDefaultHandlersstruct for the Lambda runtime. Requires theOperationtype frommake_operation!to be in scope.
§Resolver attribute
appsync_operation— attribute macro applied to async resolver functions. It validates that the function signature matches the corresponding GraphQL field and registers the function as the handler for that operation.
§Deprecated
appsync_lambda_main!(compatfeature) — the legacy monolithic macro. It combines type generation, operation dispatch, Lambda runtime setup, and AWS SDK client initialization into one call. Prefermake_appsync!or the composable macros for new code.
§Event and Response Types
Every Lambda invocation receives an AppsyncEvent<O> where O is the generated Operation
enum. The event carries:
AppsyncEvent::identity— the caller’sAppsyncIdentity(Cognito, IAM, OIDC, Lambda authorizer, or API key)AppsyncEvent::info— anAppsyncEventInfo<O>with the specific operation, selection set, and variablesAppsyncEvent::args— raw JSON arguments for the field; usearg_from_jsonto extract individual typed argumentsAppsyncEvent::source— the parent object’s resolved value for nested resolvers
Resolver functions return Result<T, AppsyncError>. The framework serializes
responses and wraps them in an AppsyncResponse.
§Identity and Authorization
AppsyncIdentity is an enum with one variant per AppSync authorization mode:
| Variant | Auth mode | Detail struct |
|---|---|---|
AppsyncIdentity::Cognito | Cognito User Pools | AppsyncIdentityCognito |
AppsyncIdentity::Iam | AWS IAM / Cognito Identity Pools | AppsyncIdentityIam |
AppsyncIdentity::Oidc | OpenID Connect | AppsyncIdentityOidc |
AppsyncIdentity::Lambda | Lambda authorizer | AppsyncIdentityLambda |
AppsyncIdentity::ApiKey | API Key | (no extra data) |
§AWS AppSync Scalar Types
The crate provides Rust types for all AppSync-specific GraphQL scalars:
ID— UUID-based GraphQLIDscalarAWSEmail,AWSPhone,AWSUrl— validated string scalarsAWSDate,AWSTime,AWSDateTime— date/time scalarsAWSTimestamp— Unix epoch timestamp scalar
§Subscription Filters
The subscription_filters module provides a type-safe builder for AppSync
enhanced subscription filters.
Filters are constructed from subscription_filters::FieldPath operator methods, combined
into subscription_filters::Filter (AND logic, up to 5 conditions) and
subscription_filters::FilterGroup (OR logic, up to 10 filters). AWS AppSync’s size
constraints are enforced at compile time.
§Error Handling
AppsyncError carries an error_type and error_message. Multiple errors can be merged
with the | operator, which concatenates both fields. Any AWS SDK error that implements
ProvideErrorMetadata converts into an AppsyncError via ?.
§Tracing Integration
When the tracing feature is enabled, the generated Handlers trait automatically wraps
each event dispatch in a tracing::info_span!("AppsyncEvent", ...) that records the
operation being executed (and the batch index, when batch mode is active). This helps give you
per-operation spans linked with the parent without writing any instrumentation boilerplate.
The feature also re-exports tracing and tracing-subscriber for convenience.
§Complete Example
Given a GraphQL schema (schema.graphql):
type Query {
players: [Player!]!
gameStatus: GameStatus!
}
type Player {
id: ID!
name: String!
team: Team!
}
enum Team {
RUST
PYTHON
JS
}
enum GameStatus {
STARTED
STOPPED
}§Using make_appsync! (recommended)
use lambda_appsync::{make_appsync, appsync_operation, AppsyncError};
// Generate types, Operation enum, and Handlers trait from schema
make_appsync!("schema.graphql");
// Implement resolver functions for GraphQL operations:
#[appsync_operation(query(players))]
async fn get_players() -> Result<Vec<Player>, AppsyncError> {
todo!()
}
#[appsync_operation(query(gameStatus))]
async fn get_game_status() -> Result<GameStatus, AppsyncError> {
todo!()
}
// Wire up the Lambda runtime in main:
#[tokio::main]
async fn main() -> Result<(), lambda_runtime::Error> {
lambda_runtime::run(
lambda_runtime::service_fn(DefaultHandlers::service_fn)
).await
}§Custom handler with authentication hook
Override the Handlers trait to add pre-processing logic (replaces the
old hook parameter from appsync_lambda_main!):
use lambda_appsync::{make_appsync, appsync_operation, AppsyncError};
use lambda_appsync::{AppsyncEvent, AppsyncResponse, AppsyncIdentity};
make_appsync!("schema.graphql");
struct MyHandlers;
impl Handlers for MyHandlers {
async fn appsync_handler(event: AppsyncEvent<Operation>) -> AppsyncResponse {
// Custom authentication check
if let AppsyncIdentity::ApiKey = &event.identity {
return AppsyncResponse::unauthorized();
}
// Delegate to the default operation dispatch
event.info.operation.execute(event).await
}
}
#[appsync_operation(query(players))]
async fn get_players() -> Result<Vec<Player>, AppsyncError> {
todo!()
}
#[appsync_operation(query(gameStatus))]
async fn get_game_status() -> Result<GameStatus, AppsyncError> {
todo!()
}
#[tokio::main]
async fn main() -> Result<(), lambda_runtime::Error> {
lambda_runtime::run(
lambda_runtime::service_fn(MyHandlers::service_fn)
).await
}§Using the composable macros
For multi-crate setups (e.g. a shared types library with separate Lambda binaries), use the individual macros:
use lambda_appsync::{make_types, make_operation, make_handlers, appsync_operation, AppsyncError};
// Step 1: Generate types (could live in a shared lib crate)
make_types!("schema.graphql");
// Step 2: Generate Operation enum and dispatch logic
make_operation!("schema.graphql");
// Step 3: Generate Handlers trait and DefaultHandlers
make_handlers!();
#[appsync_operation(query(players))]
async fn get_players() -> Result<Vec<Player>, AppsyncError> {
todo!()
}
#[appsync_operation(query(gameStatus))]
async fn get_game_status() -> Result<GameStatus, AppsyncError> {
todo!()
}
#[tokio::main]
async fn main() -> Result<(), lambda_runtime::Error> {
lambda_runtime::run(
lambda_runtime::service_fn(DefaultHandlers::service_fn)
).await
}§Feature Flags
| Feature | Description |
|---|---|
compat | Enables the deprecated appsync_lambda_main! macro and re-exports aws_config, lambda_runtime, and tokio. Not required when using make_appsync! or the composable macros (you depend on lambda_runtime and tokio directly). |
log | Re-exports the log crate so resolver code can use log::info! etc. without a separate dependency. |
env_logger | Initializes env_logger for local development. Implies log and compat. |
tracing | Re-exports tracing and tracing-subscriber for structured, async-aware logging. |
Re-exports§
pub use lambda_runtime;pub use serde;pub use serde_json;pub use tokio;
Modules§
- subscription_
filters - GraphQL subscription filter implementation for AWS AppSync
Macros§
- make_
appsync - Convenience macro that combines make_types!, make_operation!, and make_handlers! into a single invocation.
- make_
handlers - Generates a
Handlerstrait and aDefaultHandlersstruct for handling AWS AppSync Lambda events. - make_
operation - Generates the
Operationenum and its dispatch logic from a GraphQL schema file. - make_
types - Generates Rust types (structs and enums) from a GraphQL schema file.
Structs§
- AWSDate
- AWS AppSync specific GraphQL scalar type implemented a String new-type
- AWSDate
Time - AWS AppSync specific GraphQL scalar type implemented a String new-type
- AWSEmail
- AWS AppSync specific GraphQL scalar type implemented a String new-type
- AWSPhone
- AWS AppSync specific GraphQL scalar type implemented a String new-type
- AWSTime
- AWS AppSync specific GraphQL scalar type implemented a String new-type
- AWSTimestamp
- AWS AppSync specific GraphQL scalar type implemented SystemTime new-type. Note that this type implements Copy
- AWSUrl
- AWS AppSync specific GraphQL scalar type implemented a String new-type
- Appsync
Error - Error type for AWS AppSync operations
- Appsync
Event - Represents a complete AWS AppSync event sent to a Lambda resolver.
- Appsync
Event Info - Metadata about an AppSync GraphQL operation execution.
- Appsync
Identity Cognito - Identity information for Cognito User Pools authenticated requests.
- Appsync
Identity Iam - Identity information for IAM-authenticated requests.
- Appsync
Identity Lambda - Identity information for Lambda-authorized requests.
- Appsync
Identity Oidc - Identity information for OIDC-authenticated requests.
- Appsync
Response - Response structure returned to AWS AppSync from a Lambda resolver.
- Cognito
Federated Identity - Cognito Identity Pool information for federated IAM authentication
- ID
- A custom UUID-based identifier type for AppSync GraphQL objects.
Enums§
- Appsync
Auth Strategy - Authorization strategy for AppSync operations.
- Appsync
Identity - Identity information for an AppSync request.
- Cognito
Identity Auth Type - Authentication type in a Cognito Identity Pool
Functions§
- arg_
from_ json - Extracts and deserializes a named argument from a JSON Value into the specified type
- res_
to_ json - Serializes a value into a JSON Value for AppSync responses
Attribute Macros§
- appsync_
operation - Marks an async function as an AWS AppSync resolver operation, binding it to a specific Query, Mutation or Subscription operation defined in the GraphQL schema.