From f388b858a97d44a6520a75a350243ec9c31b69ed Mon Sep 17 00:00:00 2001 From: Stuart Harris Date: Thu, 11 Jul 2024 14:15:50 +0100 Subject: [PATCH 1/2] capabiilties do their own typegen --- crux_core/src/capability/mod.rs | 21 ++-- crux_macros/src/export.rs | 174 ++++---------------------------- examples/counter/Cargo.lock | 14 +-- examples/counter/Cargo.toml | 8 +- 4 files changed, 43 insertions(+), 174 deletions(-) diff --git a/crux_core/src/capability/mod.rs b/crux_core/src/capability/mod.rs index 8a8fd598..621c1786 100644 --- a/crux_core/src/capability/mod.rs +++ b/crux_core/src/capability/mod.rs @@ -193,6 +193,7 @@ mod shell_request; mod shell_stream; use futures::Future; +use serde::de::DeserializeOwned; use std::sync::Arc; pub(crate) use channel::channel; @@ -237,7 +238,6 @@ pub trait Operation: serde::Serialize + PartialEq + Send + 'static { /// # } /// /// ``` - #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)] pub enum Never {} @@ -256,19 +256,19 @@ impl Operation for Never { /// ```rust /// # use crux_core::{Capability, capability::{CapabilityContext, Operation}}; /// # pub struct Http { -/// # context: CapabilityContext, +/// # context: CapabilityContext, /// # } -/// # #[derive(serde::Serialize, PartialEq, Eq)] pub struct HttpOperation; -/// # impl Operation for HttpOperation { +/// # #[derive(serde::Serialize, serde::Deserialize, PartialEq, Eq)] pub struct HttpRequest; +/// # impl Operation for HttpRequest { /// # type Output = (); /// # } /// # impl Http where Ev: 'static, { -/// # pub fn new(context: CapabilityContext) -> Self { +/// # pub fn new(context: CapabilityContext) -> Self { /// # Self { context } /// # } /// # } /// impl Capability for Http { -/// type Operation = HttpOperation; +/// type Operation = HttpRequest; /// type MappedSelf = Http; /// /// fn map_event(&self, f: F) -> Self::MappedSelf @@ -282,7 +282,7 @@ impl Operation for Never { /// } /// ``` pub trait Capability { - type Operation: Operation; + type Operation: Operation + DeserializeOwned; type MappedSelf; @@ -291,6 +291,13 @@ pub trait Capability { F: Fn(NewEv) -> Ev + Send + Sync + 'static, Ev: 'static, NewEv: 'static + Send; + + #[cfg(feature = "typegen")] + fn register_types(generator: &mut crate::typegen::TypeGen) -> crate::typegen::Result { + generator.register_type::()?; + generator.register_type::<::Output>()?; + Ok(()) + } } /// Allows Crux to construct app's set of required capabilities, providing context diff --git a/crux_macros/src/export.rs b/crux_macros/src/export.rs index 56d3b212..1d3b98c6 100644 --- a/crux_macros/src/export.rs +++ b/crux_macros/src/export.rs @@ -47,13 +47,14 @@ impl ToTokens for ExportStructReceiver { for (capability, event) in fields.iter().map(|f| split_on_generic(&f.ty)) { output_type_exports.push(quote! { - generator.register_type::<<#capability<#event> as ::crux_core::capability::Capability<#event>>::Operation>()?; - generator - .register_type::<<<#capability<#event> as ::crux_core::capability::Capability<#event>>::Operation as ::crux_core::capability::Operation>::Output>()?; + #[cfg(feature = "typegen")] + #capability::<#event>::register_types(generator)?; }); } tokens.extend(quote! { + use ::crux_core::capability::Capability; + impl ::crux_core::typegen::Export for #ident { fn register_types(generator: &mut ::crux_core::typegen::TypeGen) -> ::crux_core::typegen::Result { #(#output_type_exports)* @@ -129,22 +130,12 @@ mod tests { let actual = quote!(#input); insta::assert_snapshot!(pretty_print(&actual), @r###" + use ::crux_core::capability::Capability; impl ::crux_core::typegen::Export for Capabilities { fn register_types( generator: &mut ::crux_core::typegen::TypeGen, ) -> ::crux_core::typegen::Result { - generator - .register_type::< - as ::crux_core::capability::Capability>::Operation, - >()?; - generator - .register_type::< - < as ::crux_core::capability::Capability< - Event, - >>::Operation as ::crux_core::capability::Operation>::Output, - >()?; + #[cfg(feature = "typegen")] Render::::register_types(generator)?; generator.register_type::()?; generator.register_type::<::crux_core::bridge::Request>()?; Ok(()) @@ -186,66 +177,16 @@ mod tests { let actual = quote!(#input); insta::assert_snapshot!(pretty_print(&actual), @r###" + use ::crux_core::capability::Capability; impl ::crux_core::typegen::Export for MyCapabilities { fn register_types( generator: &mut ::crux_core::typegen::TypeGen, ) -> ::crux_core::typegen::Result { - generator - .register_type::< - as ::crux_core::capability::Capability>::Operation, - >()?; - generator - .register_type::< - < as ::crux_core::capability::Capability< - MyEvent, - >>::Operation as ::crux_core::capability::Operation>::Output, - >()?; - generator - .register_type::< - as ::crux_core::capability::Capability>::Operation, - >()?; - generator - .register_type::< - < as ::crux_core::capability::Capability< - MyEvent, - >>::Operation as ::crux_core::capability::Operation>::Output, - >()?; - generator - .register_type::< - as ::crux_core::capability::Capability>::Operation, - >()?; - generator - .register_type::< - < as ::crux_core::capability::Capability< - MyEvent, - >>::Operation as ::crux_core::capability::Operation>::Output, - >()?; - generator - .register_type::< - as ::crux_core::capability::Capability>::Operation, - >()?; - generator - .register_type::< - < as ::crux_core::capability::Capability< - MyEvent, - >>::Operation as ::crux_core::capability::Operation>::Output, - >()?; + #[cfg(feature = "typegen")] + crux_http::Http::::register_types(generator)?; + #[cfg(feature = "typegen")] KeyValue::::register_types(generator)?; + #[cfg(feature = "typegen")] Platform::::register_types(generator)?; + #[cfg(feature = "typegen")] Render::::register_types(generator)?; generator.register_type::()?; generator.register_type::<::crux_core::bridge::Request>()?; Ok(()) @@ -272,80 +213,17 @@ mod tests { let actual = quote!(#input); insta::assert_snapshot!(pretty_print(&actual), @r###" + use ::crux_core::capability::Capability; impl ::crux_core::typegen::Export for MyCapabilities { fn register_types( generator: &mut ::crux_core::typegen::TypeGen, ) -> ::crux_core::typegen::Result { - generator - .register_type::< - as ::crux_core::capability::Capability>::Operation, - >()?; - generator - .register_type::< - < as ::crux_core::capability::Capability< - MyEvent, - >>::Operation as ::crux_core::capability::Operation>::Output, - >()?; - generator - .register_type::< - as ::crux_core::capability::Capability>::Operation, - >()?; - generator - .register_type::< - < as ::crux_core::capability::Capability< - MyEvent, - >>::Operation as ::crux_core::capability::Operation>::Output, - >()?; - generator - .register_type::< - as ::crux_core::capability::Capability>::Operation, - >()?; - generator - .register_type::< - < as ::crux_core::capability::Capability< - MyEvent, - >>::Operation as ::crux_core::capability::Operation>::Output, - >()?; - generator - .register_type::< - as ::crux_core::capability::Capability>::Operation, - >()?; - generator - .register_type::< - < as ::crux_core::capability::Capability< - MyEvent, - >>::Operation as ::crux_core::capability::Operation>::Output, - >()?; - generator - .register_type::< - as ::crux_core::capability::Capability>::Operation, - >()?; - generator - .register_type::< - < as ::crux_core::capability::Capability< - MyEvent, - >>::Operation as ::crux_core::capability::Operation>::Output, - >()?; + #[cfg(feature = "typegen")] + crux_http::Http::::register_types(generator)?; + #[cfg(feature = "typegen")] KeyValue::::register_types(generator)?; + #[cfg(feature = "typegen")] Platform::::register_types(generator)?; + #[cfg(feature = "typegen")] Render::::register_types(generator)?; + #[cfg(feature = "typegen")] Time::::register_types(generator)?; generator.register_type::()?; generator.register_type::<::crux_core::bridge::Request>()?; Ok(()) @@ -370,22 +248,12 @@ mod tests { let actual = quote!(#input); insta::assert_snapshot!(pretty_print(&actual), @r###" + use ::crux_core::capability::Capability; impl ::crux_core::typegen::Export for Capabilities { fn register_types( generator: &mut ::crux_core::typegen::TypeGen, ) -> ::crux_core::typegen::Result { - generator - .register_type::< - as ::crux_core::capability::Capability>::Operation, - >()?; - generator - .register_type::< - < as ::crux_core::capability::Capability< - Event, - >>::Operation as ::crux_core::capability::Operation>::Output, - >()?; + #[cfg(feature = "typegen")] Render::::register_types(generator)?; generator.register_type::()?; generator.register_type::<::crux_core::bridge::Request>()?; Ok(()) diff --git a/examples/counter/Cargo.lock b/examples/counter/Cargo.lock index 7f894c54..8a790e53 100644 --- a/examples/counter/Cargo.lock +++ b/examples/counter/Cargo.lock @@ -1074,8 +1074,6 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crux_core" version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cbc7f23786d97287a7f9221a7f255639e7eaae4a109394e0a00e71a41c544ce" dependencies = [ "anyhow", "bincode", @@ -1094,8 +1092,6 @@ dependencies = [ [[package]] name = "crux_http" version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc0253f5bbbb7ebc428c4ce4c9c65f45dd84b26bb386bf04afd492cac98588cc" dependencies = [ "anyhow", "async-trait", @@ -1113,8 +1109,6 @@ dependencies = [ [[package]] name = "crux_macros" version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da01ee88d58247be654239d54d58131c3bc2789a447a601ec2faf3dddacd49c4" dependencies = [ "darling", "proc-macro-error", @@ -4964,9 +4958,9 @@ dependencies = [ [[package]] name = "serde-generate" -version = "0.25.1" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8c9331265d81c61212dc75df7b0836544ed8e32dba77a522f113805ff9a948e" +checksum = "8309fc8d475cf5884e92a463b3a003d433684335be19c3f739af0451b027254b" dependencies = [ "heck 0.3.3", "include_dir", @@ -4978,9 +4972,9 @@ dependencies = [ [[package]] name = "serde-reflection" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05a5f801ac62a51a49d378fdb3884480041b99aced450b28990673e8ff99895" +checksum = "5b6798a64289ff550d8d79847467789a5fd30b42c9c406a4d6dc0bc9b567e55c" dependencies = [ "once_cell", "serde", diff --git a/examples/counter/Cargo.toml b/examples/counter/Cargo.toml index 3cabeb59..8f347d28 100644 --- a/examples/counter/Cargo.toml +++ b/examples/counter/Cargo.toml @@ -20,10 +20,10 @@ rust-version = "1.66" [workspace.dependencies] anyhow = "1.0.86" -crux_core = "0.8" -crux_http = "0.9" -# crux_core = { path = "../../crux_core" } -# crux_http = { path = "../../crux_http" } +# crux_core = "0.8" +# crux_http = "0.9" +crux_core = { path = "../../crux_core" } +crux_http = { path = "../../crux_http" } serde = "1.0.203" [workspace.metadata.bin] From 6c451a28daf9b6c4506cde3cc7fc915074419a77 Mon Sep 17 00:00:00 2001 From: Stuart Harris Date: Thu, 11 Jul 2024 15:06:42 +0100 Subject: [PATCH 2/2] override typegen for Compose capability to panic with msg --- crux_core/src/capabilities/compose.rs | 10 +++++++++ crux_macros/src/export.rs | 26 +++++++++++++----------- examples/counter/Cargo.lock | 14 +++++++++---- examples/counter/Cargo.toml | 8 ++++---- examples/counter/web-nextjs/package.json | 3 ++- 5 files changed, 40 insertions(+), 21 deletions(-) diff --git a/crux_core/src/capabilities/compose.rs b/crux_core/src/capabilities/compose.rs index 714a3ff7..cbbd599f 100644 --- a/crux_core/src/capabilities/compose.rs +++ b/crux_core/src/capabilities/compose.rs @@ -157,4 +157,14 @@ impl Capability for Compose { { Compose::new(self.context.map_event(f)) } + + #[cfg(feature = "typegen")] + fn register_types(_generator: &mut crate::typegen::TypeGen) -> crate::typegen::Result { + panic!( + r#" + The Compose Capability should not be registered for type generation. + Instead, use #[effect(skip)] to skip the generation of an effect variant for the Compose Capability. + "# + ) + } } diff --git a/crux_macros/src/export.rs b/crux_macros/src/export.rs index 1d3b98c6..4bacf453 100644 --- a/crux_macros/src/export.rs +++ b/crux_macros/src/export.rs @@ -47,7 +47,6 @@ impl ToTokens for ExportStructReceiver { for (capability, event) in fields.iter().map(|f| split_on_generic(&f.ty)) { output_type_exports.push(quote! { - #[cfg(feature = "typegen")] #capability::<#event>::register_types(generator)?; }); } @@ -56,6 +55,7 @@ impl ToTokens for ExportStructReceiver { use ::crux_core::capability::Capability; impl ::crux_core::typegen::Export for #ident { + #[cfg(feature = "typegen")] fn register_types(generator: &mut ::crux_core::typegen::TypeGen) -> ::crux_core::typegen::Result { #(#output_type_exports)* @@ -132,10 +132,11 @@ mod tests { insta::assert_snapshot!(pretty_print(&actual), @r###" use ::crux_core::capability::Capability; impl ::crux_core::typegen::Export for Capabilities { + #[cfg(feature = "typegen")] fn register_types( generator: &mut ::crux_core::typegen::TypeGen, ) -> ::crux_core::typegen::Result { - #[cfg(feature = "typegen")] Render::::register_types(generator)?; + Render::::register_types(generator)?; generator.register_type::()?; generator.register_type::<::crux_core::bridge::Request>()?; Ok(()) @@ -179,14 +180,14 @@ mod tests { insta::assert_snapshot!(pretty_print(&actual), @r###" use ::crux_core::capability::Capability; impl ::crux_core::typegen::Export for MyCapabilities { + #[cfg(feature = "typegen")] fn register_types( generator: &mut ::crux_core::typegen::TypeGen, ) -> ::crux_core::typegen::Result { - #[cfg(feature = "typegen")] crux_http::Http::::register_types(generator)?; - #[cfg(feature = "typegen")] KeyValue::::register_types(generator)?; - #[cfg(feature = "typegen")] Platform::::register_types(generator)?; - #[cfg(feature = "typegen")] Render::::register_types(generator)?; + KeyValue::::register_types(generator)?; + Platform::::register_types(generator)?; + Render::::register_types(generator)?; generator.register_type::()?; generator.register_type::<::crux_core::bridge::Request>()?; Ok(()) @@ -215,15 +216,15 @@ mod tests { insta::assert_snapshot!(pretty_print(&actual), @r###" use ::crux_core::capability::Capability; impl ::crux_core::typegen::Export for MyCapabilities { + #[cfg(feature = "typegen")] fn register_types( generator: &mut ::crux_core::typegen::TypeGen, ) -> ::crux_core::typegen::Result { - #[cfg(feature = "typegen")] crux_http::Http::::register_types(generator)?; - #[cfg(feature = "typegen")] KeyValue::::register_types(generator)?; - #[cfg(feature = "typegen")] Platform::::register_types(generator)?; - #[cfg(feature = "typegen")] Render::::register_types(generator)?; - #[cfg(feature = "typegen")] Time::::register_types(generator)?; + KeyValue::::register_types(generator)?; + Platform::::register_types(generator)?; + Render::::register_types(generator)?; + Time::::register_types(generator)?; generator.register_type::()?; generator.register_type::<::crux_core::bridge::Request>()?; Ok(()) @@ -250,10 +251,11 @@ mod tests { insta::assert_snapshot!(pretty_print(&actual), @r###" use ::crux_core::capability::Capability; impl ::crux_core::typegen::Export for Capabilities { + #[cfg(feature = "typegen")] fn register_types( generator: &mut ::crux_core::typegen::TypeGen, ) -> ::crux_core::typegen::Result { - #[cfg(feature = "typegen")] Render::::register_types(generator)?; + Render::::register_types(generator)?; generator.register_type::()?; generator.register_type::<::crux_core::bridge::Request>()?; Ok(()) diff --git a/examples/counter/Cargo.lock b/examples/counter/Cargo.lock index 8a790e53..7f894c54 100644 --- a/examples/counter/Cargo.lock +++ b/examples/counter/Cargo.lock @@ -1074,6 +1074,8 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crux_core" version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cbc7f23786d97287a7f9221a7f255639e7eaae4a109394e0a00e71a41c544ce" dependencies = [ "anyhow", "bincode", @@ -1092,6 +1094,8 @@ dependencies = [ [[package]] name = "crux_http" version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc0253f5bbbb7ebc428c4ce4c9c65f45dd84b26bb386bf04afd492cac98588cc" dependencies = [ "anyhow", "async-trait", @@ -1109,6 +1113,8 @@ dependencies = [ [[package]] name = "crux_macros" version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da01ee88d58247be654239d54d58131c3bc2789a447a601ec2faf3dddacd49c4" dependencies = [ "darling", "proc-macro-error", @@ -4958,9 +4964,9 @@ dependencies = [ [[package]] name = "serde-generate" -version = "0.26.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8309fc8d475cf5884e92a463b3a003d433684335be19c3f739af0451b027254b" +checksum = "f8c9331265d81c61212dc75df7b0836544ed8e32dba77a522f113805ff9a948e" dependencies = [ "heck 0.3.3", "include_dir", @@ -4972,9 +4978,9 @@ dependencies = [ [[package]] name = "serde-reflection" -version = "0.4.0" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b6798a64289ff550d8d79847467789a5fd30b42c9c406a4d6dc0bc9b567e55c" +checksum = "f05a5f801ac62a51a49d378fdb3884480041b99aced450b28990673e8ff99895" dependencies = [ "once_cell", "serde", diff --git a/examples/counter/Cargo.toml b/examples/counter/Cargo.toml index 8f347d28..3cabeb59 100644 --- a/examples/counter/Cargo.toml +++ b/examples/counter/Cargo.toml @@ -20,10 +20,10 @@ rust-version = "1.66" [workspace.dependencies] anyhow = "1.0.86" -# crux_core = "0.8" -# crux_http = "0.9" -crux_core = { path = "../../crux_core" } -crux_http = { path = "../../crux_http" } +crux_core = "0.8" +crux_http = "0.9" +# crux_core = { path = "../../crux_core" } +# crux_http = { path = "../../crux_http" } serde = "1.0.203" [workspace.metadata.bin] diff --git a/examples/counter/web-nextjs/package.json b/examples/counter/web-nextjs/package.json index c7a1a2a9..61574650 100644 --- a/examples/counter/web-nextjs/package.json +++ b/examples/counter/web-nextjs/package.json @@ -24,5 +24,6 @@ "@types/node": "20.14.9", "@types/react": "18.3.3", "@types/react-dom": "18.3.0" - } + }, + "packageManager": "pnpm@7.28.0+sha1.48be3292711ad554fe944f6caaf9b0f5477524fe" }