Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Get doctests working #541

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions worker-kv/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ license = "MIT OR Apache-2.0"
[package.metadata.release]
release = false


# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
Expand All @@ -32,3 +33,11 @@ tokio = { version = "1.5.0", features = [
"test-util",
"time",
] }

[dependencies.axum]
version = "0.7"
optional = true
default-features = false

[features]
axum = ["dep:axum"]
10 changes: 10 additions & 0 deletions worker-kv/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,3 +232,13 @@ impl<T: Serialize> ToRawKvValue for T {
fn get(target: &JsValue, name: &str) -> Result<JsValue, JsValue> {
Reflect::get(target, &JsValue::from(name))
}

#[cfg(feature = "axum")]
impl axum::response::IntoResponse for KvError {
fn into_response(self) -> axum::response::Response<axum::body::Body> {
axum::response::Response::builder()
.status(500)
.body("INTERNAL SERVER ERROR".into())
.unwrap()
}
}
14 changes: 13 additions & 1 deletion worker/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ readme = "../README.md"
[package.metadata.docs.rs]
all-features = true

[dev-dependencies]
tokio-test = "0.4"
wasm-bindgen-test = "0.3.0"

[dev-dependencies.axum]
version="0.7"
default-features = false

[dev-dependencies.tower-service]
version="0.3"
default-features = false

[dependencies]
async-trait.workspace = true
bytes = "1.5"
Expand Down Expand Up @@ -67,5 +79,5 @@ default-features = false
queue = ["worker-macros/queue", "worker-sys/queue"]
d1 = ["worker-sys/d1"]
http = ["worker-macros/http"]
axum = ["dep:axum"]
axum = ["dep:axum", "worker-kv/axum"]
timezone = ["dep:chrono-tz"]
2 changes: 1 addition & 1 deletion worker/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl Context {
/// until the given future has been completed. The future is executed before the handler
/// terminates but does not block the response. For example, this is ideal for caching
/// responses or handling logging.
/// ```no_run
/// ```ignore
/// context.wait_until(async move {
/// let _ = cache.put(request, response).await;
/// });
Expand Down
4 changes: 4 additions & 0 deletions worker/src/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use wasm_bindgen::JsValue;

/// The equivalent to a JavaScript `Date` Object.
/// ```no_run
/// # use worker::Date;
/// # use worker::DateInit;
/// let now = Date::now();
/// let millis = now.as_millis();
/// // or use a specific point in time:
Expand All @@ -24,6 +26,8 @@ impl PartialEq for Date {

/// Initialize a `Date` by constructing this enum.
/// ```no_run
/// # use worker::DateInit;
/// # use worker::Date;
/// let t1: Date = DateInit::Millis(1630611511000).into();
/// let t2: Date = DateInit::String("Thu, 02 Sep 2021 19:38:31 GMT".to_string()).into();
/// ```
Expand Down
8 changes: 6 additions & 2 deletions worker/src/durable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,12 +295,12 @@ impl Storage {
///
/// ```no_run
/// # use worker::Storage;
/// use worker::JsValue;
/// use wasm_bindgen::JsValue;
///
/// # let storage: Storage = todo!();
///
/// let obj = js_sys::Object::new();
/// js_sys::Reflect::set(&obj, &JsValue::from_str("foo"), JsValue::from_u64(1));
/// js_sys::Reflect::set(&obj, &JsValue::from_str("foo"), &JsValue::from_f64(1.0));
///
/// storage.put_multiple_raw(obj);
/// ```
Expand Down Expand Up @@ -744,6 +744,10 @@ macro to both the impl block and the struct type definition.
```no_run
use worker::*;

struct Message;

struct User;

#[durable_object]
pub struct Chatroom {
users: Vec<User>,
Expand Down
10 changes: 10 additions & 0 deletions worker/src/dynamic_dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,19 @@ use crate::{env::EnvBinding, Fetcher, Result};
/// # Example:
///
/// ```no_run
/// # use js_sys::Object;
/// # use wasm_bindgen::JsCast;
/// # let env: worker::Env = Object::new().unchecked_into();
/// # tokio_test::block_on(async {
/// # #[cfg(feature="http")]
/// # let req = http::Request::get("http://localhost:8080").body(worker::Body::empty())?;
/// # #[cfg(not(feature="http"))]
/// # let req = worker::Request::new("http://localhost:8080", worker::Method::Get)?;
/// let dispatcher = env.dynamic_dispatcher("DISPATCHER")?;
/// let fetcher = dispatcher.get("namespaced-worker-name")?;
/// let resp = fetcher.fetch_request(req).await?;
/// # Ok::<(), worker::Error>(())
/// # });
/// ```
#[derive(Debug, Clone)]
pub struct DynamicDispatcher(DynamicDispatcherSys);
Expand Down
10 changes: 10 additions & 0 deletions worker/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,13 @@ impl From<serde_json::Error> for Error {
Error::SerdeJsonError(e)
}
}

#[cfg(feature = "axum")]
impl axum::response::IntoResponse for Error {
fn into_response(self) -> axum::response::Response<axum::body::Body> {
axum::response::Response::builder()
.status(500)
.body("INTERNAL SERVER ERROR".into())
.unwrap()
}
}
55 changes: 41 additions & 14 deletions worker/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@
//!
//! Enables `queue` event type in [`[event]`](worker_macros::event) macro.
//!
//! ```
//! ```no_run
//! # mod scope {
//! // Consume messages from a queue
//! # use worker::{Env, Context, Result, MessageBatch, event};
//!
//! struct MyType;
//!
//! #[event(queue)]
//! pub async fn main(message_batch: MessageBatch<MyType>, env: Env, _ctx: Context) -> Result<()> {
//! pub async fn handle(message_batch: MessageBatch<MyType>, env: Env, _ctx: Context) -> Result<()> {
//! Ok(())
//! }
//! # }
//! ```
//!
//! ## `http`
Expand All @@ -33,15 +39,20 @@
//!
//! The end result is being able to use frameworks like `axum` directly (see [example](./examples/axum)):
//!
//! ```rust
//! ```no_run
//! # mod scope {
//! # use worker::{Context, Env, HttpRequest, Result};
//! # use axum::routing::get;
//! # use axum::Router;
//! # use worker::event;
//! # use tower_service::Service;
//! pub async fn root() -> &'static str {
//! "Hello Axum!"
//! }
//!
//! fn router() -> Router {
//! Router::new().route("/", get(root))
//! }
//!
//! #[event(fetch)]
//! async fn fetch(
//! req: HttpRequest,
Expand All @@ -50,6 +61,7 @@
//! ) -> Result<http::Response<axum::body::Body>> {
//! Ok(router().call(req).await?)
//! }
//! # }
//! ```
//!
//! We also implement `try_from` between `worker::Request` and `http::Request<worker::Body>`, and between `worker::Response` and `http::Response<worker::Body>`.
Expand All @@ -64,8 +76,11 @@
//!
//! 1. [`send::SendFuture`] - wraps any `Future` and marks it as `Send`:
//!
//! ```rust
//! ```no_run
//! // `fut` is `Send`
//! # use worker::send;
//! # use wasm_bindgen_futures::JsFuture;
//! # let promise = js_sys::Promise::new(&mut |_, _| {});
//! let fut = send::SendFuture::new(async move {
//! // `JsFuture` is not `Send`
//! JsFuture::from(promise).await
Expand All @@ -75,31 +90,43 @@
//! 2. [`send::SendWrapper`] - Marks an arbitrary object as `Send` and implements `Deref` and `DerefMut`, as well as `Clone`, `Debug`, and `Display` if the
//! inner type does. This is useful for attaching types as state to an `axum` `Router`:
//!
//! ```rust
//! ```no_run
//! # use axum::Extension;
//! # use worker::send;
//! # use worker_kv::KvStore;
//! // `KvStore` is not `Send`
//! let store = env.kv("FOO")?;
//! let store = KvStore::create("FOO")?;
//! // `state` is `Send`
//! let state = send::SendWrapper::new(store);
//! let router = axum::Router::new()
//! let router = axum::Router::<()>::new()
//! .layer(Extension(state));
//!
//! # Ok::<(), worker::Error>(())
//! ```
//!
//! 3. [`[worker::send]`](macro@crate::send) - Macro to make any `async` function `Send`. This can be a little tricky to identify as the problem, but
//! `axum`'s `[debug_handler]` macro can help, and looking for warnings that a function or object cannot safely be sent
//! between threads.
//!
//! ```rust
//! ```no_run
//! # #[cfg(feature="http")]
//! # {
//! # use axum::routing::get;
//! # use axum::Extension;
//! # use axum::response::Result;
//! # use worker::Env;
//! // This macro makes the whole function (i.e. the `Future` it returns) `Send`.
//! #[worker::send]
//! async fn handler(Extension(env): Extension<Env>) -> Response<String> {
//! let kv = env.kv("FOO").unwrap()?;
//! async fn handler(Extension(env): Extension<Env>) -> Result<String> {
//! let kv = env.kv("FOO")?;
//! // Holding `kv`, which is not `Send` across `await` boundary would mark this function as `!Send`
//! let value = kv.get("foo").text().await?;
//! Ok(format!("Got value: {:?}", value));
//! Ok(format!("Got value: {:?}", value))
//! }
//!
//! let router = axum::Router::new()
//! .route("/", get(handler))
//! let router = axum::Router::<()>::new()
//! .route("/", get(handler));
//! # }
//! ```

#[doc(hidden)]
Expand Down
18 changes: 16 additions & 2 deletions worker/src/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,12 +576,19 @@ impl Queue {
///
/// ## Example
/// ```no_run
/// # use serde::Serialize;
/// # use js_sys::Object;
/// # use wasm_bindgen::JsCast;
/// #[derive(Serialize)]
/// pub struct MyMessage {
/// my_data: u32,
/// }
///
/// # let env: worker::Env = Object::new().unchecked_into();
/// # tokio_test::block_on(async {
/// # let queue = env.queue("FOO")?;
/// queue.send(MyMessage{ my_data: 1}).await?;
/// # Ok::<(), worker::Error>(())
/// # });
/// ```
pub async fn send<T, U: Into<SendMessage<T>>>(&self, message: U) -> Result<()>
where
Expand Down Expand Up @@ -615,12 +622,19 @@ impl Queue {
///
/// ## Example
/// ```no_run
/// # use serde::Serialize;
/// # use wasm_bindgen::JsCast;
/// # use js_sys::Object;
/// #[derive(Serialize)]
/// pub struct MyMessage {
/// my_data: u32,
/// }
///
/// # let env: worker::Env = Object::new().unchecked_into();
/// # tokio_test::block_on(async {
/// # let queue = env.queue("FOO")?;
/// queue.send_batch(vec![MyMessage{ my_data: 1}]).await?;
/// # Ok::<(), worker::Error>(())
/// # });
/// ```
pub async fn send_batch<T: Serialize, U: Into<BatchSendMessage<T>>>(
&self,
Expand Down
5 changes: 3 additions & 2 deletions worker/src/r2/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ impl<'bucket> CreateMultipartUploadOptionsBuilder<'bucket> {
}

/// Metadata that's automatically rendered into R2 HTTP API endpoints.
/// ```
/// ```ignore
/// * contentType -> content-type
/// * contentLanguage -> content-language
/// etc...
Expand Down Expand Up @@ -378,7 +378,8 @@ impl<'bucket> ListOptionsBuilder<'bucket> {
/// you are sending into one bucket. Make sure to look at `truncated` for the result
/// rather than having logic like
///
/// ```no_run
/// ```ignore
/// # let limit = 10;
/// while listed.len() < limit {
/// listed = bucket.list()
/// .limit(limit),
Expand Down
Loading
Loading