make_appsync!() { /* proc-macro */ }Expand description
Convenience macro that combines make_types!, make_operation!, and make_handlers! into a single invocation.
§Usage
make_appsync!("path/to/schema.graphql");
// or with options:
make_appsync!(
"path/to/schema.graphql",
batch = true, // enable/disable batch handling
type_override = Type.field: CustomType, // override a field type
type_override = Query.operation: CustomType, // override an operation return type
type_override = Query.operation.arg: CustomType, // override an operation argument type
name_override = TypeName: NewTypeName, // rename a type
name_override = Type.field: new_field_name, // rename a field
default_traits = MyType: false, // disable default traits for a type
derive = MyType: Default, // add an extra derive macro to a type
derive = MyType: PartialEq, // (specify multiple times for multiple derives)
error_logging = false, // disable error logging (feature: log)
);This generates everything needed to implement an AWS AppSync Direct Lambda resolver from a GraphQL schema:
- Rust types for all GraphQL types (enums, inputs, objects) — same as make_types!
- The
Operationenum withQueryField/MutationField/SubscriptionFieldsub-enums and dispatch logic — same as make_operation! - The
Handlerstrait andDefaultHandlersstruct — same as make_handlers!
This is the recommended macro for the common single-Lambda-function use case. For multi-crate setups or when you need finer control over what gets generated where, use the individual macros instead.
§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
make_appsync! accepts the union of parameters from make_types!, make_operation!, and
make_handlers!, except for parameters that only make sense in a multi-crate setup.
§From make_types! / make_operation!
type_override— Override Rust types for fields, operation return types, or operation arguments. See make_types! and make_operation! for full syntax.name_override— Rename types, fields, or enum variants. See make_types! for full syntax.default_traits— Control whether default traits are implemented for a type. See make_types! for full syntax and details.derive— Add extra derive macros on top of the defaults for a type. See make_types! for full syntax and details.
§From make_operation! (feature: log)
error_logging = bool(default:true): When enabled, the generatedexecutemethod logs errors vialog::error!before converting them to anAppsyncResponse. Only available with thelogfeature.
§From make_handlers!
batch = bool(default:true): Enable/disable batch request handling. See make_handlers! for details.
§Parameters NOT available
type_module(from make_operation!) — Not needed since types are generated in the same scopeoperation_type(from make_handlers!) — Not needed sinceOperationis generated in the same scope
§Type Overrides
The type_override option allows overriding Rust types affected to various schema elements:
- GraphQL
typeandinputfield 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.
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.
§Examples
§Basic usage:
use lambda_appsync::make_appsync;
make_appsync!("schema.graphql");
#[tokio::main]
async fn main() -> Result<(), lambda_runtime::Error> {
lambda_runtime::run(
lambda_runtime::service_fn(DefaultHandlers::service_fn)
).await
}§With type and name overrides:
lambda_appsync::make_appsync!(
"schema.graphql",
type_override = Player.id: String,
type_override = Query.player.id: String,
type_override = Mutation.deletePlayer.id: String,
type_override = Subscription.onDeletePlayer.id: String,
name_override = Player: GqlPlayer,
// *MUST* also override ALL the operations return type when changing the name of a type!!!
type_override = Query.players: GqlPlayer,
type_override = Query.player: GqlPlayer,
type_override = Mutation.createPlayer: GqlPlayer,
type_override = Mutation.deletePlayer: GqlPlayer,
);§Disable batch processing:
lambda_appsync::make_appsync!(
"schema.graphql",
batch = false,
);§With a custom handler:
use lambda_appsync::{make_appsync, appsync_operation, AppsyncError, AppsyncResponse, AppsyncEvent, AppsyncIdentity};
make_appsync!("schema.graphql");
struct MyHandlers;
impl Handlers for MyHandlers {
async fn appsync_handler(event: AppsyncEvent<Operation>) -> AppsyncResponse {
if let AppsyncIdentity::ApiKey = &event.identity {
return AppsyncResponse::unauthorized();
}
event.info.operation.execute(event).await
}
}
#[appsync_operation(query(players))]
async fn get_players() -> Result<Vec<Player>, AppsyncError> {
Ok(vec![])
}
#[tokio::main]
async fn main() -> Result<(), lambda_runtime::Error> {
lambda_runtime::run(
lambda_runtime::service_fn(MyHandlers::service_fn)
).await
}§Equivalence
The following make_appsync! invocation:
lambda_appsync::make_appsync!(
"schema.graphql",
batch = true,
type_override = Player.id: String,
default_traits = Player: false,
derive = Player: Debug,
derive = Player: serde::Serialize,
);is equivalent to:
lambda_appsync::make_types!(
"schema.graphql",
type_override = Player.id: String,
default_traits = Player: false,
derive = Player: Debug,
derive = Player: serde::Serialize,
);
lambda_appsync::make_operation!(
"schema.graphql",
type_override = Player.id: String,
);
lambda_appsync::make_handlers!(
batch = true,
);§When to Use make_appsync! vs Individual Macros
| Scenario | Recommendation |
|---|---|
| Single Lambda function, all code in one crate | Use make_appsync! |
| Shared types library + multiple Lambda binaries | Use make_types! in the lib, make_operation! + make_handlers! in each binary |
| Custom handler logic only | Use make_appsync! + override Handlers trait methods |
| Need different operations per Lambda | Use make_types! shared, separate make_operation! per Lambda |