improve quality of rust sdk and add tooling

also bump version to 0.1.2

- add makefile with all commands for rust sdk developers
  to run all relevant checks and test,
  which also auto formatting of code and toml deps
- fixed broken clippy rules
  (this also required fixing some stuff in consts)

Also fixed the docs.rs attributes to ensure _all_
modules and symbols get published in docs,
instead of only those that are available in default features
(which was missing the framework specific stuff in docs)

Only nitpick issue left: in generated code (consts.rs)
some descriptions can contain 'html' code which is not escaped,
pretty certain this html will be rendered in docs.rs
as rust docs renders docs as markdown (which includes html),
but given that's auto generated I have left that for now as-is.
This commit is contained in:
Glen De Cauwsemaecker 2025-04-18 21:27:18 +02:00
parent 47a095f04a
commit 0eb448570e
15 changed files with 193 additions and 82 deletions

View File

@ -1,8 +1,13 @@
{%- func rustConsts(data *ConstTemplateData) -%}
//! Datastar constants
#![allow(rustdoc::invalid_html_tags)]
// {%s data.DoNotEdit %}
pub const _DATASTAR_KEY: &str = "{%s data.DatastarKey %}";
pub const _VERSION: &str = "{%s data.Version %}";
#[expect(unused)]
pub(crate) const DATASTAR_KEY: &str = "{%s data.DatastarKey %}";
#[expect(unused)]
pub(crate) const VERSION: &str = "{%s data.Version %}";
// #region Defaults
@ -19,7 +24,7 @@ pub const DEFAULT_{%s d.Name.ScreamingSnake %}: u64 = {%d durationToMs(d.Duratio
{%- for _, s := range data.DefaultStrings -%}
/// {%s= s.Description %}
pub const DEFAULT_{%s s.Name.ScreamingSnake %}: &str = "{%s s.Value %}";
pub(crate) const DEFAULT_{%s s.Name.ScreamingSnake %}: &str = "{%s s.Value %}";
{%- endfor -%}
// #endregion
@ -27,7 +32,7 @@ pub const DEFAULT_{%s s.Name.ScreamingSnake %}: &str = "{%s s.Value %}";
// #region Datalines
{%- for _, literal := range data.DatalineLiterals -%}
pub const {%s literal.ScreamingSnake %}_DATALINE_LITERAL: &str = "{%s literal.Camel %}";
pub(crate) const {%s literal.ScreamingSnake %}_DATALINE_LITERAL: &str = "{%s literal.Camel %}";
{%- endfor -%}
// #endregion
@ -36,7 +41,7 @@ pub const {%s literal.ScreamingSnake %}_DATALINE_LITERAL: &str = "{%s literal.Ca
{%- for _, b := range data.DefaultBools -%}
/// {%s= b.Description %}
pub const DEFAULT_{%s b.Name.ScreamingSnake %}: bool = {%v b.Value %};
pub(crate) const DEFAULT_{%s b.Name.ScreamingSnake %}: bool = {%v b.Value %};
{%- endfor -%}
// #endregion
@ -58,7 +63,7 @@ pub enum {%s enum.Name.Pascal %} {
impl {%s enum.Name.Pascal %} {
/// Returns the [`{%s enum.Name.Pascal %}`] as a string.
pub const fn as_str(&self) -> &str {
pub(crate) const fn as_str(&self) -> &str {
match self {
{%- for _, entry := range enum.Values -%}
Self::{%s entry.Name.Pascal %} => "{%s entry.Value %}",
@ -70,4 +75,4 @@ impl {%s enum.Name.Pascal %} {
// #endregion
// #endregion
{%- endfunc -%}
{%- endfunc -%}

View File

@ -4,40 +4,66 @@ authors = [
"Glen Henri J. De Cauwsemaecker <glen@plabayo.tech>",
]
categories = ["web-programming"]
description = "Datastar is the Rust implementation of the [Datastar](https://data-star.dev) SDK."
description = "Datastar SDK for Rust"
documentation = "https://docs.rs/datastar"
edition = "2024"
homepage = "https://data-star.dev"
keywords = ["datastar", "web", "backend"]
keywords = ["datastar", "web", "backend", "axum", "rama", "rocket"]
license = "MIT OR Apache-2.0"
name = "datastar"
readme = "README.md"
repository = "https://github.com/starfederation/datastar-rs"
version = "0.1.1"
version = "0.1.2"
rust-version = "1.85.0"
[dev-dependencies]
async-stream = { version = "0.3.6", default-features = false }
serde = { version = "1", default-features = false, features = ["derive"] }
serde_json = { version = "1", default-features = false, features = ["std"] }
tokio = { version = "1.43.0", features = ["full"] }
axum = { version = "0.8.1" }
rocket = { version = "0.5.1", features = ["json"] }
rama = { version = "0.2.0-alpha.10", features = ["http-full"] }
[lints.rust]
unreachable_pub = "deny"
elided_lifetimes_in_paths = "allow"
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(fuzzing)'] }
[lints.clippy]
all = { level = "warn", priority = -1 }
todo = "warn"
empty_enum = "warn"
enum_glob_use = "warn"
mem_forget = "warn"
unused_self = "warn"
filter_map_next = "warn"
needless_continue = "warn"
needless_borrow = "warn"
match_wildcard_for_single_variants = "warn"
if_let_mutex = "warn"
await_holding_lock = "warn"
match_on_vec_items = "warn"
imprecise_flops = "warn"
suboptimal_flops = "warn"
lossy_float_literal = "warn"
rest_pat_in_fully_bound_structs = "warn"
fn_params_excessive_bools = "warn"
exit = "warn"
inefficient_to_string = "warn"
linkedlist = "warn"
macro_use_imports = "warn"
option_option = "warn"
verbose_file_reads = "warn"
unnested_or_patterns = "warn"
str_to_string = "warn"
type_complexity = "allow"
[dependencies]
matchit = "0.8.4"
axum = { version = "0.8.1", default-features = false, optional = true, features = [
"query",
"tokio",
] }
bytes = { version = "1", default-features = false, optional = true }
futures-util = { version = "0.3", default-features = false }
http-body = { version = "1.0", default-features = false, optional = true }
matchit = "0.8.4"
pin-project-lite = { version = "0.2", default-features = false, optional = true }
rocket = { version = "0.5.1", default-features = false, optional = true }
rama = { version = "0.2.0-alpha.11", default-features = false, optional = true, features = [
"http",
] }
rocket = { version = "0.5.1", default-features = false, optional = true }
serde = { version = "1", default-features = false, optional = true, features = [
"derive",
] }
@ -45,8 +71,15 @@ serde_json = { version = "1", default-features = false, optional = true, feature
"std",
] }
sync_wrapper = { version = "1", default-features = false, optional = true }
bytes = { version = "1", default-features = false, optional = true }
[dev-dependencies]
async-stream = { version = "0.3.6", default-features = false }
axum = { version = "0.8.1" }
rama = { version = "0.2.0-alpha.11", features = ["http-full"] }
rocket = { version = "0.5.1", features = ["json"] }
serde = { version = "1", default-features = false, features = ["derive"] }
serde_json = { version = "1", default-features = false, features = ["std"] }
tokio = { version = "1.43.0", features = ["full"] }
[features]
axum = [
@ -77,3 +110,7 @@ opt-level = 3
[profile.release]
codegen-units = 1
lto = "thin"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

51
sdk/rust/Makefile Normal file
View File

@ -0,0 +1,51 @@
.PHONY: all
all:
@echo "Usage:"
@echo "fmt - run the rust formatter"
@echo "sort - sort TOML dependencies"
@echo "lint - combine fmt+sort"
@echo "check - shallow check of rust code (pre-compile)"
@echo "clippy - run clippy checks"
@echo "doc - doc checks"
@echo "hack - test feature matrix compatibility"
@echo "test - run all unit and doc tests"
@echo "qa - combine lint+check+clippy+doc+hack+test"
@echo "hello-axum - run hello-world example using the Axum framework"
@echo "hello-rama - run hello-world example using the Rama framework"
@echo "hello-rocket - run hello-world example using the Rocket framework"
.PHONY:
fmt:
cargo fmt --all
sort:
cargo sort --grouped
lint: fmt sort
check:
cargo check --all-targets --all-features
clippy:
cargo clippy --all-targets --all-features
doc:
RUSTDOCFLAGS="-D rustdoc::broken-intra-doc-links" cargo doc --all-features --no-deps
hack:
cargo hack check --each-feature --no-dev-deps --workspace
test:
cargo test --all-features --workspace
qa: lint check clippy doc test
hello-axum:
cd ../../examples/rust/axum/hello-world && cargo run
hello-rama:
cd ../../examples/rust/rama/hello-world && cargo run
hello-rocket:
cd ../../examples/rust/rocket/hello-world && cargo run

View File

@ -1,6 +1,7 @@
# Datastar Rust SDK
An implementation of the Datastar SDK in Rust with framework integration for Axum, Rocket and Rama.
An implementation of the [Datastar] SDK in Rust
with framework integration for [Axum], [Rocket] and [Rama].
# Usage
@ -16,3 +17,8 @@ Sse(stream! {
yield MergeSignals::new("{response: '', answer: 'bread'}").into();
})
```
[Datastar]: https://data-star.dev
[Axum]: https://github.com/tokio-rs/axum
[Rocket]: https://github.com/rwf2/rocket
[Rama]: https://github.com/plabayo/rama

View File

@ -1,7 +1,7 @@
//! Axum integration for Datastar.
use {
crate::{prelude::DatastarEvent, Sse, TrySse},
crate::{Sse, TrySse, prelude::DatastarEvent},
axum::{
body::{Body, Bytes, HttpBody},
extract::{FromRequest, Query, Request},
@ -16,7 +16,7 @@ use {
futures_util::{Stream, StreamExt},
http_body::Frame,
pin_project_lite::pin_project,
serde::{de::DeserializeOwned, Deserialize},
serde::{Deserialize, de::DeserializeOwned},
sync_wrapper::SyncWrapper,
};
@ -162,9 +162,9 @@ mod tests {
testing::{self, Signals},
},
axum::{
Router,
response::IntoResponse,
routing::{get, post},
Router,
},
tokio::net::TcpListener,
};
@ -174,6 +174,7 @@ mod tests {
}
#[tokio::test]
#[ignore]
async fn sdk_test() -> Result<(), Box<dyn core::error::Error>> {
let listener = TcpListener::bind("127.0.0.1:3000").await?;
let app = Router::new()

View File

@ -1,7 +1,12 @@
//! Datastar constants
#![allow(rustdoc::invalid_html_tags)]
// This is auto-generated by Datastar. DO NOT EDIT.
pub const _DATASTAR_KEY: &str = "datastar";
pub const _VERSION: &str = "1.0.0-beta.11";
#[expect(unused)]
pub(crate) const DATASTAR_KEY: &str = "datastar";
#[expect(unused)]
pub(crate) const VERSION: &str = "1.0.0-beta.11";
// #region Defaults
@ -15,40 +20,40 @@ pub const DEFAULT_SSE_RETRY_DURATION: u64 = 1000;
// #region Default strings
/// The default attributes for <script/> element use when executing scripts. It is a set of key-value pairs delimited by a newline \\n character.
pub const DEFAULT_EXECUTE_SCRIPT_ATTRIBUTES: &str = "type module";
pub(crate) const DEFAULT_EXECUTE_SCRIPT_ATTRIBUTES: &str = "type module";
// #endregion
// #region Datalines
pub const SELECTOR_DATALINE_LITERAL: &str = "selector";
pub const MERGE_MODE_DATALINE_LITERAL: &str = "mergeMode";
pub const FRAGMENTS_DATALINE_LITERAL: &str = "fragments";
pub const USE_VIEW_TRANSITION_DATALINE_LITERAL: &str = "useViewTransition";
pub const SIGNALS_DATALINE_LITERAL: &str = "signals";
pub const ONLY_IF_MISSING_DATALINE_LITERAL: &str = "onlyIfMissing";
pub const PATHS_DATALINE_LITERAL: &str = "paths";
pub const SCRIPT_DATALINE_LITERAL: &str = "script";
pub const ATTRIBUTES_DATALINE_LITERAL: &str = "attributes";
pub const AUTO_REMOVE_DATALINE_LITERAL: &str = "autoRemove";
pub(crate) const SELECTOR_DATALINE_LITERAL: &str = "selector";
pub(crate) const MERGE_MODE_DATALINE_LITERAL: &str = "mergeMode";
pub(crate) const FRAGMENTS_DATALINE_LITERAL: &str = "fragments";
pub(crate) const USE_VIEW_TRANSITION_DATALINE_LITERAL: &str = "useViewTransition";
pub(crate) const SIGNALS_DATALINE_LITERAL: &str = "signals";
pub(crate) const ONLY_IF_MISSING_DATALINE_LITERAL: &str = "onlyIfMissing";
pub(crate) const PATHS_DATALINE_LITERAL: &str = "paths";
pub(crate) const SCRIPT_DATALINE_LITERAL: &str = "script";
pub(crate) const ATTRIBUTES_DATALINE_LITERAL: &str = "attributes";
pub(crate) const AUTO_REMOVE_DATALINE_LITERAL: &str = "autoRemove";
// #endregion
// #region Default booleans
/// Should fragments be merged using the ViewTransition API?
pub const DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS: bool = false;
pub(crate) const DEFAULT_FRAGMENTS_USE_VIEW_TRANSITIONS: bool = false;
/// Should a given set of signals merge if they are missing?
pub const DEFAULT_MERGE_SIGNALS_ONLY_IF_MISSING: bool = false;
pub(crate) const DEFAULT_MERGE_SIGNALS_ONLY_IF_MISSING: bool = false;
/// Should script element remove itself after execution?
pub const DEFAULT_EXECUTE_SCRIPT_AUTO_REMOVE: bool = true;
pub(crate) const DEFAULT_EXECUTE_SCRIPT_AUTO_REMOVE: bool = true;
// #endregion
// #region Enums
/// The mode in which a fragment is merged into the DOM.
#[derive(Default,Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FragmentMergeMode {
/// Morphs the fragment into the existing element using idiomorph.
#[default]
@ -71,7 +76,7 @@ pub enum FragmentMergeMode {
impl FragmentMergeMode {
/// Returns the [`FragmentMergeMode`] as a string.
pub const fn as_str(&self) -> &str {
pub(crate) const fn as_str(&self) -> &str {
match self {
Self::Morph => "morph",
Self::Inner => "inner",
@ -101,7 +106,7 @@ pub enum EventType {
impl EventType {
/// Returns the [`EventType`] as a string.
pub const fn as_str(&self) -> &str {
pub(crate) const fn as_str(&self) -> &str {
match self {
Self::MergeFragments => "datastar-merge-fragments",
Self::MergeSignals => "datastar-merge-signals",
@ -113,4 +118,4 @@ impl EventType {
}
// #endregion
// #endregion
// #endregion

View File

@ -1,7 +1,7 @@
//! [`ExecuteScript`] executes JavaScript in the browser.
use {
crate::{consts, DatastarEvent},
crate::{DatastarEvent, consts},
core::time::Duration,
};
@ -27,10 +27,10 @@ use {
pub struct ExecuteScript {
/// `id` can be used by the backend to replay events.
/// This is part of the SSE spec and is used to tell the browser how to handle the event.
/// For more details see https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#id
/// For more details see <https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#id>
pub id: Option<String>,
/// `retry` is part of the SSE spec and is used to tell the browser how long to wait before reconnecting if the connection is lost.
/// For more details see https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#retry
/// For more details see <https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#retry>
pub retry: Duration,
/// `script` is a string that represents the JavaScript to be executed by the browser.
pub script: String,
@ -49,7 +49,7 @@ impl ExecuteScript {
retry: Duration::from_millis(consts::DEFAULT_SSE_RETRY_DURATION),
script: script.into(),
auto_remove: consts::DEFAULT_EXECUTE_SCRIPT_AUTO_REMOVE,
attributes: vec![consts::DEFAULT_EXECUTE_SCRIPT_ATTRIBUTES.to_string()],
attributes: vec![consts::DEFAULT_EXECUTE_SCRIPT_ATTRIBUTES.to_owned()],
}
}

View File

@ -19,7 +19,7 @@ pub mod remove_signals;
#[cfg(test)]
mod testing;
mod consts;
pub mod consts;
/// The prelude for the `datastar` crate
pub mod prelude {
@ -28,9 +28,9 @@ pub mod prelude {
#[cfg(all(feature = "rama", not(feature = "axum")))]
pub use crate::rama::ReadSignals;
pub use crate::{
consts::FragmentMergeMode, execute_script::ExecuteScript, merge_fragments::MergeFragments,
merge_signals::MergeSignals, remove_fragments::RemoveFragments,
remove_signals::RemoveSignals, DatastarEvent, Sse, TrySse,
DatastarEvent, Sse, TrySse, consts::FragmentMergeMode, execute_script::ExecuteScript,
merge_fragments::MergeFragments, merge_signals::MergeSignals,
remove_fragments::RemoveFragments, remove_signals::RemoveSignals,
};
}
@ -47,10 +47,10 @@ pub struct DatastarEvent {
pub event: consts::EventType,
/// `id` is can be used by the backend to replay events.
/// This is part of the SSE spec and is used to tell the browser how to handle the event.
/// For more details see https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#id
/// For more details see <https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#id>
pub id: Option<String>,
/// `retry` is part of the SSE spec and is used to tell the browser how long to wait before reconnecting if the connection is lost.
/// For more details see https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#retry
/// For more details see <https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#retry>
pub retry: Duration,
/// `data` is the data that is sent with the event.
pub data: Vec<String>,

View File

@ -3,8 +3,8 @@
use {
crate::{
consts::{self, FragmentMergeMode},
DatastarEvent,
consts::{self, FragmentMergeMode},
},
core::time::Duration,
};
@ -33,10 +33,10 @@ use {
pub struct MergeFragments {
/// `id` is can be used by the backend to replay events.
/// This is part of the SSE spec and is used to tell the browser how to handle the event.
/// For more details see https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#id
/// For more details see <https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#id>
pub id: Option<String>,
/// `retry` is part of the SSE spec and is used to tell the browser how long to wait before reconnecting if the connection is lost.
/// For more details see https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#retry
/// For more details see <https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#retry>
pub retry: Duration,
/// The HTML fragments to merge into the DOM.
pub fragments: String,

View File

@ -1,7 +1,7 @@
//! [`MergeSignals`] sends one or more signals to the browser to be merged into the signals.
use {
crate::{consts, DatastarEvent},
crate::{DatastarEvent, consts},
core::time::Duration,
};
@ -25,10 +25,10 @@ use {
pub struct MergeSignals {
/// `id` can be used by the backend to replay events.
/// This is part of the SSE spec and is used to tell the browser how to handle the event.
/// For more details see https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#id
/// For more details see <https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#id>
pub id: Option<String>,
/// `retry` is part of the SSE spec and is used to tell the browser how long to wait before reconnecting if the connection is lost.
/// For more details see https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#retry
/// For more details see <https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#retry>
pub retry: Duration,
/// `signals` is a JavaScript object or JSON string that will be sent to the browser to update signals in the signals.
/// The data ***must*** evaluate to a valid JavaScript. It will be converted to signals by the Datastar client side.

View File

@ -8,11 +8,14 @@ use {
bytes::Bytes,
futures_util::{Stream, StreamExt},
pin_project_lite::pin_project,
rama::http::{
Body, BodyExtractExt, IntoResponse, Method, Request, Response, StatusCode,
dep::http_body::{Body as HttpBody, Frame},
header,
service::web::extract::{FromRequest, Query},
rama::{
error::BoxError,
http::{
Body, BodyExtractExt, IntoResponse, Method, Request, Response, StatusCode,
dep::http_body::{Body as HttpBody, Frame},
header,
service::web::extract::{FromRequest, Query},
},
},
serde::{Deserialize, de::DeserializeOwned},
std::{
@ -52,7 +55,7 @@ where
impl<S, E> IntoResponse for TrySse<S>
where
S: Stream<Item = Result<DatastarEvent, E>> + Send + 'static,
E: Into<Box<dyn std::error::Error + Send + Sync>>,
E: Into<BoxError>,
{
fn into_response(self) -> Response {
(
@ -157,12 +160,13 @@ mod tests {
use {
super::Sse,
crate::{
prelude::ReadSignals,
rama::ReadSignals,
testing::{self, Signals},
},
rama::{
error::BoxError,
http::{IntoResponse, server::HttpServer, service::web::Router},
net::address::SocketAddress,
rt::Executor,
},
};
@ -172,10 +176,11 @@ mod tests {
}
#[tokio::test]
#[ignore]
async fn sdk_test() -> Result<(), BoxError> {
HttpServer::auto(Executor::default())
.listen(
"127.0.0.1:3000",
SocketAddress::local_ipv4(3000),
Router::new().get("/test", test).post("/test", test),
)
.await?;

View File

@ -1,7 +1,7 @@
//! [`RemoveFragments`] sends a selector to the browser to remove HTML fragments from the DOM.
use {
crate::{consts, DatastarEvent},
crate::{DatastarEvent, consts},
core::time::Duration,
};
@ -26,10 +26,10 @@ use {
pub struct RemoveFragments {
/// `id` can be used by the backend to replay events.
/// This is part of the SSE spec and is used to tell the browser how to handle the event.
/// For more details see https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#id
/// For more details see <https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#id>
pub id: Option<String>,
/// `retry` is part of the SSE spec and is used to tell the browser how long to wait before reconnecting if the connection is lost.
/// For more details see https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#retry
/// For more details see <https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#retry>
pub retry: Duration,
/// `selector` is a CSS selector that represents the fragments to be removed from the DOM.
/// The selector must be a valid CSS selector.

View File

@ -1,7 +1,7 @@
//! [`RemoveSignals`] sends signals to the browser to be removed from the signals.
use {
crate::{consts, DatastarEvent},
crate::{DatastarEvent, consts},
core::time::Duration,
};
@ -23,10 +23,10 @@ use {
pub struct RemoveSignals {
/// `id` can be used by the backend to replay events.
/// This is part of the SSE spec and is used to tell the browser how to handle the event.
/// For more details see https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#id
/// For more details see <https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#id>
pub id: Option<String>,
/// `retry` is part of the SSE spec and is used to tell the browser how long to wait before reconnecting if the connection is lost.
/// For more details see https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#retry
/// For more details see <https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#retry>
pub retry: Duration,
/// `paths` is a list of strings that represent the signal paths to be removed from the signals.
/// The paths ***must*** be valid . delimited paths to signals within the signals.

View File

@ -1,13 +1,13 @@
//! Rocket integration for Datastar.
use {
crate::{prelude::DatastarEvent, Sse, TrySse},
crate::{Sse, TrySse, prelude::DatastarEvent},
core::error::Error,
futures_util::{Stream, StreamExt},
rocket::{
http::ContentType,
response::{self, stream::ReaderStream, Responder},
Request, Response,
http::ContentType,
response::{self, Responder, stream::ReaderStream},
},
std::io::Cursor,
};
@ -60,14 +60,15 @@ where
mod tests {
use {
crate::{
testing::{self, Signals},
DatastarEvent, Sse,
testing::{self, Signals},
},
futures_util::Stream,
rocket::{get, post, routes, serde::json::Json},
};
#[tokio::test]
#[ignore]
async fn sdk_test() {
rocket::build()
.mount("/", routes![get_test, post_test])

View File

@ -12,7 +12,7 @@ use {
#[derive(Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum TestEvent {
pub(crate) enum TestEvent {
#[serde(rename_all = "camelCase")]
ExecuteScript {
script: String,
@ -53,11 +53,11 @@ pub enum TestEvent {
}
#[derive(Deserialize)]
pub struct Signals {
pub(crate) struct Signals {
pub events: Vec<TestEvent>,
}
pub fn test(events: Vec<TestEvent>) -> impl Stream<Item = DatastarEvent> {
pub(crate) fn test(events: Vec<TestEvent>) -> impl Stream<Item = DatastarEvent> + Send + 'static {
stream! {
for event in events {
yield match event {