mod durable_object; mod event; mod send; use proc_macro::TokenStream; /// Integrate the struct with the Workers Runtime as Durable Object.\ /// Requires the `DurableObject` trait with the durable_object attribute macro on the struct. /// /// ## Example /// /// ```rust /// #[durable_object] /// pub struct Chatroom { /// users: Vec, /// messages: Vec, /// state: State, /// env: Env, // access `Env` across requests, use inside `fetch` /// } /// /// impl DurableObject for Chatroom { /// fn new(state: State, env: Env) -> Self { /// Self { /// users: vec![], /// messages: vec![], /// state, /// env, /// } /// } /// /// async fn fetch(&self, _req: Request) -> Result { /// // do some work when a worker makes a request to this DO /// Response::ok(&format!("{} active users.", self.users.len())) /// } /// } /// ``` /// /// ## Note /// /// By default all durable object events are enabled. /// Arguments may be provided to the macro to only generate the desired events, and reduce the generated JS & Wasm output: /// /// * `fetch`: simple `fetch` target /// * `alarm`: with [Alarms API](https://developers.cloudflare.com/durable-objects/examples/alarms-api/) /// * `websocket`: [WebSocket server](https://developers.cloudflare.com/durable-objects/examples/websocket-hibernation-server/) /// /// ```rust /// #[durable_object(fetch)] /// pub struct Chatroom { /// users: Vec, /// messages: Vec, /// state: State, /// env: Env, // access `Env` across requests, use inside `fetch` /// } /// ``` #[proc_macro_attribute] pub fn durable_object(attr: TokenStream, item: TokenStream) -> TokenStream { durable_object::expand_macro(attr.into(), item.into()) .unwrap_or_else(syn::Error::into_compile_error) .into() } /// The `event` macro is used to denote a [Worker handler](https://developers.cloudflare.com/workers/runtime-apis/handlers/), essentially binding from /// the JS runtime to a Rust function. /// /// As of right now, the following attributes are supported: /// * `fetch`: [Fetch Handler](https://developers.cloudflare.com/workers/runtime-apis/handlers/fetch/) /// * `scheduled`: [Scheduled Handler](https://developers.cloudflare.com/workers/runtime-apis/handlers/scheduled/) /// * `queue`: [Queue Handler](https://developers.cloudflare.com/queues/reference/javascript-apis/#consumer) /// * This attribute is only available when the `queue` feature is enabled. /// * `start`: merely creates a [wasm-bindgen start function](https://rustwasm.github.io/wasm-bindgen/reference/attributes/on-rust-exports/start.html) /// * `respond_with_errors`: if this attribute is present, the function will return a `Response` object with a 500 status code and the status text of the error message, if an error occurs /// /// The macro is expanded into a different function signature, depending on the attributes used /// /// # Fetch /// /// At a high-level, the `fetch` handler is used to handle incoming HTTP requests. The function signature for a `fetch` handler is conceptually something like: /// /// ```rust /// async fn fetch(req: impl From, env: Env, ctx: Context) -> Result, impl Into>> /// ``` /// /// In other words, it takes some "request" object that can be derived *from* a `web_sys::Request` (into whatever concrete Request type you like), /// and returns some "response" object that can be converted *into* a `web_sys::Response` (from whatever concrete Response type you like). /// Error types can be any type that implements [`std::error::Error`]. /// /// In practice, the "request" and "response" objects are usually one of these concrete types, supported out of the box: /// /// ### worker::{Request, Response} /// /// ```rust /// #[event(fetch, respond_with_errors)] /// async fn main(req: worker::Request, env: Env, ctx: Context) -> Result { /// worker::Response::ok("Hello World (worker type)") /// } /// ``` /// /// ### web_sys::{Request, Response} /// /// ```rust /// #[event(fetch, respond_with_errors)] /// async fn main(req: web_sys::Request, env: Env, ctx: Context) -> Result { /// Ok(web_sys::Response::new_with_opt_str(Some("Hello World (native type)".into())).unwrap()) /// } /// ``` /// /// ### axum (with `http` feature) /// /// ```rust /// #[event(fetch)] /// async fn fetch(req: HttpRequest, env: Env, ctx: Context) -> Result> { /// Ok(router().call(req).await?) /// } /// ``` #[proc_macro_attribute] pub fn event(attr: TokenStream, item: TokenStream) -> TokenStream { event::expand_macro(attr, item) } #[proc_macro_attribute] /// Convert an async function which is `!Send` to be `Send`. /// /// This is useful for implementing async handlers in frameworks which /// expect the handler to be `Send`, such as `axum`. /// /// ```rust /// #[worker::send] /// async fn foo() { /// // JsFuture is !Send /// let fut = JsFuture::from(promise); /// fut.await /// } /// ``` pub fn send(attr: TokenStream, stream: TokenStream) -> TokenStream { send::expand_macro(attr, stream) } #[doc(hidden)] #[proc_macro_attribute] pub fn consume(_: TokenStream, _: TokenStream) -> TokenStream { TokenStream::new() }